Skip to content

Commit 0d9e000

Browse files
committed
bagr
1 parent 0d9e000 commit 0d9e000

File tree

3 files changed

+98
-78
lines changed

3 files changed

+98
-78
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"deno.enable": true,
3-
"deno.unstable": false,
3+
"deno.unstable": [],
44
"[typescript]": {
55
"editor.defaultFormatter": "esbenp.prettier-vscode"
66
}

server.deno.ts

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,48 +5,50 @@ import { serveDir } from "https://deno.land/std@0.190.0/http/file_server.ts";
55
import {
66
handleRequest as handleTgRequest,
77
handleTgWeb,
8+
RequestEvent,
89
init as tgBotInit,
910
webhookPath as tgWebhookPath,
1011
} from "./tgbot.deno.ts";
1112

1213
const indexContent = new TextDecoder().decode(
13-
await Deno.readFile("index.html"),
14+
await Deno.readFile("index.html")
1415
);
15-
const indxContent = new TextDecoder().decode(
16-
await Deno.readFile("indx.html"),
17-
);
18-
19-
async function handleHttp(conn: Deno.Conn) {
20-
for await (const e of Deno.serveHttp(conn)) {
21-
const start = performance.now();
22-
23-
const mockEvent: Deno.RequestEvent = {
24-
request: e.request,
25-
async respondWith(r) {
26-
const resp = await r;
27-
const end = performance.now();
28-
console.log(
29-
`${
30-
new Date().toISOString()
31-
} ${resp.status} ${e.request.method} ${e.request.url} ${
32-
(end - start).toFixed(1)
33-
}ms`,
34-
);
35-
return await e.respondWith(resp);
36-
},
37-
};
38-
39-
handleEvent(mockEvent)
40-
.then(async (response) => {
41-
if (response !== null) {
42-
await mockEvent.respondWith(response);
43-
}
44-
})
45-
.catch((err) => console.error(err));
46-
}
16+
const indxContent = new TextDecoder().decode(await Deno.readFile("indx.html"));
17+
18+
async function handleHttp(request: Request): Promise<Response> {
19+
const start = performance.now();
20+
21+
let resolve: (value: Response) => void;
22+
const responsePromise = new Promise<Response>((res) => {
23+
resolve = res;
24+
});
25+
26+
const mockEvent: RequestEvent = {
27+
request,
28+
async respondWith(r) {
29+
const resp = await r;
30+
const end = performance.now();
31+
console.log(
32+
`${new Date().toISOString()} ${resp.status} ${request.method} ${
33+
request.url
34+
} ${(end - start).toFixed(1)}ms`
35+
);
36+
resolve(resp);
37+
},
38+
};
39+
40+
handleEvent(mockEvent)
41+
.then(async (response) => {
42+
if (response !== null) {
43+
await mockEvent.respondWith(response);
44+
}
45+
})
46+
.catch((err) => console.error(err));
47+
48+
return await responsePromise;
4749
}
4850

49-
async function handleEvent(e: Deno.RequestEvent): Promise<Response | null> {
51+
async function handleEvent(e: RequestEvent): Promise<Response | null> {
5052
const url = new URL(e.request.url);
5153
if (url.pathname === tgWebhookPath) {
5254
await handleTgRequest(e);
@@ -56,24 +58,16 @@ async function handleEvent(e: Deno.RequestEvent): Promise<Response | null> {
5658
if (url.pathname === "/" || url.pathname === "/index.html") {
5759
return Math.random() < 0.01
5860
? new Response(indxContent, {
59-
headers: {
60-
"content-type": "text/html; charset=utf-8",
61-
},
62-
status: 418,
63-
})
61+
headers: {
62+
"content-type": "text/html; charset=utf-8",
63+
},
64+
status: 418,
65+
})
6466
: new Response(indexContent, {
65-
headers: {
66-
"content-type": "text/html; charset=utf-8",
67-
},
68-
});
69-
}
70-
71-
if (url.pathname === "/postele.html") {
72-
return new Response(posteleContent, {
73-
headers: {
74-
"content-type": "text/html; charset=utf-8",
75-
},
76-
});
67+
headers: {
68+
"content-type": "text/html; charset=utf-8",
69+
},
70+
});
7771
}
7872

7973
if (url.pathname === "/about") {
@@ -117,6 +111,4 @@ async function handleEvent(e: Deno.RequestEvent): Promise<Response | null> {
117111

118112
await tgBotInit();
119113

120-
for await (const conn of Deno.listen({ port: 8000 })) {
121-
handleHttp(conn).catch((err) => console.error(err));
122-
}
114+
Deno.serve({ port: 8000 }, handleHttp);

tgbot.deno.ts

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// deno-lint-ignore-file no-explicit-any
12
// The authors disclaim copyright to this source code (they are ashamed to
23
// admit they wrote it)
34

@@ -14,9 +15,15 @@ const MAIN_CHAT_ID = parseInt(Deno.env.get("TG_MAIN_CHAT_ID")!);
1415
const DOMAIN = Deno.env.get("DOMAIN")!;
1516
const STICEKR_SET_NAME = Deno.env.get("STICKER_SET_NAME")!;
1617
const STICEKR_SET_OWNER = parseInt(Deno.env.get("STICKER_SET_OWNER")!);
18+
const PRINTER_TOKEN = Deno.env.get("PRINTER_TOKEN")!;
1719

1820
export const webhookPath = "/tg-webhook";
1921

22+
export type RequestEvent = {
23+
request: Request;
24+
respondWith(r: Response): Promise<void>;
25+
};
26+
2027
function genRandomToken(bytes: number) {
2128
return btoa(
2229
String.fromCharCode(...crypto.getRandomValues(new Uint8Array(bytes)))
@@ -57,7 +64,7 @@ async function tgCall(
5764
// Apply rate limiting before making the request
5865
await rateLimitedDelay();
5966

60-
let req = await fetch(`https://api.telegram.org/bot${token}/${endpoint}`, {
67+
const req = await fetch(`https://api.telegram.org/bot${token}/${endpoint}`, {
6168
method: "POST",
6269
headers: {
6370
"Content-Type": "application/json",
@@ -66,7 +73,7 @@ async function tgCall(
6673
});
6774

6875
try {
69-
let resp = await req.json();
76+
const resp = await req.json();
7077

7178
// Handle rate limiting with exponential backoff
7279
if (!resp.ok && resp.error_code === 429 && retryCount < maxRetries) {
@@ -91,7 +98,7 @@ async function tgCall(
9198
console.log("Req to", endpoint, "with", options, "failed:", resp);
9299
}
93100
return resp;
94-
} catch (e) {
101+
} catch {
95102
// Handle network errors with exponential backoff
96103
if (retryCount < maxRetries) {
97104
const delay = baseDelay * Math.pow(2, retryCount);
@@ -282,8 +289,9 @@ export async function init() {
282289
);
283290

284291
await tgCall({
285-
text: "prokop hazejici vlastovku",
286-
});
292+
photo: "AgACAgQAAxkBAAIHQmkk0fV6aEF7Rpz_P_DRidFVgittAALWxzEb-Kg4UXc1AknVNzxLAQADAgADeAADNgQ",
293+
chat_id: MAIN_CHAT_ID,
294+
}, "sendPhoto");
287295

288296
Deno.cron("tuuuuuuuuuu", "0 12 * * 3#1", () => {
289297
tgCall({
@@ -294,7 +302,7 @@ export async function init() {
294302
postGeohash();
295303
}
296304

297-
export async function handleRequest(e: Deno.RequestEvent) {
305+
export async function handleRequest(e: RequestEvent) {
298306
if (
299307
e.request.method.toUpperCase() !== "POST" ||
300308
e.request.headers.get("X-Telegram-Bot-Api-Secret-Token") !== webhookUrlToken
@@ -330,7 +338,7 @@ async function processTgUpdate(data: any) {
330338
for await (const data of handleTgUpdate(dato)) {
331339
for await (const dato of handleTgUpdate(data)) {
332340
for await (const data of handleTgUpdate(dato)) {
333-
for await (const dato of handleTgUpdate(data)) {
341+
for await (const _ of handleTgUpdate(data)) {
334342
tgCall({ text: "🔥" });
335343
}
336344
}
@@ -529,6 +537,29 @@ Be grateful for your abilities and your incredible success and your considerable
529537
yield* handleLogo(data, text.slice(6));
530538
}
531539

540+
const trig = "/řekni_tomovi";
541+
if (text.startsWith(trig) && data.message.chat.id === MAIN_CHAT_ID) {
542+
const response = await fetch("https://printomat.slama.dev/submit", {
543+
headers: {
544+
"Content-Type": "application/x-www-form-urlencoded",
545+
},
546+
body: new URLSearchParams({
547+
message: `${data.message.from} říká: ${text.slice(trig.length).trim()}`,
548+
image: "",
549+
token: PRINTER_TOKEN,
550+
}).toString(),
551+
method: "POST",
552+
});
553+
const txt = await response.text();
554+
await tgCall({
555+
chat_id: data.message.chat.id,
556+
reply_to_message_id: data.message.message_id,
557+
text: `Tom říká (${response.status}): ${
558+
/<p>(.*?)<\/p>/.exec(txt)?.[1] ?? txt
559+
}`,
560+
});
561+
}
562+
532563
if (
533564
text.toLowerCase() === "sticker this" &&
534565
data.message.chat.id === MAIN_CHAT_ID
@@ -750,17 +781,16 @@ async function generateLogos(text: string, filename: string) {
750781
const texted = LOGO_TEMPLATE.replace("TEMPLATETEXT", text.trim());
751782
await Deno.writeTextFile(`./static/persistent/logos/${filename}.svg`, texted);
752783
return (
753-
await Deno.run({
754-
cmd: [
755-
"inkscape",
784+
await new Deno.Command("inkscape", {
785+
args: [
756786
`./static/persistent/logos/${filename}.svg`,
757787
"-o",
758788
`./static/persistent/logos/${filename}.png`,
759789
"-w",
760790
LOGO_RENDER_SIZE.toString(),
761791
],
762792
stderr: "null",
763-
}).status()
793+
}).spawn().status
764794
).code;
765795
}
766796

@@ -879,13 +909,13 @@ async function* reportProcessResult(
879909
exitCode: number
880910
) {
881911
const outPath = `${tempDir}/${id}.out`;
882-
const fileProc = Deno.run({
883-
cmd: ["file", "-ib", outPath],
912+
const fileProc = new Deno.Command("file", {
913+
args: ["-ib", outPath],
884914
stdout: "piped",
885-
});
915+
}).spawn();
916+
const out = await fileProc.output();
886917
// need to await the status to not create zombie processes
887-
await fileProc.status();
888-
const mime = decoder.decode(await fileProc.output());
918+
const mime = decoder.decode(out.stdout);
889919
contentTypes.set(id, mime);
890920
const isText =
891921
mime.startsWith("text/") || mime.startsWith("application/json");
@@ -920,17 +950,15 @@ async function handleCallbackQuery(data: any) {
920950
if (cbData.startsWith("kill:")) {
921951
const proc = runningProcesses.get(cbData.slice(5));
922952
if (proc === undefined) return;
923-
const killProc = Deno.run({
924-
cmd: ["rkill", "-9", proc.pid.toString()],
925-
});
926-
await killProc.status();
953+
const killProc = new Deno.Command("rkill", {
954+
args: ["-9", proc.pid.toString()],
955+
}).spawn();
956+
await killProc.status;
927957
return;
928958
}
929959
}
930960

931-
export async function handleTgWeb(
932-
e: Deno.RequestEvent
933-
): Promise<Response | null> {
961+
export async function handleTgWeb(e: RequestEvent): Promise<Response | null> {
934962
const url = new URL(e.request.url);
935963
const path = url.pathname.slice(7);
936964
const ct = contentTypes.get(path);

0 commit comments

Comments
 (0)