mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-08-08 15:03:42 +08:00
feat: add telegram mini app (#250)
This commit is contained in:
@@ -5,6 +5,7 @@ import { Writable } from 'node:stream'
|
||||
import { Bindings } from '../types'
|
||||
import { newTelegramBot, initTelegramBotCommands, sendMailToTelegram } from './telegram'
|
||||
import settings from './settings'
|
||||
import miniapp from './miniapp'
|
||||
|
||||
export const api = new Hono<{ Bindings: Bindings }>();
|
||||
export { sendMailToTelegram }
|
||||
@@ -67,3 +68,4 @@ api.get("/admin/telegram/status", async (c) => {
|
||||
|
||||
api.get("/admin/telegram/settings", settings.getTelegramSettings);
|
||||
api.post("/admin/telegram/settings", settings.saveTelegramSettings);
|
||||
api.post("/telegram/bind_address", miniapp.getTelegramBindAddress);
|
||||
|
||||
70
worker/src/telegram_api/miniapp.ts
Normal file
70
worker/src/telegram_api/miniapp.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Context } from "hono";
|
||||
import { Jwt } from 'hono/utils/jwt'
|
||||
import { Bindings } from "../types";
|
||||
import { CONSTANTS } from "../constants";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
|
||||
async function getTelegramBindAddress(c: Context<{ Bindings: Bindings }>): Promise<Response> {
|
||||
// check if the request is from telegram
|
||||
const { initData } = await c.req.json();
|
||||
const initDataObj = new URLSearchParams(initData);
|
||||
initDataObj.sort()
|
||||
const hash = initDataObj.get('hash');
|
||||
initDataObj.delete("hash");
|
||||
const dataToCheck = [...initDataObj.entries()].map(([key, value]) => key + "=" + value).join("\n");
|
||||
const auth_date = Number(initDataObj.get('auth_date'));
|
||||
// valid for 300 seconds
|
||||
if (auth_date + 300 < (new Date().getTime() / 1000)) {
|
||||
return c.text("OutDate initData", 400);
|
||||
}
|
||||
const user = initDataObj.get('user');
|
||||
if (!hash || !user) {
|
||||
return c.text("Invalid initData", 400);
|
||||
}
|
||||
const { id: userId } = JSON.parse(user);
|
||||
const cryptoKey = await crypto.subtle.importKey(
|
||||
"raw",
|
||||
encoder.encode("WebAppData"),
|
||||
{ name: "HMAC", hash: { name: "SHA-256" } },
|
||||
false,
|
||||
["sign"]
|
||||
);
|
||||
const secretKeyBuffer = await crypto.subtle.sign(
|
||||
"HMAC", cryptoKey, encoder.encode(c.env.TELEGRAM_BOT_TOKEN)
|
||||
);
|
||||
const secretKey = await crypto.subtle.importKey(
|
||||
"raw",
|
||||
secretKeyBuffer,
|
||||
{ name: "HMAC", hash: { name: "SHA-256" } },
|
||||
false,
|
||||
["sign", "verify"]
|
||||
);
|
||||
const calcHmac = await crypto.subtle.sign(
|
||||
"HMAC", secretKey, encoder.encode(dataToCheck)
|
||||
);
|
||||
const calcHash = Array.from(new Uint8Array(calcHmac))
|
||||
.map((b) => b.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
if (calcHash != hash) {
|
||||
return c.text("Invalid initData", 400);
|
||||
}
|
||||
// get the address list from the KV
|
||||
const jwtList = await c.env.KV.get<string[]>(`${CONSTANTS.TG_KV_PREFIX}:${userId}`, 'json') || [];
|
||||
const res = [];
|
||||
for (const jwt of jwtList) {
|
||||
try {
|
||||
const { address } = await Jwt.verify(jwt, c.env.JWT_SECRET, "HS256");
|
||||
res.push({ address, jwt });
|
||||
} catch (e) {
|
||||
console.error(`failed to verify jwt with error: ${e}`)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return c.json(res);
|
||||
}
|
||||
|
||||
export default {
|
||||
getTelegramBindAddress
|
||||
}
|
||||
@@ -63,7 +63,7 @@ export function newTelegramBot(c: Context<{ Bindings: Bindings }>, token: string
|
||||
const prefix = getStringValue(c.env.PREFIX)
|
||||
const domains = getDomains(c);
|
||||
return await ctx.reply(
|
||||
"欢迎使用本机器人\n\n"
|
||||
"欢迎使用本机器人, 您可以点击左下角打开 mini app \n\n"
|
||||
+ (prefix ? `当前已启用前缀: ${prefix}\n` : '')
|
||||
+ "新建邮箱地址, 如果要自定义邮箱地址, "
|
||||
+ "请输入 /new <name>@<domain>, name [a-zA-Z0-9.] 有效\n"
|
||||
@@ -241,7 +241,6 @@ export function newTelegramBot(c: Context<{ Bindings: Bindings }>, token: string
|
||||
|
||||
|
||||
export async function initTelegramBotCommands(bot: Telegraf) {
|
||||
bot.telegram.sendMessage
|
||||
await bot.telegram.setMyCommands(COMMANDS);
|
||||
}
|
||||
|
||||
@@ -251,13 +250,16 @@ const parseMail = async (raw_mail: string | undefined | null) => {
|
||||
}
|
||||
try {
|
||||
const parsedEmail = await PostalMime.parse(raw_mail);
|
||||
if (parsedEmail?.text?.length && parsedEmail?.text?.length > 1000) {
|
||||
parsedEmail.text = parsedEmail.text.substring(0, 1000) + "...";
|
||||
}
|
||||
return {
|
||||
isHtml: false,
|
||||
mail: `From: ${parsedEmail.from ? `${parsedEmail.from.name}[${parsedEmail.from.address}]` : "无发件人"}\n`
|
||||
+ `To: ${parsedEmail.to?.map(t => `${t.name}[${t.address}]`).join(" ")}\n`
|
||||
+ `Subject: ${parsedEmail.subject}\n`
|
||||
+ `Date: ${parsedEmail.date}\n`
|
||||
+ `Content:\n${parsedEmail.text?.substring(0, 100) || "解析失败"}`
|
||||
+ `Content:\n${parsedEmail.text || "解析失败,请点击左下角打开 mini app 查看"}`
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user