Compare commits

...

60 Commits

Author SHA1 Message Date
Ceda EI 2ca39208d9 Merge branch 'main' of https://gitlab.com/ceda_ei/Quadnite-Bot 2024-10-13 20:28:07 +05:30
Ceda EI 7cf9689420 Copy message text for feedback instead of forwarding
Telegram's pseudo-DRM prevents bots from forwarding messages in chats
with "Restrict Saving Content"
2024-10-13 20:26:07 +05:30
Ceda EI 1d5c29564f Merge branch 'main' of https://gitlab.com/ceda_ei/Quadnite-Bot 2024-10-04 12:22:22 +05:30
Ceda EI e3a5f1a67b Change rate limit config
Don't send a message and use the chat as key when possible
2024-10-02 22:39:36 +05:30
Ceda EI 7ea30c8c71 Merge branch 'main' of https://gitlab.com/ceda_ei/Quadnite-Bot 2024-09-30 10:52:54 +05:30
Ceda EI cd374090f2 Merge branch 'feat/ratelimit' into 'main'
feat: add rate limiter middleware

See merge request ceda_ei/Quadnite-Bot!4
2024-09-30 05:22:36 +00:00
Sphericalkat 8274ab0980
feat: add rate limiter middleware
Signed-off-by: Sphericalkat <me@kat.bio>
2024-09-30 10:39:07 +05:30
Ceda EI 3177a1a444 Merge branch 'main' of https://gitlab.com/ceda_ei/Quadnite-Bot 2024-09-30 10:08:02 +05:30
Ceda EI 80a0dbd2d3 Fix crash on failing to send gif 2024-09-30 10:05:45 +05:30
Ceda EI 04268d9e22 Merge branch 'main' of https://gitlab.com/ceda_ei/Quadnite-Bot 2024-08-09 16:34:35 +05:30
Ceda EI 41ae943913 Remove donate link 2024-08-09 16:33:14 +05:30
Ceda EI 579bf67576 Merge branch 'main' of https://gitlab.com/ceda_ei/Quadnite-Bot 2024-04-16 19:16:47 +05:30
Ceda EI bdf52331b1 Add username in feedback 2024-04-16 19:15:54 +05:30
Ceda EI 63dbcba4d8 Merge branch 'main' of https://gitlab.com/ceda_ei/Quadnite-Bot 2024-02-06 18:17:23 +05:30
Ceda EI 5ededd535f Fix typos 2024-02-06 18:16:42 +05:30
Ceda EI 5c5718bc1c Merge remote-tracking branch 'quadnite/main' 2024-01-25 00:43:26 +05:30
Ceda EI 21871c9cd6 Update telegraf to 4.15 2024-01-25 00:38:35 +05:30
Ceda EI c01ad5109d Update commands_list.txt 2024-01-25 00:37:34 +05:30
Ceda EI b91f8102a3 Merge remote-tracking branch 'quadnite/master' 2023-10-19 21:22:28 +05:30
Ceda EI 5f7f1ced01 Match dice for full line optionally as a command 2023-10-19 21:20:20 +05:30
Ceda EI 025a664da5 Merge remote-tracking branch 'quadnite/master' 2023-10-14 23:01:00 +05:30
Ceda EI d844ac8455 Make dice command case-insensitive 2023-10-14 23:00:15 +05:30
Ceda EI 4c7f8f97e9 Merge remote-tracking branch 'quadnite/master' 2023-10-14 22:48:10 +05:30
Ceda EI 69448a1052 Add dice 2023-10-14 21:17:06 +05:30
Ceda EI f44d83c89a Remove questions of the form "... beginning with the letter ..." 2022-01-26 17:43:51 +05:30
Ceda EI 83f6f5c529 Merge branch 'master' of https://gitlab.com/ceda_ei/Quadnite-Bot 2021-11-25 00:08:06 +05:30
Ceda EI ae21f68cc7 Add /donate 2021-11-25 00:05:57 +05:30
Ceda EI 4b8aecf28a Allow aliases in roleplay.json. Add runs, sob, sobs, handhold aliases 2021-10-06 22:59:08 +05:30
Ceda EI f1740ce4c0 Update README 2021-09-28 14:54:05 +05:30
Ceda EI 5ac1c1e4a6 Better logging for ugokiUpload failures 2021-09-27 23:53:59 +05:30
Ceda EI ce9611f079 Move text files to static/ 2021-09-27 23:53:33 +05:30
Ceda EI 7527fb6a1a Use ugoki server instead of hard coded gifs 2021-09-27 22:10:34 +05:30
Ceda EI 159ca9e87d Add /suggest to upload gifs to ugoki api server 2021-09-27 21:36:21 +05:30
Ceda EI 54c06ad7d4 Merge branch 'master' of https://gitlab.com/ceda_ei/Quadnite-Bot 2021-07-18 00:59:29 +05:30
Ceda EI 4878274656 Fix typo in /bonk message 2021-07-18 00:57:42 +05:30
Ceda EI e06c85f448 Merge branch 'master' of https://gitlab.com/ceda_ei/Quadnite-Bot 2021-07-09 13:22:56 +05:30
Ceda EI f0a918f77e Allow roleplay to include a user via reply 2021-07-09 13:22:01 +05:30
Ceda EI 9b41271e85 Merge branch 'master' of https://gitlab.com/ceda_ei/Quadnite-Bot 2021-06-22 19:06:52 +05:30
Ceda EI 463d9c254b Update gif URLs to self hosted gifs 2021-06-22 19:04:30 +05:30
Ceda EI fde5830309 Update /commands to include new commands 2021-06-21 23:18:13 +05:30
Ceda EI 71e6f6927d Add roleplay commands 2021-06-21 23:17:45 +05:30
Ceda EI bbc7a7d398 Merge branch 'master' of https://gitlab.com/ceda_ei/Quadnite-Bot 2020-11-25 18:58:35 +05:30
Ceda EI 6da0e12171 Add insults suggested by @piratecaveman 2020-11-25 18:57:10 +05:30
Ceda EI 3926f3e550 Merge branch 'master' of https://gitlab.com/ceda_ei/Quadnite-Bot 2020-11-20 21:57:17 +05:30
Ceda EI b0eff87e72 Fix untested code with more untested code 2020-11-20 21:56:16 +05:30
Ceda EI 472c7489f9 Merge branch 'master' of https://gitlab.com/ceda_ei/Quadnite-Bot 2020-11-20 21:50:55 +05:30
Ceda EI 9024ec65f9 Use all args of /insult and /kys as name 2020-11-20 21:44:14 +05:30
Ceda EI 53dda834f9 Add /g to replace multiple spaces. 2020-04-23 20:33:48 +05:30
Ceda EI af56ffbbb3 Build dict for /expand. Replace multiple spaces with single space. 2020-04-23 20:30:19 +05:30
Ceda EI 382579ba3f Ignore 's words in /expand. Return letter if nothing starting with it is found. 2020-04-23 20:10:37 +05:30
Ceda EI 8f16112b2e Add /expand to commands_list 2020-04-22 21:59:33 +05:30
Ceda EI 72e69b7ac1 Add /expand 2020-04-22 21:56:31 +05:30
Ceda EI 3ed015b584 Fix typo firstName -> first_name 2020-04-19 18:17:12 +05:30
Ceda EI 77270db9b4 Alternate start text for octanite. 2019-07-17 14:52:12 +05:30
Ceda EI 2914321b3c Fix typo in kys.txt 2019-03-24 23:45:22 +05:30
Ceda EI 375f032b97 Add package-lock and catch errors 2019-03-04 14:48:26 +05:30
Ceda EI dcf77e56a3 Remove empty lines from questions.txt 2019-02-18 22:35:40 +05:30
Ceda EI e4311467b3 Fix wrong date in /info 2019-02-14 20:01:02 +05:30
Ceda EI bd2f38679c Add /start 2019-02-14 19:00:19 +05:30
Ceda EI 59e8db799a Merge branch 'node_port' into 'master'
Node port

