123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- package feed
- import (
- "fmt"
- "net/http"
- "sync"
- "time"
- )
- type githubReleaseLatestResponseJson struct {
- TagName string `json:"tag_name"`
- PublishedAt string `json:"published_at"`
- HtmlUrl string `json:"html_url"`
- Reactions struct {
- Downvotes int `json:"-1"`
- } `json:"reactions"`
- }
- func fetchLatestGithubRelease(request *ReleaseRequest) (*AppRelease, error) {
- httpRequest, err := http.NewRequest(
- "GET",
- fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", request.Repository),
- nil,
- )
- if err != nil {
- return nil, err
- }
- if request.Token != nil {
- httpRequest.Header.Add("Authorization", "Bearer "+(*request.Token))
- }
- response, err := decodeJsonFromRequest[githubReleaseLatestResponseJson](defaultClient, httpRequest)
- if err != nil {
- return nil, err
- }
- version := response.TagName
- if len(version) > 0 && version[0] != 'v' {
- version = "v" + version
- }
- return &AppRelease{
- Source: ReleaseSourceGithub,
- Name: request.Repository,
- Version: version,
- NotesUrl: response.HtmlUrl,
- TimeReleased: parseRFC3339Time(response.PublishedAt),
- Downvotes: response.Reactions.Downvotes,
- }, nil
- }
- type GithubTicket struct {
- Number int
- CreatedAt time.Time
- Title string
- }
- type RepositoryDetails struct {
- Name string
- Stars int
- Forks int
- OpenPullRequests int
- PullRequests []GithubTicket
- OpenIssues int
- Issues []GithubTicket
- }
- type githubRepositoryDetailsResponseJson struct {
- Name string `json:"full_name"`
- Stars int `json:"stargazers_count"`
- Forks int `json:"forks_count"`
- }
- type githubTicketResponseJson struct {
- Count int `json:"total_count"`
- Tickets []struct {
- Number int `json:"number"`
- CreatedAt string `json:"created_at"`
- Title string `json:"title"`
- } `json:"items"`
- }
- func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs int, maxIssues int) (RepositoryDetails, error) {
- repositoryRequest, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s", repository), nil)
- if err != nil {
- return RepositoryDetails{}, fmt.Errorf("%w: could not create request with repository: %v", ErrNoContent, err)
- }
- PRsRequest, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/search/issues?q=is:pr+is:open+repo:%s&per_page=%d", repository, maxPRs), nil)
- issuesRequest, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/search/issues?q=is:issue+is:open+repo:%s&per_page=%d", repository, maxIssues), nil)
- if token != "" {
- token = fmt.Sprintf("Bearer %s", token)
- repositoryRequest.Header.Add("Authorization", token)
- PRsRequest.Header.Add("Authorization", token)
- issuesRequest.Header.Add("Authorization", token)
- }
- var detailsResponse githubRepositoryDetailsResponseJson
- var detailsErr error
- var PRsResponse githubTicketResponseJson
- var PRsErr error
- var issuesResponse githubTicketResponseJson
- var issuesErr error
- var wg sync.WaitGroup
- wg.Add(1)
- go (func() {
- defer wg.Done()
- detailsResponse, detailsErr = decodeJsonFromRequest[githubRepositoryDetailsResponseJson](defaultClient, repositoryRequest)
- })()
- if maxPRs > 0 {
- wg.Add(1)
- go (func() {
- defer wg.Done()
- PRsResponse, PRsErr = decodeJsonFromRequest[githubTicketResponseJson](defaultClient, PRsRequest)
- })()
- }
- if maxIssues > 0 {
- wg.Add(1)
- go (func() {
- defer wg.Done()
- issuesResponse, issuesErr = decodeJsonFromRequest[githubTicketResponseJson](defaultClient, issuesRequest)
- })()
- }
- wg.Wait()
- if detailsErr != nil {
- return RepositoryDetails{}, fmt.Errorf("%w: could not get repository details: %s", ErrNoContent, detailsErr)
- }
- details := RepositoryDetails{
- Name: detailsResponse.Name,
- Stars: detailsResponse.Stars,
- Forks: detailsResponse.Forks,
- PullRequests: make([]GithubTicket, 0, len(PRsResponse.Tickets)),
- Issues: make([]GithubTicket, 0, len(issuesResponse.Tickets)),
- }
- err = nil
- if maxPRs > 0 {
- if PRsErr != nil {
- err = fmt.Errorf("%w: could not get PRs: %s", ErrPartialContent, PRsErr)
- } else {
- details.OpenPullRequests = PRsResponse.Count
- for i := range PRsResponse.Tickets {
- details.PullRequests = append(details.PullRequests, GithubTicket{
- Number: PRsResponse.Tickets[i].Number,
- CreatedAt: parseRFC3339Time(PRsResponse.Tickets[i].CreatedAt),
- Title: PRsResponse.Tickets[i].Title,
- })
- }
- }
- }
- if maxIssues > 0 {
- if issuesErr != nil {
- // TODO: fix, overwriting the previous error
- err = fmt.Errorf("%w: could not get issues: %s", ErrPartialContent, issuesErr)
- } else {
- details.OpenIssues = issuesResponse.Count
- for i := range issuesResponse.Tickets {
- details.Issues = append(details.Issues, GithubTicket{
- Number: issuesResponse.Tickets[i].Number,
- CreatedAt: parseRFC3339Time(issuesResponse.Tickets[i].CreatedAt),
- Title: issuesResponse.Tickets[i].Title,
- })
- }
- }
- }
- return details, err
- }
|