commit 83ab9cc
Artur Manuel
·
2026-04-20 19:24:27 +0000 UTC
parent 5c10f1f
feat(cli): add server and build subcommands
7 files changed,
+141,
-32
+48,
-0
1@@ -0,0 +1,48 @@
2+package main
3+
4+import (
5+ "context"
6+ "html/template"
7+ "os"
8+
9+ "codeberg.org/amadaluzia/webfetch/internal"
10+ "github.com/urfave/cli/v3"
11+)
12+
13+var build = cli.Command{
14+ Name: "build",
15+ Usage: "Build fetch into an HTML file",
16+ Arguments: []cli.Argument{
17+ &cli.StringArg{
18+ Name: "template",
19+ Value: "./webfetch.html",
20+ },
21+ },
22+ Flags: []cli.Flag{
23+ &cli.StringFlag{
24+ Name: "output",
25+ Value: "index.html",
26+ Usage: "Build page to `FILE`",
27+ },
28+ },
29+ Action: func(ctx context.Context, cmd *cli.Command) error {
30+ templateFile := cmd.StringArg("template")
31+ outputFile := cmd.String("output")
32+ sysinfo, err := internal.GetSysinfo()
33+ if err != nil {
34+ return err
35+ }
36+ master, err := template.ParseFiles(templateFile)
37+ if err != nil {
38+ return err
39+ }
40+ f, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE, 0644)
41+ if err != nil {
42+ return err
43+ }
44+ if err := master.Execute(f, sysinfo); err != nil {
45+ return err
46+ }
47+ return nil
48+ },
49+}
+13,
-16
1@@ -1,27 +1,24 @@
2 package main
3
4 import (
5- "html/template"
6+ "context"
7 "log"
8 "os"
9
10- "codeberg.org/amadaluzia/webfetch/internal"
11+ "github.com/urfave/cli/v3"
12 )
13
14+var cmd = cli.Command{
15+ Name: "webfetch",
16+ Usage: "Fetch system info and display it in your browser",
17+ Commands: []*cli.Command{
18+ &build,
19+ &server,
20+ },
21+}
22+
23 func main() {
24- var sys internal.SystemInfo
25- if err := sys.Load(); err != nil {
26- log.Fatalln(err)
27- }
28- output, err := os.OpenFile("output.html", os.O_WRONLY|os.O_CREATE, 0644)
29- if err != nil {
30- log.Fatalln(err)
31- }
32- t, err := template.ParseFiles("webfetch.html")
33- if err != nil {
34- log.Fatalln(err)
35- }
36- if err := t.Execute(output, sys); err != nil {
37- log.Fatalln(err)
38+ if err := cmd.Run(context.Background(), os.Args); err != nil {
39+ log.Fatalln(err)
40 }
41 }
+59,
-0
1@@ -0,0 +1,59 @@
2+package main
3+
4+import (
5+ "context"
6+ "errors"
7+ "fmt"
8+ "html/template"
9+ "log"
10+ "net/http"
11+ "os"
12+
13+ "codeberg.org/amadaluzia/webfetch/internal"
14+ "github.com/urfave/cli/v3"
15+)
16+
17+var server = cli.Command{
18+ Name: "server",
19+ Usage: "Serve fetch via HTTP",
20+ Flags: []cli.Flag{
21+ &cli.IntFlag{
22+ Name: "port",
23+ Value: 8080,
24+ Usage: "Serve HTML to `PORT`",
25+ },
26+ },
27+ Arguments: []cli.Argument{
28+ &cli.StringArg{
29+ Name: "template",
30+ Value: "./webfetch.html",
31+ },
32+ },
33+ Action: func(ctx context.Context, cmd *cli.Command) error {
34+ mux := http.NewServeMux()
35+ templateFile := cmd.StringArg("template")
36+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
37+ sysinfo, err := internal.GetSysinfo()
38+ if err != nil {
39+ log.Fatalln(err)
40+ }
41+ master, err := template.ParseFiles(templateFile)
42+ if err != nil {
43+ log.Fatalf("failed to parse template %s: %v", templateFile, err)
44+ }
45+ if err := master.Execute(w, sysinfo); err != nil {
46+ fmt.Fprintf(w, "failed to execute template %s: %v", templateFile, err)
47+ }
48+ })
49+ port := cmd.Int("port")
50+ address := fmt.Sprintf(":%d", port)
51+ log.Printf("Server starting! http://localhost:%d", port)
52+ err := http.ListenAndServe(address, mux)
53+ if errors.Is(err, http.ErrServerClosed) {
54+ fmt.Fprintln(os.Stderr, "Server closed")
55+ } else {
56+ return fmt.Errorf("failed to start server: %v", err)
57+ }
58+ return nil
59+ },
60+}
M
go.mod
+2,
-0
1@@ -1,3 +1,5 @@
2 module codeberg.org/amadaluzia/webfetch
3
4 go 1.26.1
5+
6+require github.com/urfave/cli/v3 v3.8.0 // indirect
A
go.sum
+2,
-0
1@@ -0,0 +1,2 @@
2+github.com/urfave/cli/v3 v3.8.0 h1:XqKPrm0q4P0q5JpoclYoCAv0/MIvH/jZ2umzuf8pNTI=
3+github.com/urfave/cli/v3 v3.8.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
+15,
-14
1@@ -16,52 +16,53 @@ type SystemInfo struct {
2 Terminal string
3 }
4
5-func (sysinfo *SystemInfo) Load() error {
6+func GetSysinfo() (SystemInfo, error) {
7+ var sysinfo SystemInfo
8 hostname, err := GetHostname()
9 if err != nil {
10- return err
11+ return sysinfo, err
12 }
13 osRelease, err := GetOsRelease()
14 if err != nil {
15- return err
16+ return sysinfo, err
17 }
18 username, err := GetUsername()
19 if err != nil {
20- return err
21+ return sysinfo, err
22 }
23 var uname syscall.Utsname
24 if err := syscall.Uname(&uname); err != nil {
25- return err
26+ return sysinfo, err
27 }
28 kversion, err := GetKernelRelease(uname)
29 if err != nil {
30- return err
31+ return sysinfo, err
32 }
33 kname, err := GetKernelName(uname)
34 if err != nil {
35- return err
36+ return sysinfo, err
37 }
38 march, err := GetMachineArch(uname)
39 if err != nil {
40- return err
41+ return sysinfo, err
42 }
43 passwd, err := GetPasswd()
44 if err != nil {
45- return err
46+ return sysinfo, err
47 }
48 shell, err := GetShell(username, passwd)
49 if err != nil {
50- return err
51+ return sysinfo, err
52 }
53 up, err := GetUptime()
54 if err != nil {
55- return err
56+ return sysinfo, err
57 }
58 terminal, err := GetTerminal()
59 if err != nil {
60- return err
61+ return sysinfo, err
62 }
63- sysinfo.OS = osRelease["PRETTY_NAME"]
64+ sysinfo.OS = osRelease["PRETTY_NAME"]
65 sysinfo.Hostname = hostname
66 sysinfo.Username = username
67 sysinfo.KernelRelease = kversion
68@@ -70,5 +71,5 @@ func (sysinfo *SystemInfo) Load() error {
69 sysinfo.Shell = shell
70 sysinfo.Uptime = up.String()
71 sysinfo.Terminal = terminal
72- return nil
73+ return sysinfo, nil
74 }
+2,
-2
1@@ -30,7 +30,7 @@ func GetKernelRelease(uname syscall.Utsname) (string, error) {
2 return "", fmt.Errorf("failed to write kernel release to buffer: %v", err)
3 }
4 }
5- return cleanNulls(b.String()) , nil
6+ return cleanNulls(b.String()), nil
7 }
8
9 func GetMachineArch(uname syscall.Utsname) (string, error) {
10@@ -40,5 +40,5 @@ func GetMachineArch(uname syscall.Utsname) (string, error) {
11 return "", fmt.Errorf("failed to write machine to buffer: %v", err)
12 }
13 }
14- return cleanNulls(b.String()) , nil
15+ return cleanNulls(b.String()), nil
16 }