chore: add thread support

This commit is contained in:
Kyle Fang
2023-05-01 15:25:57 +08:00
parent 3e9e0eb9dd
commit e4622adc67
4 changed files with 43 additions and 121 deletions

View File

@@ -16,7 +16,6 @@
"test": "vitest"
},
"dependencies": {
"@cfworker/web": "^1.12.5",
"telegraf": "^4.12.2"
"@cfworker/web": "^1.12.5"
}
}

102
pnpm-lock.yaml generated
View File

@@ -4,9 +4,6 @@ dependencies:
'@cfworker/web':
specifier: ^1.12.5
version: 1.12.5
telegraf:
specifier: ^4.12.2
version: 4.12.2
devDependencies:
'@cloudflare/workers-types':
@@ -741,13 +738,6 @@ packages:
pretty-format: 27.5.1
dev: true
/abort-controller@3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
dependencies:
event-target-shim: 5.0.1
dev: false
/acorn-walk@8.2.0:
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
engines: {node: '>=0.4.0'}
@@ -801,21 +791,6 @@ packages:
fill-range: 7.0.1
dev: true
/buffer-alloc-unsafe@1.1.0:
resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==}
dev: false
/buffer-alloc@1.2.0:
resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==}
dependencies:
buffer-alloc-unsafe: 1.1.0
buffer-fill: 1.0.0
dev: false
/buffer-fill@1.0.0:
resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==}
dev: false
/buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
dev: true
@@ -924,6 +899,7 @@ packages:
optional: true
dependencies:
ms: 2.1.2
dev: true
/deep-eql@4.1.3:
resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
@@ -1011,11 +987,6 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
dev: false
/execa@6.1.0:
resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -1238,13 +1209,9 @@ packages:
ufo: 1.1.1
dev: true
/mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
dev: false
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
/mustache@4.2.0:
resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
@@ -1262,18 +1229,6 @@ packages:
engines: {node: '>= 0.6'}
dev: false
/node-fetch@2.6.9:
resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==}
engines: {node: 4.x || >=6.0.0}
peerDependencies:
encoding: ^0.1.0
peerDependenciesMeta:
encoding:
optional: true
dependencies:
whatwg-url: 5.0.0
dev: false
/node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'}
@@ -1314,11 +1269,6 @@ packages:
yocto-queue: 1.0.0
dev: true
/p-timeout@4.1.0:
resolution: {integrity: sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==}
engines: {node: '>=10'}
dev: false
/parse-package-name@1.0.0:
resolution: {integrity: sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==}
dev: true
@@ -1425,17 +1375,6 @@ packages:
fsevents: 2.3.2
dev: true
/safe-compare@1.1.4:
resolution: {integrity: sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==}
dependencies:
buffer-alloc: 1.2.0
dev: false
/sandwich-stream@2.0.2:
resolution: {integrity: sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==}
engines: {node: '>= 0.10'}
dev: false
/secure-json-parse@2.7.0:
resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
dev: false
@@ -1544,24 +1483,6 @@ packages:
acorn: 8.8.2
dev: true
/telegraf@4.12.2:
resolution: {integrity: sha512-PgwqI4wD86cMqVfFtEM9JkGGnMHgvgLJbReZMmwW4z35QeOi4DvbdItONld4bPnYn3A1jcO0SRKs0BXmR+x+Ew==}
engines: {node: ^12.20.0 || >=14.13.1}
hasBin: true
dependencies:
abort-controller: 3.0.0
debug: 4.3.4
mri: 1.2.0
node-fetch: 2.6.9
p-timeout: 4.1.0
safe-compare: 1.1.4
sandwich-stream: 2.0.2
typegram: 4.3.0
transitivePeerDependencies:
- encoding
- supports-color
dev: false
/time-zone@1.0.0:
resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==}
engines: {node: '>=4'}
@@ -1588,19 +1509,11 @@ packages:
is-number: 7.0.0
dev: true
/tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
dev: false
/type-detect@4.0.8:
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
engines: {node: '>=4'}
dev: true
/typegram@4.3.0:
resolution: {integrity: sha512-pS4STyOZoJ++Mwa9GPMTNjOwEzMkxFfFt1By6IbMOJfheP0utMP/H1ga6J9R4DTjAYBr0UDn4eQg++LpWBvcAg==}
dev: false
/typescript@5.0.4:
resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==}
engines: {node: '>=12.20'}
@@ -1749,22 +1662,11 @@ packages:
- terser
dev: true
/webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
dev: false
/well-known-symbols@2.0.0:
resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==}
engines: {node: '>=6'}
dev: true
/whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
dependencies:
tr46: 0.0.3
webidl-conversions: 3.0.1
dev: false
/which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}

