summaryrefslogtreecommitdiff
path: root/internal/codeberg
diff options
context:
space:
mode:
Diffstat (limited to 'internal/codeberg')
-rw-r--r--internal/codeberg/codeberg.go133
1 files changed, 133 insertions, 0 deletions
diff --git a/internal/codeberg/codeberg.go b/internal/codeberg/codeberg.go
new file mode 100644
index 0000000..288d1e7
--- /dev/null
+++ b/internal/codeberg/codeberg.go
@@ -0,0 +1,133 @@
+package codeberg
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "time"
+)
+
+// Repository represents a Codeberg/Gitea repository
+type Repository struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ FullName string `json:"full_name"`
+ Description string `json:"description"`
+ Private bool `json:"private"`
+ Fork bool `json:"fork"`
+ CreatedAt time.Time `json:"created_at"`
+ UpdatedAt time.Time `json:"updated_at"`
+ CloneURL string `json:"clone_url"`
+ SSHURL string `json:"ssh_url"`
+ Size int `json:"size"`
+ Archived bool `json:"archived"`
+ Empty bool `json:"empty"`
+}
+
+// Client handles Codeberg API operations
+type Client struct {
+ baseURL string
+ org string
+}
+
+// CLAUDE: Is there a rason, that we return a pointer of Client?
+// NewClient creates a new Codeberg API client
+func NewClient(org string) *Client {
+ return &Client{
+ baseURL: "https://codeberg.org/api/v1",
+ org: org,
+ }
+}
+
+// ListPublicRepos lists all public repositories for an organization
+func (c *Client) ListPublicRepos() ([]Repository, error) {
+ var allRepos []Repository
+ page := 1
+ perPage := 50
+
+ for {
+ url := fmt.Sprintf("%s/orgs/%s/repos?page=%d&limit=%d", c.baseURL, c.org, page, perPage)
+
+ resp, err := http.Get(url)
+ if err != nil {
+ return nil, fmt.Errorf("failed to fetch repositories: %w", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != 200 {
+ return nil, fmt.Errorf("API returned status %d", resp.StatusCode)
+ }
+
+ var repos []Repository
+ if err := json.NewDecoder(resp.Body).Decode(&repos); err != nil {
+ return nil, fmt.Errorf("failed to parse response: %w", err)
+ }
+
+ // Filter only public, non-fork, non-archived, non-empty repos
+ for _, repo := range repos {
+ if !repo.Private && !repo.Fork && !repo.Archived && !repo.Empty {
+ allRepos = append(allRepos, repo)
+ }
+ }
+
+ // If we got fewer repos than requested, we've reached the end
+ if len(repos) < perPage {
+ break
+ }
+
+ page++
+ }
+
+ return allRepos, nil
+}
+
+// ListUserPublicRepos lists all public repositories for a user
+func (c *Client) ListUserPublicRepos() ([]Repository, error) {
+ var allRepos []Repository
+ page := 1
+ perPage := 50
+
+ for {
+ url := fmt.Sprintf("%s/users/%s/repos?page=%d&limit=%d", c.baseURL, c.org, page, perPage)
+
+ resp, err := http.Get(url)
+ if err != nil {
+ return nil, fmt.Errorf("failed to fetch repositories: %w", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != 200 {
+ return nil, fmt.Errorf("API returned status %d", resp.StatusCode)
+ }
+
+ var repos []Repository
+ if err := json.NewDecoder(resp.Body).Decode(&repos); err != nil {
+ return nil, fmt.Errorf("failed to parse response: %w", err)
+ }
+
+ // Filter only public, non-fork, non-archived, non-empty repos
+ for _, repo := range repos {
+ if !repo.Private && !repo.Fork && !repo.Archived && !repo.Empty {
+ allRepos = append(allRepos, repo)
+ }
+ }
+
+ // If we got fewer repos than requested, we've reached the end
+ if len(repos) < perPage {
+ break
+ }
+
+ page++
+ }
+
+ return allRepos, nil
+}
+
+// GetRepoNames returns just the repository names
+func GetRepoNames(repos []Repository) []string {
+ names := make([]string, 0, len(repos))
+ for _, repo := range repos {
+ names = append(names, repo.Name)
+ }
+ return names
+}