mirror of
https://github.com/zhigang1992/telert.git
synced 2026-04-30 20:22:25 +08:00
refactor: use env bindings instead of globals for Cloudflare Workers
Replace global declarations with Env interface and access environment variables through context.environmentBindings for proper CF Workers module format compatibility. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
73
src/index.ts
73
src/index.ts
@@ -14,14 +14,11 @@ import { get } from "./get";
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import indexHtml from './index.html';
|
import indexHtml from './index.html';
|
||||||
|
|
||||||
declare global {
|
interface Env {
|
||||||
const BOT_TOKEN: string;
|
BOT_TOKEN: string;
|
||||||
|
WEBHOOK_PREFIX: string;
|
||||||
const WEBHOOK_PREFIX: string;
|
WEBHOOK_PASSWORD: string;
|
||||||
|
TG_GROUPS: KVNamespace;
|
||||||
const WEBHOOK_PASSWORD: string;
|
|
||||||
|
|
||||||
const TG_GROUPS: KVNamespace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Your code here, but do not `bot.launch()`
|
// Your code here, but do not `bot.launch()`
|
||||||
@@ -34,24 +31,25 @@ router.get("/", (context) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("/bot", async (context) => {
|
router.post("/bot", async (context) => {
|
||||||
|
const env = context.environmentBindings as Env;
|
||||||
// Check for authentication password in query parameter
|
// Check for authentication password in query parameter
|
||||||
const password = context.req.url.searchParams.get('password');
|
const password = context.req.url.searchParams.get('password');
|
||||||
const expectedPassword = WEBHOOK_PASSWORD;
|
|
||||||
|
|
||||||
if (!password || password !== expectedPassword) {
|
if (!password || password !== env.WEBHOOK_PASSWORD) {
|
||||||
context.res.status = 401;
|
context.res.status = 401;
|
||||||
context.res.body = { ok: false, error: "Unauthorized" };
|
context.res.body = { ok: false, error: "Unauthorized" };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: Update = await context.req.body.json();
|
const result: Update = await context.req.body.json();
|
||||||
await processUpdate(result);
|
await processUpdate(result, env);
|
||||||
console.log(JSON.stringify(result, null, 2));
|
console.log(JSON.stringify(result, null, 2));
|
||||||
context.res.body = { ok: true };
|
context.res.body = { ok: true };
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/t/:webhookId/raw", async (context) => {
|
router.post("/t/:webhookId/raw", async (context) => {
|
||||||
const chat = await TG_GROUPS.get(
|
const env = context.environmentBindings as Env;
|
||||||
|
const chat = await env.TG_GROUPS.get(
|
||||||
`webhook-chat:${context.req.params.webhookId}`
|
`webhook-chat:${context.req.params.webhookId}`
|
||||||
);
|
);
|
||||||
if (chat == null) {
|
if (chat == null) {
|
||||||
@@ -60,14 +58,15 @@ router.post("/t/:webhookId/raw", async (context) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const result = await context.req.body.text();
|
const result = await context.req.body.text();
|
||||||
await sendToChat(JSON.parse(chat), result, {
|
await sendToChat(env, JSON.parse(chat), result, {
|
||||||
parseMode: context.req.url.searchParams.get('parseMode') as 'HTML' | undefined,
|
parseMode: context.req.url.searchParams.get('parseMode') as 'HTML' | undefined,
|
||||||
});
|
});
|
||||||
context.res.body = { ok: true };
|
context.res.body = { ok: true };
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/t/:webhookId/file", async (context) => {
|
router.post("/t/:webhookId/file", async (context) => {
|
||||||
const chat = await TG_GROUPS.get(
|
const env = context.environmentBindings as Env;
|
||||||
|
const chat = await env.TG_GROUPS.get(
|
||||||
`webhook-chat:${context.req.params.webhookId}`
|
`webhook-chat:${context.req.params.webhookId}`
|
||||||
);
|
);
|
||||||
if (chat == null) {
|
if (chat == null) {
|
||||||
@@ -76,12 +75,13 @@ router.post("/t/:webhookId/file", async (context) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const result = await context.req.body.json();
|
const result = await context.req.body.json();
|
||||||
await uploadFileToChat(JSON.parse(chat), result.fileName, result.content);
|
await uploadFileToChat(env, JSON.parse(chat), result.fileName, result.content);
|
||||||
context.res.body = { ok: true };
|
context.res.body = { ok: true };
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/t/:webhookId", async (context) => {
|
router.post("/t/:webhookId", async (context) => {
|
||||||
const chat = await TG_GROUPS.get(
|
const env = context.environmentBindings as Env;
|
||||||
|
const chat = await env.TG_GROUPS.get(
|
||||||
`webhook-chat:${context.req.params.webhookId}`
|
`webhook-chat:${context.req.params.webhookId}`
|
||||||
);
|
);
|
||||||
if (chat == null) {
|
if (chat == null) {
|
||||||
@@ -90,7 +90,7 @@ router.post("/t/:webhookId", async (context) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const result: RichMessage = await context.req.body.json();
|
const result: RichMessage = await context.req.body.json();
|
||||||
await sendToChat(JSON.parse(chat), formatRichMessage(result), {
|
await sendToChat(env, JSON.parse(chat), formatRichMessage(result), {
|
||||||
parseMode: "HTML",
|
parseMode: "HTML",
|
||||||
disableNotification: result.notify === false,
|
disableNotification: result.notify === false,
|
||||||
});
|
});
|
||||||
@@ -98,7 +98,8 @@ router.post("/t/:webhookId", async (context) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get("/t/:webhookId", async (context) => {
|
router.get("/t/:webhookId", async (context) => {
|
||||||
const chat = await TG_GROUPS.get(
|
const env = context.environmentBindings as Env;
|
||||||
|
const chat = await env.TG_GROUPS.get(
|
||||||
`webhook-chat:${context.req.params.webhookId}`
|
`webhook-chat:${context.req.params.webhookId}`
|
||||||
);
|
);
|
||||||
if (chat == null) {
|
if (chat == null) {
|
||||||
@@ -117,7 +118,7 @@ router.get("/t/:webhookId", async (context) => {
|
|||||||
metadata: search.get("metadata") ? JSON.parse(search.get("metadata") || "{}") : undefined,
|
metadata: search.get("metadata") ? JSON.parse(search.get("metadata") || "{}") : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
await sendToChat(JSON.parse(chat), formatRichMessage(result), {
|
await sendToChat(env, JSON.parse(chat), formatRichMessage(result), {
|
||||||
parseMode: "HTML",
|
parseMode: "HTML",
|
||||||
disableNotification: result.notify === false,
|
disableNotification: result.notify === false,
|
||||||
});
|
});
|
||||||
@@ -125,7 +126,8 @@ router.get("/t/:webhookId", async (context) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("/t/:webhookId/map", async (context) => {
|
router.post("/t/:webhookId/map", async (context) => {
|
||||||
const chat = await TG_GROUPS.get(
|
const env = context.environmentBindings as Env;
|
||||||
|
const chat = await env.TG_GROUPS.get(
|
||||||
`webhook-chat:${context.req.params.webhookId}`
|
`webhook-chat:${context.req.params.webhookId}`
|
||||||
);
|
);
|
||||||
if (chat == null) {
|
if (chat == null) {
|
||||||
@@ -163,7 +165,7 @@ router.post("/t/:webhookId/map", async (context) => {
|
|||||||
])
|
])
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
await sendToChat(JSON.parse(chat), formatRichMessage(result), {
|
await sendToChat(env, JSON.parse(chat), formatRichMessage(result), {
|
||||||
parseMode: "HTML",
|
parseMode: "HTML",
|
||||||
disableNotification: result.notify === false,
|
disableNotification: result.notify === false,
|
||||||
});
|
});
|
||||||
@@ -193,7 +195,7 @@ export default {
|
|||||||
app.handleRequest(request, env, ctx),
|
app.handleRequest(request, env, ctx),
|
||||||
};
|
};
|
||||||
|
|
||||||
async function processUpdate(update: Update): Promise<void> {
|
async function processUpdate(update: Update, env: Env): Promise<void> {
|
||||||
const message = update.message ?? update.channel_post;
|
const message = update.message ?? update.channel_post;
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
return;
|
return;
|
||||||
@@ -209,7 +211,7 @@ async function processUpdate(update: Update): Promise<void> {
|
|||||||
chatId: oldChatId,
|
chatId: oldChatId,
|
||||||
messageThreadId: message.message_thread_id,
|
messageThreadId: message.message_thread_id,
|
||||||
});
|
});
|
||||||
const webhookId = await TG_GROUPS.get(`chat-webhook:${oldChat}`);
|
const webhookId = await env.TG_GROUPS.get(`chat-webhook:${oldChat}`);
|
||||||
|
|
||||||
if (webhookId) {
|
if (webhookId) {
|
||||||
// Update the stored chat info with new chat ID
|
// Update the stored chat info with new chat ID
|
||||||
@@ -217,11 +219,11 @@ async function processUpdate(update: Update): Promise<void> {
|
|||||||
chatId: newChatId,
|
chatId: newChatId,
|
||||||
messageThreadId: message.message_thread_id,
|
messageThreadId: message.message_thread_id,
|
||||||
});
|
});
|
||||||
await TG_GROUPS.put(`chat-webhook:${newChat}`, webhookId);
|
await env.TG_GROUPS.put(`chat-webhook:${newChat}`, webhookId);
|
||||||
await TG_GROUPS.put(`webhook-chat:${webhookId}`, newChat);
|
await env.TG_GROUPS.put(`webhook-chat:${webhookId}`, newChat);
|
||||||
|
|
||||||
// Delete old mapping
|
// Delete old mapping
|
||||||
await TG_GROUPS.delete(`chat-webhook:${oldChat}`);
|
await env.TG_GROUPS.delete(`chat-webhook:${oldChat}`);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -234,18 +236,19 @@ async function processUpdate(update: Update): Promise<void> {
|
|||||||
};
|
};
|
||||||
const chatKey = JSON.stringify(chat);
|
const chatKey = JSON.stringify(chat);
|
||||||
const key = `chat-webhook:${chatKey}`;
|
const key = `chat-webhook:${chatKey}`;
|
||||||
const result = await TG_GROUPS.get(key);
|
const result = await env.TG_GROUPS.get(key);
|
||||||
let webhookUrl: string;
|
let webhookUrl: string;
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
const uuid = crypto.randomUUID();
|
const uuid = crypto.randomUUID();
|
||||||
await TG_GROUPS.put(key, uuid);
|
await env.TG_GROUPS.put(key, uuid);
|
||||||
await TG_GROUPS.put(`webhook-chat:${uuid}`, chatKey);
|
await env.TG_GROUPS.put(`webhook-chat:${uuid}`, chatKey);
|
||||||
webhookUrl = `${WEBHOOK_PREFIX}/t/${uuid}`;
|
webhookUrl = `${env.WEBHOOK_PREFIX}/t/${uuid}`;
|
||||||
} else {
|
} else {
|
||||||
await TG_GROUPS.put(`webhook-chat:${result}`, chatKey);
|
await env.TG_GROUPS.put(`webhook-chat:${result}`, chatKey);
|
||||||
webhookUrl = `${WEBHOOK_PREFIX}/t/${result}`;
|
webhookUrl = `${env.WEBHOOK_PREFIX}/t/${result}`;
|
||||||
}
|
}
|
||||||
await sendToChat(
|
await sendToChat(
|
||||||
|
env,
|
||||||
chat,
|
chat,
|
||||||
`<code>${webhookUrl}</code>
|
`<code>${webhookUrl}</code>
|
||||||
|
|
||||||
@@ -272,6 +275,7 @@ async function processUpdate(update: Update): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function sendToChat(
|
async function sendToChat(
|
||||||
|
env: Env,
|
||||||
chat: {
|
chat: {
|
||||||
chatId: number;
|
chatId: number;
|
||||||
messageThreadId?: number;
|
messageThreadId?: number;
|
||||||
@@ -282,7 +286,7 @@ async function sendToChat(
|
|||||||
disableNotification?: boolean;
|
disableNotification?: boolean;
|
||||||
}
|
}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await fetch(`https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`, {
|
await fetch(`https://api.telegram.org/bot${env.BOT_TOKEN}/sendMessage`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -298,6 +302,7 @@ async function sendToChat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function uploadFileToChat(
|
async function uploadFileToChat(
|
||||||
|
env: Env,
|
||||||
chat: {
|
chat: {
|
||||||
chatId: number;
|
chatId: number;
|
||||||
messageThreadId?: number;
|
messageThreadId?: number;
|
||||||
@@ -305,7 +310,7 @@ async function uploadFileToChat(
|
|||||||
fileName: string,
|
fileName: string,
|
||||||
content: string
|
content: string
|
||||||
) {
|
) {
|
||||||
await fetch(`https://api.telegram.org/bot${BOT_TOKEN}/sendDocument`, {
|
await fetch(`https://api.telegram.org/bot${env.BOT_TOKEN}/sendDocument`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "multipart/form-data; boundary=WebAppBoundary",
|
"Content-Type": "multipart/form-data; boundary=WebAppBoundary",
|
||||||
|
|||||||
Reference in New Issue
Block a user