Skip to content

Commit 92f2ae2

Browse files
committed
feat: Implement user command functionality for group management and reporting
- Added `/rules` command to display, add, or delete group rules. - Added `/codetime` command for sending humiliating messages in a fun context. - Added `/future` command to send a predefined message about future plans. - Added `/groupinfo` command to fetch and send detailed information about the current group. - Added `/report` and `/cancel` commands for reporting issues and canceling messages, utilizing `ReportCommand`. - Added `/link` command to share the group's invite link. - Added `/adminlist` command to send a list of group admins. These commands help with group management, user interaction, and providing group-related information. Implemented a structured response format using `BotReply` for consistency.
1 parent e32d485 commit 92f2ae2

1 file changed

Lines changed: 208 additions & 0 deletions

File tree

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import { Context } from 'grammy';
2+
import { BotReply } from '../../../utils/chat/BotReply';
3+
import { RoastMessages } from '../../../types/CommandTypes';
4+
import * as roastMessages from '../../../utils/jsons/roast.json';
5+
import { ReportCommand } from './ReportCommand';
6+
import { ServiceProvider } from '../../../service/database/ServiceProvider';
7+
export class UserCommands {
8+
/**
9+
* Sends the rules of the group.
10+
* This command retrieves and sends the rules of the current group to the user.
11+
* It helps ensure that group members are aware of the guidelines for interaction.
12+
*/
13+
static async rules(ctx: Context) {
14+
const reply = new BotReply(ctx);
15+
const groupService = await ServiceProvider.getInstance().getGroupService();
16+
17+
const input = ctx.message?.text!.split(/\s+/).slice(1);
18+
const action = input![0]?.toLowerCase();
19+
const ruleContent = input!.join(' ');
20+
if (!action) {
21+
// Default behavior: Display all rules
22+
const rulesMessage = await groupService.getRules(ctx.chat?.id!);
23+
if (rulesMessage.length === 0) {
24+
await reply.markdownReply('No rules have been set for this group.');
25+
} else {
26+
await reply.markdownReply(rulesMessage.join('\n'));
27+
}
28+
return;
29+
}
30+
31+
if (action === 'lr') {
32+
// Delete the last rule
33+
const updatedRules = await groupService.deleteLastRule(ctx.chat?.id!);
34+
if (!updatedRules) {
35+
await reply.markdownReply('No rules to delete.');
36+
} else {
37+
await reply.markdownReply('Last rule has been deleted.');
38+
}
39+
} else if (action === 'r') {
40+
// Clear all rules
41+
await groupService.clearRules(ctx.chat?.id!);
42+
await reply.markdownReply('All rules have been deleted.');
43+
} else {
44+
// Add a new rule
45+
if (!ruleContent) {
46+
await reply.markdownReply('Please provide a rule to add.');
47+
return;
48+
}
49+
await groupService.addRule(ctx.chat?.id!, ruleContent);
50+
await reply.markdownReply(`Rule added: "${ruleContent}"`);
51+
}
52+
}
53+
/**
54+
* Sends a humiliating message when the /codetime command is triggered by a group member
55+
* or when someone replies to the bot with this command.
56+
* This is typically used for fun purposes,
57+
*/
58+
static async codetime(ctx: Context) {
59+
const user = ctx.from;
60+
if (!user) return;
61+
const reply = new BotReply(ctx);
62+
63+
const targetUser = ctx.message?.reply_to_message?.from;
64+
65+
const randomHours = (min: number, max: number) => {
66+
return Math.floor(Math.random() * (max - min + 1)) + min;
67+
};
68+
// Function to get a random message from the appropriate category
69+
const getRandomMessage = (category: keyof RoastMessages) => {
70+
const messages = roastMessages[category];
71+
const randomIndex = Math.floor(Math.random() * messages.length);
72+
return messages[randomIndex];
73+
};
74+
75+
if (targetUser?.id === ctx.me?.id) {
76+
const hours = randomHours(7, 10);
77+
const message = getRandomMessage('replyToBot').replace('{hours}', hours.toString());
78+
return await reply.textReply(message);
79+
}
80+
if (targetUser) {
81+
const hours = randomHours(3, 10);
82+
const username = targetUser.username ? `@${targetUser.username}` : targetUser.first_name;
83+
const message = getRandomMessage('replyToUser').replace('{username}', username).replace('{hours}', hours.toString());
84+
await reply.replyToMessage(message);
85+
} else {
86+
const hours = randomHours(1, 7);
87+
const message = getRandomMessage('notReplyingToAnyone').replace('{hours}', hours.toString());
88+
await reply.send(message);
89+
}
90+
}
91+
/**
92+
* Sends a message with the content: "We will go to ga".
93+
* This is a simple, predefined message that might be part of a larger set of group commands.
94+
* It could be used to inform the group about future plans or events.
95+
*/
96+
static future(ctx: Context) {
97+
return new BotReply(ctx).textReply('We will go to ga');
98+
}
99+
/**
100+
* Sends the last post from a specific module or CodeModule.
101+
* This could be used to inform the group about the latest developments or announcements related to the project.
102+
* It requires access to the channel to fetch the latest message.
103+
*/
104+
static async news(ctx: Context) {}
105+
/**
106+
* Sends information about the current group the user is in.
107+
* This command is useful for users to learn more about the group they are interacting with.
108+
* The information could include the group name, description, and any additional relevant data.
109+
*/
110+
static async groupinfo(ctx: Context) {
111+
const group = ctx.chat;
112+
const reply = new BotReply(ctx);
113+
// Ensure we are in a group context
114+
if (!group || (group.type !== 'group' && group.type !== 'supergroup')) {
115+
await reply.send('This command can only be used in groups.');
116+
return;
117+
}
118+
119+
// Fetch detailed chat information from Telegram API if necessary
120+
const chatDetails = await ctx.api.getChat(group.id);
121+
122+
// Extract information
123+
const groupName = chatDetails.title || 'Unnamed Group';
124+
const groupDescription = chatDetails.description || 'No description available';
125+
const groupType = chatDetails.type === 'supergroup' ? 'Supergroup' : 'Group';
126+
const memberCount = await ctx.api.getChatMemberCount(group.id);
127+
const inviteLink = chatDetails.invite_link || 'Invite link not available';
128+
const creator = await ctx.api.getChatAdministrators(group.id);
129+
const adminList = creator.filter((admin) => admin.status === 'administrator' || admin.status === 'creator');
130+
131+
// Format admin list
132+
const admins = adminList
133+
.map((admin) => {
134+
const username = admin.user.username ? `@${admin.user.username}` : admin.user.first_name;
135+
return `${username} (${admin.status === 'creator' ? 'Creator' : 'Admin'})`;
136+
})
137+
.join(', ');
138+
139+
// Create the response message
140+
const response = `
141+
<b>Group Information:</b>
142+
- <b>Name:</b> ${groupName}
143+
- <b>Type:</b> ${groupType}
144+
- <b>Description:</b> ${groupDescription}
145+
- <b>Members:</b> ${memberCount}
146+
- <b>Admins:</b> ${admins || 'No admins available'}
147+
- <b>Invite Link:</b> ${inviteLink}
148+
`.trim();
149+
150+
// Send the response to the chat
151+
await reply.htmlReply(response);
152+
}
153+
/**
154+
* Sends a message to the group admins.
155+
* This command allows users to report issues or ask questions directly to the group admins.
156+
* It’s typically used for urgent matters or when a user needs assistance.
157+
*/
158+
static async report(ctx: Context) {
159+
ReportCommand.report(ctx);
160+
}
161+
/**
162+
* Cancels and deletes a message that was supposed to be sent.
163+
* This is useful for preventing spam or correcting mistakes before sending the message to the group.
164+
* It’s a safety measure to ensure that unwanted messages are not posted.
165+
*/
166+
static cancel(ctx: Context) {
167+
ReportCommand.cancel(ctx);
168+
}
169+
/**
170+
* Sends the link of the group the user is in.
171+
* This command is useful for users who want to share the group’s link with others.
172+
* The link can be used to invite others or for reference purposes.
173+
*/
174+
static async link(ctx: Context) {
175+
const reply = new BotReply(ctx);
176+
// Fetch the group chat details, which should include the invite link if the bot has the necessary permissions
177+
const chat = await ctx.api.getChat(ctx.chat!.id);
178+
if (chat.invite_link) {
179+
// Send the invite link to the user
180+
await reply.textReply(`Here is the invite link for this group: ${chat.invite_link}`);
181+
} else {
182+
// If no link exists, try to generate a new one (requires admin rights)
183+
const inviteLink = await ctx.api.exportChatInviteLink(ctx.chat!.id);
184+
await reply.textReply(`Here is the invite link for this group: ${inviteLink}`);
185+
}
186+
}
187+
/**
188+
* Sends a list of admins in the current group.
189+
* This is helpful for users to know who the admins are, especially in larger groups.
190+
* Admins can handle issues, provide support, and moderate the group.
191+
*/
192+
static async adminlist(ctx: Context) {
193+
const reply = new BotReply(ctx);
194+
// Fetch the list of administrators in the group
195+
const admins = await ctx.api.getChatAdministrators(ctx.chat!.id);
196+
const adminList = admins
197+
.filter((admin) => !admin.user.is_bot) // Exclude bots from the admin list
198+
.map((admin) => `- ${admin.user.first_name} (@${admin.user.username || 'No username'})`)
199+
.join('\n');
200+
201+
if (adminList) {
202+
// Send the formatted list of admins to the user
203+
await reply.htmlReply(`<b>Admins in this group:</b>\n${adminList}`);
204+
} else {
205+
await reply.textReply("There are no admins in this group or I couldn't fetch them.");
206+
}
207+
}
208+
}

0 commit comments

Comments
 (0)