package api import ( "code.gitea.io/gitea/modules/structs" "fmt" "github.com/google/go-github/v59/github" "time" ) func stringPtr(s string) *string { return &s } func numberPtr(n int) *int { return &n } func intPtr(n int) *int { return &n } func int64Ptr(n int64) *int64 { return &n } func boolPtr(b bool) *bool { return &b } func timePtr(t time.Time) *github.Timestamp { timestamp := github.Timestamp{Time: t} return ×tamp } func timePtrIfNotNil(t *time.Time) *github.Timestamp { if t == nil { return nil } return timePtr(*t) } func convertUser(user *structs.User) *github.User { if user == nil { return &github.User{} } return &github.User{ Login: stringPtr(user.UserName), ID: int64Ptr(user.ID), } } func convertUsers(users []*structs.User) []*github.User { var ghUsers []*github.User for _, user := range users { ghUsers = append(ghUsers, convertUser(user)) } return ghUsers } func convertMilestone(milestone *structs.Milestone) *github.Milestone { if milestone == nil { return &github.Milestone{} } return &github.Milestone{ Title: stringPtr(milestone.Title), } } func convertLabels(labels []*structs.Label) []*github.Label { if labels == nil { return make([]*github.Label, 0) } var ghLabels []*github.Label for _, label := range labels { if label == nil { continue } ghLabels = append(ghLabels, &github.Label{ Name: stringPtr(label.Name), }) } return ghLabels } func convertPRBranch(branch *structs.PRBranchInfo) *github.PullRequestBranch { if branch == nil { return &github.PullRequestBranch{} } return &github.PullRequestBranch{ Label: stringPtr(branch.Name), Ref: stringPtr(branch.Ref), SHA: stringPtr(branch.Sha), Repo: convertRepo(branch.Repository), } } func convertRepo(repo *structs.Repository) *github.Repository { if repo == nil { return &github.Repository{} } return &github.Repository{ ID: int64Ptr(repo.ID), Name: stringPtr(repo.Name), Owner: convertUser(repo.Owner), FullName: stringPtr(repo.FullName), Description: stringPtr(repo.Description), Homepage: stringPtr(repo.Website), HTMLURL: stringPtr(repo.HTMLURL), CloneURL: stringPtr(repo.CloneURL), GitURL: stringPtr(repo.CloneURL), SSHURL: stringPtr(repo.SSHURL), DefaultBranch: stringPtr(repo.DefaultBranch), CreatedAt: timePtr(repo.Created), UpdatedAt: timePtr(repo.Updated), Private: boolPtr(repo.Private), Fork: boolPtr(repo.Fork), Size: intPtr(repo.Size), StargazersCount: intPtr(repo.Stars), SubscribersCount: intPtr(repo.Watchers), ForksCount: intPtr(repo.Forks), Watchers: intPtr(repo.Watchers), WatchersCount: intPtr(repo.Stars), OpenIssuesCount: intPtr(repo.OpenIssues), Archived: boolPtr(repo.Archived), } } func convertPullRequest(request *structs.PullRequest) *github.PullRequest { if request == nil { return &github.PullRequest{} } pr := &github.PullRequest{ ID: int64Ptr(request.ID), Number: intPtr(int(request.Index)), State: stringPtr(string(request.State)), Title: stringPtr(request.Title), Body: stringPtr(request.Body), CreatedAt: timePtr(*request.Created), UpdatedAt: timePtr(*request.Updated), ClosedAt: timePtrIfNotNil(request.Closed), MergedAt: timePtrIfNotNil(request.Merged), Merged: boolPtr(request.HasMerged), Mergeable: boolPtr(request.Mergeable), MergeCommitSHA: request.MergedCommitID, URL: stringPtr(request.URL), HTMLURL: stringPtr(request.HTMLURL), DiffURL: stringPtr(request.DiffURL), PatchURL: stringPtr(request.PatchURL), Comments: intPtr(request.Comments), Assignee: convertUser(request.Assignee), Assignees: convertUsers(request.Assignees), Milestone: convertMilestone(request.Milestone), Labels: convertLabels(request.Labels), } // Convert PR branch info if request.Head != nil { pr.Head = convertPRBranch(request.Head) } if request.Base != nil { pr.Base = convertPRBranch(request.Base) } return pr } func convertChanges(changes *structs.ChangesPayload) *github.EditChange { if changes == nil { return &github.EditChange{} } return &github.EditChange{ Title: &github.EditTitle{ From: stringPtr(changes.Title.From), }, Body: &github.EditBody{ From: stringPtr(changes.Body.From), }, Base: &github.EditBase{ Ref: &github.EditRef{ From: stringPtr(changes.Ref.From), }, }, } } func convertLabel(label *structs.Label) *github.Label { if label == nil { return &github.Label{} } return &github.Label{ ID: int64Ptr(label.ID), Name: stringPtr(label.Name), Color: stringPtr(label.Color), Description: stringPtr(label.Description), URL: stringPtr(label.URL), } } func convertCommitFile(file *structs.ChangedFile) *github.CommitFile { if file == nil { return &github.CommitFile{} } return &github.CommitFile{ Filename: stringPtr(file.Filename), PreviousFilename: stringPtr(file.PreviousFilename), Additions: intPtr(file.Additions), Deletions: intPtr(file.Deletions), Changes: intPtr(file.Changes), Status: stringPtr(file.Status), BlobURL: stringPtr(file.ContentsURL), RawURL: stringPtr(file.RawURL), } } func translatePrAction(action structs.HookIssueAction) string { translatedAction := "" switch action { case structs.HookIssueOpened: translatedAction = "opened" case structs.HookIssueClosed: translatedAction = "closed" case structs.HookIssueReOpened: translatedAction = "reopened" case structs.HookIssueEdited: translatedAction = "edited" case structs.HookIssueAssigned: translatedAction = "assigned" case structs.HookIssueUnassigned: translatedAction = "unassigned" case structs.HookIssueLabelUpdated: // GitHub does not have a direct "label_updated" event; use "labeled" as the closest action translatedAction = "labeled" // Assuming you handle the update as adding a label case structs.HookIssueLabelCleared: // GitHub does not have a direct "label_cleared" event; use "unlabeled" as the closest action translatedAction = "unlabeled" // Assuming you handle the clearing as removing a label case structs.HookIssueSynchronized: translatedAction = "synchronize" case structs.HookIssueMilestoned: translatedAction = "milestoned" case structs.HookIssueDemilestoned: translatedAction = "demilestoned" case structs.HookIssueReviewed: // GitHub does not have a direct "reviewed" event for PRs; this might be closest to a review submitted translatedAction = "review_submitted" // This is not a direct GitHub event, consider how best to map this action case structs.HookIssueReviewRequested: translatedAction = "review_requested" case structs.HookIssueReviewRequestRemoved: translatedAction = "review_request_removed" default: // Fallback for any unhandled actions translatedAction = "unknown_action" } translatedAction = fmt.Sprintf("pull_request.%s", translatedAction) return translatedAction }