|
| 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