This commit is contained in:
Corey Johnson 2025-11-12 17:13:25 -08:00
parent 34de1f8e40
commit e2feb9cc1a
3 changed files with 370 additions and 58 deletions

View File

@ -1,46 +1,8 @@
import { insertComment } from "../db"
import { type Gitea } from "./types"
const giteaUrl = "https://git.nose.space"
export namespace Gitea {
export type User = {
id: number
login: string
username: string
}
export type PullRequest = {
id: number
number: number
title: string
body: string
user: User
html_url: string
state: string
merged: boolean
}
export type Issue = {
id: number
number: number
pull_request?: {
html_url: string
}
}
export type Comment = {
id: number
body: string
user: User
html_url: string
}
export type Repository = {
name: string
full_name: string
}
}
type CreateCommentResponse = {
id: number
body: string

View File

@ -0,0 +1,366 @@
// Types borrowed from gitea-js@1.23.0
// https://github.com/anbraten/gitea-js
export namespace Gitea {
export interface User {
id: number
login: string
full_name: string
avatar_url: string
active?: boolean
created?: string
description?: string
email?: string
followers_count?: number
following_count?: number
html_url?: string
is_admin?: boolean
language?: string
last_login?: string
location?: string
login_name?: string
prohibit_login?: boolean
restricted?: boolean
source_id?: number
starred_repos_count?: number
visibility?: string
website?: string
}
export interface PullRequest {
id: number
number: number
title: string
body: string
user: User
html_url: string
state: StateType
merged: boolean
created_at: string
updated_at: string
draft: boolean
base: PRBranchInfo
head: PRBranchInfo
additions?: number
allow_maintainer_edit?: boolean
assignee?: User
assignees?: User[]
changed_files?: number
closed_at?: string
comments?: number
deletions?: number
diff_url?: string
due_date?: string
is_locked?: boolean
labels?: Label[]
merge_base?: string
merge_commit_sha?: string
mergeable?: boolean
merged_at?: string
merged_by?: User
milestone?: Milestone
patch_url?: string
pin_order?: number
requested_reviewers?: User[]
requested_reviewers_teams?: Team[]
review_comments?: number
url?: string
}
export interface Issue {
id: number
number: number
title: string
body: string
user: User
html_url: string
state: StateType
created_at: string
updated_at: string
assets?: Attachment[]
assignee?: User
assignees?: User[]
closed_at?: string
comments?: number
due_date?: string
is_locked?: boolean
labels?: Label[]
milestone?: Milestone
original_author?: string
original_author_id?: number
pin_order?: number
pull_request?: PullRequestMeta
ref?: string
repository?: RepositoryMeta
url?: string
}
export interface Comment {
id: number
body: string
user: User
html_url: string
created_at: string
updated_at: string
assets?: Attachment[]
issue_url?: string
original_author?: string
original_author_id?: number
pull_request_url?: string
}
export interface Repository {
id: number
name: string
full_name: string
owner: User
html_url: string
private: boolean
allow_fast_forward_only_merge?: boolean
allow_merge_commits?: boolean
allow_rebase?: boolean
allow_rebase_explicit?: boolean
allow_rebase_update?: boolean
allow_squash_merge?: boolean
archived?: boolean
archived_at?: string
avatar_url?: string
clone_url?: string
created_at?: string
default_allow_maintainer_edit?: boolean
default_branch?: string
default_delete_branch_after_merge?: boolean
default_merge_style?: string
description?: string
empty?: boolean
external_tracker?: ExternalTracker
external_wiki?: ExternalWiki
fork?: boolean
forks_count?: number
has_actions?: boolean
has_issues?: boolean
has_packages?: boolean
has_projects?: boolean
has_pull_requests?: boolean
has_releases?: boolean
has_wiki?: boolean
ignore_whitespace_conflicts?: boolean
internal?: boolean
internal_tracker?: InternalTracker
language?: string
languages_url?: string
licenses?: string[]
link?: string
mirror?: boolean
mirror_interval?: string
mirror_updated?: string
object_format_name?: "sha1" | "sha256"
open_issues_count?: number
open_pr_counter?: number
original_url?: string
parent?: Repository
permissions?: Permission
projects_mode?: string
release_counter?: number
repo_transfer?: RepoTransfer
size?: number
ssh_url?: string
stars_count?: number
template?: boolean
topics?: string[]
updated_at?: string
url?: string
watchers_count?: number
website?: string
}
// Supporting types
export type StateType = "open" | "closed" | "all"
export interface PRBranchInfo {
label?: string
ref?: string
repo?: Repository
repo_id?: number
sha?: string
}
export interface Label {
color?: string
description?: string
exclusive?: boolean
id?: number
is_archived?: boolean
name?: string
url?: string
}
export interface Milestone {
closed_at?: string
closed_issues?: number
created_at?: string
description?: string
due_on?: string
id?: number
open_issues?: number
state?: StateType
title?: string
updated_at?: string
}
export interface Team {
can_create_org_repo?: boolean
description?: string
id?: number
includes_all_repositories?: boolean
name?: string
organization?: Organization
permission?: "none" | "read" | "write" | "admin" | "owner"
units?: string[]
units_map?: Record<string, string>
}
export interface Organization {
avatar_url?: string
description?: string
email?: string
full_name?: string
id?: number
location?: string
name?: string
repo_admin_change_team_access?: boolean
username?: string
visibility?: string
website?: string
}
export interface Attachment {
browser_download_url?: string
created_at?: string
download_count?: number
id?: number
name?: string
size?: number
uuid?: string
}
export interface PullRequestMeta {
merged?: boolean
merged_at?: string
html_url?: string
}
export interface RepositoryMeta {
full_name?: string
id?: number
name?: string
owner?: string
}
export interface ExternalTracker {
external_tracker_format?: string
external_tracker_regexp_pattern?: string
external_tracker_style?: string
external_tracker_url?: string
}
export interface ExternalWiki {
external_wiki_url?: string
}
export interface InternalTracker {
allow_only_contributors_to_track_time?: boolean
enable_issue_dependencies?: boolean
enable_time_tracker?: boolean
}
export interface Permission {
admin?: boolean
pull?: boolean
push?: boolean
}
export interface RepoTransfer {
doer?: User
recipient?: User
teams?: Team[]
}
// Webhook-specific stricter types (fields that are always present in webhooks)
export interface WebhookUser {
id: number
login: string
full_name: string
avatar_url: string
email?: string
}
export interface WebhookRepository {
id: number
name: string
full_name: string
owner: User
html_url: string
description?: string
private: boolean
}
export interface WebhookPullRequest {
id: number
number: number
title: string
body: string
user: WebhookUser
html_url: string
state: StateType
merged: boolean
merged_at?: string
created_at: string
updated_at: string
closed_at?: string
draft: boolean
base: PRBranchInfo
head: PRBranchInfo
}
export interface WebhookIssue {
id: number
number: number
title: string
body: string
user: WebhookUser
html_url: string
state: StateType
pull_request?: PullRequestMeta
created_at: string
updated_at: string
}
export interface WebhookComment {
id: number
body: string
user: WebhookUser
html_url: string
created_at: string
updated_at: string
}
// Webhook payload types (not from gitea-js, these are custom)
export interface PullRequestWebhook {
action: "opened" | "closed" | "edited" | "synchronized" | "reviewed" | "reopened"
number: number
pull_request: WebhookPullRequest
repository: WebhookRepository
sender: WebhookUser
}
export interface IssueCommentWebhook {
action: "created" | "edited" | "deleted"
issue: WebhookIssue
comment: WebhookComment
repository: WebhookRepository
sender: WebhookUser
}
export type Webhook = PullRequestWebhook | IssueCommentWebhook
}

View File

@ -3,9 +3,10 @@ import { insertPR, getPRByGiteaId, insertComment, getCommentByGiteaId } from "..
import { getConfig } from "../config"
import { ChannelType, ThreadChannel, type Channel } from "discord.js"
import { assertNever } from "@workshop/shared/utils"
import { fetchPR, type Gitea } from "./api"
import { fetchPR } from "./api"
import type { Gitea } from "./types"
export const handleGiteaWebhook = async (payload: GiteaWebhook) => {
export const handleGiteaWebhook = async (payload: Gitea.Webhook) => {
const isDev = process.env.NODE_ENV !== "production"
if (!isDev && payload.repository.name === "ignore-me") return
@ -301,20 +302,3 @@ const convertMentionsToDiscord = async (text: string): Promise<string> => {
return result
}
interface PullRequestWebhook {
action: "opened" | "closed" | "edited" | "synchronized" | "reviewed" | "reopened"
number: number
pull_request: Gitea.PullRequest
repository: Gitea.Repository
sender: Gitea.User
}
interface IssueCommentWebhook {
action: "created" | "edited" | "deleted"
issue: Gitea.Issue
comment: Gitea.Comment
repository: Gitea.Repository
}
type GiteaWebhook = PullRequestWebhook | IssueCommentWebhook