See merge request ceda_ei/Quadnite-Bot!3
2019-02-14 13:16:28 +00:00
24 changed files with 1407 additions and 226 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
node_modules
data/*
!data/.gitkeep

View File

@ -1,2 +1,18 @@
# Quadnite-Bot
Source code for @quadnite_bot
Source code for [@quadnite\_bot](https://t.me/quadnite_bot)
## Running your own instance
Quadnite bot depends on [Ugoki](https://gitlab.com/ceda_ei/ugoki) for providing
roleplay gifs. Once you have an instance of Ugoki (and optionally
[Ugoki Frontend](https://gitlab.com/ceda_ei/ugoki-frontend)) running:
- Clone this repo
- `npm install`
- `export BOT_API_KEY="your-token-for-bot"`
- `export FEEDBACK_ID="chat-id-where-feedback-is-forwarded-to"`
- `export UGOKI_ROOT="https://root.of.ugoki.api/server/"`
- `export RATE_TIMEFRAME=5000 # rate limit time interval in milliseconds`
- `export RATE_LIMIT=5 # number of requests allowed in the timeframe`
- `npm start`

17
bot.js
View File

@ -1,10 +1,19 @@
const Telegraf = require("telegraf");
const { BOT_API_KEY, FEEDBACK_ID } = process.env;
const { Telegraf } = require("telegraf");
const { BOT_API_KEY, FEEDBACK_ID, UGOKI_ROOT, RATE_TIMEFRAME, RATE_LIMIT } = process.env;
const fs = require("fs").promises;
const commands = require("./commands");
const axios = require("axios");
const roleplay = require("./static/roleplay.json");
const { limit } = require("@grammyjs/ratelimiter");
const bot = new Telegraf(BOT_API_KEY);
bot.catch((err) => console.log(err));
bot.use(limit({
// default config: 1 message per 1 second
timeFrame: RATE_TIMEFRAME ?? 1000,
limit: RATE_LIMIT ?? 1,
keyGenerator: (ctx) => ctx.chat?.id.toString() ?? ctx.from?.id.toString(),
}))
const data = [
"questions",
@ -13,12 +22,12 @@ const data = [
"commands_list",
"words"
].map(file =>
fs.readFile(file + ".txt", "utf-8")
fs.readFile("static/" + file + ".txt", "utf-8")
.then(list =>
list.split("\n")));
Promise.all(data)
.then(data =>
commands(bot, data, FEEDBACK_ID, axios));
commands(bot, [...data, roleplay], FEEDBACK_ID, BOT_API_KEY, UGOKI_ROOT, axios));
bot.launch();

View File

@ -16,7 +16,7 @@ module.exports = () => (ctx) => {
} else {
if (ctx.message.reply_to_message)
if (ctx.message.reply_to_message && !ctx.message.reply_to_message.is_topic_message)
return absurdify(ctx.message.reply_to_message.text);
else
return "Need text to absurdify. Send /absurdify text or reply to a"

31
commands/dice.js Normal file
View File

@ -0,0 +1,31 @@
function diceRoll(side) {
return Math.ceil(Math.random() * side);
}
module.exports = () => async (ctx) => {
const numDice = parseInt(ctx.match[1] || "1");
const diceSides = parseInt(ctx.match[2]);
const rolls = Array(numDice)
.fill(0)
.map(() => diceRoll(diceSides));
const total = rolls.reduce((acc, curr) => acc + curr, 0);
const message = rolls
.map((i) => `_You roll a_ *D${diceSides}* _and get a_ *${i}*`)
.join("\n");
let totalMessage = "";
if (numDice > 1 || ctx.match[4])
totalMessage = `*Total:* ${total}`;
if (ctx.match[4]) {
const modifier = parseInt(ctx.match[6]);
const sign = ctx.match[5];
if (sign === "+") totalMessage += ` + ${modifier} = ${total + modifier}`;
else totalMessage += ` - ${modifier} = ${total - modifier}`;
}
ctx.reply(message + "\n\n" + totalMessage, { parse_mode: "Markdown" });
};

48
commands/expand.js Normal file
View File

@ -0,0 +1,48 @@
function expand(words, text) {
const letters = text.trim().toLowerCase().split("");
// Build a dictionary with lowercase letters as keys
const dict = {};
words.forEach(word => {
if (word == "")
return;
const initial = word.split("")[0].toLowerCase();
if (initial in dict)
dict[initial].push(word);
else
dict[initial] = [word];
});
return letters.map((letter) => {
if (!(letter.toLowerCase() in dict))
return letter;
const wordsWithLetter = dict[letter.toLowerCase()];
const word = wordsWithLetter[Math.floor(Math.random() * wordsWithLetter.length)];
return word;
}).reduce((acc, cur) => acc + " " + cur).replace(/\s{2,}/g, " ");
}
module.exports = (words = []) => (ctx) => {
words = words.filter(i => ! i.match(/'s$/));
const message = ctx.message.text.replace(/^[^ ]+/, "");
if (message) {
return expand(words, message);
} else {
if (ctx.message.reply_to_message && !ctx.message.reply_to_message.is_topic_message)
return expand(words, ctx.message.reply_to_message.text);
else
return "Need text to expand. Send /expand text or reply to a "
+ "message with /expand";
}
};

View File

@ -1,14 +1,27 @@
module.exports = (feedback_id) => (ctx) => {
module.exports = (bot, feedback_id) => (ctx) => {
const message = ctx.message.text.replace(/^[^ ]+/, "");
if (message) {
ctx.forwardMessage(feedback_id);
return "Thanks for the feedback";
const from = ctx.message.from;
let contactable = "The developer might contact you regarding your feedback.";
let message;
if (from.username) {
message = `Feedback from: @${from.username}`;
} else {
contactable = "The developer might not be able to contact you due to lack of your username.";
message = `Feedback from User ${from.id}`;
}
bot.telegram.sendMessage(feedback_id, `${message} ${ctx.message.text}`).catch(console.log);
return `Thanks for the feedback! ${contactable}`;
} else {
return "To send feedback type in /feedback followed by the feedback";
return "To send feedback type in /feedback followed by the feedback. Note that developers may contact you regarding the feedback.";
}

View File

@ -7,9 +7,12 @@ const absurdify = require("./absurdify");
const feedback = require("./feedback");
const media_wiki = require("./media_wiki");
const info = require("./info");
const expand = require("./expand");
const roleplay = require("./roleplay");
const suggest = require("./suggest");
const dice = require("./dice");
module.exports = (bot, [ questions, kys, insults, commands_list, words ],
feedback_id, axios) => {
module.exports = (bot, [ questions, kys, insults, commands_list, words, roleplay_data ], feedback_id, apiToken, ugokiRoot, axios) => {
bot.command("question", (ctx) => ctx.reply(random(questions)()));
bot.command("word", (ctx) => ctx.reply(random(words)()));
@ -18,7 +21,7 @@ module.exports = (bot, [ questions, kys, insults, commands_list, words ],
.then(bot_user => {
const default_text = (command, text) => `Do you want to ${text} `
+ `yourself?\nIf no, reply to someone with /${command} to kill`
+ `yourself?\nIf no, reply to someone with /${command} to ${command}`
+ ` them or run /${command} username/name.\nYou can suggest `
+ `more /${command} replies using /feedback`;
@ -32,7 +35,7 @@ module.exports = (bot, [ questions, kys, insults, commands_list, words ],
});
bot.command("commands", (ctx) => ctx.reply(commands_list.join("\n")));
bot.command("commands", (ctx) => ctx.reply(commands_list.join("\n"), {parse_mode: "html"}));
bot.command("is", (ctx) => ctx.reply(is(random)(ctx)));
bot.command("are", (ctx) => ctx.reply(is(random)(ctx)));
bot.command("can", (ctx) => ctx.reply(is(random)(ctx)));
@ -52,7 +55,7 @@ module.exports = (bot, [ questions, kys, insults, commands_list, words ],
"Markdown"}));
bot.command("weebify", (ctx) => ctx.reply(weebify()(ctx)));
bot.command("absurdify", (ctx) => ctx.reply(absurdify()(ctx)));
bot.command("feedback", (ctx) => ctx.reply(feedback(feedback_id)(ctx)));
bot.command("feedback", (ctx) => ctx.reply(feedback(bot, feedback_id)(ctx)));
bot.command("wiki", (ctx) => media_wiki(axios,
"https://en.wikipedia.org/w/api.php")(ctx).then(x => ctx.reply(x,
{parse_mode: "HTML"})));
@ -60,5 +63,40 @@ module.exports = (bot, [ questions, kys, insults, commands_list, words ],
"https://wiki.archlinux.org/api.php")(ctx).then(x => ctx.reply(x,
{parse_mode: "HTML"})));
bot.command("info", (ctx) => ctx.reply(info()(ctx), {parse_mode: "Markdown"}));
bot.command("expand", (ctx) => ctx.reply(expand(words)(ctx)));
bot.command("start", (ctx) => ctx.reply("Hi! I'm Octanite. Sibling of @quadnite_bot. My creator @ceda_ei created me as 'another option' to users who want the bot in their groups to have privacy mode enabled. \n\nPrivacy mode? Wut is that?\n- Well basically disabling privacy mode enables a bot to read all the messages. @quadnite_bot has that disabled. Enabling privacy mode causes the bot to not recieve messages at some times. To circumvet that, you need to append @octanite_bot to your commands or simply use @quadnite_bot. \n\n[P.S. - My creator doesn't store any messages or personal data. It's safe to use any of the two bots.]\nTo give feedback, use /feedback"));
bot.hears(/^\/?(\d*)d(\d+)(@\w+)?(\s*([-+])\s*(\d+))?$/i, dice());
function getGetGif(command) {
const alias = roleplay_data[command].alias;
if (alias)
return getGetGif(alias);
return () => axios.get(
`category/${command}/gif`,
{
baseURL: ugokiRoot
}
);
}
function getForms(name) {
if (roleplay_data[name].forms)
return roleplay_data[name].forms;
return getForms(roleplay_data[name].alias);
}
// Add all roleplay commands
Object.keys(roleplay_data).map(command =>
bot.command(command,
(ctx) => roleplay(getForms(command), getGetGif(command))(ctx)
)
);
bot.command("suggest", (ctx) => suggest(axios, apiToken, ugokiRoot)(ctx));
};

View File

@ -5,7 +5,7 @@ module.exports = () => (ctx) => {
text += `Message ID: \`${msg.message_id}\`\n`;
text += `Chat ID: \`${msg.chat.id}\`\n`;
text += `User ID: \`${msg.from.id}\`\n`;
if (msg.reply_to_message) {
if (ctx.message.reply_to_message && !ctx.message.reply_to_message.is_topic_message) {
const reply = msg.reply_to_message;
text += "\n*Reply to*\n";
@ -24,7 +24,7 @@ module.exports = () => (ctx) => {
text += "Channel ID: ";
text += `\`${forward.id}\`\n`;
text += "Message Date: `";
const date = new Date(reply.forward_date);
const date = new Date(reply.forward_date*1000);
text += date.toUTCString();
text += "`";

View File

@ -1,9 +1,9 @@
module.exports = (random, kys, default_text, bot_text, excluded_names) => (ctx) => {
if (ctx.message.reply_to_message) {
if (ctx.message.reply_to_message && !ctx.message.reply_to_message.is_topic_message) {
const { from } = ctx.message.reply_to_message;
const name = from.username ? "@" + from.username : from.firstName;
const name = from.username ? "@" + from.username : from.first_name;
if (name == excluded_names[0])
return bot_text;
return random(kys)().replace(/##name##/g, name);
@ -13,7 +13,7 @@ module.exports = (random, kys, default_text, bot_text, excluded_names) => (ctx)
const text_array = ctx.message.text.split(" ");
if (text_array.length > 1) {
const name = text_array[1];
const name = text_array.slice(1).reduce((i, j) => i + " " + j).trim();
if (excluded_names.includes(name)
|| excluded_names.includes("@" + name))
return bot_text;

44
commands/roleplay.js Normal file
View File

@ -0,0 +1,44 @@
function joinUsers(users) {
if (users.length == 1)
return users[0];
return users.slice(0, users.length - 1).join(", ")
+ ` and ${users[users.length - 1]}`;
}
module.exports = (forms, getGif) => (ctx) => {
const message = ctx.message.text.replace(/^[^ ]+\s*/, "")
.match(/^((@\w+(\s+|$))*)(.*)/);
const users = message[1].trim().split(" ").filter(i => i.length);
const rtm = ctx.message.reply_to_message;
if (rtm && !rtm.is_topic_message)
users.push(rtm.from.username ? "@" + rtm.from.username
: rtm.from.first_name);
const reason = message[4];
let reply = "";
const from = ctx.message.from;
const user = from.username ? "@" + from.username : from.first_name;
if (users.length > 0 && reason.length > 0)
reply = forms.both
.replace("{}", user)
.replace("{}", joinUsers(users))
.replace("{}", reason);
else if (users.length > 0)
reply = forms.others
.replace("{}", user)
.replace("{}", joinUsers(users));
else if (reason.length > 0)
reply = forms.reason
.replace("{}", user)
.replace("{}", reason);
else
reply = forms.none
.replace("{}", user);
return getGif()
.then(gif => ctx.replyWithAnimation(gif.data.url, {caption: reply}));
};

