mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-06-03 21:02:16 +08:00
Show AI extraction results in Telegram notifications
This commit is contained in:
parent
2221342560
commit
e9f857063d
@ -151,17 +151,17 @@ export async function extractEmailInfo(
|
||||
env: Bindings,
|
||||
message_id: string | null,
|
||||
address: string
|
||||
): Promise<void> {
|
||||
): Promise<ExtractResult | null> {
|
||||
try {
|
||||
// Check if AI extraction is enabled via environment variable
|
||||
if (!getBooleanValue(env.ENABLE_AI_EMAIL_EXTRACT)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Ensure AI binding is available
|
||||
if (!env.AI) {
|
||||
console.error('AI binding not available');
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check allowlist if enabled
|
||||
@ -187,7 +187,7 @@ export async function extractEmailInfo(
|
||||
|
||||
if (!isAllowed) {
|
||||
console.log(`AI extraction skipped for ${address}: not in allowlist`);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +196,7 @@ export async function extractEmailInfo(
|
||||
const emailContent = parsedEmail?.text || parsedEmail?.html || "";
|
||||
|
||||
if (!emailContent) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Truncate content if too long (max 4000 characters to avoid token limits)
|
||||
@ -219,9 +219,12 @@ export async function extractEmailInfo(
|
||||
).bind(metadata, message_id).run();
|
||||
|
||||
console.log(`AI extraction completed for ${message_id}: ${result.type}`);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
console.error('AI email extraction error:', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -122,11 +122,14 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
|
||||
// forward email
|
||||
await forwardEmail(message, env);
|
||||
|
||||
// AI email content extraction
|
||||
const aiExtractResult = await extractEmailInfo(parsedEmailContext, env, message_id, toAddress);
|
||||
|
||||
// send email to telegram
|
||||
try {
|
||||
await sendMailToTelegram(
|
||||
{ env: env } as Context<HonoCustomType>,
|
||||
toAddress, parsedEmailContext, message_id);
|
||||
toAddress, parsedEmailContext, message_id, aiExtractResult);
|
||||
} catch (error) {
|
||||
console.error("send mail to telegram error", error);
|
||||
}
|
||||
@ -158,9 +161,6 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
|
||||
|
||||
// auto reply email
|
||||
await auto_reply(message, env, toAddress);
|
||||
|
||||
// AI email content extraction
|
||||
await extractEmailInfo(parsedEmailContext, env, message_id, toAddress);
|
||||
}
|
||||
|
||||
export { email }
|
||||
|
||||
@ -174,6 +174,12 @@ const messages: LocaleMessages = {
|
||||
TgNoPermissionViewMailMsg: "No permission to view this mail",
|
||||
TgBotTokenRequiredMsg: "TELEGRAM_BOT_TOKEN is required",
|
||||
TgLangFeatureDisabledMsg: "Language setting feature is disabled. System default language is used.",
|
||||
TgAiExtractResultMsg: "AI extracted",
|
||||
TgAiExtractAuthCodeMsg: "Verification code",
|
||||
TgAiExtractAuthLinkMsg: "Verification link",
|
||||
TgAiExtractServiceLinkMsg: "Service link",
|
||||
TgAiExtractSubscriptionLinkMsg: "Subscription link",
|
||||
TgAiExtractOtherLinkMsg: "Other link",
|
||||
}
|
||||
|
||||
export default messages;
|
||||
|
||||
@ -172,4 +172,10 @@ export type LocaleMessages = {
|
||||
TgNoPermissionViewMailMsg: string
|
||||
TgBotTokenRequiredMsg: string
|
||||
TgLangFeatureDisabledMsg: string
|
||||
TgAiExtractResultMsg: string
|
||||
TgAiExtractAuthCodeMsg: string
|
||||
TgAiExtractAuthLinkMsg: string
|
||||
TgAiExtractServiceLinkMsg: string
|
||||
TgAiExtractSubscriptionLinkMsg: string
|
||||
TgAiExtractOtherLinkMsg: string
|
||||
}
|
||||
|
||||
@ -174,6 +174,12 @@ const messages: LocaleMessages = {
|
||||
TgNoPermissionViewMailMsg: "无权查看此邮件",
|
||||
TgBotTokenRequiredMsg: "需要设置 TELEGRAM_BOT_TOKEN",
|
||||
TgLangFeatureDisabledMsg: "语言设置功能已禁用,使用系统默认语言",
|
||||
TgAiExtractResultMsg: "AI 提取",
|
||||
TgAiExtractAuthCodeMsg: "验证码",
|
||||
TgAiExtractAuthLinkMsg: "验证链接",
|
||||
TgAiExtractServiceLinkMsg: "服务链接",
|
||||
TgAiExtractSubscriptionLinkMsg: "订阅链接",
|
||||
TgAiExtractOtherLinkMsg: "其他链接",
|
||||
}
|
||||
|
||||
export default messages;
|
||||
|
||||
@ -14,6 +14,7 @@ import { RawMailRow } from "../models";
|
||||
import { UserFromGetMe } from "telegraf/types";
|
||||
import i18n from "../i18n";
|
||||
import { LocaleMessages } from "../i18n/type";
|
||||
import type { ExtractResult } from "../email/ai_extract";
|
||||
|
||||
|
||||
// Helper to get messages by userId
|
||||
@ -75,6 +76,62 @@ const COMMANDS = [
|
||||
},
|
||||
]
|
||||
|
||||
const getAiExtractLabel = (
|
||||
msgs: LocaleMessages,
|
||||
type: ExtractResult["type"]
|
||||
): string => {
|
||||
switch (type) {
|
||||
case "auth_code":
|
||||
return msgs.TgAiExtractAuthCodeMsg;
|
||||
case "auth_link":
|
||||
return msgs.TgAiExtractAuthLinkMsg;
|
||||
case "service_link":
|
||||
return msgs.TgAiExtractServiceLinkMsg;
|
||||
case "subscription_link":
|
||||
return msgs.TgAiExtractSubscriptionLinkMsg;
|
||||
case "other_link":
|
||||
return msgs.TgAiExtractOtherLinkMsg;
|
||||
default:
|
||||
return msgs.TgAiExtractResultMsg;
|
||||
}
|
||||
}
|
||||
|
||||
const parseAiExtractMetadata = (
|
||||
metadata: string | undefined | null
|
||||
): ExtractResult | null => {
|
||||
if (!metadata) return null;
|
||||
try {
|
||||
const parsed = JSON.parse(metadata);
|
||||
const result = parsed?.ai_extract;
|
||||
if (
|
||||
result
|
||||
&& typeof result.type === "string"
|
||||
&& result.type !== "none"
|
||||
&& typeof result.result === "string"
|
||||
&& result.result
|
||||
) {
|
||||
return result as ExtractResult;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("Failed to parse AI extraction metadata", error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const formatAiExtractForTelegram = (
|
||||
msgs: LocaleMessages,
|
||||
aiExtract: ExtractResult | null | undefined
|
||||
): string => {
|
||||
if (!aiExtract || aiExtract.type === "none" || !aiExtract.result) {
|
||||
return "";
|
||||
}
|
||||
const label = getAiExtractLabel(msgs, aiExtract.type);
|
||||
const displayText = aiExtract.type !== "auth_code" && aiExtract.result_text
|
||||
? ` (${aiExtract.result_text})`
|
||||
: "";
|
||||
return `${msgs.TgAiExtractResultMsg}\n${label}: ${aiExtract.result}${displayText}\n\n`;
|
||||
}
|
||||
|
||||
export const getTelegramCommands = (c: Context<HonoCustomType>) => {
|
||||
return getBooleanValue(c.env.TG_ALLOW_USER_LANG)
|
||||
? COMMANDS
|
||||
@ -312,7 +369,10 @@ export function newTelegramBot(c: Context<HonoCustomType>, token: string): Teleg
|
||||
const raw = mailRow ? await resolveRawEmail(mailRow) : undefined;
|
||||
const mailId = mailRow?.id;
|
||||
const created_at = mailRow?.created_at;
|
||||
const { mail } = raw ? await parseMail(msgs, { rawEmail: raw }, queryAddress, created_at) : { mail: msgs.TgNoMoreMailsMsg };
|
||||
const aiExtract = parseAiExtractMetadata(mailRow?.metadata);
|
||||
const { mail } = raw
|
||||
? await parseMail(msgs, { rawEmail: raw }, queryAddress, created_at, aiExtract)
|
||||
: { mail: msgs.TgNoMoreMailsMsg };
|
||||
const settings = await c.env.KV.get<TelegramSettings>(CONSTANTS.TG_KV_SETTINGS_KEY, "json");
|
||||
const miniAppButtons = []
|
||||
if (settings?.miniAppUrl && settings?.miniAppUrl?.length > 0 && mailId) {
|
||||
@ -381,7 +441,9 @@ export async function initTelegramBotCommands(c: Context<HonoCustomType>, bot: T
|
||||
const parseMail = async (
|
||||
msgs: LocaleMessages,
|
||||
parsedEmailContext: ParsedEmailContext,
|
||||
address: string, created_at: string | undefined | null
|
||||
address: string,
|
||||
created_at: string | undefined | null,
|
||||
aiExtract?: ExtractResult | null
|
||||
) => {
|
||||
if (!parsedEmailContext.rawEmail) {
|
||||
return {};
|
||||
@ -394,7 +456,8 @@ const parseMail = async (
|
||||
}
|
||||
return {
|
||||
isHtml: false,
|
||||
mail: `From: ${parsedEmail?.sender || msgs.TgNoSenderMsg}\n`
|
||||
mail: formatAiExtractForTelegram(msgs, aiExtract)
|
||||
+ `From: ${parsedEmail?.sender || msgs.TgNoSenderMsg}\n`
|
||||
+ `To: ${address}\n`
|
||||
+ (created_at ? `Date: ${created_at}\n` : "")
|
||||
+ `Subject: ${parsedEmail?.subject}\n`
|
||||
@ -412,7 +475,8 @@ const parseMail = async (
|
||||
export async function sendMailToTelegram(
|
||||
c: Context<HonoCustomType>, address: string,
|
||||
parsedEmailContext: ParsedEmailContext,
|
||||
message_id: string | null
|
||||
message_id: string | null,
|
||||
aiExtract?: ExtractResult | null
|
||||
) {
|
||||
if (!c.env.TELEGRAM_BOT_TOKEN || !c.env.KV) {
|
||||
return;
|
||||
@ -429,7 +493,9 @@ export async function sendMailToTelegram(
|
||||
const bot = newTelegramBot(c, c.env.TELEGRAM_BOT_TOKEN);
|
||||
|
||||
const buildAndSend = async (targetUserId: string, msgs: LocaleMessages) => {
|
||||
const { mail } = await parseMail(msgs, parsedEmailContext, address, new Date().toUTCString());
|
||||
const { mail } = await parseMail(
|
||||
msgs, parsedEmailContext, address, new Date().toUTCString(), aiExtract
|
||||
);
|
||||
if (!mail) return;
|
||||
const attachments = parsedEmailContext.parsedEmail?.attachments || [];
|
||||
const buttons = [];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user