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