wip: support

This commit is contained in:
Frank
2026-01-20 23:06:06 -05:00
parent dac73572e0
commit be9a0bfee7
8 changed files with 176 additions and 1 deletions

View File

@@ -4,6 +4,10 @@ const GITHUB_APP_ID = new sst.Secret("GITHUB_APP_ID")
const GITHUB_APP_PRIVATE_KEY = new sst.Secret("GITHUB_APP_PRIVATE_KEY")
export const EMAILOCTOPUS_API_KEY = new sst.Secret("EMAILOCTOPUS_API_KEY")
const ADMIN_SECRET = new sst.Secret("ADMIN_SECRET")
const DISCORD_SUPPORT_BOT_TOKEN = new sst.Secret("DISCORD_SUPPORT_BOT_TOKEN")
const DISCORD_SUPPORT_CHANNEL_ID = new sst.Secret("DISCORD_SUPPORT_CHANNEL_ID")
const FEISHU_APP_ID = new sst.Secret("FEISHU_APP_ID")
const FEISHU_APP_SECRET = new sst.Secret("FEISHU_APP_SECRET")
const bucket = new sst.cloudflare.Bucket("Bucket")
export const api = new sst.cloudflare.Worker("Api", {
@@ -13,7 +17,16 @@ export const api = new sst.cloudflare.Worker("Api", {
WEB_DOMAIN: domain,
},
url: true,
link: [bucket, GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY, ADMIN_SECRET],
link: [
bucket,
GITHUB_APP_ID,
GITHUB_APP_PRIVATE_KEY,
ADMIN_SECRET,
DISCORD_SUPPORT_BOT_TOKEN,
DISCORD_SUPPORT_CHANNEL_ID,
FEISHU_APP_ID,
FEISHU_APP_SECRET,
],
transform: {
worker: (args) => {
args.logpush = true

View File

@@ -34,6 +34,14 @@ declare module "sst" {
"type": "sst.cloudflare.SolidStart"
"url": string
}
"DISCORD_SUPPORT_BOT_TOKEN": {
"type": "sst.sst.Secret"
"value": string
}
"DISCORD_SUPPORT_CHANNEL_ID": {
"type": "sst.sst.Secret"
"value": string
}
"Database": {
"database": string
"host": string
@@ -46,6 +54,14 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_ID": {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_SECRET": {
"type": "sst.sst.Secret"
"value": string
}
"GITHUB_APP_ID": {
"type": "sst.sst.Secret"
"value": string

View File

@@ -34,6 +34,14 @@ declare module "sst" {
"type": "sst.cloudflare.SolidStart"
"url": string
}
"DISCORD_SUPPORT_BOT_TOKEN": {
"type": "sst.sst.Secret"
"value": string
}
"DISCORD_SUPPORT_CHANNEL_ID": {
"type": "sst.sst.Secret"
"value": string
}
"Database": {
"database": string
"host": string
@@ -46,6 +54,14 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_ID": {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_SECRET": {
"type": "sst.sst.Secret"
"value": string
}
"GITHUB_APP_ID": {
"type": "sst.sst.Secret"
"value": string

View File

@@ -34,6 +34,14 @@ declare module "sst" {
"type": "sst.cloudflare.SolidStart"
"url": string
}
"DISCORD_SUPPORT_BOT_TOKEN": {
"type": "sst.sst.Secret"
"value": string
}
"DISCORD_SUPPORT_CHANNEL_ID": {
"type": "sst.sst.Secret"
"value": string
}
"Database": {
"database": string
"host": string
@@ -46,6 +54,14 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_ID": {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_SECRET": {
"type": "sst.sst.Secret"
"value": string
}
"GITHUB_APP_ID": {
"type": "sst.sst.Secret"
"value": string

View File

@@ -34,6 +34,14 @@ declare module "sst" {
"type": "sst.cloudflare.SolidStart"
"url": string
}
"DISCORD_SUPPORT_BOT_TOKEN": {
"type": "sst.sst.Secret"
"value": string
}
"DISCORD_SUPPORT_CHANNEL_ID": {
"type": "sst.sst.Secret"
"value": string
}
"Database": {
"database": string
"host": string
@@ -46,6 +54,14 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_ID": {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_SECRET": {
"type": "sst.sst.Secret"
"value": string
}
"GITHUB_APP_ID": {
"type": "sst.sst.Secret"
"value": string

View File

@@ -12,6 +12,20 @@ type Env = {
WEB_DOMAIN: string
}
async function getFeishuTenantToken(): Promise<string> {
const response = await fetch("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
app_id: Resource.FEISHU_APP_ID.value,
app_secret: Resource.FEISHU_APP_SECRET.value,
}),
})
const data = (await response.json()) as { tenant_access_token?: string }
if (!data.tenant_access_token) throw new Error("Failed to get Feishu tenant token")
return data.tenant_access_token
}
export class SyncServer extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env)
@@ -200,6 +214,58 @@ export default new Hono<{ Bindings: Env }>()
return c.json({ info, messages })
})
.post("/feishu", async (c) => {
const body = (await c.req.json()) as {
challenge?: string
event?: {
message?: {
message_id?: string
root_id?: string
parent_id?: string
chat_id?: string
content?: string
}
}
}
console.log(JSON.stringify(body, null, 2))
const challenge = body.challenge
if (challenge) return c.json({ challenge })
const content = body.event?.message?.content
const parsed =
typeof content === "string" && content.trim().startsWith("{") ? (JSON.parse(content) as {
text?: string
}) : undefined
const text = typeof parsed?.text === "string" ? parsed.text : typeof content === "string" ? content : ""
let message = text.trim().replace(/^@_user_\d+\s*/, "")
message = message.replace(/^aiden,?\s*/i, "<@759257817772851260> ")
if (!message) return c.json({ ok: true })
const threadId = body.event?.message?.root_id || body.event?.message?.message_id
if (threadId) message = `${message} [${threadId}]`
const response = await fetch(
`https://discord.com/api/v10/channels/${Resource.DISCORD_SUPPORT_CHANNEL_ID.value}/messages`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bot ${Resource.DISCORD_SUPPORT_BOT_TOKEN.value}`,
},
body: JSON.stringify({
content: `${message}`,
}),
},
)
if (!response.ok) {
console.error(await response.text())
return c.json({ error: "Discord bot message failed" }, { status: 502 })
}
return c.json({ ok: true })
})
/**
* Used by the GitHub action to get GitHub installation access token given the OIDC token
*/

View File

@@ -34,6 +34,14 @@ declare module "sst" {
"type": "sst.cloudflare.SolidStart"
"url": string
}
"DISCORD_SUPPORT_BOT_TOKEN": {
"type": "sst.sst.Secret"
"value": string
}
"DISCORD_SUPPORT_CHANNEL_ID": {
"type": "sst.sst.Secret"
"value": string
}
"Database": {
"database": string
"host": string
@@ -46,6 +54,14 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_ID": {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_SECRET": {
"type": "sst.sst.Secret"
"value": string
}
"GITHUB_APP_ID": {
"type": "sst.sst.Secret"
"value": string

16
sst-env.d.ts vendored
View File

@@ -49,6 +49,14 @@ declare module "sst" {
"type": "sst.cloudflare.SolidStart"
"url": string
}
"DISCORD_SUPPORT_BOT_TOKEN": {
"type": "sst.sst.Secret"
"value": string
}
"DISCORD_SUPPORT_CHANNEL_ID": {
"type": "sst.sst.Secret"
"value": string
}
"Database": {
"database": string
"host": string
@@ -65,6 +73,14 @@ declare module "sst" {
"name": string
"type": "sst.cloudflare.Bucket"
}
"FEISHU_APP_ID": {
"type": "sst.sst.Secret"
"value": string
}
"FEISHU_APP_SECRET": {
"type": "sst.sst.Secret"
"value": string
}
"GITHUB_APP_ID": {
"type": "sst.sst.Secret"
"value": string