Skip to content

Commit

Permalink
merge: #169 from feat/better-admin-log
Browse files Browse the repository at this point in the history
  • Loading branch information
MKRhere authored Oct 2, 2023
2 parents 970a12e + efcd382 commit 45cb897
Show file tree
Hide file tree
Showing 16 changed files with 2,299 additions and 1,673 deletions.
26 changes: 0 additions & 26 deletions .circleci/config.yml

This file was deleted.

5 changes: 2 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"prettier/@typescript-eslint"
"prettier"
],
"rules": {
"@typescript-eslint/ban-ts-ignore": "warn",
"@typescript-eslint/ban-ts-comment": "warn",
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-floating-promises": "error",
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Checks
on:
push:
branches:
- develop
pull_request:
branches:
- develop

jobs:
release:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- run : npm ci
- name: Lint
run: npm run -s lint
- name: Typecheck
run: npm run -s typecheck
55 changes: 0 additions & 55 deletions bot/context.js

This file was deleted.

79 changes: 79 additions & 0 deletions bot/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import warn from "../actions/warn";
import ban from "../actions/ban";
import batchBan from "../actions/batchBan";
import { scheduleDeletion } from "../utils/tg";

import { config } from "../utils/config";
import { ContextExtensions } from "../typings/context";

const {
warnInlineKeyboard,
chats = {},
deleteWarnsAfter = false,
deleteBansAfter = false,
} = config;

const normalisedDeleteWarnsAfter =
typeof deleteWarnsAfter === "object"
? deleteWarnsAfter
: { auto: deleteWarnsAfter, manual: deleteWarnsAfter };

const reply_markup = { inline_keyboard: warnInlineKeyboard };

export const extn: ContextExtensions = {
async ban({ admin, reason, userToBan, msg }) {
const banMessage = await ban({ admin, reason, userToBan });

const done = await this.loggedReply(banMessage, msg).then(
scheduleDeletion(deleteBansAfter),
);

if (msg)
this.telegram
.deleteMessage(msg.chat.id, msg.message_id)
.catch(() => null);

return done;
},

async batchBan({ admin, reason, targets }) {
const banMessage = await batchBan({ admin, reason, targets });
return this.loggedReply(banMessage).then(scheduleDeletion(deleteBansAfter));
},

async warn({ admin, amend, reason, userToWarn, mode, msg }) {
const warnMessage = await warn({ admin, amend, reason, userToWarn });

const done = await this.loggedReply(warnMessage, msg, {
reply_markup,
}).then(scheduleDeletion(normalisedDeleteWarnsAfter[mode]));

if (msg)
this.telegram
.deleteMessage(msg.chat.id, msg.message_id)
.catch(() => null);

return done;
},

async loggedReply(html, reply, extra) {
if (chats.adminLog) {
const msg =
reply &&
(await this.telegram.forwardMessage(
chats.adminLog,
reply.chat.id,
reply.message_id,
));
this.telegram
// @ts-expect-error sendMessage is monkeypatched to accept TgHtml
.sendMessage(chats.adminLog, html, {
parse_mode: "HTML",
reply_to_message_id: msg?.message_id,
})
.catch(() => null);
}
// @ts-expect-error sendMessage is monkeypatched to accept TgHtml
return this.replyWithHTML(html, extra);
},
};
2 changes: 1 addition & 1 deletion bot/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ Object.defineProperty(bot.context, "botInfo", {

// cyclic dependency
// bot/index requires context requires actions/warn requires bot/index
Object.assign(bot.context, require('./context'));
Object.assign(bot.context, require('./context').extn);
16 changes: 15 additions & 1 deletion example.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ const config = {

chats: {

/**
* @type {(number | false)}
* Chat to send member (un)ban/(un)warn/report notifications and
* relevant messages to. Pass false to disable this feature.
*/
adminLog: false,

/**
* @type {(number | false)}
* Chat to send member join/leave notifications to.
Expand All @@ -56,6 +63,13 @@ const config = {
* Pass false to disable this feature.
*/
report: false,

/**
* @type {(true | false)}
* Disable whether clicking on `[Report handled]` deletes the
* report chat message.
*/
noReportChatDeletion: false,
},

/**
Expand All @@ -67,7 +81,7 @@ const config = {

deleteCustom: {
longerThan: 450, // UTF-16 characters
after: '20 minutes'
after: '20 minutes',
},

/**
Expand Down
6 changes: 1 addition & 5 deletions handlers/commands/ban.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ const banHandler = async (ctx) => {
return ctx.replyWithHTML('ℹ️ <b>Can\'t ban other admins.</b>');
}

if (ctx.message.reply_to_message) {
ctx.deleteMessage(ctx.message.reply_to_message.message_id)
.catch(() => null);
}

if (!flags.has('amend') && userToBan.status === 'banned') {
return ctx.replyWithHTML(
html`🚫 ${displayUser(userToBan)} <b>is already banned.</b>`,
Expand All @@ -67,6 +62,7 @@ const banHandler = async (ctx) => {
admin: ctx.from,
reason: '[' + ctx.chat.title + '] ' + await substom(reason),
userToBan,
msg: ctx.message.reply_to_message
});
};

Expand Down
15 changes: 9 additions & 6 deletions handlers/commands/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,32 @@ const reportHandler = async ctx => {
// Ignore monospaced reports
if (ctx.message.entities?.[0]?.type === 'code' && ctx.message.entities[0].offset === 0)
return null;
if (!ctx.message.reply_to_message) {
const reply = ctx.message.reply_to_message;
if (!reply) {
await ctx.deleteMessage();
return ctx.replyWithHTML(
'ℹ️ <b>Reply to message you\'d like to report</b>',
'ℹ️ <b>Reply to the message you\'d like to report</b>',
).then(scheduleDeletion());
}
const admins = (await ctx.getChatAdministrators())
.filter(isQualified)
.map(adminMention);
// eslint-disable-next-line max-len
const s = TgHtml.tag`❗️ <b>Message from ${link(ctx.message.reply_to_message.from)} was reported to the admins</b>.${TgHtml.join('', admins)}`;
const s = TgHtml.tag`❗️ <b>Message from ${link(reply.from)} was reported to the admins</b>.${TgHtml.join('', admins)}`;
const report = await ctx.replyWithHTML(s, {
reply_to_message_id: ctx.message.reply_to_message.message_id,
reply_to_message_id: reply.message_id,
});
if (chats.report) {
const msg = await ctx.telegram.forwardMessage(chats.report, ctx.chat.id, reply.message_id);
await ctx.deleteMessage();
await ctx.telegram.sendMessage(
chats.report,
TgHtml.tag`❗️ ${link(ctx.from)} reported <a href="${msgLink(
ctx.message.reply_to_message,
)}">a message</a> from ${link(ctx.message.reply_to_message.from)} in ${ctx.chat.title}!`,
reply,
)}">a message</a> from ${link(reply.from)} in ${ctx.chat.title}!`,
{
parse_mode: 'HTML',
reply_to_message_id: msg.message_id,
reply_markup: { inline_keyboard: [ [ {
text: '✔️ Handled',
callback_data: Cmd.stringify({
Expand Down
6 changes: 1 addition & 5 deletions handlers/commands/warn.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,13 @@ const warnHandler = async (ctx) => {
.then(scheduleDeletion());
}

if (ctx.message.reply_to_message) {
ctx.deleteMessage(ctx.message.reply_to_message.message_id)
.catch(() => null);
}

return ctx.warn({
admin: ctx.from,
amend: flags.has('amend'),
reason: '[' + ctx.chat.title + '] ' + await substom(reason),
userToWarn,
mode: 'manual',
msg: ctx.message.reply_to_message,
});
};

Expand Down
22 changes: 18 additions & 4 deletions handlers/middlewares/reportHandled.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
import { CallbackQuery, Message, Update } from "telegraf/types";
import { config } from "../../utils/config";
import type { ExtendedContext } from "../../typings/context";

export = (ctx: ExtendedContext) => {
export = async (
ctx: ExtendedContext<Update.CallbackQueryUpdate<CallbackQuery.DataQuery>>,
) => {
if (ctx.from?.status !== "admin") {
return ctx.answerCbQuery("✋ Not permitted!", false, { cache_time: 600 });
return ctx.answerCbQuery("✋ Not permitted!", { cache_time: 600 });
}

const [, chatId, msgId] = ctx.match!;
// @ts-expect-error ctx.match is available but not registered in this callback type
const [, chatId, msgId] = (ctx.match as string[])!;

// delete the report in the actual chat
await ctx.telegram.deleteMessage(+chatId, +msgId);

if (config.chats?.noReportChatDeletion) return null;
return Promise.all([
// delete the report in the report chat
ctx.deleteMessage(),
ctx.telegram.deleteMessage(+chatId, +msgId),
// delete the forwarded contextual message in report chat
ctx.deleteMessage(
(ctx.callbackQuery.message as Message.TextMessage)?.reply_to_message
?.message_id,
),
]);
};
Loading

0 comments on commit 45cb897

Please sign in to comment.