mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
feat(feishu): add Feishu inbound webhook, /gh commands and card actions
- add feishu_links D1 table and link store helpers - implement X-Lark-Signature verification, url_verification, /gh login|logout|comment|merge|close and card.action.trigger Merge/Close - render interactive cards with clickable title link, inline links and callback buttons (no whole-card card_link) - bind Feishu account in OAuth callback - document event subscription and required scopes
This commit is contained in:
parent
3437ac5513
commit
4b99f6d33d
38 changed files with 2449 additions and 1412 deletions
37
server/lib/drivers/feishu/index.ts
Normal file
37
server/lib/drivers/feishu/index.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import type { RouteTarget, Env, NeutralMessage } from "../../types";
|
||||
import type { PlatformDriver, SendResult } from "../types";
|
||||
import { getTenantAccessToken, sendMessage, updateMessage } from "./rest";
|
||||
import { renderNeutralMessage } from "./render";
|
||||
|
||||
export class FeishuDriver implements PlatformDriver {
|
||||
readonly id = "feishu";
|
||||
|
||||
async send(message: NeutralMessage, target: RouteTarget, env: Env): Promise<SendResult> {
|
||||
const chatId = target.chatId ?? "";
|
||||
if (!chatId) {
|
||||
return { ok: false, error: "target.chatId is required", errorCode: "NO_TARGET" };
|
||||
}
|
||||
const tokenRes = await getTenantAccessToken(env);
|
||||
if (!tokenRes.ok || !tokenRes.token) {
|
||||
return { ok: false, error: tokenRes.error ?? "No token", errorCode: tokenRes.errorCode ?? "NO_TOKEN" };
|
||||
}
|
||||
return sendMessage(tokenRes.token, chatId, renderNeutralMessage(message));
|
||||
}
|
||||
|
||||
async edit(
|
||||
message: NeutralMessage,
|
||||
target: RouteTarget,
|
||||
env: Env,
|
||||
messageId: string,
|
||||
): Promise<SendResult> {
|
||||
const chatId = target.chatId ?? "";
|
||||
if (!chatId) {
|
||||
return { ok: false, error: "target.chatId is required", errorCode: "NO_TARGET" };
|
||||
}
|
||||
const tokenRes = await getTenantAccessToken(env);
|
||||
if (!tokenRes.ok || !tokenRes.token) {
|
||||
return { ok: false, error: tokenRes.error ?? "No token", errorCode: tokenRes.errorCode ?? "NO_TOKEN" };
|
||||
}
|
||||
return updateMessage(tokenRes.token, messageId, renderNeutralMessage(message));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue