Readme

The beating heart of the @ValTownBot on Telegram: https://www.val.town/v/stevekrouse.telegram

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { fetch } from "https://esm.town/v/std/fetch";
import { isValidURL } from "https://esm.town/v/stevekrouse/isValidURL";
import { email } from "https://esm.town/v/std/email?v=9";
import { set } from "https://esm.town/v/std/set?v=11";
import { nanoid } from "https://esm.town/v/stevekrouse/nanoid";
import { telegramSendMessage } from "https://esm.town/v/vtdocs/telegramSendMessage?v=5";
import { telegramValTownBotSecrets } from "https://esm.town/v/stevekrouse/telegramValTownBotSecrets";
import process from "node:process";
export const telegramValTownBotWebhook = async (
req: express.Request,
res: express.Response,
) => {
// Verify this webhook came from our bot
if (
req.get("x-telegram-bot-api-secret-token") !==
process.env.telegramWebhookSecret
) {
return res.status(401);
}
res.status(200).end(); // TODO sometimes we do want telegram to try again, so make this more nuanced
const text: string = req.body.message.text;
const chatId: number = req.body.message.chat.id;
let chat = telegramValTownBotSecrets.find((c) =>
c.chatId === chatId
);
// Helper function to message back the user that triggered this webhook
let messageBack = (message) =>
telegramSendMessage(process.env.telegramBot, {
chat_id: chatId,
text: message,
});
// Save a new user
if (!chat) {
let secret = await nanoid();
telegramValTownBotSecrets.push({
chatId,
secret,
});
await set(
"telegramValTownBotSecrets",
telegramValTownBotSecrets,
);
await email({
text: JSON.stringify(req.body, null, 2),
subject: "New Telegram Bot User!",
});
return messageBack(
`Your secret is ${secret} - Instructions: https://www.val.town/v/stevekrouse.telegram`,
);
}
// Save a webhook
if (chat.settingWebhook) {
chat.settingWebhook = false;
let url = text.trim();
if (!isValidURL(url)) {
return messageBack("Not a valid webhook URL:\n\n" + url);
}
chat.webhook = url;
try {
await fetch(url, { method: "POST", body: JSON.stringify(req.body) });
return messageBack(
"Webhook setup!\n\nWe forwarded your last message to your webhook as a test",
);
}
catch (e) {
return messageBack(
"Webhook setup!\n\nWe forwarded your last message to your webhook as a test, but it errored.",
);
}
}
// Enter webhook-saving mode
if (text === "/webhook") {
chat.settingWebhook = true;
return messageBack(
"What's the URL of the webhook you'd like your messages to go to?",
);
}
if (text === "/roll") {
chat.secret = await nanoid();
return messageBack(
`Your new secret is ${chat.secret} - Instructions: https://www.val.town/v/stevekrouse.telegram`,
);
}
if (text === "/help") {
return messageBack(
"@ValTownBot lets your send and receive Telegram messages from Val Town\n\n/roll - Roll your secret\n/webhook - Register a webhook\n\nLearn more: https://www.val.town/v/stevekrouse.telegram",
);
}
// Send your message to your webhook if you have one set
if (chat.webhook) {
return fetch(chat.webhook, {
method: "POST",
body: JSON.stringify(req.body),
});
}
};
👆 This is a val. Vals are TypeScript snippets of code, written in the browser and run on our servers. Create scheduled functions, email yourself, and persist small pieces of data — all from the browser.