84
commands/suggest.js Normal file
View File

@ -0,0 +1,84 @@
const ffmpeg = require("fluent-ffmpeg");
const fs = require("fs");
const FormData = require("form-data");
function ugokiUpload(axios, ugokiRoot, ctx, category, path) {
const form = new FormData();
form.append("file", fs.createReadStream(path));
return axios.post(`new_suggestion/${category}`, form,
{ headers: form.getHeaders(), baseURL: ugokiRoot })
.then(() => {
ctx.reply("Suggestion added.");
fs.unlink(path, () => {});
})
.catch((err) => {
console.error(err);
if (err.response && err.response.status == 404)
ctx.reply("Category doesn't exist");
else if (err.response && err.response.status == 409)
ctx.reply("Already suggested / added.");
else
ctx.reply("No clue what the hell happened but adding suggestion failed.");
});
}
module.exports = (axios, apiToken, ugokiRoot) => (ctx) => {
const category = ctx.message.text.split(" ")[1];
const reply = ctx.message.reply_to_message;
if (category && reply && reply.animation) {
return ctx.telegram.getFile(reply.animation.file_id)
.then(resp => {
return axios({
method: "get",
url: `https://api.telegram.org/file/bot${apiToken}/${resp.file_path}`,
responseType: "stream"
})
.then(async (response) => {
let stream = response.data;
let path = `data/${resp.file_unique_id}`;
const writer = fs.createWriteStream(path);
if (!resp.file_path.match(/\.gif$/)) {
await stream.pipe(writer);
stream = ffmpeg(path)
.on("error", function () {
fs.unlink(path, () => {});
ctx.reply("Something went wrong processing the gif");
})
.on("end", function () {
fs.unlink(path, () => {});
ugokiUpload(axios, ugokiRoot, ctx, category, path + ".gif");
})
.output(path + ".gif")
.outputFormat("gif")
.run();
} else
ugokiUpload(axios, ugokiRoot, category, ctx, path);
}
);
});
} else
ctx.reply("Reply to a gif with /suggest [category] "
+ "to suggest it to be used for [category]");
};

