mirror of
https://github.com/thedevs-network/the-guard-bot
synced 2025-08-30 21:55:17 +00:00
Merge pull request #29 from TheDevs-Network/develop
better custom commands and overall improvements
This commit is contained in:
@@ -39,7 +39,7 @@
|
||||
"consistent-return": "error",
|
||||
"curly": [
|
||||
"error",
|
||||
"all"
|
||||
"multi-line"
|
||||
],
|
||||
"default-case": "error",
|
||||
"dot-location": [
|
||||
|
36
README.md
36
README.md
@@ -20,25 +20,29 @@ You need [Node.js](https://nodejs.org/) (> 8.1) to run this bot.
|
||||
Now you can add the bot as **administrator** to your groups.
|
||||
|
||||
## Commands
|
||||
Command | Role | Description
|
||||
-------- | ------ | -----------
|
||||
`/admin` | _Master_ | Makes the user admin.
|
||||
`/unadmin` | _Master_ | Demotes the user from admin list.
|
||||
`/leave` | _Master_ | Makes the bot leave the group cleanly.
|
||||
`/warn <reason>` | _Admin_ | Warns the user.
|
||||
`/unwarn` | _Admin_ | Removes the last warn from the user.
|
||||
`/nowarns` | _Admin_ | Clears warns for the user.
|
||||
`/getwarns` | _Admin_ | Shows a list of warns for the user.
|
||||
`/ban <reason>` | _Admin_ | Bans the user from groups.
|
||||
`/unban` | _Admin_ | Removes the user from ban list.
|
||||
`/staff` | _All_ | Shows a list of admins.
|
||||
`/link` | _All_ | Show the current group's link.
|
||||
`/groups` | _All_ | Show a list of groups which the bot is admin in.
|
||||
`/report` | _All_ | Reports the replied-to message to admins.
|
||||
Command | Role | Available at | Description
|
||||
----------------------- | ---------- | ------------ | -----------------
|
||||
`/admin` | _Master_ | _Everywhere_ | Makes the user admin.
|
||||
`/unadmin` | _Master_ | _Everywhere_ | Demotes the user from admin list.
|
||||
`/leave <name\|id>` | _Master_ | _Everywhere_ | Make the bot to leave the group cleanly.
|
||||
`/warn <reason>` | _Admin_ | _Groups_ | Warns the user.
|
||||
`/unwarn` | _Admin_ | _Everywhere_ | Removes the last warn from the user.
|
||||
`/nowarns` | _Admin_ | _Everywhere_ | Clears warns for the user.
|
||||
`/getwarns` | _Admin_ | _Everywhere_ | Shows a list of warns for the user.
|
||||
`/ban <reason>` | _Admin_ | _Groups_ | Bans the user from groups.
|
||||
`/unban` | _Admin_ | _Everywhere_ | Removes the user from ban list.
|
||||
`/addcommand` | _Admin_ | _In-Bot_ | Create a custom command.
|
||||
`/removecommand <name>` | _Admin_ | _In-Bot_ | Remove a custom command.
|
||||
`/staff` | _Everyone_ | _Everywhere_ | Shows a list of admins.
|
||||
`/link` | _Everyone_ | _Everywhere_ | Shows the current group's link.
|
||||
`/groups` | _Everyone_ | _Everywhere_ | Shows a list of groups which the bot is admin in.
|
||||
`/report` | _Everyone_ | _Everywhere_ | Reports the replied-to message to admins.
|
||||
`/commands` | _Everyone_ | _In-Bot_ | Shows a list of available commands.
|
||||
`/help` \| `/start` | _Everyone_ | _In-Bot_ | How to use the bot.
|
||||
|
||||
All commands and actions are synchronized across all of the groups managed by the owner and they work with both **replying** and **mentioning** a user.
|
||||
|
||||
If used by reply, `/ban` and `/warn` remove the replied-to message.
|
||||
If used by reply, `/ban` and `/warn` would remove the replied-to message.
|
||||
|
||||
The bot is still in alpha phase so feel free to open issues and ask for a _feature_.
|
||||
|
||||
|
@@ -1,8 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Telegraf = require('telegraf');
|
||||
const { loadJSON } = require('../utils/json');
|
||||
const config = loadJSON('config.json');
|
||||
const config = require('../config.json');
|
||||
|
||||
const bot = new Telegraf(config.token);
|
||||
|
||||
|
@@ -1,24 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
// DB
|
||||
const { isAdmin } = require('../../stores/user');
|
||||
const { addCommand } = require('../../stores/command');
|
||||
|
||||
// Bot
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
const addCommandHandler = async ({ chat, message, reply }) => {
|
||||
const user = message.from;
|
||||
if (chat.type !== 'private') {
|
||||
return null;
|
||||
}
|
||||
if (!await isAdmin(user)) {
|
||||
const addCommandHandler = async ({ chat, reply, state }) => {
|
||||
const { isAdmin, user } = state;
|
||||
if (chat.type !== 'private') return null;
|
||||
|
||||
if (!isAdmin) {
|
||||
return reply('ℹ️ <b>Sorry, only admins access this command.</b>',
|
||||
replyOptions);
|
||||
}
|
||||
await addCommand({ id: user.id });
|
||||
return reply('Enter a name for the command.\n\nFor example: <b>rules</b>',
|
||||
replyOptions);
|
||||
return reply('Enter a name for the command without forward slash "/".' +
|
||||
'\n\nFor example: <b>rules</b>',
|
||||
replyOptions);
|
||||
};
|
||||
|
||||
module.exports = addCommandHandler;
|
||||
|
@@ -1,13 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
// Utils
|
||||
const { loadJSON } = require('../../utils/json');
|
||||
const { link } = require('../../utils/tg');
|
||||
const { logError } = require('../../utils/log');
|
||||
|
||||
// Config
|
||||
const { masterID } = loadJSON('config.json');
|
||||
|
||||
// Bot
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
@@ -20,16 +16,15 @@ const {
|
||||
nowarns
|
||||
} = require('../../stores/user');
|
||||
|
||||
const adminHandler = async ({ message, reply }) => {
|
||||
if (message.from.id !== masterID) {
|
||||
return null;
|
||||
}
|
||||
const adminHandler = async ({ message, reply, state }) => {
|
||||
const { isMaster, user } = state;
|
||||
if (!isMaster) return null;
|
||||
|
||||
const userToAdmin = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
: message.commandMention
|
||||
? message.commandMention
|
||||
: message.from;
|
||||
: user;
|
||||
|
||||
if (await isBanned(userToAdmin)) {
|
||||
return reply('ℹ️ <b>Can\'t admin banned user.</b>', replyOptions);
|
||||
|
@@ -12,10 +12,8 @@ const { replyOptions } = require('../../bot/options');
|
||||
const { listGroups } = require('../../stores/group');
|
||||
const { isAdmin, isBanned, ban } = require('../../stores/user');
|
||||
|
||||
const banHandler = async ({ chat, message, reply, telegram, me }) => {
|
||||
if (!await isAdmin(message.from)) {
|
||||
return null;
|
||||
}
|
||||
const banHandler = async ({ chat, message, reply, telegram, me, state }) => {
|
||||
if (!state.isAdmin) return null;
|
||||
|
||||
const userToBan = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
@@ -69,7 +67,7 @@ const banHandler = async ({ chat, message, reply, telegram, me }) => {
|
||||
logError(err);
|
||||
}
|
||||
|
||||
return reply(`🚫 ${link(message.from)} <b>banned</b> ${link(userToBan)} ` +
|
||||
return reply(`🚫 ${link(state.user)} <b>banned</b> ${link(userToBan)} ` +
|
||||
`<b>for:</b>\n\n${reason}`, replyOptions);
|
||||
};
|
||||
|
||||
|
@@ -29,16 +29,15 @@ const actions = `\n
|
||||
/removecommand <code><name></code> - to remove a custom command.`;
|
||||
|
||||
const commandReferenceHandler = async ({ chat, replyWithHTML }) => {
|
||||
if (chat.type !== 'private') {
|
||||
return null;
|
||||
}
|
||||
if (chat.type !== 'private') return null;
|
||||
|
||||
const customCommands = await listCommands();
|
||||
const customCommandsText = customCommands.length
|
||||
? '\n<b>Custom commands:</b>\n' +
|
||||
customCommands
|
||||
.filter(command => command.isActive)
|
||||
.sort((a, b) => a.role < b.role)
|
||||
.map(command => `[${command.role}] <code>/${command.name}</code>`)
|
||||
.map(command => `[${command.role}] <code>!${command.name}</code>`)
|
||||
.join('\n')
|
||||
: '';
|
||||
|
||||
|
@@ -7,12 +7,12 @@ const { link } = require('../../utils/tg');
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
// DB
|
||||
const { isAdmin, getWarns } = require('../../stores/user');
|
||||
const { getWarns } = require('../../stores/user');
|
||||
|
||||
const getWarnsHandler = async ({ message, reply, state }) => {
|
||||
const { isAdmin } = state;
|
||||
if (!isAdmin) return null;
|
||||
|
||||
const getWarnsHandler = async ({ message, reply }) => {
|
||||
if (!await isAdmin(message.from)) {
|
||||
return null;
|
||||
}
|
||||
const theUser = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
: message.commandMention
|
||||
|
@@ -19,9 +19,8 @@ and @mattatabot might be better choices for you.
|
||||
`;
|
||||
|
||||
const helpHandler = ({ chat, replyWithHTML }) => {
|
||||
if (chat.type !== 'private') {
|
||||
return null;
|
||||
}
|
||||
if (chat.type !== 'private') return null;
|
||||
|
||||
return replyWithHTML(
|
||||
message,
|
||||
Markup.inlineKeyboard(
|
||||
|
@@ -1,15 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const { masterID } = require('../../config.json');
|
||||
|
||||
const { removeGroup } = require('../../stores/group');
|
||||
const { managesGroup, removeGroup } = require('../../stores/group');
|
||||
|
||||
const leaveCommandHandler = async ctx => {
|
||||
if (ctx.from.id !== masterID) {
|
||||
return null;
|
||||
const { chat, message, telegram, state, replyWithHTML } = ctx;
|
||||
const { isMaster } = state;
|
||||
if (!isMaster) return null;
|
||||
|
||||
const groupName = message.text.split(' ').slice(1).join(' ');
|
||||
|
||||
if (groupName) {
|
||||
const group = /^-?\d+/.test(groupName)
|
||||
? { id: Number(groupName) }
|
||||
: { title: groupName };
|
||||
console.log(group);
|
||||
const isGroup = await managesGroup(group);
|
||||
if (!isGroup) {
|
||||
return replyWithHTML(
|
||||
'ℹ️ <b>Couldn\'t find a group with that ID/name.</b>'
|
||||
);
|
||||
}
|
||||
await Promise.all([
|
||||
removeGroup(isGroup),
|
||||
telegram.leaveChat(isGroup.id)
|
||||
]);
|
||||
return replyWithHTML(
|
||||
'✅ <b>I no longer manage that group.</b>'
|
||||
);
|
||||
}
|
||||
await removeGroup(ctx.chat);
|
||||
return ctx.telegram.leaveChat(ctx.chat.id);
|
||||
|
||||
await removeGroup(chat);
|
||||
return telegram.leaveChat(chat.id);
|
||||
};
|
||||
|
||||
module.exports = leaveCommandHandler;
|
||||
|
@@ -7,7 +7,7 @@ const bot = require('../../bot');
|
||||
const { managesGroup } = require('../../stores/group');
|
||||
|
||||
const linkHandler = async ({ chat, replyWithHTML }) => {
|
||||
const group = await managesGroup(chat);
|
||||
const group = await managesGroup({ id: chat.id });
|
||||
|
||||
const { message_id } = await replyWithHTML(
|
||||
'ℹ️ <b>Group\'s link:</b>\n\n' +
|
||||
|
@@ -8,12 +8,11 @@ const { logError } = require('../../utils/log');
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
// DB
|
||||
const { isAdmin, getWarns, nowarns } = require('../../stores/user');
|
||||
const { getWarns, nowarns } = require('../../stores/user');
|
||||
|
||||
const nowarnsHandler = async ({ message, reply }) => {
|
||||
if (!await isAdmin(message.from)) {
|
||||
return null;
|
||||
}
|
||||
const nowarnsHandler = async ({ message, reply, state }) => {
|
||||
const { isAdmin, user } = state;
|
||||
if (!isAdmin) return null;
|
||||
|
||||
const userToUnwarn = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
@@ -39,7 +38,7 @@ const nowarnsHandler = async ({ message, reply }) => {
|
||||
}
|
||||
|
||||
return reply(
|
||||
`♻️ ${link(message.from)} <b>pardoned</b> ${link(userToUnwarn)} ` +
|
||||
`♻️ ${link(user)} <b>pardoned</b> ${link(userToUnwarn)} ` +
|
||||
'<b>for all of their warnings.</b>',
|
||||
replyOptions);
|
||||
};
|
||||
|
@@ -1,25 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
// Utils
|
||||
const { loadJSON } = require('../../utils/json');
|
||||
|
||||
// Config
|
||||
const { masterID } = loadJSON('config.json');
|
||||
|
||||
// DB
|
||||
const { isAdmin } = require('../../stores/user');
|
||||
const { getCommand, removeCommand } = require('../../stores/command');
|
||||
|
||||
// Bot
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
const removeCommandHandler = async ({ chat, message, reply }) => {
|
||||
const user = message.from;
|
||||
const removeCommandHandler = async ({ chat, message, reply, state }) => {
|
||||
const { isAdmin, isMaster } = state;
|
||||
const { text } = message;
|
||||
if (chat.type !== 'private') {
|
||||
return null;
|
||||
}
|
||||
if (!await isAdmin(user)) {
|
||||
if (chat.type !== 'private') return null;
|
||||
|
||||
if (!isAdmin) {
|
||||
return reply('ℹ️ <b>Sorry, only admins access this command.</b>',
|
||||
replyOptions);
|
||||
}
|
||||
@@ -37,7 +29,7 @@ const removeCommandHandler = async ({ chat, message, reply }) => {
|
||||
replyOptions);
|
||||
}
|
||||
|
||||
if (command.role === 'Master' && user.id !== masterID) {
|
||||
if (command.role === 'Master' && !isMaster) {
|
||||
return reply('ℹ️ <b>Sorry, only master can remove this command.</b>',
|
||||
replyOptions);
|
||||
}
|
||||
|
@@ -17,12 +17,12 @@ const reportHandler = async ctx => {
|
||||
}
|
||||
const admins = await getAdmins();
|
||||
const adminObjects = admins.map(user => ({
|
||||
first_name: '⭐️', // small hack to be able to use link function
|
||||
first_name: '', // small hack to be able to use link function
|
||||
id: user.id,
|
||||
}));
|
||||
const stars = adminObjects.map(link).join('');
|
||||
const s = `📋 ${link(ctx.from)} <b>reported the message to admins:</b> ` +
|
||||
`${stars}`;
|
||||
const adminsMention = adminObjects.map(link).join('');
|
||||
const s = `❗️${link(ctx.from)} <b>reported the message to the admins.</b>` +
|
||||
`${adminsMention}`;
|
||||
return ctx.replyWithHTML(s, {
|
||||
reply_to_message_id: msg.reply_to_message.message_id
|
||||
});
|
||||
|
@@ -1,23 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
// Utils
|
||||
const { loadJSON } = require('../../utils/json');
|
||||
const { link } = require('../../utils/tg');
|
||||
const { logError } = require('../../utils/log');
|
||||
|
||||
// Config
|
||||
const { masterID } = loadJSON('config.json');
|
||||
|
||||
// Bot
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
// DB
|
||||
const { isAdmin, unadmin } = require('../../stores/user');
|
||||
|
||||
const unAdminHandler = async ({ message, reply }) => {
|
||||
if (message.from.id !== masterID) {
|
||||
return null;
|
||||
}
|
||||
const unAdminHandler = async ({ message, reply, state }) => {
|
||||
const { isMaster } = state;
|
||||
if (!isMaster) return null;
|
||||
|
||||
const userToUnadmin = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
|
@@ -9,14 +9,13 @@ const { replyOptions } = require('../../bot/options');
|
||||
|
||||
// DB
|
||||
const { listGroups } = require('../../stores/group');
|
||||
const { isAdmin, isBanned, unban } = require('../../stores/user');
|
||||
const { isBanned, unban } = require('../../stores/user');
|
||||
|
||||
const noop = Function.prototype;
|
||||
|
||||
const unbanHandler = async ({ message, reply, telegram }) => {
|
||||
if (!await isAdmin(message.from)) {
|
||||
return null;
|
||||
}
|
||||
const unbanHandler = async ({ message, reply, telegram, state }) => {
|
||||
const { isAdmin, user } = state;
|
||||
if (!isAdmin) return null;
|
||||
|
||||
const userToUnban = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
@@ -60,7 +59,7 @@ const unbanHandler = async ({ message, reply, telegram }) => {
|
||||
// hance .catch(noop)
|
||||
// (it's an expected, non-critical failure)
|
||||
|
||||
return reply(`♻️ ${link(message.from)} <b>unbanned</b> ` +
|
||||
return reply(`♻️ ${link(user)} <b>unbanned</b> ` +
|
||||
`${link(userToUnban)}.`, replyOptions);
|
||||
};
|
||||
|
||||
|
@@ -7,12 +7,11 @@ const { link } = require('../../utils/tg');
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
// DB
|
||||
const { isAdmin, getWarns, unwarn } = require('../../stores/user');
|
||||
const { getWarns, unwarn } = require('../../stores/user');
|
||||
|
||||
const unwarnHandler = async ({ message, reply }) => {
|
||||
if (!await isAdmin(message.from)) {
|
||||
return null;
|
||||
}
|
||||
const unwarnHandler = async ({ message, reply, state }) => {
|
||||
const { isAdmin, user } = state;
|
||||
if (!isAdmin) return null;
|
||||
|
||||
const userToUnwarn = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
@@ -35,9 +34,9 @@ const unwarnHandler = async ({ message, reply }) => {
|
||||
await unwarn(userToUnwarn);
|
||||
|
||||
return reply(
|
||||
`❎ ${link(message.from)} <b>pardoned</b> ${link(userToUnwarn)} ` +
|
||||
`❎ ${link(user)} <b>pardoned</b> ${link(userToUnwarn)} ` +
|
||||
`<b>for:</b>\n\n${allWarns[allWarns.length - 1]}` +
|
||||
`(${allWarns.length - 1}/3)`,
|
||||
` (${allWarns.length - 1}/3)`,
|
||||
replyOptions);
|
||||
};
|
||||
|
||||
|
@@ -1,12 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
// Utils
|
||||
const { loadJSON } = require('../../utils/json');
|
||||
const { link } = require('../../utils/tg');
|
||||
const { logError } = require('../../utils/log');
|
||||
|
||||
// Config
|
||||
const { numberOfWarnsToBan } = loadJSON('config.json');
|
||||
const { numberOfWarnsToBan } = require('../../config.json');
|
||||
|
||||
// Bot
|
||||
const bot = require('../../bot');
|
||||
@@ -15,10 +14,9 @@ const { replyOptions } = require('../../bot/options');
|
||||
// DB
|
||||
const { isAdmin, ban, getWarns, warn } = require('../../stores/user');
|
||||
|
||||
const warnHandler = async ({ message, chat, reply, me }) => {
|
||||
if (!await isAdmin(message.from)) {
|
||||
return null;
|
||||
}
|
||||
const warnHandler = async ({ message, chat, reply, me, state }) => {
|
||||
const { user } = state;
|
||||
if (!state.isAdmin) return null;
|
||||
|
||||
const userToWarn = message.reply_to_message
|
||||
? message.reply_to_message.from
|
||||
@@ -59,14 +57,14 @@ const warnHandler = async ({ message, chat, reply, me }) => {
|
||||
|
||||
if (warnCount.length < numberOfWarnsToBan) {
|
||||
promises.push(reply(
|
||||
`⚠️ ${link(message.from)} <b>warned</b> ${link(userToWarn)} ` +
|
||||
`⚠️ ${link(user)} <b>warned</b> ${link(userToWarn)} ` +
|
||||
`<b>for:</b>\n\n ${reason} (${warnCount.length}/3)`,
|
||||
replyOptions));
|
||||
} else {
|
||||
promises.push(bot.telegram.kickChatMember(chat.id, userToWarn.id));
|
||||
promises.push(ban(userToWarn, 'Reached max number of warnings'));
|
||||
promises.push(reply(
|
||||
`🚫 ${link(message.from)} <b>banned</b> ${link(userToWarn)} ` +
|
||||
`🚫 ${link(user)} <b>banned</b> ${link(userToWarn)} ` +
|
||||
'<b>for:</b>\n\nReached max number of warnings ' +
|
||||
`(${warnCount.length}/3)\n\n`,
|
||||
replyOptions));
|
||||
|
@@ -6,16 +6,20 @@ const { Markup } = require('telegraf');
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
// DB
|
||||
const { isAdmin } = require('../../stores/user');
|
||||
const {
|
||||
getCommand,
|
||||
removeCommand,
|
||||
updateCommand
|
||||
} = require('../../stores/command');
|
||||
|
||||
const addCustomCmdHandler = async ({ chat, message, reply }, next) => {
|
||||
const preserved = [ 'admin', 'unadmin', 'leave', 'warn', 'unwarn', 'nowarns',
|
||||
'getwarns', 'ban', 'unban', 'report', 'staff', 'link', 'groups', 'commands',
|
||||
'addcommand', 'removecommand' ];
|
||||
|
||||
const addCustomCmdHandler = async ({ chat, message, reply, state }, next) => {
|
||||
const { text, photo, document, video, audio } = message;
|
||||
const { id } = message.from;
|
||||
const { isAdmin, user } = state;
|
||||
const { id } = user;
|
||||
|
||||
if (text && /^\/\w+/.test(text)) {
|
||||
await removeCommand({ id, isActive: false });
|
||||
@@ -24,18 +28,23 @@ const addCustomCmdHandler = async ({ chat, message, reply }, next) => {
|
||||
|
||||
const command = await getCommand({ id, isActive: false });
|
||||
if (chat.type !== 'private' ||
|
||||
!await isAdmin(message.from) ||
|
||||
!isAdmin ||
|
||||
!command ||
|
||||
!command.state) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const { state } = command;
|
||||
if (state === 'add') {
|
||||
if (command.state === 'add') {
|
||||
if (!/^(?=\D)\w+$/.test(text)) {
|
||||
reply('Please send a valid command.');
|
||||
return next();
|
||||
}
|
||||
if (preserved.includes(text.toLowerCase())) {
|
||||
reply('❗️Sorry you can\'t use this name, it\'s preserved.\n\n' +
|
||||
'Try another one.');
|
||||
return next();
|
||||
}
|
||||
|
||||
if (await getCommand({ isActive: true, name: text })) {
|
||||
reply(
|
||||
'ℹ️ <b>This command already exists.</b>\n\n' +
|
||||
@@ -56,7 +65,7 @@ const addCustomCmdHandler = async ({ chat, message, reply }, next) => {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (state === 'role') {
|
||||
if (command.state === 'role') {
|
||||
if (text !== 'Master' && text !== 'Admins' && text !== 'Everyone') {
|
||||
reply('Please send a valid role.', Markup.keyboard([
|
||||
[ 'Master', 'Admins', 'Everyone' ]
|
||||
@@ -75,7 +84,7 @@ const addCustomCmdHandler = async ({ chat, message, reply }, next) => {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (state === 'content') {
|
||||
if (command.state === 'content') {
|
||||
let newCommand;
|
||||
if (text) {
|
||||
newCommand = { content: text, type: 'text' };
|
||||
@@ -106,7 +115,8 @@ const addCustomCmdHandler = async ({ chat, message, reply }, next) => {
|
||||
]);
|
||||
reply(
|
||||
'✅ <b>New command has been created successfully.</b>\n\n' +
|
||||
'This command can be used in groups now. ' +
|
||||
'Custom commands work with ! instead of /.\n\n' +
|
||||
'For example: <code>!rules</code>\n\n' +
|
||||
'Custom commands can reply other messages too.\n\n' +
|
||||
'/commands - to see the list of commands.\n' +
|
||||
'/addcommand - to add a new command.\n' +
|
47
handlers/messages/addUser.js
Normal file
47
handlers/messages/addUser.js
Normal file
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
// Config
|
||||
const { masterID } = require('../../config.json');
|
||||
|
||||
// DB
|
||||
const { addUser, isUser } = require('../../stores/user');
|
||||
|
||||
const addUserHandler = async (ctx, next) => {
|
||||
const { message } = ctx;
|
||||
const { new_chat_members } = message;
|
||||
const newUser = message.from;
|
||||
const user = newUser && await isUser(message.from);
|
||||
const usersToAdd = [];
|
||||
|
||||
if (new_chat_members) {
|
||||
new_chat_members.forEach(async member => {
|
||||
if (!await isUser(member)) {
|
||||
usersToAdd.push(addUser(member));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!user && newUser) {
|
||||
usersToAdd.push(addUser(newUser));
|
||||
}
|
||||
|
||||
ctx.state = {
|
||||
isAdmin: user && user.status === 'admin',
|
||||
isMaster: user && user.id === masterID,
|
||||
user: newUser,
|
||||
};
|
||||
|
||||
if (
|
||||
message.reply_to_message &&
|
||||
message.reply_to_message.from &&
|
||||
!await isUser(message.reply_to_message.from)
|
||||
) {
|
||||
usersToAdd.push(addUser(message.reply_to_message.from));
|
||||
}
|
||||
|
||||
await Promise.all(usersToAdd);
|
||||
|
||||
return next();
|
||||
};
|
||||
|
||||
module.exports = addUserHandler;
|
@@ -13,6 +13,7 @@ const checkUsernameHandler = async ({ message }, next) => {
|
||||
entity.type === 'mention');
|
||||
const hasTextMention = message.entities.some(entity =>
|
||||
entity.type === 'text_mention');
|
||||
const hasId = /^\d+/.test(messageArr[1]);
|
||||
|
||||
if (!isCommand) {
|
||||
return next();
|
||||
@@ -42,6 +43,16 @@ const checkUsernameHandler = async ({ message }, next) => {
|
||||
message.commandMention = user;
|
||||
return next();
|
||||
}
|
||||
|
||||
if (hasId) {
|
||||
const [ , id ] = messageArr;
|
||||
const user = await getUser({ id: Number(id) });
|
||||
if (user) {
|
||||
message.text = message.text.replace(` ${id}`, '');
|
||||
message.commandMention = user;
|
||||
}
|
||||
return next();
|
||||
}
|
||||
return next();
|
||||
};
|
||||
|
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
// Utils
|
||||
const { loadJSON } = require('../../utils/json');
|
||||
const { link } = require('../../utils/tg');
|
||||
const { logError } = require('../../utils/log');
|
||||
|
||||
@@ -10,17 +9,18 @@ const {
|
||||
excludedChannels,
|
||||
excludedGroups,
|
||||
numberOfWarnsToBan
|
||||
} = loadJSON('config.json');
|
||||
} = require('../../config.json');
|
||||
|
||||
// Bot
|
||||
const bot = require('../../bot');
|
||||
const { replyOptions } = require('../../bot/options');
|
||||
|
||||
// DB
|
||||
const { isAdmin, ban, warn } = require('../../stores/user');
|
||||
const { ban, warn } = require('../../stores/user');
|
||||
const { listGroups } = require('../../stores/group');
|
||||
|
||||
const removeLinks = async ({ message, chat, reply }, next) => {
|
||||
const removeLinks = async ({ message, chat, reply, state }, next) => {
|
||||
const { isAdmin, user } = state;
|
||||
const groups = await listGroups();
|
||||
const groupLinks = [
|
||||
...groups.map(group => group.link
|
||||
@@ -41,26 +41,25 @@ const removeLinks = async ({ message, chat, reply }, next) => {
|
||||
!(excludedChannels.includes(message.text) ||
|
||||
groupLinks.includes(message.text.split('/joinchat/')[1]))
|
||||
) {
|
||||
const userToWarn = message.from;
|
||||
if (await isAdmin(userToWarn)) {
|
||||
if (isAdmin) {
|
||||
return next();
|
||||
}
|
||||
const reason = 'Channel forward/link';
|
||||
const warnCount = await warn(userToWarn, reason);
|
||||
const warnCount = await warn(user, reason);
|
||||
const promises = [
|
||||
bot.telegram.deleteMessage(chat.id, message.message_id)
|
||||
];
|
||||
if (warnCount < numberOfWarnsToBan) {
|
||||
promises.push(reply(
|
||||
`⚠️ ${link(userToWarn)} <b>got warned!</b> (${warnCount}/3)` +
|
||||
`⚠️ ${link(user)} <b>got warned!</b> (${warnCount}/3)` +
|
||||
`\n\nReason: ${reason}`,
|
||||
replyOptions));
|
||||
} else {
|
||||
promises.push(bot.telegram.kickChatMember(chat.id, userToWarn.id));
|
||||
promises.push(ban(userToWarn,
|
||||
promises.push(bot.telegram.kickChatMember(chat.id, user.id));
|
||||
promises.push(ban(user,
|
||||
'Reached max number of warnings'));
|
||||
promises.push(reply(
|
||||
`🚫 ${link(userToWarn)} <b>got banned</b>! (${warnCount}/3)` +
|
||||
`🚫 ${link(user)} <b>got banned</b>! (${warnCount}/3)` +
|
||||
'\n\nReason: Reached max number of warnings',
|
||||
replyOptions));
|
||||
}
|
@@ -1,25 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
// Utils
|
||||
const { loadJSON } = require('../../utils/json');
|
||||
|
||||
// Config
|
||||
const { masterID } = loadJSON('config.json');
|
||||
|
||||
// DB
|
||||
const { getCommand } = require('../../stores/command');
|
||||
const { isAdmin } = require('../../stores/user');
|
||||
|
||||
const runCustomCmdHandler = async (ctx, next) => {
|
||||
const { message } = ctx;
|
||||
const user = message.from;
|
||||
const isCommand = message.entities &&
|
||||
message.entities.filter(entity => entity.type === 'bot_command');
|
||||
if (!isCommand || !isCommand.length) {
|
||||
const { message, state } = ctx;
|
||||
const { isAdmin, isMaster } = state;
|
||||
const isCommand = /^!\w+/.test(message.text);
|
||||
if (!isCommand) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const commandName = message.text.split(' ')[0].replace('/', '');
|
||||
const commandName = message.text.split(' ')[0].replace('!', '');
|
||||
const command = await getCommand({ isActive: true, name: commandName });
|
||||
|
||||
if (!command) {
|
||||
@@ -33,9 +25,9 @@ const runCustomCmdHandler = async (ctx, next) => {
|
||||
const options = Object.assign(replyTo, caption ? { caption } : {});
|
||||
if (
|
||||
role === 'Master' &&
|
||||
user.id !== masterID ||
|
||||
!isMaster ||
|
||||
role === 'Admins' &&
|
||||
!await isAdmin(user)
|
||||
!isAdmin
|
||||
) {
|
||||
return next();
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// Utils
|
||||
const { logError } = require('../../utils/log');
|
||||
|
||||
// DB
|
||||
const { addUser, isUser } = require('../../stores/user');
|
||||
|
||||
const addUserHandler = async ({ message }, next) => {
|
||||
const usersToAdd = [];
|
||||
if (message.from && !await isUser(message.from)) {
|
||||
usersToAdd.push(message.from);
|
||||
}
|
||||
if (
|
||||
message.reply_to_message &&
|
||||
message.reply_to_message.from &&
|
||||
!await isUser(message.reply_to_message.from)
|
||||
) {
|
||||
usersToAdd.push(message.reply_to_message.from);
|
||||
}
|
||||
|
||||
usersToAdd.forEach(async user => {
|
||||
try {
|
||||
await addUser(user);
|
||||
} catch (err) {
|
||||
logError(err);
|
||||
}
|
||||
});
|
||||
|
||||
return next();
|
||||
};
|
||||
|
||||
module.exports = addUserHandler;
|
@@ -15,7 +15,7 @@ const addedToGroupHandler = async (ctx, next) => {
|
||||
user.username === ctx.me);
|
||||
if (wasAdded && ctx.from.id === masterID) {
|
||||
await admin(ctx.from);
|
||||
if (!await managesGroup(ctx.chat)) {
|
||||
if (!await managesGroup({ id: ctx.chat.id })) {
|
||||
try {
|
||||
const link = await telegram.exportChatInviteLink(ctx.chat.id);
|
||||
ctx.chat.link = link ? link : '';
|
||||
|
@@ -47,7 +47,9 @@ const randomChoice = arr => arr[Math.floor(Math.random() * arr.length)];
|
||||
* @returns {Promise.<*>} - returns next object
|
||||
*/
|
||||
const leaveUnmanagedHandler = async (ctx, next) => {
|
||||
if (ctx.chat.type === 'private' || await managesGroup(ctx.chat)) {
|
||||
if (
|
||||
ctx.chat.type === 'private' ||
|
||||
await managesGroup({ id: ctx.chat.id })) {
|
||||
return next();
|
||||
}
|
||||
|
||||
|
18
index.js
18
index.js
@@ -26,6 +26,7 @@ const delTimeout = 2 * 60 * 1000;
|
||||
* Path of middlewares and commands
|
||||
*/
|
||||
const middleware = './handlers/middlewares';
|
||||
const message = './handlers/messages';
|
||||
const command = './handlers/commands';
|
||||
|
||||
/**
|
||||
@@ -35,14 +36,19 @@ const command = './handlers/commands';
|
||||
const leaveUnmanagedHandler = require(`${middleware}/leaveUnmanaged`);
|
||||
const removeCommandsHandler = require(`${middleware}/removeCommands`);
|
||||
const kickBannedHandler = require(`${middleware}/kickBanned`);
|
||||
const addUserHandler = require(`${middleware}/addUser`);
|
||||
const removeLinksHandler = require(`${middleware}/removeLinks`);
|
||||
const checkUsernameHandler = require(`${middleware}/checkUsername`);
|
||||
const addCustomCmdHandler = require(`${middleware}/addCustomCmd`);
|
||||
const runCustomCmdHandler = require(`${middleware}/runCustomCmd`);
|
||||
const antibotHandler = require(`${middleware}/antibot`);
|
||||
const addedToGroupHandler = require(`${middleware}/addedToGroup`);
|
||||
|
||||
/**
|
||||
* @type {function}
|
||||
* Messages Handlers
|
||||
*/
|
||||
const addUserHandler = require(`${message}/addUser`);
|
||||
const removeLinksHandler = require(`${message}/removeLinks`);
|
||||
const checkUsernameHandler = require(`${message}/checkUsername`);
|
||||
const addCustomCmdHandler = require(`${message}/addCustomCmd`);
|
||||
const runCustomCmdHandler = require(`${message}/runCustomCmd`);
|
||||
|
||||
/**
|
||||
* @type {function}
|
||||
* Commmands Handlers
|
||||
@@ -88,7 +94,7 @@ bot.command('getwarns', getWarnsHandler);
|
||||
bot.command('ban', banHandler);
|
||||
bot.command('unban', unbanHandler);
|
||||
bot.command('report', reportHandler);
|
||||
bot.hears(/^@admins?$/i, reportHandler);
|
||||
bot.hears(/^@admins?\s?/i, reportHandler);
|
||||
bot.command('staff', staffHandler);
|
||||
bot.command('link', linkHandler);
|
||||
bot.command('groups', groupsHandler);
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "thedevs_bot",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "thedevs_bot",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"description": "Official Bot for The Devs community.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
@@ -19,7 +19,7 @@ const listGroups = () =>
|
||||
Group.find({});
|
||||
|
||||
const managesGroup = group =>
|
||||
Group.findOne({ id: group.id });
|
||||
Group.findOne(group);
|
||||
|
||||
const removeGroup = ({ id }) =>
|
||||
Group.remove({ id });
|
||||
|
@@ -47,10 +47,12 @@ const isAdmin = ({ id }) =>
|
||||
User.findOne({ id, status: 'admin' });
|
||||
|
||||
const ban = ({ id }, ban_reason) =>
|
||||
User.update({ id }, { $set: { ban_reason, status: 'banned', warns: [] } });
|
||||
User.update({ id }, { $set: { ban_reason, status: 'banned' } });
|
||||
|
||||
const unban = ({ id }) =>
|
||||
User.update({ id }, { $set: { banReason: '', status: 'member' } });
|
||||
User.update(
|
||||
{ id },
|
||||
{ $set: { ban_reason: null, status: 'member', warns: [] } });
|
||||
|
||||
const isBanned = ({ id }) =>
|
||||
User.findOne({ id, status: 'banned' })
|
||||
|
@@ -1,10 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { readFileSync, writeFileSync } = require('fs');
|
||||
|
||||
const loadJSON = file => JSON.parse(readFileSync(file, 'utf8'));
|
||||
|
||||
const saveJSON = (file, data) => writeFileSync(file,
|
||||
JSON.stringify(data, null, '\t'));
|
||||
|
||||
module.exports = { loadJSON, saveJSON };
|
@@ -5,12 +5,14 @@ const { inspect } = require('util');
|
||||
/**
|
||||
* @param {Error} err
|
||||
* Logs errors to console
|
||||
* @returns {undefined}
|
||||
*/
|
||||
const logError = err => console.error(err);
|
||||
|
||||
/**
|
||||
* @param {Object} value
|
||||
* Echos the value of a value.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
const print = value =>
|
||||
console.log(inspect(value, { colors: true, depth: null }));
|
||||
|
Reference in New Issue
Block a user