feat(suggestion-box): ✨ referrer
parent
09e1e33de9
commit
ff7c568cfe
|
@ -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("<", "<")
|
.replaceAll('<', '<')
|
||||||
.replaceAll(">", ">")
|
.replaceAll('>', '>')
|
||||||
.replaceAll("&", "&");
|
.replaceAll('&', '&')
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue