Skip to content

Commit 07780e9

Browse files
Refactor chat join request handling into a dedicated handler function
1 parent 8966b2e commit 07780e9

File tree

2 files changed

+248
-144
lines changed

2 files changed

+248
-144
lines changed
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
import { Context } from 'hono';
2+
import { Environment } from '../types';
3+
import { TelegramService } from '../services/telegram';
4+
import { MemberSheetServices } from '../services/membership-manager/member-sheet-services';
5+
import { AllMessagesGroupsCrud } from '../crud/all-messages-groups';
6+
import { D1DatabaseConnection } from '../crud/database';
7+
import { escapeMarkdownV2 } from '../utils/helpers';
8+
9+
/**
10+
* Handler for Telegram chat join requests
11+
* This handles the logic when users request to join a group/channel
12+
*/
13+
export async function handleChatJoinRequest(
14+
update: any,
15+
c: Context<{ Bindings: Environment }>
16+
): Promise<Response> {
17+
const joinRequest = update.chat_join_request;
18+
const telegramId = joinRequest.from.id;
19+
const chatId = joinRequest.chat.id;
20+
const username = joinRequest.from.username;
21+
const firstName = joinRequest.from.first_name;
22+
const lastName = joinRequest.from.last_name || '';
23+
const fullName = `${firstName} ${lastName}`.trim();
24+
25+
console.log('Received chat join request:', {
26+
chatId,
27+
chatTitle: joinRequest.chat.title,
28+
userId: telegramId,
29+
username,
30+
firstName,
31+
lastName,
32+
date: new Date(joinRequest.date * 1000).toISOString()
33+
});
34+
35+
// Store the join request in all_messages_groups table
36+
await storeJoinRequest(joinRequest, fullName, username, c.env);
37+
38+
const telegramService = new TelegramService(c.env);
39+
const memberSheetServices = new MemberSheetServices(c.env);
40+
41+
// Check if the user has the bot activated (can receive messages)
42+
const hasBotActivated = await telegramService.canSendMessageToUser(telegramId);
43+
44+
if (hasBotActivated) {
45+
// User has bot activated - check if they are verified
46+
await handleUserWithBot(
47+
telegramId,
48+
chatId,
49+
fullName,
50+
username,
51+
memberSheetServices,
52+
telegramService
53+
);
54+
} else {
55+
// User doesn't have bot activated - send silent message to group
56+
await handleUserWithoutBot(
57+
telegramId,
58+
chatId,
59+
fullName,
60+
username,
61+
telegramService,
62+
c
63+
);
64+
}
65+
66+
return c.json({ ok: true });
67+
}
68+
69+
/**
70+
* Store join request in database
71+
*/
72+
async function storeJoinRequest(
73+
joinRequest: any,
74+
fullName: string,
75+
username: string | undefined,
76+
env: Environment
77+
): Promise<void> {
78+
try {
79+
const db = new D1DatabaseConnection(env.DB);
80+
const groupMessagesCrud = new AllMessagesGroupsCrud(db);
81+
82+
// Create a message-like structure for the join request
83+
const joinRequestMessage = {
84+
chat: joinRequest.chat,
85+
from: joinRequest.from,
86+
date: joinRequest.date,
87+
user_chat_id: joinRequest.user_chat_id,
88+
bio: joinRequest.bio,
89+
invite_link: joinRequest.invite_link,
90+
// Mark this as a join request
91+
message_type: 'chat_join_request'
92+
};
93+
94+
await groupMessagesCrud.storeMessage(
95+
joinRequestMessage,
96+
`Join request from ${fullName} (@${username || 'no_username'})`
97+
);
98+
99+
console.log('Stored chat join request in database');
100+
} catch (storageError) {
101+
console.error('Failed to store chat join request:', storageError);
102+
}
103+
}
104+
105+
/**
106+
* Handle user who has the bot activated
107+
* Checks verification status and sends appropriate response
108+
*/
109+
async function handleUserWithBot(
110+
telegramId: number,
111+
chatId: number,
112+
fullName: string,
113+
username: string | undefined,
114+
memberSheetServices: MemberSheetServices,
115+
telegramService: TelegramService
116+
): Promise<void> {
117+
// Check if user is verified
118+
const member = await memberSheetServices.getMemberByTelegramId(telegramId.toString());
119+
120+
if (member && member.telegram_id) {
121+
// User is verified - create and send private invite link
122+
await sendPrivateInviteLink(
123+
telegramId,
124+
chatId,
125+
fullName,
126+
telegramService
127+
);
128+
} else {
129+
// User has bot but not verified - ask them to verify
130+
await sendVerificationPrompt(telegramId, fullName, telegramService);
131+
}
132+
}
133+
134+
/**
135+
* Send private invite link to verified user
136+
*/
137+
async function sendPrivateInviteLink(
138+
telegramId: number,
139+
chatId: number,
140+
fullName: string,
141+
telegramService: TelegramService
142+
): Promise<void> {
143+
try {
144+
const inviteLink = await telegramService.createChatInviteLink(
145+
chatId,
146+
telegramId,
147+
fullName
148+
);
149+
150+
if (inviteLink) {
151+
// Send the private invite link to the user
152+
await telegramService.sendMessage(
153+
telegramId,
154+
`مرحباً ${escapeMarkdownV2(fullName)}\\! 🎉\n\n` +
155+
`تم التحقق من عضويتك بنجاح\\.\n\n` +
156+
`إليك رابط الانضمام الخاص بك:\n` +
157+
`${escapeMarkdownV2(inviteLink)}\n\n` +
158+
`⚠️ *ملاحظة مهمة:*\n` +
159+
`• هذا الرابط خاص بك فقط\n` +
160+
`• يمكن استخدامه مرة واحدة فقط\n` +
161+
`• لا تشاركه مع أي شخص آخر`
162+
);
163+
164+
console.log(`Sent private invite link to verified user ${telegramId}`);
165+
166+
// Optionally approve the join request automatically
167+
// await telegramService.approveChatJoinRequest(chatId, telegramId);
168+
} else {
169+
// Failed to create invite link - fall back to manual approval
170+
await telegramService.sendMessage(
171+
telegramId,
172+
`مرحباً ${escapeMarkdownV2(fullName)}\\!\n\n` +
173+
`تم التحقق من عضويتك\\. سيتم الموافقة على طلبك قريباً\\.`
174+
);
175+
console.log(`Failed to create invite link, sent confirmation to user ${telegramId}`);
176+
}
177+
} catch (error) {
178+
console.error('Error creating/sending invite link:', error);
179+
}
180+
}
181+
182+
/**
183+
* Send verification prompt to unverified user
184+
*/
185+
async function sendVerificationPrompt(
186+
telegramId: number,
187+
fullName: string,
188+
telegramService: TelegramService
189+
): Promise<void> {
190+
try {
191+
await telegramService.sendMessage(
192+
telegramId,
193+
`مرحباً ${escapeMarkdownV2(fullName)}\\!\n\n` +
194+
`لقد تلقينا طلب انضمامك إلى المجموعة\\.\n\n` +
195+
`يرجى استخدام الأمر /verify للتحقق من عضويتك حتى تتمكن من الوصول إلى المجموعة\\.`
196+
);
197+
console.log(`Sent verification message to unverified user ${telegramId}`);
198+
} catch (error) {
199+
console.error('Error sending message to user with bot activated:', error);
200+
}
201+
}
202+
203+
/**
204+
* Handle user who doesn't have the bot activated
205+
* Sends a silent message to the group that auto-deletes
206+
*/
207+
async function handleUserWithoutBot(
208+
telegramId: number,
209+
chatId: number,
210+
fullName: string,
211+
username: string | undefined,
212+
telegramService: TelegramService,
213+
c: Context<{ Bindings: Environment }>
214+
): Promise<void> {
215+
try {
216+
const usernameText = username ? `@${escapeMarkdownV2(username)}` : '';
217+
const messageText = `عزيزي/عزيزتي ${escapeMarkdownV2(fullName)} ${usernameText}\n\n` +
218+
`يرجى التواصل مع هذا البوت على الخاص حتى تتمكن من الانضمام إلى المجموعة\\.`;
219+
220+
const sentMessageId = await telegramService.sendMessage(
221+
chatId,
222+
messageText,
223+
'MarkdownV2',
224+
undefined,
225+
undefined,
226+
undefined,
227+
true // disable_notification for silent message
228+
);
229+
230+
console.log(`Sent silent message to group for user ${telegramId} who doesn't have bot activated`);
231+
232+
// Schedule message deletion after 10 seconds
233+
// Note: Using waitUntil to ensure the deletion happens even after response is sent
234+
if (sentMessageId) {
235+
c.executionCtx.waitUntil(
236+
(async () => {
237+
await new Promise(resolve => setTimeout(resolve, 10000));
238+
await telegramService.deleteMessage(chatId, sentMessageId);
239+
console.log(`Deleted notification message ${sentMessageId} from group ${chatId}`);
240+
})()
241+
);
242+
}
243+
} catch (error) {
244+
console.error('Error sending/deleting message to group:', error);
245+
}
246+
}

0 commit comments

Comments
 (0)