View File

@ -44,7 +44,7 @@ module.exports = () => (ctx) => {
} else {
if (ctx.message.reply_to_message)
if (ctx.message.reply_to_message && !ctx.message.reply_to_message.is_topic_message)
return weebify(ctx.message.reply_to_message.text);
else
return "Need text to weebify. Send /weebify text or reply to a "

View File

@ -1,23 +0,0 @@
question - Get a random question
word - Get a random word
words - Get n random words
kys - Kill yourself
coin - Tosses a coin
wiki - Search Wikipedia
arch_wiki - Search the Arch wiki
insult - As expected, insults
weebify - Weebifies the given text
absurdify - mAke tExT aBSUrd
is - Is <your question>
are - Are <your question>
can - Can <your question>
will - will <your question>
shall - shall <your question>
was - Was <your question>
do - Do <your question>
does - Does <your question>
did - Did <your question>
should - Should <your question>
help - Need help? Go here
feedback - Send feedback, suggestion for kys, insult text
rate - Rate me on TGDR

0
data/.gitkeep Normal file
View File

499
package-lock.json generated Normal file
View File

@ -0,0 +1,499 @@
{
"name": "quadnite-bot",
"version": "2.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "quadnite-bot",
"version": "2.0.0",
"license": "GPL-3.0",
"dependencies": {
"@grammyjs/ratelimiter": "^1.2.0",
"axios": "^0.21.0",
"fluent-ffmpeg": "^2.1.2",
"form-data": "^4.0.0",
"telegraf": "^4.15.3"
}
},
"node_modules/@grammyjs/ratelimiter": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@grammyjs/ratelimiter/-/ratelimiter-1.2.0.tgz",
"integrity": "sha512-xBkH/ATJsuv5JgVYX9yQM9DNg75Qqjw+gh82lVsBn4j+d0DkxxC+kuy6WFoB96Cb6oifQfaBJL8CTikdYG4v0A=="
},
"node_modules/@telegraf/types": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/@telegraf/types/-/types-6.9.1.tgz",
"integrity": "sha512-bzqwhicZq401T0e09tu8b1KvGfJObPmzKU/iKCT5V466AsAZZWQrBYQ5edbmD1VZuHLEwopoOVY5wPP4HaLtug=="
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"dependencies": {
"event-target-shim": "^5.0.0"
},
"engines": {
"node": ">=6.5"
}
},
"node_modules/async": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz",
"integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
},
"node_modules/buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"dependencies": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"node_modules/buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
},
"node_modules/buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ=="
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"engines": {
"node": ">=6"
}
},
"node_modules/fluent-ffmpeg": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
"integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
"dependencies": {
"async": ">=0.2.9",
"which": "^1.1.1"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/follow-redirects": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"node_modules/mime-db": {
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
"integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.32",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz",
"integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==",
"dependencies": {
"mime-db": "1.49.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"engines": {
"node": ">=4"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/p-timeout": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
"integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==",
"engines": {
"node": ">=10"
}
},
"node_modules/safe-compare": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/safe-compare/-/safe-compare-1.1.4.tgz",
"integrity": "sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==",
"dependencies": {
"buffer-alloc": "^1.2.0"
}
},
"node_modules/sandwich-stream": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-2.0.2.tgz",
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/telegraf": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.15.3.tgz",
"integrity": "sha512-pm2ZQAisd0YlUvnq6xdymDfoQR++8wTalw0nfw7Tjy0va+V/0HaBLzM8kMNid8pbbt7GHTU29lEyA5CAAr8AqA==",
"dependencies": {
"@telegraf/types": "^6.9.1",
"abort-controller": "^3.0.0",
"debug": "^4.3.4",
"mri": "^1.2.0",
"node-fetch": "^2.6.8",
"p-timeout": "^4.1.0",
"safe-compare": "^1.1.4",
"sandwich-stream": "^2.0.2"
},
"bin": {
"telegraf": "lib/cli.mjs"
},
"engines": {
"node": "^12.20.0 || >=14.13.1"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"which": "bin/which"
}
}
},
"dependencies": {
"@grammyjs/ratelimiter": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@grammyjs/ratelimiter/-/ratelimiter-1.2.0.tgz",
"integrity": "sha512-xBkH/ATJsuv5JgVYX9yQM9DNg75Qqjw+gh82lVsBn4j+d0DkxxC+kuy6WFoB96Cb6oifQfaBJL8CTikdYG4v0A=="
},
"@telegraf/types": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/@telegraf/types/-/types-6.9.1.tgz",
"integrity": "sha512-bzqwhicZq401T0e09tu8b1KvGfJObPmzKU/iKCT5V466AsAZZWQrBYQ5edbmD1VZuHLEwopoOVY5wPP4HaLtug=="
},
"abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"requires": {
"event-target-shim": "^5.0.0"
}
},
"async": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz",
"integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg=="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
"follow-redirects": "^1.14.0"
}
},
"buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"requires": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
},
"buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ=="
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"requires": {
"ms": "2.1.2"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
},
"fluent-ffmpeg": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
"integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
"requires": {
"async": ">=0.2.9",
"which": "^1.1.1"
}
},
"follow-redirects": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"mime-db": {
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
"integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA=="
},
"mime-types": {
"version": "2.1.32",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz",
"integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==",
"requires": {
"mime-db": "1.49.0"
}
},
"mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"p-timeout": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
"integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw=="
},
"safe-compare": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/safe-compare/-/safe-compare-1.1.4.tgz",
"integrity": "sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==",
"requires": {
"buffer-alloc": "^1.2.0"
}
},
"sandwich-stream": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-2.0.2.tgz",
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ=="
},
"telegraf": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.15.3.tgz",
"integrity": "sha512-pm2ZQAisd0YlUvnq6xdymDfoQR++8wTalw0nfw7Tjy0va+V/0HaBLzM8kMNid8pbbt7GHTU29lEyA5CAAr8AqA==",
"requires": {
"@telegraf/types": "^6.9.1",
"abort-controller": "^3.0.0",
"debug": "^4.3.4",
"mri": "^1.2.0",
"node-fetch": "^2.6.8",
"p-timeout": "^4.1.0",
"safe-compare": "^1.1.4",
"sandwich-stream": "^2.0.2"
}
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"requires": {
"isexe": "^2.0.0"
}
}
}
}

View File

@ -1,10 +1,10 @@
{
"name": "quadnite-bot",
"version": "1.0.0",
"version": "2.0.0",
"description": "A Telegram bot that makes chats in group more fun.",
"main": "bot.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"start": "node bot.js"
},
"repository": {
"type": "git",
@ -22,7 +22,10 @@
},
"homepage": "https://gitlab.com/ceda_ei/Quadnite-Bot#readme",
"dependencies": {
"axios": "^0.18.0",
"telegraf": "^3.27.1"
"@grammyjs/ratelimiter": "^1.2.0",
"axios": "^0.21.0",
"fluent-ffmpeg": "^2.1.2",
"form-data": "^4.0.0",
"telegraf": "^4.15.3"
}
}

View File

@ -1,81 +0,0 @@
dependencies:
axios: 0.18.0
telegraf: 3.27.1
packages:
/@types/node/10.12.24:
dev: false
resolution:
integrity: sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ==
/axios/0.18.0:
dependencies:
follow-redirects: 1.6.1
is-buffer: 1.1.6
dev: false
resolution:
integrity: sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=
/debug/3.1.0:
dependencies:
ms: 2.0.0
dev: false
resolution:
integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
/debug/4.1.1:
dependencies:
ms: 2.1.1
dev: false
resolution:
integrity: sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
/follow-redirects/1.6.1:
dependencies:
debug: 3.1.0
dev: false
engines:
node: '>=4.0'
resolution:
integrity: sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==
/is-buffer/1.1.6:
dev: false
resolution:
integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
/ms/2.0.0:
dev: false
resolution:
integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
/ms/2.1.1:
dev: false
resolution:
integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
/node-fetch/2.3.0:
dev: false
engines:
node: 4.x || >=6.0.0
resolution:
integrity: sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==
/sandwich-stream/2.0.2:
dev: false
engines:
node: '>= 0.10'
resolution:
integrity: sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==
/telegraf/3.27.1:
dependencies:
'@types/node': 10.12.24
debug: 4.1.1
node-fetch: 2.3.0
sandwich-stream: 2.0.2
telegram-typings: 3.6.1
dev: false
engines:
node: '>=6.2.0'
resolution:
integrity: sha512-RQUnuNAEEWcLhRap81qwGUUqAy1KcvqANnA0G3pzZqFkhMe6LrTk5lVi9tdOaF0Ud/yOx5fdx0rNPYfiB27Z+w==
/telegram-typings/3.6.1:
dev: false
resolution:
integrity: sha512-njVv1EAhIZnmQVLocZEADYUyqA1WIXuVcDYlsp+mXua/XB0pxx+PKtMSPeZ/EE4wPWTw9h/hA9ASTT6yQelkiw==
registry: 'https://registry.npmjs.org/'
shrinkwrapMinorVersion: 9
shrinkwrapVersion: 3
specifiers:
axios: ^0.18.0
telegraf: ^3.27.1

71
static/commands_list.txt Normal file
View File

@ -0,0 +1,71 @@
<b>Random</b>
coin - Tosses a coin
wiki - Search Wikipedia
arch_wiki - Search the Arch wiki
kys - Kill yourself
insult - As expected, insults
<b>Wordplay</b>
question - Get a random question
word - Get a random word
words - Get n random words
weebify - Weebifies the given text
absurdify - mAke tExT aBSUrd
expand - Expands a given abbreviation
<b>Ask a question</b>
<code>
is are can
will did shall
was do does
should
</code>
<b>Roleplay</b>
<code>
angry bite
blush bored
bonk boop
chase cheer
cringe cry
cuddle dab
dance die
eat facepalm
feed glomp
happy hate
holdhands hide
highfive hug
kill kiss
laugh lick
love lurk
nervous no
nom nuzzle
panic pat
peck poke
pout run
shoot shrug
sip slap
sleep snuggle
stab tease
think thumbsup
tickle triggered
twerk wag
wave wink
yes
</code>
<b>Miscellaneous</b>
help - Need help? Go here
feedback - Send feedback, suggestions for kys, insult text
rate - Rate me on TGDR
<b>Dice</b>
<code>[num]d[sides] [modifier]</code>
<i>num</i> is the number of the dices to roll. (Optional)
<i>sides</i> is the number of sides of the dice. (Required)
<i>modifier</i> is in the form of + or - followed by a number. (Optional)
<i>Examples</i>: 1d6, 2d10 + 5, 3d20 - 2, 2d20

View File

@ -67,3 +67,20 @@ Everyone has the right to be stupid but ##name## is abusing the privilege.
##name## Id tell you how I really feel, but I wasnt born with enough middle fingers to express myself in this case.
##name## Stupiditys not a crime, so feel free to go.
##name## Id tell you to go fuck yourself, but that would be cruel and unusual punishment.
I've finally found how ##name## is related to their pants, they're both full of shit.
There has been a rumor going around about ##name## acting like a dumbass. They're not acting.
##name## calling you an idiot would be an insult to stupid people.
##name## you know how laughter is supposed to be the best medicine? I'm surprised you haven't received an award for your face.
##name## you're the reason why shampoo bottles need directions.
They say trash takes 10-1000 years to go away, I sure hope you're going for a speedrun ##name##.
##name## makes me wish I had less eyes and ears.
##name## if you ran as much as your mouth maybe people would actually like you.
##name## mother nature takes pity on you.
If I had a face like ##name##'s I would file a lawsuit against my parents.
##name## I'm glad to see you finally graduated kindergarten.....oh no, I'm sorry I thought-
It makes me really sad to see how much time it takes ##name## to get ready in the morning, not that it makes much of a difference.
##name## I would try to insult you but it would take you the rest of the day to figure it out.
##name## I'm surprised your portraits don't hang themselves.
Many people think ##name## is a vampire because their reflection quit on the first day.
##name## you make satan consider going to church.
When god said 'Let there be light' he should have reconsidered after meeting ##name##.

View File

@ -26,7 +26,7 @@
##name## You should try playing snake and ladders, with real snakes and no ladders.
##name## Dance naked on a couple of HT wires.
##name## An active volcano is the best swimming pool for you.
##name## You shoulf try hot bath in a volcano.
##name## You should try hot bath in a volcano.
##name## Try to spend one day in a coffin and it will be yours forever.
##name## Hit Uranium with a slow moving neutron in your presence. It will be a worthwhile experience.
##name## You can be the first person to step on the sun. Have a try.

View File

@ -1,4 +1,3 @@
name?
How old are you?
Whats your Birthday?
What starsign does that make it?
@ -606,32 +605,32 @@ On a scale of 1-10 how bitchy would you say you are?
On a scale of 1-10 how polite would you say you are?
On a scale of 1-10 how attractive would you say you are?
If you could be any famous person who would you be and why?
Whats your favourite animal beginning with the letter A?
Whats your favourite item of clothing beginning with the letter B?
Whats your favourite expleitive beginning with the letter C?
Whats your favourite boys name beginning with the letter D?
Whats your favourite girls name beginning with the letter E?
Whats your favourite book beginning with the letter F?
Whats your favourite bodypart beginning with the letter G?
Whats your favourite musical instrument beginning with the letter H?
Whats your favourite song beginning with the letter I?
Whats your favourite actress beginning with the letter J?
Whats your favourite actor beginning with the letter K?
Whats your favourite film beginning with the letter L?
Whats your favourite tv show beginning with the letter M?
Whats your favourite game beginning with the letter N?
Whats your favourite non alcoholic drink beginning with the letter O?
Whats your favourite food beginning with the letter P?
Whats your favourite band beginning with the letter Q?
Whats your favourite author beginning with the letter R?
Whats your favourite sport beginning with the letter S?
Whats your favourite job beginning with the letter T?
Whats your favourite mythical creature beginning with the letter U?
Whats your favourite alcoholic drink beginning with the letter V?
Whats your favourite cartoon character beginning with the letter W?
Whats your favourite word beginning with the letter X?
Whats your favourite city beginning with the letter Y?
Whats your favourite country beginning with the letter Z?
Whats your favourite animal?
Whats your favourite item of clothing?
Whats your favourite expleitive?
Whats your favourite boys name?
Whats your favourite girls name?
Whats your favourite book?
Whats your favourite bodypart?
Whats your favourite musical instrument?
Whats your favourite song?
Whats your favourite actress?
Whats your favourite actor?
Whats your favourite film?
Whats your favourite tv show?
Whats your favourite game?
Whats your favourite non alcoholic drink?
Whats your favourite food?
Whats your favourite band?
Whats your favourite author?
Whats your favourite sport?
Whats your favourite job?
Whats your favourite mythical creature?
Whats your favourite alcoholic drink?
Whats your favourite cartoon character?
Whats your favourite word?
Whats your favourite city?
Whats your favourite country?
Do you get seasick?
If you discovered a new species of dinosaur what would you call it?
Do you own a paddling pool?
@ -1233,28 +1232,7 @@ If you were to remake a movie, what actors would you cast?
If you were to replace a character in your favourite movie, who would you replace with who?
Under rated actor who deserves to be famous in your opinion?
Whos your favourite celebrity with the same birthday or name as you?
Whats your favorite movie beginning with the letter A?
Whats your fav movie beginning with the letter B?
Whats your fav movie beginning with the letter C?
Whats your fav movie beginning with the letter D?
Whats your fav movie beginning with the letter E?
Whats your fav movie beginning with the letter F?
Whats your fav movie beginning with the letter G?
Whats your fav movie beginning with the letter H?
Whats your fav movie beginning with the letter I?
Whats your fav movie beginning with the letter J?
Whats your fav movie beginning with the letter K?
Whats your fav movie beginning with the letter L?
Whats your fav movie beginning with the letter M?
Whats your fav movie beginning with the letter N?
Whats your fav movie beginning with the letter O?
Whats your fav movie beginning with the letter P?
Whats your fav movie beginning with the letter S?
Whats your fav movie beginning with the letter Q?
Whats your fav movie beginning with the letter V?
Whats your fav movie beginning with the letter X?
Whats your fav movie beginning with the letter Y?
Whats your fav movie beginning with the letter Z?
Whats your favorite movie?
What movie would you wish to come to life?
Movies you think one should watch before dying?
Favourite actor who has not won a oscar yet?
@ -1576,28 +1554,7 @@ What is your favourite cheat in GTA?
What car do you prefer to drive in GTA?
Hardest mission youve done in GTA?
Easiest mission youve done in GTA?
Whats your favourite game beginning with the letter A?
Whats your favourite game beginning with the letter B?
Whats your favourite game beginning with the letter C?
Whats your favourite game beginning with the letter D?
Whats your favourite game beginning with the letter E?
Whats your favourite game beginning with the letter F?
Whats your favourite game beginning with the letter G?
Whats your favourite game beginning with the letter H?
Whats your favourite game beginning with the letter I?
Whats your favourite game beginning with the letter J?
Whats your favourite game beginning with the letter K?
Whats your favourite game beginning with the letter L?
Whats your favourite game beginning with the letter M?
Whats your favourite game beginning with the letter N?
Whats your favourite game beginning with the letter O?
Whats your favourite game beginning with the letter P?
Whats your favourite game beginning with the letter S?
Whats your favourite game beginning with the letter Q?
Whats your favourite game beginning with the letter V?
Whats your favourite game beginning with the letter X?
Whats your favourite game beginning with the letter Y?
Whats your favourite game beginning with the letter Z?
Whats your favourite game?
Do you usually win or lose when playing against friends?
What are your parents inputs on you gaming?
What type of games do you like to play with your partner?
@ -1632,8 +1589,7 @@ What impact do you think phones have had on the world?
Life without smartphone be like?
Have you ever did a prank call on anyone? If so, who and how did you prank them?
What was their reaction?
Have you ever been prank called?
What was your reaction?
Have you ever been prank called? What was your reaction?
Favourite smartphone logo?
Your favourite iphone?
Your favourite samsung phone?
@ -1651,28 +1607,7 @@ Worst app youve installed?
Do you prefer free or paid apps?
Have you bought any paid apps? If so which?
Most expensive paid app you bought and were you satisfied with it?
Whats your favourite mobile app beginning with the letter A?
Whats your favourite mobile app beginning with the letter B?
Whats your favourite mobile app beginning with the letter C?
Whats your favourite mobile app beginning with the letter D?
Whats your favourite mobile appbeginning with the letter E?
Whats your favourite mobile app beginning with the letter F?
Whats your favourite mobile app beginning with the letter G?
Whats your favourite mobile app beginning with the letter H?
Whats your favourite mobile app beginning with the letter I?
Whats your favourite mobile app beginning with the letter J?
Whats your favourite mobile app beginning with the letter K?
Whats your favourite mobile app beginning with the letter L?
Whats your favourite mobile app beginning with the letter M?
Whats your favourite mobile app beginning with the letter N?
Whats your favourite mobile app beginning with the letter O?
Whats your favourite mobile app beginning with the letter P?
Whats your favourite mobile app beginning with the letter S?
Whats your favourite mobile app beginning with the letter Q?
Whats your favourite mobile app beginning with the letter V?
Whats your favourite mobile app beginning with the letter X?
Whats your favourite mobile app beginning with the letter Y?
Whats your favourite mobile app beginning with the letter Z?
Whats your favourite mobile app?
How do you usually take your photos? (With camera, phone? etc)
What software do you use to backup your photos?
Total number of photos youve in your gallery?
@ -1755,4 +1690,3 @@ How do you memorize your numbers?
Have you ever been stuck in a bad situation but had no phone?
How many signal bars do you usually get in your room?
What service provider do you think is the best and why so?