View File

@@ -31,52 +31,61 @@ router.post("/bot", async (context) => {
});
router.post("/t/:webhookId/raw", async (context) => {
const chatId = await TG_GROUPS.get(
const chat = await TG_GROUPS.get(
`webhook-chat:${context.req.params.webhookId}`
);
if (chatId == null) {
if (chat == null) {
context.res.body = { ok: false, error: "chatId not found" };
context.res.status = 404;
return;
}
const result = await context.req.body.text();
await sendToChat(Number(chatId), result);
await sendToChat(JSON.parse(chat), result);
context.res.body = { ok: true };
});
router.post("/t/:webhookId", async (context) => {
const chatId = await TG_GROUPS.get(
const chat = await TG_GROUPS.get(
`webhook-chat:${context.req.params.webhookId}`
);
if (chatId == null) {
if (chat == null) {
context.res.body = { ok: false, error: "chatId not found" };
context.res.status = 404;
return;
}
const result: RichMessage = await context.req.body.json();
await sendToChat(Number(chatId), formatRichMessage(result), "HTML");
await sendToChat(JSON.parse(chat), formatRichMessage(result), "HTML");
context.res.body = { ok: true };
});
new Application().use(router.middleware).listen();
async function processUpdate(update: Update): Promise<void> {
console.log(JSON.stringify(update, null, 2));
if (update.message == null) {
return;
}
if (update.message.text === "/webhook") {
const chatId = update.message.chat.id;
const key = `chat-webhook:${chatId}`;
const chat = {
chatId,
messageThreadId: update.message.message_thread_id,
};
const key = `chat-webhook:${JSON.stringify(chat)}`;
const result = await TG_GROUPS.get(key);
let webhookUrl: string;
if (result == null) {
const uuid = crypto.randomUUID();
await TG_GROUPS.put(key, uuid);
await TG_GROUPS.put(`webhook-chat:${uuid}`, chatId.toString());
await TG_GROUPS.put(`webhook-chat:${uuid}`, JSON.stringify(chat));
webhookUrl = `${WEBHOOK_PREFIX}/t/${uuid}`;
} else {
await TG_GROUPS.put(`webhook-chat:${result}`, chatId.toString());
await TG_GROUPS.put(`webhook-chat:${result}`, JSON.stringify(chat));
webhookUrl = `${WEBHOOK_PREFIX}/t/${result}`;
}
await sendToChat(chatId, `<a href="${webhookUrl}">${webhookUrl}</a>
await sendToChat(
chat,
`<a href="${webhookUrl}">${webhookUrl}</a>
<code>
{
@@ -88,12 +97,17 @@ async function processUpdate(update: Update): Promise<void> {
}
}
</code>
`, 'HTML');
`,
"HTML"
);
}
}
async function sendToChat(
chatId: number,
chat: {
chatId: number;
messageThreadId?: number;
},
text: string,
parseMode?: "HTML"
): Promise<void> {
@@ -103,7 +117,8 @@ async function sendToChat(
"Content-Type": "application/json",
},
body: JSON.stringify({
chat_id: chatId,
chat_id: chat.chatId,
message_thread_id: chat.messageThreadId,
text,
parse_mode: parseMode,
}),

View File

@@ -1,5 +1,5 @@
export type RichMessage = {
topic: string;
channel?: string;
event: string;
text?: string;
emoji?: string;
@@ -10,13 +10,19 @@ export function formatRichMessage(message: RichMessage): string {
const metadata = Object.entries(message.metadata ?? {})
.map(([key, value]) => `#${key}: ${value}`)
.join("\n");
return `${message.emoji ? message.emoji + " • " : ""}<ins>#${
message.topic
}</ins>
return `${message.emoji ? message.emoji + " • " : ""}${
message.channel
? `<ins>#${message.channel}</ins>
<b>${message.event}</b>${message.text ? `
`
: ""
}<b>${message.event}</b>${
message.text
? `
<code>${message.text}</code>` : ""}
<code>${message.text}</code>`
: ""
}
${metadata}`;
}