mirror of
https://github.com/muerwre/vk-tg-bot.git
synced 2025-04-25 06:56:40 +07:00
add roll command
This commit is contained in:
parent
6230217741
commit
2a08ec9f86
3 changed files with 150 additions and 2 deletions
107
src/commands/roll.ts
Normal file
107
src/commands/roll.ts
Normal file
|
@ -0,0 +1,107 @@
|
|||
import axios from "axios";
|
||||
|
||||
interface RollResult {
|
||||
distance: number;
|
||||
id: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
const url = `https://backend-map.vault48.org/api/route/random`;
|
||||
const successMessages = [
|
||||
"Вот маршрут для тебя: {link}, {dist}км",
|
||||
"Ну вот есть, например, {link}, всего {dist}км",
|
||||
"Нашёл {link}, всего {dist}км, надо ехать",
|
||||
"Вот, {link}, всего {dist}км, катал его, нет?",
|
||||
];
|
||||
|
||||
const failureMessages = [
|
||||
"Ничего не нашёл 🤷",
|
||||
"Не, такого нет, попробуй снова",
|
||||
"Может, что-то и было такое, но сейчас я не ничего не нашёл.",
|
||||
];
|
||||
|
||||
const say = (vals: string[]) =>
|
||||
vals[Math.floor(Math.random() * (vals.length - 1))];
|
||||
|
||||
const parseVal = (val?: string) => {
|
||||
const parsed = val && parseInt(val, 10);
|
||||
|
||||
if (!parsed || !Number.isFinite(parsed) || parsed <= 0 || parsed >= 10000) {
|
||||
return;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
};
|
||||
|
||||
const escape = (val?: string) => val && val.replace(/([-.\[\]])/g, "\\$1");
|
||||
const deviate = (max: number, factor: number) => [
|
||||
Math.round(max * (1 - factor)),
|
||||
Math.round(max * (1 + factor)),
|
||||
];
|
||||
|
||||
// begin search in range of 80%-120% of specified distance
|
||||
const startDeviation = 0.2;
|
||||
// add 10% each time we haven't found anything
|
||||
const deviationStep = 0.1;
|
||||
// perform this amount of tries, increasing deviation each time we haven't found anything
|
||||
const deviationTries = 8;
|
||||
|
||||
const getRoute = async (
|
||||
min?: number,
|
||||
max?: number
|
||||
): Promise<RollResult | undefined> => {
|
||||
if (!min && !max) {
|
||||
return axios.get<RollResult>(url).then((it) => it.data);
|
||||
}
|
||||
|
||||
if (min && max && min > max) {
|
||||
return axios
|
||||
.get<RollResult>(url, { params: { min: max, max: min } })
|
||||
.then((it) => it.data);
|
||||
}
|
||||
|
||||
if (min && max) {
|
||||
return axios
|
||||
.get<RollResult>(url, { params: { min, max } })
|
||||
.then((it) => it.data);
|
||||
}
|
||||
|
||||
if (!min) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < deviationTries; i += 1) {
|
||||
const deviation = startDeviation + deviationStep * i;
|
||||
|
||||
let [devMin, devMax] = deviate(min, deviation);
|
||||
|
||||
try {
|
||||
return await axios
|
||||
.get<RollResult>(url, { params: { min: devMin, max: devMax } })
|
||||
.then((it) => it.data)
|
||||
.catch();
|
||||
} catch (error) {}
|
||||
}
|
||||
};
|
||||
|
||||
export const roll = async (text: string) => {
|
||||
try {
|
||||
const parts = text.trim().split(" ");
|
||||
|
||||
const result = await getRoute(parseVal(parts[1]), parseVal(parts[2]));
|
||||
|
||||
if (!result || !result?.id) {
|
||||
return say(failureMessages);
|
||||
}
|
||||
|
||||
const link = `https://map.vault48.org/${result.id}`;
|
||||
const distance = result.distance.toFixed(0);
|
||||
const message = say(successMessages);
|
||||
|
||||
return message
|
||||
.replace("{dist}", distance)
|
||||
.replace("{link}", `[${escape(result.title ?? link)}](${escape(link)})`);
|
||||
} catch (error) {
|
||||
console.warn("Error, when trying to fetch random route", error);
|
||||
}
|
||||
};
|
|
@ -6,6 +6,7 @@ import { TelegramApi } from "./api/telegram";
|
|||
import { HttpApi } from "./api/http";
|
||||
import { PostgresDB } from "./service/db/postgres";
|
||||
import { PgTransport } from "./service/db/postgres/loggerTransport";
|
||||
import { roll } from "./commands/roll";
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
|
@ -29,9 +30,11 @@ async function main() {
|
|||
await httpApi.listen();
|
||||
await telegramApi.probe();
|
||||
|
||||
telegram.hears(/\/roll(.*)/, roll);
|
||||
|
||||
logger.info("bot successfully started");
|
||||
} catch (e) {
|
||||
logger.error(`FATAL EXCEPTION ${e.message}`);
|
||||
logger.error(`FATAL EXCEPTION ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ import { ExtraReplyMessage } from "telegraf/typings/telegram-types";
|
|||
|
||||
// import SocksProxyAgent from 'socks-proxy-agent';
|
||||
|
||||
const maxMessageAge = 3 * 60e3; // skip messages older than this seconds
|
||||
|
||||
export class TelegramService {
|
||||
public readonly bot: Telegraf;
|
||||
public readonly webhook: WebhookConfig = {};
|
||||
|
@ -18,7 +20,7 @@ export class TelegramService {
|
|||
telegram: {
|
||||
webhookReply: true,
|
||||
apiMode: "bot",
|
||||
// agent, // TODO: add proxy support
|
||||
// agent, // TODO: add proxy support if they block it
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -158,4 +160,40 @@ export class TelegramService {
|
|||
!!username && !!this.props.owners && this.props.owners.includes(username)
|
||||
);
|
||||
};
|
||||
|
||||
public hears = (
|
||||
what: string | RegExp,
|
||||
callback: (
|
||||
text: string
|
||||
) => string | Promise<string | undefined> | undefined | void
|
||||
) =>
|
||||
this.bot.hears(what, async (ctx) => {
|
||||
let text: string | void | undefined = "%% not received %%";
|
||||
|
||||
try {
|
||||
const age = Date.now() - ctx.message.date * 1000;
|
||||
const message = ctx.update.message.text;
|
||||
|
||||
if (age > maxMessageAge) {
|
||||
console.warn(
|
||||
`skipped message "${message}", since its age ${age / 1000} seconds`
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
text = await callback(message);
|
||||
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.reply(text, { parse_mode: "MarkdownV2" });
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
`error replying to ${what} (${ctx.update.message.text}) with message "${text}"`,
|
||||
error
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue