package main import ( "context" "encoding/json" "fmt" "io/ioutil" "net/http" ) // A RepoHost hosts repositories, and can be queried as to whether it hosts a // repository with a specific name. type RepoHost interface { HostsRepo(ctx context.Context, name string) (string, bool, error) } // Sourcehut is a RepoHost // // https://git.sr.ht type Sourcehut struct { Token string // a personal access token Username string // the username } // HostsRepo implements RepoHost func (s Sourcehut) HostsRepo(ctx context.Context, name string) (string, bool, error) { endpoint := "https://git.sr.ht/api/~" + s.Username + "/repos/" + name type response struct { Name string `json:"name"` Visibility string `json:"visibility"` } var repo response if err := makeRequest(ctx, &repo, endpoint, "token "+s.Token); err != nil { return "", false, err } if repo.Visibility != "public" || repo.Name == "" { return "", false, nil } return "https://git.sr.ht/~" + s.Username + "/" + repo.Name, true, nil } // Github is a RepoHost // // https://github.com type Github struct { Username string Token string } // HostsRepo implements RepoHost func (g Github) HostsRepo(ctx context.Context, name string) (string, bool, error) { endpoint := "https://api.github.com/repos/" + g.Username + "/" + name type response struct { URL string `json:"html_url"` Private bool `json:"private"` } var repo response if err := makeRequest(ctx, &repo, endpoint, "token "+g.Token); err != nil { return "", false, err } if repo.Private || repo.URL == "" { return "", false, nil } return repo.URL, true, nil } func makeRequest(ctx context.Context, out interface{}, url string, auth string) error { req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return err } req.Header.Set("Authorization", auth) resp, err := http.DefaultClient.Do(req) if err != nil { return err } if resp.StatusCode == http.StatusNotFound { return nil } if resp.StatusCode != http.StatusOK { return fmt.Errorf("get %s: %s", url, resp.Status) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if err := json.Unmarshal(body, out); err != nil { return err } return nil }