commit ee425b3
delthas
·
2023-06-19 13:34:26 +0000 UTC
parent 1318e78
Add setup assistant I can't be bothered to create configuration folders and files manually :-)
3 files changed,
+91,
-25
+12,
-13
1@@ -12,20 +12,21 @@ senpai is an IRC client that works best with bouncers:
2 - history is fetched from the server via [CHATHISTORY],
3 - networks are fetched from the server via [bouncer-networks].
4
5-## How do I use this?
6+## Installing
7
8+From source (requires Go):
9 ```shell
10-mkdir -p ~/.config/senpai
11-cat <<EOF >~/.config/senpai/senpai.scfg
12-address chat.sr.ht
13-nickname senpai
14-password "my password can't be this cute (2010)"
15-# alternatively, specify a command to fetch your password:
16-# password-cmd gopass show irc/<username>
17-EOF
18-go run ./cmd/senpai
19+go install git.sr.ht/~taiite/senpai/cmd/senpai@master
20 ```
21
22+## Running
23+
24+From your terminal:
25+```shell
26+senpai
27+```
28+Senpai will guide you through a configuration assistant on your first run.
29+
30 Then, type `/join #senpai` on [Libera.Chat] and have a... chat!
31
32 See `doc/senpai.1.scd` for more information and `doc/senpai.5.scd` for more
33@@ -43,8 +44,7 @@ things out with an IRC server, then you have two options:
34
35 ## Contributing and stuff
36
37-Contributions are accepted as patches to [the mailing list][ml] and as pull
38-requests on [Github].
39+Contributions are accepted as patches to [the mailing list][ml].
40
41 Browse tickets at <https://todo.sr.ht/~taiite/senpai>.
42
43@@ -56,6 +56,5 @@ Copyright (C) 2021 The senpai Contributors
44
45 [bouncer-networks]: https://git.sr.ht/~emersion/soju/tree/master/item/doc/ext/bouncer-networks.md
46 [CHATHISTORY]: https://ircv3.net/specs/extensions/chathistory
47-[Github]: https://github.com/hhirtz/senpai/pulls
48 [Libera.Chat]: https://libera.chat/
49 [ml]: https://lists.sr.ht/~delthas/senpai-dev
+74,
-2
1@@ -1,6 +1,7 @@
2 package main
3
4 import (
5+ "errors"
6 "flag"
7 "fmt"
8 "io/ioutil"
9@@ -37,8 +38,79 @@ func main() {
10
11 cfg, err := senpai.LoadConfigFile(configPath)
12 if err != nil {
13- fmt.Fprintf(os.Stderr, "failed to load the required configuration file at %q: %s\n", configPath, err)
14- os.Exit(1)
15+ if !errors.Is(err, os.ErrNotExist) {
16+ fmt.Fprintf(os.Stderr, "failed to load the required configuration file at %q: %s\n", configPath, err)
17+ os.Exit(1)
18+ return
19+ }
20+ var host, port string
21+ tls := true
22+ var nick, password string
23+ fmt.Fprintf(os.Stderr, "The configuration file at %q was not found.\n", configPath)
24+ fmt.Fprintf(os.Stderr, "Configuration assistant: senpai will create a configuration file for you.\n")
25+ fmt.Fprintf(os.Stderr, "Configuration assistant: Enter your server host (examples: example.com, localhost, 1.2.3.4): ")
26+ for host == "" {
27+ fmt.Scanln(&host)
28+ }
29+ fmt.Fprintf(os.Stderr, "Configuration assistant: Enter your server port (examples: 6667, 6697) [optional]: ")
30+ fmt.Scanln(&port)
31+ fmt.Fprintf(os.Stderr, "Configuration assistant: Enter whether your server uses TLS (examples: yes, no) [optional, default: yes]: ")
32+ for {
33+ var tlsStr string
34+ fmt.Scanln(&tlsStr)
35+ if tlsStr == "" {
36+ break
37+ }
38+ if _, err := fmt.Fscan(strings.NewReader(tlsStr), &tls); err == nil {
39+ break
40+ }
41+ }
42+ fmt.Fprintf(os.Stderr, "Configuration assistant: Enter your nickname: ")
43+ for nick == "" {
44+ fmt.Scanln(&nick)
45+ }
46+ fmt.Fprintf(os.Stderr, "Configuration assistant: Enter your password (only enter if you already have an account) [optional]: ")
47+ fmt.Scanln(&password)
48+
49+ folderPath := path.Dir(configPath)
50+ if err := os.MkdirAll(folderPath, 0700); err != nil {
51+ fmt.Fprintf(os.Stderr, "failed to create the configuration file folder at %q: %s\n", folderPath, err)
52+ os.Exit(1)
53+ return
54+ }
55+ f, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
56+ if err != nil {
57+ fmt.Fprintf(os.Stderr, "failed to create the configuration file at %q: %s\n", configPath, err)
58+ os.Exit(1)
59+ return
60+ }
61+ var addr string
62+ if !tls {
63+ addr += "irc+insecure://"
64+ }
65+ addr += host
66+ if port != "" {
67+ addr += ":" + port
68+ }
69+ fmt.Fprintf(f, "address %q\n", addr)
70+ fmt.Fprintf(f, "nickname %q\n", nick)
71+ if password != "" {
72+ fmt.Fprintf(f, "password %q\n", password)
73+ }
74+ f.Close()
75+
76+ cfg, err = senpai.LoadConfigFile(configPath)
77+ if err != nil {
78+ fmt.Fprintf(os.Stderr, "failed to load the configuration file at %q: %s\n", configPath, err)
79+ os.Exit(1)
80+ return
81+ }
82+
83+ fmt.Fprintf(os.Stderr, "Configuration assistant: Configuration saved to %q. Now starting.", configPath)
84+ for i := 0; i < 6; i++ {
85+ time.Sleep(500 * time.Millisecond)
86+ fmt.Fprintf(os.Stderr, ".")
87+ }
88 }
89
90 cfg.Debug = cfg.Debug || debug
+5,
-10
1@@ -88,8 +88,8 @@ func DefaultHighlightPath() (string, error) {
2 return path.Join(configDir, "senpai", "highlight"), nil
3 }
4
5-func Defaults() (cfg Config, err error) {
6- cfg = Config{
7+func Defaults() Config {
8+ return Config{
9 Addr: "",
10 Nick: "",
11 Real: "",
12@@ -115,15 +115,10 @@ func Defaults() (cfg Config, err error) {
13 },
14 Debug: false,
15 }
16-
17- return
18 }
19
20 func LoadConfigFile(filename string) (cfg Config, err error) {
21- cfg, err = Defaults()
22- if err != nil {
23- return
24- }
25+ cfg = Defaults()
26
27 err = unmarshal(filename, &cfg)
28 if err != nil {
29@@ -164,7 +159,7 @@ func LoadConfigFile(filename string) (cfg Config, err error) {
30 func unmarshal(filename string, cfg *Config) (err error) {
31 directives, err := scfg.Load(filename)
32 if err != nil {
33- return fmt.Errorf("error parsing scfg: %s", err)
34+ return fmt.Errorf("error parsing scfg: %w", err)
35 }
36
37 for _, d := range directives {
38@@ -205,7 +200,7 @@ func unmarshal(filename string, cfg *Config) (err error) {
39 cmd := exec.Command(cmdName, d.Params[1:]...)
40 var stdout []byte
41 if stdout, err = cmd.Output(); err != nil {
42- return fmt.Errorf("error running password command: %s", err)
43+ return fmt.Errorf("error running password command: %w", err)
44 }
45
46 passCmdOut := strings.Split(string(stdout), "\n")