diff --git a/cmd/main.go b/cmd/main.go index 8a50ef1..4be929f 100755 --- a/cmd/main.go +++ b/cmd/main.go @@ -57,7 +57,7 @@ func main() { } if args.Command == common.CommandReload { - if err := query.ReloadServer(); err.HasError() { + if err := query.ReloadServer(); err != nil { log.Fatal(err) } log.Print("ok") @@ -94,7 +94,7 @@ func main() { return case common.CommandListRoutes: routes, err := query.ListRoutes() - if err.HasError() { + if err != nil { log.Printf("failed to connect to api server: %s", err) log.Printf("falling back to config file") printJSON(cfg.RoutesByAlias()) @@ -102,6 +102,13 @@ func main() { printJSON(routes) } return + case common.CommandListIcons: + icons, err := internal.ListAvailableIcons() + if err != nil { + log.Fatal(err) + } + printJSON(icons) + return case common.CommandDebugListEntries: printJSON(cfg.DumpEntries()) return @@ -110,7 +117,7 @@ func main() { return case common.CommandDebugListMTrace: trace, err := query.ListMiddlewareTraces() - if err.HasError() { + if err != nil { log.Fatal(err) } printJSON(trace) @@ -213,7 +220,7 @@ func funcName(f func()) string { func printJSON(obj any) { j, err := E.Check(json.MarshalIndent(obj, "", " ")) - if err.HasError() { + if err != nil { logrus.Fatal(err) } rawLogger := log.New(os.Stdout, "", 0) diff --git a/internal/common/args.go b/internal/common/args.go index 5505991..947c105 100644 --- a/internal/common/args.go +++ b/internal/common/args.go @@ -17,6 +17,7 @@ const ( CommandValidate = "validate" CommandListConfigs = "ls-config" CommandListRoutes = "ls-routes" + CommandListIcons = "ls-icons" CommandReload = "reload" CommandDebugListEntries = "debug-ls-entries" CommandDebugListProviders = "debug-ls-providers" @@ -29,6 +30,7 @@ var ValidCommands = []string{ CommandValidate, CommandListConfigs, CommandListRoutes, + CommandListIcons, CommandReload, CommandDebugListEntries, CommandDebugListProviders, diff --git a/internal/list-icons.go b/internal/list-icons.go new file mode 100644 index 0000000..f4b9c84 --- /dev/null +++ b/internal/list-icons.go @@ -0,0 +1,99 @@ +package internal + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "time" + + "log" + + "github.com/yusing/go-proxy/internal/utils" +) + +type GitHubContents struct { //! keep this, may reuse in future + Type string `json:"type"` + Path string `json:"path"` + Name string `json:"name"` + Sha string `json:"sha"` + Size int `json:"size"` +} + +const iconsCachePath = "/tmp/icons_cache.json" +const updateInterval = 1 * time.Hour + +func ListAvailableIcons() ([]string, error) { + owner := "walkxcode" + repo := "dashboard-icons" + ref := "main" + + var lastUpdate time.Time + var icons = make([]string, 0) + info, err := os.Stat(iconsCachePath) + if err == nil { + lastUpdate = info.ModTime().Local() + } + if time.Since(lastUpdate) < updateInterval { + err := utils.LoadJson(iconsCachePath, &icons) + if err == nil { + return icons, nil + } + } + + contents, err := getRepoContents(http.DefaultClient, owner, repo, ref, "") + if err != nil { + return nil, err + } + for _, content := range contents { + if content.Type != "dir" { + icons = append(icons, content.Path) + } + } + err = utils.SaveJson(iconsCachePath, &icons, 0o644).Error() + if err != nil { + log.Print("error saving cache", err) + } + return icons, nil +} + +func getRepoContents(client *http.Client, owner string, repo string, ref string, path string) ([]GitHubContents, error) { + req, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s/%s/contents/%s?ref=%s", owner, repo, path, ref), nil) + if err != nil { + return nil, err + } + req.Header.Set("Accept", "application/json") + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var contents []GitHubContents + err = json.Unmarshal(body, &contents) + if err != nil { + return nil, err + } + + filesAndDirs := make([]GitHubContents, 0) + for _, content := range contents { + if content.Type == "dir" { + subContents, err := getRepoContents(client, owner, repo, ref, content.Path) + if err != nil { + return nil, err + } + filesAndDirs = append(filesAndDirs, subContents...) + } else { + filesAndDirs = append(filesAndDirs, content) + } + } + + return filesAndDirs, nil +} diff --git a/internal/setup.go b/internal/setup.go index aa17dd4..e71f54a 100644 --- a/internal/setup.go +++ b/internal/setup.go @@ -85,7 +85,12 @@ func touch(pathname string) { } func fetch(remoteFilename string, outFileName string) { if hasFileOrDir(outFileName) { - return + if remoteFilename == outFileName { + log.Printf("%q already exists, not overwriting\n", outFileName) + return + } + log.Printf("%q already exists, downloading to %q\n", outFileName, remoteFilename) + outFileName = remoteFilename } log.Printf("downloading %q\n", remoteFilename) @@ -111,5 +116,5 @@ func fetch(remoteFilename string, outFileName string) { log.Fatalf("failed to write to file: %s\n", err) } - log.Printf("downloaded %q\n", outFileName) + log.Printf("downloaded to %q\n", outFileName) }