Skip to content

Commit b94fcc1

Browse files
committed
refactor(bot): Updated BotReply class, added new methods to ChatInfo class, modified COMMANDS array in index.ts, added parseDuration and tehranZone functions, and removed blacklist.json file.
1 parent 66477f8 commit b94fcc1

4 files changed

Lines changed: 122 additions & 13 deletions

File tree

src/utils/chat/BotReply.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ export class BotReply {
1717
/**
1818
* Sends a plain text reply.
1919
* @param message - The plain text message to send.
20-
* @param replyToMessage - Optionally, reply to a specific message.
20+
* @param options - Additional options such as reply markup.
2121
*/
22-
async textReply(message: string): Promise<void> {
22+
async textReply(message: string, options: { reply_markup?: InlineKeyboard } = {}): Promise<void> {
2323
await this.ctx.reply(message, {
24-
reply_parameters: {
25-
message_id: this.ctx.message?.message_id!,
26-
},
24+
reply_markup: options.reply_markup,
25+
reply_to_message_id: this.ctx.message?.message_id, // Corrected the key to `reply_to_message_id`
2726
});
2827
}
2928
/**

src/utils/chat/ChatInfo.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Context } from 'grammy';
22
import { BotReply } from './BotReply';
3+
import { RateLimiter } from '../RateLimiter';
34
export class ChatInfo {
45
constructor(private _ctx: Context) {}
56

@@ -49,4 +50,67 @@ export class ChatInfo {
4950
}
5051
return undefined;
5152
}
53+
async userIsAdmin(): Promise<boolean> {
54+
const userId = this._ctx.from!.id;
55+
const chatMember = await this._ctx.getChatMember(userId);
56+
57+
return chatMember.status === 'administrator' || chatMember.status === 'creator';
58+
}
59+
async userReplyIsAdmin(): Promise<boolean | undefined> {
60+
const reply = new BotReply(this._ctx);
61+
const repliedMessage = await reply.getReplyMessage();
62+
if (repliedMessage?.from?.id) {
63+
const userId = repliedMessage.from.id;
64+
const chatMember = await this._ctx.getChatMember(userId);
65+
return chatMember.status === 'administrator' || chatMember.status === 'creator';
66+
}
67+
return undefined;
68+
}
69+
async adminList(): Promise<string> {
70+
const admins = await this._ctx.api.getChatAdministrators(this._ctx.chat!.id);
71+
const adminList = admins
72+
.filter((admin) => !admin.user.is_bot) // Exclude bots from the admin list
73+
.map((admin) => `- ${admin.user.first_name} (@${admin.user.username || 'No username'})`)
74+
.join('\n');
75+
return adminList;
76+
}
77+
78+
async chatInfo(): Promise<{
79+
groupName: string;
80+
groupType: string;
81+
groupDescription: string;
82+
memberCount: number;
83+
admins: string;
84+
inviteLink: string;
85+
} | null> {
86+
const group = this._ctx.chat;
87+
// Ensure we are in a group context
88+
if (!group || (group.type !== 'group' && group.type !== 'supergroup')) {
89+
return null;
90+
}
91+
const chatDetails = await this._ctx.api.getChat(group.id);
92+
93+
// Extract information
94+
const groupName = chatDetails.title || 'Unnamed Group';
95+
const groupDescription = chatDetails.description || 'No description available';
96+
const groupType = chatDetails.type === 'supergroup' ? 'Supergroup' : 'Group';
97+
const memberCount = await this._ctx.api.getChatMemberCount(group.id);
98+
const inviteLink = chatDetails.invite_link || 'Invite link not available';
99+
const creator = await this._ctx.api.getChatAdministrators(group.id);
100+
const adminList = creator.filter((admin) => admin.status === 'administrator' || admin.status === 'creator');
101+
const admins = adminList
102+
.map((admin) => {
103+
const username = admin.user.username ? `@${admin.user.username}` : admin.user.first_name;
104+
return `${username} (${admin.status === 'creator' ? 'Creator' : 'Admin'})`;
105+
})
106+
.join(', ');
107+
return { groupName, groupType, groupDescription, memberCount, admins, inviteLink };
108+
}
109+
async isAdmin(ctx: Context, userId: number): Promise<boolean> {
110+
if (!RateLimiter.limit(ctx.chat!.id)) {
111+
return false;
112+
}
113+
const chatAdmins = await ctx.getChatAdministrators();
114+
return chatAdmins.some((admin) => admin.user.id === userId);
115+
}
52116
}

src/utils/index.ts

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,75 @@ export const COMMANDS: string[] = [
1818
'adminlist',
1919
/** admin Commands */
2020
/** Approved Commands */
21-
'approved','disapproved','approvedlist',
21+
'approved',
22+
'disapproved',
23+
'approvedlist',
2224
/** Ban Commands */
23-
'ban','unban',
25+
'ban',
26+
'unban',
2427
/** Warn Commands */
25-
'warn','rmwarn','warns','warnslist',
28+
'warn',
29+
'rmwarn',
30+
'warns',
31+
'warnslist',
2632
/** Mute Commands */
27-
'mute','unmute','mutelist',
33+
'mute',
34+
'unmute',
35+
'mutelist',
2836
/** Admin Command */
29-
'grant','revoke',
37+
'grant',
38+
'revoke',
3039
/** BlackList Command */
31-
'blacklist','rmbl','abl',
40+
'blacklist',
41+
'rmbl',
42+
'abl',
43+
'clrbl',
3244
/** Rules Commands */
3345
'rules',
3446
/** Pin Command */
35-
'pin','unpin',
47+
'pin',
48+
'unpin',
3649
/** Purge Command */
3750
'purge',
3851
/** Group Setting Command */
39-
'lock','unlock','title','welcome',
52+
'welcome',
4053
/** General Commands */
4154
'group_stats',
4255
'shahin',
4356
'aran',
4457
] as const;
4558

4659
export type CommandName = (typeof COMMANDS)[number];
60+
61+
export function parseDuration(durationStr: string): number | null {
62+
const match = durationStr.match(/^(\d+)([smhd])$/);
63+
64+
if (!match) return null;
65+
66+
const value = parseInt(match[1], 10);
67+
const unit = match[2];
68+
69+
switch (unit) {
70+
case 's':
71+
return value * 1000; // Seconds
72+
case 'm':
73+
return value * 60 * 1000; // Minutes
74+
case 'h':
75+
return value * 60 * 60 * 1000; // Hours
76+
case 'd':
77+
return value * 24 * 60 * 60 * 1000; // Days
78+
default:
79+
return null;
80+
}
81+
}
82+
export function tehranZone() {
83+
// Get current date and adjust to Tehran time zone
84+
const now = new Date();
85+
const utcTime = now.getTime() + now.getTimezoneOffset() * 60000;
86+
87+
// Tehran timezone offset in minutes (UTC+3:30)
88+
const tehranOffset = 3.5 * 60;
89+
90+
// Adjust time to Tehran timezone without considering DST
91+
return new Date(utcTime + tehranOffset * 60000);
92+
}

src/utils/jsons/blacklist.json

Whitespace-only changes.

0 commit comments

Comments
 (0)