1+ const { driver } = require ( '@rocket.chat/sdk' ) ;
2+ const { TelegramBot } = require ( 'node-telegram-bot-api' ) ;
3+ require ( 'dotenv' ) . config ( ) ;
4+
5+ const HOST = process . env . ROCKETCHAT_URL ;
6+ const USER = process . env . USER_NAME ;
7+ const PASS = process . env . USER_PASS ;
8+ const TOKEN = process . env . TELEGRAM_TOKEN ;
9+ const SSL = true ;
10+ const ROOM = '' ;
11+ const MAX_ATTEMPTS = 10 ;
12+ const LIFETIME = 5 * 60 * 1000 ;
13+
14+ const sessions = new Map ( ) ;
15+ let myId ;
16+
17+ function genCode ( ) {
18+ return Math . floor ( 100000000000 + Math . random ( ) * 900000000 ) . toString ( ) ;
19+ }
20+
21+ function genTag ( ) {
22+ const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
23+ return letters [ Math . floor ( Math . random ( ) * 26 ) ] + letters [ Math . floor ( Math . random ( ) * 26 ) ] ;
24+ }
25+
26+ async function connRc ( ) {
27+ try {
28+ await driver . connect ( { host : HOST , useSsl : SSL } ) ;
29+ myId = await driver . login ( { username : USER , password : PASS } ) ;
30+ return true ;
31+ } catch ( e ) {
32+ return false ;
33+ }
34+ }
35+
36+ async function sendRc ( text , tag ) {
37+ if ( ! myId ) {
38+ const ok = await connRc ( ) ;
39+ if ( ! ok ) throw new Error ( 'нет связи с рокетом' ) ;
40+ }
41+
42+ const msg = tag ? `[${ tag } ] ${ text } ` : text ;
43+ await driver . sendToRoom ( msg , ROOM ) ;
44+ }
45+
46+ function getSess ( chatId ) {
47+ const s = sessions . get ( chatId ) ;
48+ if ( ! s ) return null ;
49+ if ( Date . now ( ) - s . started > LIFETIME ) {
50+ s . status = 'expired' ;
51+ sessions . set ( chatId , s ) ;
52+ return s ;
53+ }
54+ return s ;
55+ }
56+
57+ async function newSess ( chatId ) {
58+ const code = genCode ( ) ;
59+ const tag = genTag ( ) ;
60+ const sess = {
61+ code,
62+ tag,
63+ attempts : 0 ,
64+ started : Date . now ( ) ,
65+ status : 'waiting'
66+ } ;
67+ sessions . set ( chatId , sess ) ;
68+ await sendRc ( '---' ) ;
69+ await sendRc ( code ) ;
70+ await sendRc ( 'код работает до 5 минут и бот тг примет до 10 попыток' , tag ) ;
71+ await sendRc ( '---' ) ;
72+ return sess ;
73+ }
74+
75+ async function handleCode ( chatId , text , bot ) {
76+ const s = getSess ( chatId ) ;
77+ if ( ! s ) {
78+ await bot . sendMessage ( chatId , 'нет активной сессии. /numbers для начала.' ) ;
79+ return ;
80+ }
81+ if ( s . status === 'completed' ) {
82+ await bot . sendMessage ( chatId , 'ты уже подтвердил код, больше нельзя.' ) ;
83+ return ;
84+ }
85+ if ( s . status === 'expired' ) {
86+ await bot . sendMessage ( chatId , 'время истекло. жми /numbers заново.' ) ;
87+ return ;
88+ }
89+ if ( s . attempts >= MAX_ATTEMPTS ) {
90+ s . status = 'expired' ;
91+ sessions . set ( chatId , s ) ;
92+ await bot . sendMessage ( chatId , 'все 10 попыток сожрал. /numbers для нового.' ) ;
93+ return ;
94+ }
95+ const input = text . trim ( ) ;
96+ if ( input === s . code ) {
97+ s . status = 'completed' ;
98+ sessions . set ( chatId , s ) ;
99+ await bot . sendMessage ( chatId , 'верный код! доступ подтверждён к... (пока не знаю к каким каналам, списочек от дорогих мортиботоводов не помешал бы)' ) ;
100+ } else {
101+ s . attempts += 1 ;
102+ const rem = MAX_ATTEMPTS - s . attempts ;
103+ sessions . set ( chatId , s ) ;
104+ if ( rem > 0 ) {
105+ await bot . sendMessage ( chatId , `неверно, осталось ${ rem } попыток.` ) ;
106+ } else {
107+ s . status = 'expired' ;
108+ sessions . set ( chatId , s ) ;
109+ await bot . sendMessage ( chatId , 'попытки кончились. /numbers для нового.' ) ;
110+ }
111+ }
112+ }
113+
114+ const bot = new TelegramBot ( TOKEN , { polling : true } ) ;
115+ bot . onText ( / \/ n u m b e r s / , async ( msg ) => {
116+ const chatId = msg . chat . id ;
117+ const existing = getSess ( chatId ) ;
118+ if ( existing && existing . status === 'completed' ) {
119+ await bot . sendMessage ( chatId , 'ты уже успешно верифицировался, больше нельзя.' ) ;
120+ return ;
121+ }
122+
123+ if ( existing && existing . status === 'waiting' ) {
124+ await bot . sendMessage ( chatId , 'у тебя уже активный код, введи его или подожди 5 минут.' ) ;
125+ return ;
126+ }
127+ try {
128+ const sess = await newSess ( chatId ) ;
129+ await bot . sendMessage ( chatId , `код с тегом [${ sess . tag } ] улетел в рокет (комната ${ ROOM } ).\nу тебя 10 попыток и 5 минут, введи его сюда.` ) ;
130+ } catch ( e ) {
131+ await bot . sendMessage ( chatId , 'что-то с рокетом, попробуй позже или пиши в issues.' ) ;
132+ }
133+ } ) ;
134+
135+ bot . on ( 'message' , async ( msg ) => {
136+ const chatId = msg . chat . id ;
137+ const text = msg . text ;
138+ if ( ! text || text . startsWith ( '/' ) ) return ;
139+ const s = getSess ( chatId ) ;
140+ if ( ! s || s . status !== 'waiting' ) return ;
141+ await handleCode ( chatId , text , bot ) ;
142+ } ) ;
143+
144+ bot . onText ( / \/ c a n c e l / , async ( msg ) => {
145+ const chatId = msg . chat . id ;
146+ if ( sessions . has ( chatId ) ) {
147+ sessions . delete ( chatId ) ;
148+ await bot . sendMessage ( chatId , 'сессия отменена.' ) ;
149+ } else {
150+ await bot . sendMessage ( chatId , 'нет активной сессии.' ) ;
151+ }
152+ } ) ;
153+
154+ ( async ( ) => {
155+ await connRc ( ) ;
156+ } ) ( ) ;
157+
158+ process . on ( 'SIGINT' , ( ) => {
159+ driver . disconnect ( ) ;
160+ bot . stopPolling ( ) ;
161+ process . exit ( 0 ) ;
162+ } ) ;
0 commit comments