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
M go.mod
A go.sum
+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 }