// forgejo.go package main import ( "fmt" forgejo "codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v3" ) // ForgejoScraper retrieves public repositories from a Forgejo instance. type ForgejoScraper struct { Client *forgejo.Client PageSize int } // NewForgejoScraper creates a scraper for a Forgejo instance. // BaseURL should be the instance URL, e.g. https://codeberg.org. func NewForgejoScraper(baseURL string) (*ForgejoScraper, error) { client, err := forgejo.NewClient(baseURL) if err != nil { return nil, fmt.Errorf("create Forgejo client: %w", err) } return &ForgejoScraper{ Client: client, PageSize: 50, }, nil } // GetProjects retrieves every public repository visible through the // Forgejo repository search API and maps it to the generic Project type. func (s *ForgejoScraper) GetProjects() ([]Project, error) { pageSize := s.PageSize if pageSize <= 0 { pageSize = 50 } isPrivate := false var projects []Project for page := 1; ; page++ { repos, _, err := s.Client.SearchRepos(forgejo.SearchRepoOptions{ ListOptions: forgejo.ListOptions{ Page: page, PageSize: pageSize, }, IsPrivate: &isPrivate, Sort: "alpha", Order: "asc", }) if err != nil { return nil, fmt.Errorf( "list public Forgejo repositories (page %d): %w", page, err, ) } if len(repos) == 0 { break } for _, repo := range repos { if repo == nil { continue } projects = append(projects, Project{ Name: repo.FullName, Url: repo.HTMLURL, Description: repo.Description, Topics: repo.Topics, OpenIssues: repo.OpenIssues, OpenPRs: repo.OpenPulls, }) } // A short page indicates that there are no further results. if len(repos) < pageSize { break } } return projects, nil }