11import { Context } from "grammy" ;
22import { AppDataSource } from "../config/db" ;
33import { GroupSettings } from "../entities/GroupSettings" ;
4- import { Repository } from " typeorm" ;
4+ import { Repository } from ' typeorm' ;
55import * as BlackListJson from "../helper/black_list.json" ;
66import { MuteService } from "./command/mute" ;
77import { BanService } from "./command/ban" ;
88import { SafeExecution } from "../decorators/SafeExecution" ;
99import { ApprovedUser } from "../entities/ApprovedUser" ;
1010import { GroupSettingsService } from "./db/group" ;
1111import { Logger } from "../config/logger" ;
12- import { BlacklistService } from "./command/blacklist" ;
1312import { UserService } from "./db/user" ;
14- import { GroupMembershipService } from "./db/group/Membership" ;
1513import { MESSAGE } from "../helper/message" ;
1614import { RateLimiter } from "../helper/RateLimiter" ;
17- const logger = new Logger ( { file : "join_group.log" , level : "info" , timestampFormat :'locale' } ) ;
15+ const logger = new Logger ( {
16+ file : "join_group.log" ,
17+ level : "info" ,
18+ timestampFormat : "locale" ,
19+ } ) ;
1820
1921export class MessageCheck {
22+ @SafeExecution ( )
23+ private static async getEntities ( ctx : Context ) {
24+ if ( ! ctx . chat ) {
25+ console . error ( "No ctx.chat found, skipping isNewUser check." ) ;
26+ return { groupSettings : null , group : null } ;
27+ }
28+ const groupSettings = new GroupSettingsService ( ) ;
29+ const groupId = ctx . chat ! . id ;
30+
31+ // Fetch the group settings for the current chat
32+ let group = await groupSettings . getByGroupId ( groupId ) ;
33+
34+ if ( ! group ) {
35+ await groupSettings . init ( ctx ) ;
36+ }
37+ return { groupSettings, group } ;
38+ }
39+
40+ @SafeExecution ( )
41+ static async isNewUser ( ctx : Context ) {
42+ const entity = await MessageCheck . getEntities ( ctx ) ;
43+ const { group, groupSettings } = entity || { } ;
44+ if ( ! group || ! groupSettings ) {
45+ return ;
46+ }
47+ if ( ctx . message ?. new_chat_members ?. length ! > 0 ) {
48+ const users = ctx . message ! . new_chat_members ! ;
49+
50+ for ( const user of users ) {
51+ if ( user . id !== ctx . me ?. id ) {
52+ const username = user . username
53+ ? `@${ user . username } `
54+ : user . first_name ;
55+ if ( ! group ! . members ) {
56+ group ! . members = [ ] ;
57+ }
58+ if ( ! group ! . members . includes ( user . id . toString ( ) ) ) {
59+ group ! . members . push ( user . id . toString ( ) ) ;
60+ }
61+
62+ await ctx . reply (
63+ `Dear ${ username } , welcome to ${ ctx . chat ! . title } chat ❤️`
64+ ) ;
65+ }
66+ }
67+
68+ // Save the updated group settings
69+ await groupSettings . save ( group ! ) ;
70+ }
71+ }
72+ @SafeExecution ( )
73+ static async leftGroup ( ctx : Context ) {
74+ const entity = await MessageCheck . getEntities ( ctx ) ;
75+ const { group, groupSettings } = entity || { } ;
76+ if ( ! group || ! groupSettings ) {
77+ return ;
78+ }
79+ if ( ctx . message ?. left_chat_member ) {
80+ const user = ctx . message . left_chat_member ! ;
81+
82+ if ( user . id !== ctx . me ?. id ) {
83+ // Remove the user from the members array
84+ if ( group ! . members ) {
85+ group ! . members = group ! . members . filter (
86+ ( memberId ) => memberId !== user . id . toString ( )
87+ ) ;
88+ }
89+ // Notify the group about the member leaving
90+ const username = user . username ? `@${ user . username } ` : user . first_name ;
91+ await ctx . reply ( `${ username } has left the chat.` ) ;
92+
93+ await groupSettings . save ( group ! ) ;
94+ }
95+ }
96+ }
97+
2098 @SafeExecution ( )
2199 static async CheckBlackList ( ctx : Context ) {
22100 const groupId = ctx . chat ?. id ;
101+ if ( ! groupId ) {
102+ return ;
103+ }
23104 const messageText = ctx . message ?. text ;
24105 const username = ctx . message ?. from ?. username || "User" ;
25106 const messageId = ctx . message ?. message_id ;
@@ -78,12 +159,12 @@ export class MessageCheck {
78159 return text . replace ( / [ ^ a - z A - Z آ - ی ] / g, "" ) . toLowerCase ( ) ;
79160 }
80161
162+ @SafeExecution ( )
81163 static async isAdmin ( ctx : Context , userId : number ) : Promise < boolean > {
82164 if ( ! RateLimiter . limit ( ctx . chat ! . id ) ) {
83- // If rate limit exceeded, you might want to log or handle it accordingly
84- logger . warn ( 'Rate limit exceeded for getChatAdministrators.' ) ;
85- return false ;
86- }
165+ logger . warn ( "Rate limit exceeded for getChatAdministrators." ) ;
166+ return false ;
167+ }
87168 const chatAdmins = await ctx . getChatAdministrators ( ) ;
88169 return chatAdmins . some ( ( admin ) => admin . user . id === userId ) ;
89170 }
@@ -124,7 +205,7 @@ export class MessageCheck {
124205 break ;
125206 }
126207 }
127-
208+ @ SafeExecution ( )
128209 static calculateMuteDuration ( duration : string ) : Date {
129210 const now = new Date ( ) ;
130211 const time = parseInt ( duration . slice ( 0 , - 1 ) , 10 ) ;
@@ -147,8 +228,15 @@ export class MessageCheck {
147228
148229 return now ;
149230 }
231+ @SafeExecution ( )
150232 static async initialGroup ( ctx : Context ) {
233+ if ( ! ctx . chat ) {
234+ return ;
235+ }
151236 const chat = ctx . chat ! ;
237+ if ( ! chat ) {
238+ return ;
239+ }
152240 const from = ctx . from ;
153241 try {
154242 const groupRepo = new GroupSettingsService ( ) ;
@@ -175,39 +263,27 @@ export class MessageCheck {
175263 let user = await userRepo . getByTelegramId ( from ?. id ! ) ;
176264
177265 if ( ! user ) {
178- user = await userRepo . create ( {
179- telegram_id : from ?. id ! ,
180- role : "admin" ,
181- } ) ;
182-
183- await userRepo . save ( user ) ;
266+ user = await userRepo . createUser ( ctx , from ?. id ! ) ;
184267 } else {
185268 // Update user role if needed
186269 if ( user . role !== "admin" ) {
187270 user . role = "admin" ;
188271 await userRepo . save ( user ) ;
189272 }
190273 }
191-
192- // Create a GroupMembership record
193- const membershipRepo = new GroupMembershipService ( ) ;
194- let membership = await membershipRepo . getGroupAndUserId (
195- groupSettings . id ,
196- user . id
197- ) ;
198-
199- if ( ! membership ) {
200- membership = await membershipRepo . create ( {
201- group : groupSettings ,
202- user : user ,
203- is_admin : true ,
204- } ) ;
205-
206- await membershipRepo . save ( membership ) ;
207- }
208274 await ctx . reply ( MESSAGE . newGroupJoin ( ctx , from ?. username ! ) ) ;
209275 } catch ( error : any ) {
210276 logger . error ( "Failed to save group settings" , error , "GROUP" ) ;
211277 }
212278 }
279+ static async isCode ( ctx : Context ) {
280+ const entities = ctx . message ! . entities ;
281+ entities ?. forEach ( ( e ) => {
282+ if ( e . type === "pre" && e . language ) {
283+ ctx . reply ( `Your code is garbage.\n\n- Linus Torvalds` , {
284+ reply_to_message_id : ctx . message ?. message_id ,
285+ } ) ;
286+ }
287+ } ) ;
288+ }
213289}
0 commit comments