feat(suggestion-box): referrer

pull/448/head
BeiyanYunyi 2024-10-02 19:00:16 +08:00
parent 09e1e33de9
commit ff7c568cfe
No known key found for this signature in database
GPG Key ID: 912D4689CDEE0CD2
1 changed files with 89 additions and 84 deletions

View File

@ -1,130 +1,135 @@
import { Bot, InputFile, InputMediaBuilder } from "grammy"; import type { InputMediaPhoto } from 'grammy/types'
import { InputMediaPhoto } from "grammy/types"; import type { ENV } from './types'
import { Hono } from "hono"; import { Bot, InputFile, InputMediaBuilder } from 'grammy'
import { env } from "hono/adapter"; import { Hono } from 'hono'
import { handle } from "hono/cloudflare-pages"; import { env } from 'hono/adapter'
import { ENV } from "./types"; import { handle } from 'hono/cloudflare-pages'
const IP_HEADER = "CF-Connecting-IP"; const IP_HEADER = 'CF-Connecting-IP'
const newSuccess = (message = "success") => ({ code: 0, message }); const newSuccess = (message = 'success') => ({ code: 0, message })
const newError500 = (message = "server internal error") => ({ function newError500(message = 'server internal error') {
return {
code: 500.001, code: 500.001,
message, message,
}); }
const newErrorFormat400 = ( }
message = "The data format of the request is invalid. Please check and use the correct data format." function newErrorFormat400(message = 'The data format of the request is invalid. Please check and use the correct data format.') {
) => ({ code: 400.001, message }); return { code: 400.001, message }
}
const app = new Hono(); const app = new Hono()
app.onError((err, c) => { app.onError((err, c) => {
console.error(String(err)); console.error(String(err))
return c.json(newError500(), 500); return c.json(newError500(), 500)
}); })
app.get("/api", (c) => { app.get('/api', (c) => {
return c.text("Hello, Project Trans SuggestionBox!"); return c.text('Hello, Project Trans SuggestionBox!')
}); })
app.post("/api/v1/suggestion", async (c) => { app.post('/api/v1/suggestion', async (c) => {
const { TG_BOT_TOKEN, TG_GROUP_ID } = env<ENV>(c); const { TG_BOT_TOKEN, TG_GROUP_ID } = env<ENV>(c)
if (!TG_BOT_TOKEN) { if (!TG_BOT_TOKEN) {
throw new Error("TG_BOT_TOKEN is not set"); throw new Error('TG_BOT_TOKEN is not set')
} }
if (!TG_GROUP_ID) { if (!TG_GROUP_ID) {
throw new Error("TG_GROUP_ID is not set"); throw new Error('TG_GROUP_ID is not set')
} }
const bot = new Bot(TG_BOT_TOKEN); const bot = new Bot(TG_BOT_TOKEN)
let metaUA = ""; let metaUA = ''
let metaIP = ""; let metaIP = ''
let metaReferrer = ""; let metaReferrer = ''
let contactContent = ""; let contactContent = ''
let textContent = ""; let textContent = ''
const reqImages: File[] = []; const reqImages: File[] = []
const msgImages: InputMediaPhoto[] = []; const msgImages: InputMediaPhoto[] = []
try { try {
const form = await c.req.formData(); const form = await c.req.formData()
metaIP = c.req.header(IP_HEADER) || ""; metaIP = c.req.header(IP_HEADER) || ''
metaReferrer = c.req.header("Referer") || ""; metaReferrer = form.get('referrer') || c.req.header('Referer') || ''
metaUA = c.req.header("User-Agent") || ""; metaUA = c.req.header('User-Agent') || ''
textContent = form.get("textContent") || ""; textContent = form.get('textContent') || ''
contactContent = form.get("contactContent") || ""; contactContent = form.get('contactContent') || ''
reqImages.push(...(form.getAll("images") as unknown as File[])); reqImages.push(...(form.getAll('images') as unknown as File[]))
for (const image of reqImages) { for (const image of reqImages) {
const buffer = new Uint8Array(await image.arrayBuffer()); const buffer = new Uint8Array(await image.arrayBuffer())
const tgInputFile = new InputFile(buffer, image.name); const tgInputFile = new InputFile(buffer, image.name)
msgImages.push(InputMediaBuilder.photo(tgInputFile)); msgImages.push(InputMediaBuilder.photo(tgInputFile))
} }
} catch (error) { }
catch (error) {
// TODO log error // TODO log error
console.error(error); console.error(error)
return c.json(newErrorFormat400(), 400); return c.json(newErrorFormat400(), 400)
} }
const msgs = [`<b>意见箱收到新消息</b>\n`]; const msgs = [`<b>意见箱收到新消息</b>\n`]
msgs.push(`${replaceHtmlTag(textContent)}\n`); msgs.push(`${replaceHtmlTag(textContent)}\n`)
contactContent &&
msgs.push(
`<b>联系方式</b>\n<blockquote><code>${replaceHtmlTag(
contactContent contactContent
)}</code></blockquote>` && msgs.push(
); `<b>联系方式</b>\n<blockquote><code>${replaceHtmlTag(
metaReferrer && contactContent,
msgs.push( )}</code></blockquote>`,
`<b>Referrer</b>\n<blockquote>${replaceHtmlTag( )
metaReferrer metaReferrer
)}</blockquote>` && msgs.push(
); `<b>Referrer</b>\n<blockquote>${replaceHtmlTag(
metaReferrer,
)}</blockquote>`,
)
if (metaIP) { if (metaIP) {
msgs.push( msgs.push(
`<b>IP</b> <i><a href="https://ip.sb/ip/${encodeURIComponent( `<b>IP</b> <i><a href="https://ip.sb/ip/${encodeURIComponent(
metaIP metaIP,
)}">View in Web</a></i>\n<blockquote><code>${replaceHtmlTag( )}">View in Web</a></i>\n<blockquote><code>${replaceHtmlTag(
metaIP metaIP,
)}</code></blockquote>` )}</code></blockquote>`,
); )
} }
if (metaUA) { if (metaUA) {
msgs.push( msgs.push(
`<b>UA</b> <i><a href="https://uaparser.js.org/?ua=${encodeURIComponent( `<b>UA</b> <i><a href="https://uaparser.js.org/?ua=${encodeURIComponent(
metaUA metaUA,
)}">View in Web</a></i>\n<pre><code>${replaceHtmlTag( )}">View in Web</a></i>\n<pre><code>${replaceHtmlTag(
metaUA metaUA,
)}</code></pre>` )}</code></pre>`,
); )
} }
const message = msgs.join("\n"); const message = msgs.join('\n')
if (msgImages.length) { if (msgImages.length) {
msgImages[0].caption = message; msgImages[0].caption = message
msgImages[0].parse_mode = "HTML"; msgImages[0].parse_mode = 'HTML'
} }
try { try {
if (msgImages.length) { if (msgImages.length) {
await bot.api.sendMediaGroup(TG_GROUP_ID, msgImages); await bot.api.sendMediaGroup(TG_GROUP_ID, msgImages)
} else {
await bot.api.sendMessage(TG_GROUP_ID, message, { parse_mode: "HTML" });
} }
return c.json(newSuccess()); else {
} catch (error) { await bot.api.sendMessage(TG_GROUP_ID, message, { parse_mode: 'HTML' })
}
return c.json(newSuccess())
}
catch (error) {
// TODO handle error // TODO handle error
// TODO log error // TODO log error
console.error(error); console.error(error)
throw error; throw error
} }
}); })
export const onRequest = handle(app); export const onRequest = handle(app)
function replaceHtmlTag(str: string) { function replaceHtmlTag(str: string) {
return str return str
.replaceAll("<", "&lt;") .replaceAll('<', '&lt;')
.replaceAll(">", "&gt;") .replaceAll('>', '&gt;')
.replaceAll("&", "&amp;"); .replaceAll('&', '&amp;')
} }