package github import ( "fmt" "io" "iter" "net/http" "net/url" "path" "strconv" "time" "sirherobrine23.com.br/go-bds/request/internal/gitpaginator" "sirherobrine23.com.br/go-bds/request/v3" ) // File assert type ReleaseAsset struct { URL string `json:"url"` ID int `json:"id"` NodeID string `json:"node_id"` Name string `json:"name"` Label string `json:"label"` Uploader *User `json:"uploader"` ContentType string `json:"content_type"` State string `json:"state"` Size int `json:"size"` DownloadCount int `json:"download_count"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` BrowserDownloadURL string `json:"browser_download_url"` } // Release type Release struct { ID int `json:"id"` TagName string `json:"tag_name"` Name string `json:"name"` URL string `json:"url"` AssetsURL string `json:"assets_url"` UploadURL string `json:"upload_url"` HTMLURL string `json:"html_url"` NodeID string `json:"node_id"` TargetCommitish string `json:"target_commitish"` Body string `json:"body"` Draft bool `json:"draft"` Prerelease bool `json:"prerelease"` CreatedAt time.Time `json:"created_at"` PublishedAt time.Time `json:"published_at"` TarballURL string `json:"tarball_url"` ZipballURL string `json:"zipball_url"` MentionsCount int `json:"mentions_count,omitempty"` Author *User `json:"author"` Assets []*ReleaseAsset `json:"assets"` Reactions struct { URL string `json:"url"` TotalCount int `json:"total_count"` PlusOne int `json:"+1"` LessOne int `json:"-1"` Laugh int `json:"laugh"` Hooray int `json:"hooray"` Confused int `json:"confused"` Heart int `json:"heart"` Rocket int `json:"rocket"` Eyes int `json:"eyes"` } `json:"reactions"` } // Get release by tag name func (client Github) ReleaseTag(tagName string) (*Release, error) { reqOptions := &request.Options{Method: "GET", Codes: processCodes, Header: http.Header{}} client.authHeader(&reqOptions.Header) res, _, err := request.JSON[*Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases/tags", url.PathEscape(tagName))}).String(), reqOptions) return res, err } // Get release by ID func (client Github) Release(id int) (*Release, error) { reqOptions := &request.Options{Method: "GET", Codes: processCodes, Header: http.Header{}} client.authHeader(&reqOptions.Header) res, _, err := request.JSON[*Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases", strconv.Itoa(id))}).String(), reqOptions) return res, err } // Return all release from API func (client Github) ReleaseSeq() iter.Seq2[*Release, error] { releases, res, err := []*Release{}, (*http.Response)(nil), error(nil) reqOptions := &request.Options{Method: "GET", Codes: processCodes, Header: http.Header{}} client.authHeader(&reqOptions.Header) return func(yield func(*Release, error) bool) { requestUrl := client.Host.ResolveReference(&url.URL{RawQuery: "per_page=100", Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases")}).String() for requestUrl != "" { if len(releases) == 0 { if releases, res, err = request.JSON[[]*Release](requestUrl, reqOptions); res != nil { requestUrl = gitpaginator.ParsePaginator(res.Header).NextPageToken } else { requestUrl = "" } } if err != nil { yield(nil, err) return } for len(releases) > 0 { if !yield(releases[0], nil) { return } releases = releases[1:] } } } } // List all release Assets in [iter.Seq2] func (client Github) AssetsSeq(releaseID int) iter.Seq2[*ReleaseAsset, error] { asserts, res, err := []*ReleaseAsset{}, (*http.Response)(nil), error(nil) reqOptions := &request.Options{Method: "GET", Codes: processCodes, Header: http.Header{}} client.authHeader(&reqOptions.Header) return func(yield func(*ReleaseAsset, error) bool) { requestUrl := client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")}).String() for requestUrl != "" { if len(asserts) == 0 { if asserts, res, err = request.JSON[[]*ReleaseAsset](requestUrl, reqOptions); res != nil { requestUrl = gitpaginator.ParsePaginator(res.Header).NextPageToken } else { requestUrl = "" } } if err != nil { yield(nil, err) return } for len(asserts) > 0 { if !yield(asserts[0], nil) { return } asserts = asserts[1:] } } } } // Return all release in to slice func (client Github) AllReleases() ([]*Release, error) { allRels := []*Release{} for release, err := range client.ReleaseSeq() { if err != nil { return nil, err } allRels = append(allRels, release) } return allRels, nil } // List all release Assets in to slice func (client Github) AllAssets(releaseID int) ([]*ReleaseAsset, error) { asserts := []*ReleaseAsset{} for assert, err := range client.AssetsSeq(releaseID) { if err != nil { return nil, err } asserts = append(asserts, assert) } return asserts, nil } // Delete assert file from Release func (client Github) DeleteAsset(assetID int) error { reqOptions := &request.Options{Method: "DELETE", Codes: processCodes, Header: http.Header{}} client.authHeader(&reqOptions.Header) res, err := request.Request(client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases/assets", strconv.Itoa(assetID))}), reqOptions) res.Body.Close() return err } // Upload file to Release func (client Github) UploadAsset(releaseID int, name string, file io.Reader) (*ReleaseAsset, error) { reqOptions := &request.Options{ Method: "POST", Body: file, Header: http.Header{"Content-Type": {"application/octet-stream"}}, Codes: processCodes.Extends(request.CodeProcess{ 201: func(req *request.RequestStatus) (res *http.Response, err error) { return req.Res, nil }, 422: func(req *request.RequestStatus) (res *http.Response, err error) { return nil, fmt.Errorf("same filename exists in release: %s", name) }, }), } client.authHeader(&reqOptions.Header) requestUrl := client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")}) requestUrl.RawQuery = fmt.Sprintf("name=%s", url.QueryEscape(name)) fileInfo, _, err := request.JSON[*ReleaseAsset](requestUrl.String(), reqOptions) return fileInfo, err }