476
static/roleplay.json Normal file
View File

@ -0,0 +1,476 @@
{
"angry": {
"forms": {
"none": "{} is angry",
"others": "{} is angry at {}",
"reason": "{} is angry because {}",
"both": "{} is angry at {} for {}"
}
},
"bite": {
"forms": {
"none": "{} is biting",
"others": "{} is biting {}",
"reason": "{} is biting because {}",
"both": "{} is biting {} for {}"
}
},
"blush": {
"forms": {
"none": "{} is blushing",
"others": "{} is blushing at {}",
"reason": "{} is blushing because {}",
"both": "{} is blushing at {} for {}"
}
},
"bored": {
"forms": {
"none": "{} is bored",
"others": "{}, {} are bored",
"reason": "{} is bored because {}",
"both": "{}, {} are bored because {}"
}
},
"bonk": {
"forms": {
"none": "{} is bonking",
"others": "{} is bonking {}",
"reason": "{} is bonking because {}",
"both": "{} is bonking {} for {}"
}
},
"boop": {
"forms": {
"none": "{} is booping",
"others": "{} is booping {}",
"reason": "{} is booping because {}",
"both": "{} is booping {} for {}"
}
},
"chase": {
"forms": {
"none": "{} is chasing",
"others": "{} is chasing {}",
"reason": "{} is chasing because {}",
"both": "{} is chasing {} for {}"
}
},
"cheer": {
"forms": {
"none": "{} is cheering",
"others": "{} is cheering for {}",
"reason": "{} is cheering because {}",
"both": "{} is cheering for {} because {}"
}
},
"cringe": {
"forms": {
"none": "{} is cringing",
"others": "{} is cringing at {}",
"reason": "{} is cringing because {}",
"both": "{} is cringing at {} for {}"
}
},
"cry": {
"forms": {
"none": "{} is crying",
"others": "{} is crying at {}",
"reason": "{} is crying because {}",
"both": "{} is crying at {} for {}"
}
},
"cuddle": {
"forms": {
"none": "{} is cuddling",
"others": "{} is cuddling with {}",
"reason": "{} is cuddling because {}",
"both": "{} is cuddling with {} for {}"
}
},
"dab": {
"forms": {
"none": "{} is dabing",
"others": "{} is dabing at {}",
"reason": "{} is dabing because {}",
"both": "{} is dabing at {} for {}"
}
},
"dance": {
"forms": {
"none": "{} is dancing",
"others": "{} is dancing with {}",
"reason": "{} is dancing because {}",
"both": "{} is dancing with {} for {}"
}
},
"die": {
"forms": {
"none": "{} is dying",
"others": "{} is dying with {}",
"reason": "{} is dying because {}",
"both": "{} is dying with {} because {}"
}
},
"eat": {
"forms": {
"none": "{} is eating",
"others": "{} is eating with {}",
"reason": "{} is eating because {}",
"both": "{} is eating with {} for {}"
}
},
"facepalm": {
"forms": {
"none": "{} is facepalming",
"others": "{} is facepalming at {}",
"reason": "{} is facepalming because {}",
"both": "{} is facepalming at {} for {}"
}
},
"feed": {
"forms": {
"none": "{} is eating",
"others": "{} is feeding {}",
"reason": "{} is eating because {}",
"both": "{} is feeding {} for {}"
}
},
"glomp": {
"forms": {
"none": "{} is glomping",
"others": "{} is glomping {}",
"reason": "{} is glomping because {}",
"both": "{} is glomping {} for {}"
}
},
"handhold": {
"alias": "holdhands"
},
"happy": {
"forms": {
"none": "{} is happy",
"others": "{} is happy with {}",
"reason": "{} is happy because {}",
"both": "{} is happy with {} for {}"
}
},
"hate": {
"forms": {
"none": "{} is hating",
"others": "{} is hating {}",
"reason": "{} is hating because {}",
"both": "{} is hating {} for {}"
}
},
"holdhands": {
"forms": {
"none": "{} is holding hands",
"others": "{} is holding hands with {}",
"reason": "{} is holding hands because {}",
"both": "{} is holding hands with {} for {}"
}
},
"hide": {
"forms": {
"none": "{} is hiding",
"others": "{} is hiding from {}",
"reason": "{} is hiding because {}",
"both": "{} is hiding from {} for {}"
}
},
"highfive": {
"forms": {
"none": "{} is high fiving",
"others": "{} is high fiving with {}",
"reason": "{} is high fiving because {}",
"both": "{} is high fiving with {} for {}"
}
},
"hug": {
"forms": {
"none": "{} is hugging",
"others": "{} is hugging {}",
"reason": "{} is hugging because {}",
"both": "{} is hugging at {} for {}"
}
},
"kill": {
"forms": {
"none": "{} is killing",
"others": "{} is killing {}",
"reason": "{} is killing because {}",
"both": "{} is killing {} for {}"
}
},
"kiss": {
"forms": {
"none": "{} is kissing",
"others": "{} is kissing {}",
"reason": "{} is kissing because {}",
"both": "{} is kissing {} for {}"
}
},
"laugh": {
"forms": {
"none": "{} is laughing",
"others": "{} is laughing with {}",
"reason": "{} is laughing because {}",
"both": "{} is laughing with {} for {}"
}
},
"lick": {
"forms": {
"none": "{} is licking",
"others": "{} is licking {}",
"reason": "{} is licking {}",
"both": "{} is licking {} for {}"
}
},
"love": {
"forms": {
"none": "{} is loving",
"others": "{} is loving {}",
"reason": "{} is loving because {}",
"both": "{} is loving {} for {}"
}
},
"lurk": {
"forms": {
"none": "{} is lurking",
"others": "{} is lurking from {}",
"reason": "{} is lurking because {}",
"both": "{} is lurking from {} for {}"
}
},
"nervous": {
"forms": {
"none": "{} is nervous",
"others": "{} is nervous with {}",
"reason": "{} is nervous because {}",
"both": "{} is nervous with {} for {}"
}
},
"no": {
"forms": {
"none": "{} is saying no",
"others": "{} is saying no to {}",
"reason": "{} is saying no because {}",
"both": "{} is saying no to {} for {}"
}
},
"nom": {
"forms": {
"none": "{} is noming",
"others": "{} is noming {}",
"reason": "{} is noming because {}",
"both": "{} is noming {} for {}"
}
},
"nuzzle": {
"forms": {
"none": "{} is nuzzling",
"others": "{} is nuzzling {}",
"reason": "{} is nuzzling because {}",
"both": "{} is nuzzling {} for {}"
}
},
"panic": {
"forms": {
"none": "{} is panicking",
"others": "{} is panicking at {}",
"reason": "{} is panicking because {}",
"both": "{} is panicking at {} for {}"
}
},
"pat": {
"forms": {
"none": "{} is patting",
"others": "{} is patting {}",
"reason": "{} is patting because {}",
"both": "{} is patting {} for {}"
}
},
"peck": {
"forms": {
"none": "{} is pecking",
"others": "{} is pecking {}",
"reason": "{} is pecking because {}",
"both": "{} is pecking {} for {}"
}
},
"poke": {
"forms": {
"none": "{} is poking",
"others": "{} is poking {}",
"reason": "{} is poking because {}",
"both": "{} is poking {} for {}"
}
},
"pout": {
"forms": {
"none": "{} is pouting",
"others": "{} is pouting at {}",
"reason": "{} is pouting because {}",
"both": "{} is pouting at {} for {}"
}
},
"run": {
"forms": {
"none": "{} is running",
"others": "{} is running from {}",
"reason": "{} is running because {}",
"both": "{} is running from {} for {}"
}
},
"runs": {
"alias": "run"
},
"shoot": {
"forms": {
"none": "{} is shooting",
"others": "{} is shooting {}",
"reason": "{} is shooting because {}",
"both": "{} is shooting {} for {}"
}
},
"shrug": {
"forms": {
"none": "{} is shrugging",
"others": "{} is shrugging at {}",
"reason": "{} is shrugging because {}",
"both": "{} is shrugging at {} for {}"
}
},
"sip": {
"forms": {
"none": "{} is sipping",
"others": "{} is sipping with {}",
"reason": "{} is sipping because {}",
"both": "{} is sipping with {} for {}"
}
},
"slap": {
"forms": {
"none": "{} is slapping",
"others": "{} is slapping {}",
"reason": "{} is slapping because {}",
"both": "{} is slapping {} for {}"
}
},
"sleep": {
"forms": {
"none": "{} is sleeping",
"others": "{} is sleeping with {}",
"reason": "{} is sleeping because {}",
"both": "{} is sleeping {} for {}"
}
},
"sob": {
"alias": "sobs"
},
"sobs": {
"alias": "cry",
"forms": {
"none": "{} is sobbing",
"others": "{} is sobbing due to {}",
"reason": "{} is sobbing because {}",
"both": "{} is sobbing due to {} because {}"
}
},
"snuggle": {
"forms": {
"none": "{} is snuggling",
"others": "{} is snuggling {}",
"reason": "{} is snuggling because {}",
"both": "{} is snuggling {} for {}"
}
},
"stab": {
"forms": {
"none": "{} is stabbing",
"others": "{} is stabbing {}",
"reason": "{} is stabbing because {}",
"both": "{} is stabbing {} for {}"
}
},
"tease": {
"forms": {
"none": "{} is teasing",
"others": "{} is teasing {}",
"reason": "{} is teasing because {}",
"both": "{} is teasing {} for {}"
}
},
"think": {
"forms": {
"none": "{} is thinking",
"others": "{} is thinking with {}",
"reason": "{} is thinking because {}",
"both": "{} is thinking with {} for {}"
}
},
"thumbsup": {
"forms": {
"none": "{} is giving a thumbs up",
"others": "{} is giving a thumbs up to {}",
"reason": "{} is giving a thumbs up because {}",
"both": "{} is giving a thumbs up to {} for {}"
}
},
"tickle": {
"forms": {
"none": "{} is tickling",
"others": "{} is tickling {}",
"reason": "{} is tickling because {}",
"both": "{} is tickling {} for {}"
}
},
"triggered": {
"forms": {
"none": "{} is triggered",
"others": "{} is triggered by {}",
"reason": "{} is triggered because {}",
"both": "{} is triggered by {} because {}"
}
},
"twerk": {
"forms": {
"none": "{} is twerking",
"others": "{} is twerking with {}",
"reason": "{} is twerking because {}",
"both": "{} is twerking with {} because {}"
}
},
"wag": {
"forms": {
"none": "{} is wagging",
"others": "{} is wagging at {}",
"reason": "{} is wagging because {}",
"both": "{} is wagging at {} for {}"
}
},
"wave": {
"forms": {
"none": "{} is waving",
"others": "{} is waving at {}",
"reason": "{} is waving because {}",
"both": "{} is waving at {} for {}"
}
},
"wink": {
"forms": {
"none": "{} is winking",
"others": "{} is winking at {}",
"reason": "{} is winking because {}",
"both": "{} is winking at {} for {}"
}
},
"yes": {
"forms": {
"none": "{} is saying yes",
"others": "{} is saying yes to {}",
"reason": "{} is saying yes because {}",
"both": "{} is saying yes to {} for {}"
}
}
}