ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ db = $database; $this->bot = $telegram_bot; } /** * Главная админ панель */ public function handleAdminPanel($admin_id) { global $CONFIG; if (!in_array($admin_id, $CONFIG['ADMIN_IDS'])) { $this->bot->sendMessage($admin_id, "❌ Нет прав доступа"); return; } $stats = $this->db->getStatistics(); $text = "⚙️ Панель администратора\n\n"; $text .= "📊 Быстрая статистика:\n"; $text .= "👥 Пользователей: " . safe_get($stats, 'total_users', 0) . " "; $text .= "(активных: " . safe_get($stats, 'active_users', 0) . ")\n"; $text .= "🎯 Ставок: " . safe_get($stats, 'total_bets', 0) . " "; $text .= "(ожидают: " . safe_get($stats, 'pending_bets', 0) . ")\n"; $text .= "⚽ События: " . safe_get($stats, 'total_events', 0) . " "; $text .= "(активных: " . safe_get($stats, 'upcoming_events', 0) . ")\n\n"; $text .= "Выберите раздел для управления:"; $keyboard = [ 'inline_keyboard' => [ [ ['text' => '📅 События', 'callback_data' => 'admin_events'], ['text' => '👥 Пользователи', 'callback_data' => 'admin_users'] ], [ ['text' => '🎯 Ставки', 'callback_data' => 'admin_bets'], ['text' => '💰 Балансы', 'callback_data' => 'admin_balances'] ], [ ['text' => '⚙️ Настройки', 'callback_data' => 'admin_settings'], ['text' => '📊 Статистика', 'callback_data' => 'admin_stats'] ], [ ['text' => '🔙 Главное меню', 'callback_data' => 'start'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Управление событиями */ public function handleAdminEvents($admin_id) { $upcoming_events = $this->db->getEvents('upcoming', 5); $recent_finished = $this->db->getEvents('finished', 3); $text = "📅 Управление событиями\n\n"; // Предстоящие события if (!empty($upcoming_events)) { $text .= "🔜 Предстоящие события:\n"; foreach ($upcoming_events as $event) { $date = format_date($event['event_date'], 'd.m H:i'); $text .= "#{$event['event_id']} {$event['team1']} vs {$event['team2']} ({$date})\n"; } $text .= "\n"; } else { $text .= "🔜 Нет предстоящих событий\n\n"; } // Недавно завершенные if (!empty($recent_finished)) { $text .= "✅ Недавно завершенные:\n"; foreach ($recent_finished as $event) { $date = format_date($event['updated_at'], 'd.m'); $text .= "#{$event['event_id']} {$event['title']} ({$date})\n"; } $text .= "\n"; } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '➕ Добавить событие', 'callback_data' => 'admin_add_event'], ['text' => '📋 Все события', 'callback_data' => 'admin_all_events'] ], [ ['text' => '🏁 Завершить событие', 'callback_data' => 'admin_finish_event'], ['text' => '❌ Отменить событие', 'callback_data' => 'admin_cancel_event'] ], [ ['text' => '🔙 Админ панель', 'callback_data' => 'admin_panel'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Форма добавления события */ public function handleAddEvent($admin_id) { $text = "➕ Добавление нового события\n\n"; $text .= "Введите данные события в формате:\n"; $text .= "Название|Команда1|Команда2|YYYY-MM-DD HH:MM|Лига\n\n"; $text .= "Примеры:\n"; $text .= "• Финал ЧМ|Аргентина|Франция|2025-07-15 21:00|ЧМ 2026\n"; $text .= "• Матч дня|Спартак|ЦСКА|2025-06-20 19:00|РПЛ\n\n"; $text .= "💡 Лига указывается опционально"; // Устанавливаем состояние диалога self::$dialog_states[$admin_id] = ['action' => 'add_event']; $keyboard = [ 'inline_keyboard' => [ [['text' => '❌ Отмена', 'callback_data' => 'admin_events']] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Список всех событий с действиями */ public function handleAllEvents($admin_id) { $upcoming = $this->db->getEvents('upcoming', 10); $finished = $this->db->getEvents('finished', 5); $text = "📋 Все события\n\n"; if (!empty($upcoming)) { $text .= "🔜 Предстоящие (" . count($upcoming) . "):\n"; foreach ($upcoming as $event) { $date = format_date($event['event_date'], 'd.m H:i'); $text .= "#{$event['event_id']} {$event['title']}\n"; $text .= " ⚽ {$event['team1']} vs {$event['team2']}\n"; $text .= " 📅 {$date}"; if ($event['league']) { $text .= " | 🏆 {$event['league']}"; } $text .= "\n\n"; } } if (!empty($finished)) { $text .= "✅ Завершенные (последние " . count($finished) . "):\n"; foreach ($finished as $event) { $date = format_date($event['updated_at'], 'd.m'); $text .= "#{$event['event_id']} {$event['title']} ({$date})\n"; } } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '➕ Добавить', 'callback_data' => 'admin_add_event'], ['text' => '🏁 Завершить', 'callback_data' => 'admin_finish_event'] ], [ ['text' => '🔄 Обновить', 'callback_data' => 'admin_all_events'], ['text' => '🔙 Назад', 'callback_data' => 'admin_events'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Форма завершения события */ public function handleFinishEvent($admin_id) { $upcoming_events = $this->db->getEvents('upcoming', 10); if (empty($upcoming_events)) { $text = "❌ Нет предстоящих событий для завершения\n\n"; $text .= "Сначала добавьте события через кнопку \"➕ Добавить событие\""; $keyboard = [ 'inline_keyboard' => [ [['text' => '🔙 Назад', 'callback_data' => 'admin_events']] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); return; } $text = "🏁 Завершение события\n\n"; $text .= "Выберите событие для завершения:\n\n"; $keyboard = ['inline_keyboard' => []]; foreach ($upcoming_events as $event) { $date = format_date($event['event_date'], 'd.m H:i'); $button_text = "#{$event['event_id']} {$event['team1']} vs {$event['team2']}"; if (strlen($button_text) > 35) { $button_text = substr($button_text, 0, 32) . "..."; } $text .= "#{$event['event_id']} {$event['title']}\n"; $text .= " ⚽ {$event['team1']} vs {$event['team2']}\n"; $text .= " 📅 {$date}\n\n"; $keyboard['inline_keyboard'][] = [ ['text' => $button_text, 'callback_data' => "finish_event_{$event['event_id']}"] ]; } $keyboard['inline_keyboard'][] = [ ['text' => '🔙 Назад', 'callback_data' => 'admin_events'] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Форма ввода результата конкретного события */ public function handleFinishSpecificEvent($admin_id, $event_id) { $event = $this->db->getEvent($event_id); if (!$event || $event['status'] !== 'upcoming') { $this->bot->sendMessage($admin_id, "❌ Событие не найдено или уже завершено"); return; } $text = "🏁 Завершение события\n\n"; $text .= "🏟 {$event['title']}\n"; $text .= "⚽ {$event['team1']} vs {$event['team2']}\n"; $text .= "📅 " . format_date($event['event_date']) . "\n\n"; $text .= "Введите результат в формате JSON:\n"; $text .= "{\"winner\":\"team1\",\"score\":\"2-1\",\"first_goal\":\"team1\",\"total_goals\":3,\"red_card\":false,\"penalty\":true,\"own_goal\":false,\"corners_winner\":\"team1\"}\n\n"; $text .= "🔑 Ключи результата:\n"; $text .= "• winner: team1/team2/draw\n"; $text .= "• score: \"2-1\" (точный счет)\n"; $text .= "• first_goal: team1/team2\n"; $text .= "• total_goals: число голов\n"; $text .= "• red_card: true/false\n"; $text .= "• penalty: true/false\n"; $text .= "• own_goal: true/false\n"; $text .= "• corners_winner: team1/team2/draw\n\n"; $text .= "💡 Можно указать только нужные поля"; // Устанавливаем состояние диалога self::$dialog_states[$admin_id] = [ 'action' => 'finish_event', 'event_id' => $event_id ]; $keyboard = [ 'inline_keyboard' => [ [ ['text' => '⚡ Быстрый ввод', 'callback_data' => "quick_result_{$event_id}"], ['text' => '❌ Отмена', 'callback_data' => 'admin_finish_event'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Быстрый ввод результата через кнопки */ public function handleQuickResult($admin_id, $event_id) { $event = $this->db->getEvent($event_id); if (!$event) { $this->bot->sendMessage($admin_id, "❌ Событие не найдено"); return; } $text = "⚡ Быстрый ввод результата\n\n"; $text .= "🏟 {$event['title']}\n"; $text .= "⚽ {$event['team1']} vs {$event['team2']}\n\n"; $text .= "Кто победил?"; $keyboard = [ 'inline_keyboard' => [ [ ['text' => "🏆 {$event['team1']}", 'callback_data' => "qr_winner_{$event_id}_team1"], ['text' => '🤝 Ничья', 'callback_data' => "qr_winner_{$event_id}_draw"] ], [ ['text' => "🏆 {$event['team2']}", 'callback_data' => "qr_winner_{$event_id}_team2"] ], [ ['text' => '🔙 Назад', 'callback_data' => "finish_event_{$event_id}"] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Обработка выбора победителя в быстром вводе */ public function handleQuickResultWinner($admin_id, $event_id, $winner) { $event = $this->db->getEvent($event_id); if (!$event) { $this->bot->sendMessage($admin_id, "❌ Событие не найдено"); return; } // Сохраняем выбор победителя if (!isset(self::$dialog_states[$admin_id])) { self::$dialog_states[$admin_id] = []; } self::$dialog_states[$admin_id]['quick_result'] = ['winner' => $winner]; $winner_text = $winner === 'team1' ? $event['team1'] : ($winner === 'team2' ? $event['team2'] : 'Ничья'); $text = "⚡ Быстрый ввод результата\n\n"; $text .= "🏟 {$event['title']}\n"; $text .= "⚽ {$event['team1']} vs {$event['team2']}\n\n"; $text .= "✅ Победитель: {$winner_text}\n\n"; $text .= "Введите точный счет (например: 2-1):"; // Обновляем состояние диалога self::$dialog_states[$admin_id]['action'] = 'quick_result_score'; self::$dialog_states[$admin_id]['event_id'] = $event_id; $keyboard = [ 'inline_keyboard' => [ [ ['text' => '1-0', 'callback_data' => "qr_score_{$event_id}_1-0"], ['text' => '2-0', 'callback_data' => "qr_score_{$event_id}_2-0"], ['text' => '2-1', 'callback_data' => "qr_score_{$event_id}_2-1"] ], [ ['text' => '0-1', 'callback_data' => "qr_score_{$event_id}_0-1"], ['text' => '0-2', 'callback_data' => "qr_score_{$event_id}_0-2"], ['text' => '1-2', 'callback_data' => "qr_score_{$event_id}_1-2"] ], [ ['text' => '1-1', 'callback_data' => "qr_score_{$event_id}_1-1"], ['text' => '0-0', 'callback_data' => "qr_score_{$event_id}_0-0"], ['text' => '2-2', 'callback_data' => "qr_score_{$event_id}_2-2"] ], [ ['text' => '🔙 Назад', 'callback_data' => "quick_result_{$event_id}"] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Завершение быстрого ввода со счетом */ public function handleQuickResultScore($admin_id, $event_id, $score) { if (!isset(self::$dialog_states[$admin_id]['quick_result'])) { $this->bot->sendMessage($admin_id, "❌ Ошибка: потеряно состояние диалога"); return; } $event = $this->db->getEvent($event_id); if (!$event) { $this->bot->sendMessage($admin_id, "❌ Событие не найдено"); return; } // Формируем результат $result = self::$dialog_states[$admin_id]['quick_result']; $result['score'] = $score; // Определяем total_goals $score_parts = explode('-', $score); if (count($score_parts) === 2) { $result['total_goals'] = (int)$score_parts[0] + (int)$score_parts[1]; } // Определяем first_goal (упрощенно - кто больше забил) if (isset($score_parts[0], $score_parts[1])) { if ($score_parts[0] > $score_parts[1]) { $result['first_goal'] = 'team1'; } elseif ($score_parts[1] > $score_parts[0]) { $result['first_goal'] = 'team2'; } // При ничьей first_goal не устанавливаем } // Завершаем событие $finish_result = $this->db->finishEvent($event_id, $result, $admin_id); if ($finish_result) { $winner_text = $result['winner'] === 'team1' ? $event['team1'] : ($result['winner'] === 'team2' ? $event['team2'] : 'Ничья'); $text = "✅ Событие успешно завершено!\n\n"; $text .= "🏟 {$event['title']}\n"; $text .= "⚽ {$event['team1']} vs {$event['team2']}\n"; $text .= "🏆 Победитель: {$winner_text}\n"; $text .= "⚽ Счет: {$score}\n"; $text .= "📊 Голов: {$result['total_goals']}\n\n"; $text .= "🎯 Все ставки автоматически обработаны"; // Уведомляем админов notify_admins($this->bot, "✅ Событие завершено: {$event['title']} ({$score})"); // Очищаем состояние unset(self::$dialog_states[$admin_id]); } else { $text = "❌ Ошибка при завершении события\n\n"; $text .= "Попробуйте еще раз или обратитесь к разработчику."; } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🏁 Завершить еще', 'callback_data' => 'admin_finish_event'], ['text' => '📅 События', 'callback_data' => 'admin_events'] ], [ ['text' => '🔙 Админ панель', 'callback_data' => 'admin_panel'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Управление настройками ставок */ public function handleAdminSettings($admin_id) { $text = "⚙️ Настройки системы\n\n"; global $CONFIG; $text .= "💰 Экономические параметры:\n"; $text .= "• Стартовый баланс: {$CONFIG['START_BALANCE']} баллов\n"; $text .= "• Штраф за проигрыш: {$CONFIG['BET_LOSS_PENALTY']} балла\n"; $text .= "• Минимальный баланс: {$CONFIG['MIN_BALANCE']} баллов\n\n"; $text .= "🎯 Настройки наград за ставки:\n"; $bet_settings = $this->db->getBetSettings(); $types_count = []; foreach ($bet_settings as $setting) { if (!isset($types_count[$setting['bet_type']])) { $types_count[$setting['bet_type']] = [ 'count' => 0, 'min_reward' => $setting['points_reward'], 'max_reward' => $setting['points_reward'] ]; } $types_count[$setting['bet_type']]['count']++; $types_count[$setting['bet_type']]['min_reward'] = min( $types_count[$setting['bet_type']]['min_reward'], $setting['points_reward'] ); $types_count[$setting['bet_type']]['max_reward'] = max( $types_count[$setting['bet_type']]['max_reward'], $setting['points_reward'] ); } foreach ($types_count as $type => $info) { $type_name = $this->getBetTypeName($type); $reward_text = $info['min_reward'] === $info['max_reward'] ? $info['min_reward'] : "{$info['min_reward']}-{$info['max_reward']}"; $text .= "• {$type_name}: {$reward_text} баллов ({$info['count']} вариантов)\n"; } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🎯 Настроить награды', 'callback_data' => 'admin_bet_rewards'], ['text' => '💰 Экономика', 'callback_data' => 'admin_economy'] ], [ ['text' => '📊 Подробная таблица', 'callback_data' => 'bet_rewards'], ['text' => '🔙 Админ панель', 'callback_data' => 'admin_panel'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Настройка наград за ставки */ public function handleBetRewardsSettings($admin_id) { $text = "🎯 Настройка наград за ставки\n\n"; $text .= "Выберите тип ставки для редактирования:\n\n"; $bet_types = [ 'winner' => '🏆 Победитель', 'exact_score' => '⚽ Точный счет', 'first_goal' => '🥅 Первый гол', 'total_goals' => '📊 Тотал голов', 'red_card' => '🟥 Удаление', 'penalty' => '🎯 Пенальти', 'own_goal' => '🤦 Автогол', 'corners_winner' => '📐 Угловые' ]; $keyboard = ['inline_keyboard' => []]; $row = []; $count = 0; foreach ($bet_types as $type => $name) { $settings = $this->db->getBetSettings($type); $reward = !empty($settings) ? $settings[0]['points_reward'] : 8; $row[] = ['text' => "{$name} ({$reward})", 'callback_data' => "edit_bet_type_{$type}"]; $count++; if ($count % 2 === 0) { $keyboard['inline_keyboard'][] = $row; $row = []; } } if (!empty($row)) { $keyboard['inline_keyboard'][] = $row; } $keyboard['inline_keyboard'][] = [ ['text' => '🔙 Настройки', 'callback_data' => 'admin_settings'] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Редактирование конкретного типа ставки */ public function handleEditBetType($admin_id, $bet_type) { $settings = $this->db->getBetSettings($bet_type); $type_name = $this->getBetTypeName($bet_type); $text = "✏️ Редактирование: {$type_name}\n\n"; if (!empty($settings)) { $text .= "Текущие настройки:\n"; foreach ($settings as $setting) { $option_name = $this->formatBetOption($bet_type, $setting['bet_option']); $text .= "• {$option_name}: {$setting['points_reward']} баллов\n"; } $text .= "\n"; } $text .= "Введите новое количество баллов для всех вариантов этого типа ставки:"; // Устанавливаем состояние диалога self::$dialog_states[$admin_id] = [ 'action' => 'edit_bet_reward', 'bet_type' => $bet_type ]; $keyboard = [ 'inline_keyboard' => [ [ ['text' => '4 балла', 'callback_data' => "set_reward_{$bet_type}_4"], ['text' => '6 баллов', 'callback_data' => "set_reward_{$bet_type}_6"], ['text' => '8 баллов', 'callback_data' => "set_reward_{$bet_type}_8"] ], [ ['text' => '10 баллов', 'callback_data' => "set_reward_{$bet_type}_10"], ['text' => '12 баллов', 'callback_data' => "set_reward_{$bet_type}_12"] ], [ ['text' => '🔙 Назад', 'callback_data' => 'admin_bet_rewards'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Установка новой награды для типа ставки */ public function handleSetReward($admin_id, $bet_type, $reward) { try { // Обновляем все настройки для данного типа ставки $stmt = $this->db->pdo->prepare(" UPDATE bet_settings SET points_reward = ?, updated_at = CURRENT_TIMESTAMP WHERE bet_type = ? "); $result = $stmt->execute([$reward, $bet_type]); if ($result) { $type_name = $this->getBetTypeName($bet_type); $affected_rows = $stmt->rowCount(); $text = "✅ Настройки обновлены!\n\n"; $text .= "🎯 Тип ставки: {$type_name}\n"; $text .= "💰 Новая награда: {$reward} баллов\n"; $text .= "📊 Обновлено вариантов: {$affected_rows}\n\n"; $text .= "Изменения вступят в силу для новых ставок."; log_message("Admin {$admin_id} updated rewards for {$bet_type}: {$reward} points"); } else { $text = "❌ Ошибка при обновлении настроек\n\nПопробуйте еще раз."; } } catch (Exception $e) { log_message("Error updating bet rewards: " . $e->getMessage(), 'ERROR'); $text = "❌ Ошибка: " . $e->getMessage(); } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🎯 Настроить еще', 'callback_data' => 'admin_bet_rewards'], ['text' => '📊 Таблица', 'callback_data' => 'bet_rewards'] ], [ ['text' => '🔙 Настройки', 'callback_data' => 'admin_settings'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); } /** * Обработка текстовых сообщений в диалогах */ public function handleDialogMessage($admin_id, $text) { if (!isset(self::$dialog_states[$admin_id])) { return false; // Нет активного диалога } $state = self::$dialog_states[$admin_id]; switch ($state['action']) { case 'add_event': return $this->processAddEventInput($admin_id, $text); case 'finish_event': return $this->processFinishEventInput($admin_id, $text, $state['event_id']); case 'quick_result_score': return $this->processQuickScoreInput($admin_id, $text, $state['event_id']); case 'edit_bet_reward': return $this->processRewardInput($admin_id, $text, $state['bet_type']); } return false; } /** * Обработка ввода данных события */ private function processAddEventInput($admin_id, $text) { $parts = explode('|', $text); if (count($parts) < 4) { $this->bot->sendMessage($admin_id, "❌ Неверный формат! Нужно минимум 4 части через |" ); return true; } $title = trim($parts[0]); $team1 = trim($parts[1]); $team2 = trim($parts[2]); $event_date = trim($parts[3]); $league = isset($parts[4]) ? trim($parts[4]) : null; // Валидация даты $date_obj = DateTime::createFromFormat('Y-m-d H:i', $event_date); if (!$date_obj) { $this->bot->sendMessage($admin_id, "❌ Неверный формат даты! Используйте: YYYY-MM-DD HH:MM" ); return true; } // Добавляем событие $result = $this->db->addEvent($title, $team1, $team2, $event_date, $admin_id, $league); if ($result) { $text = "✅ Событие успешно добавлено!\n\n"; $text .= "🆔 ID: {$result}\n"; $text .= "🏟 Название: {$title}\n"; $text .= "⚽ Команды: {$team1} vs {$team2}\n"; $text .= "📅 Дата: " . format_date($event_date); if ($league) { $text .= "\n🏆 Лига: {$league}"; } // Уведомляем админов notify_admins($this->bot, "🆕 Добавлено событие: {$title} ({$team1} vs {$team2})"); } else { $text = "❌ Ошибка при добавлении события"; } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '➕ Добавить еще', 'callback_data' => 'admin_add_event'], ['text' => '📅 События', 'callback_data' => 'admin_events'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); // Очищаем состояние unset(self::$dialog_states[$admin_id]); return true; } /** * Обработка ввода результата события */ private function processFinishEventInput($admin_id, $text, $event_id) { // Парсим JSON $result = json_decode($text, true); if (json_last_error() !== JSON_ERROR_NONE) { $this->bot->sendMessage($admin_id, "❌ Неверный формат JSON!\nОшибка: " . json_last_error_msg() ); return true; } // Завершаем событие $finish_result = $this->db->finishEvent($event_id, $result, $admin_id); if ($finish_result) { $event = $this->db->getEvent($event_id); $text = "✅ Событие успешно завершено!\n\n"; $text .= "🏟 {$event['title']}\n"; $text .= "📊 Результат: " . json_encode($result, JSON_UNESCAPED_UNICODE) . "\n\n"; $text .= "🎯 Все ставки автоматически обработаны"; notify_admins($this->bot, "✅ Событие завершено: {$event['title']}"); } else { $text = "❌ Ошибка при завершении события"; } $keyboard = [ 'inline_keyboard' => [ [ ['text' => '🏁 Завершить еще', 'callback_data' => 'admin_finish_event'], ['text' => '📅 События', 'callback_data' => 'admin_events'] ] ] ]; $this->bot->sendMessage($admin_id, $text, $keyboard); // Очищаем состояние unset(self::$dialog_states[$admin_id]); return true; } // ======================================== // ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ // ======================================== private function getBetTypeName($bet_type) { $types = [ 'winner' => '🏆 Победитель', 'exact_score' => '⚽ Точный счет', 'first_goal' => '🥅 Первый гол', 'total_goals' => '📊 Тотал голов', 'red_card' => '🟥 Удаление', 'penalty' => '🎯 Пенальти', 'own_goal' => '🤦 Автогол', 'corners_winner' => '📐 Угловые' ]; return $types[$bet_type] ?? $bet_type; } private function formatBetOption($bet_type, $bet_option) { switch ($bet_option) { case 'team1': return 'П1'; case 'team2': return 'П2'; case 'draw': return 'Ничья'; case 'yes': return 'Да'; case 'over': return 'Больше 4.5'; case 'under': return 'Меньше 4.5'; case 'other': return 'Другой счет'; default: return $bet_option; } } /** * Обработка callback-запросов админ панели */ public function handleCallback($callback_query) { $user_id = $callback_query['from']['id']; $data = $callback_query['data']; global $CONFIG; if (!in_array($user_id, $CONFIG['ADMIN_IDS'])) { return; } $parts = explode('_', $data); $action = $parts[0] ?? ''; switch ($action) { case 'admin': $sub_action = $parts[1] ?? ''; switch ($sub_action) { case 'panel': $this->handleAdminPanel($user_id); break; case 'events': $this->handleAdminEvents($user_id); break; case 'add': if ($parts[2] === 'event') { $this->handleAddEvent($user_id); } break; case 'all': if ($parts[2] === 'events') { $this->handleAllEvents($user_id); } break; case 'finish': if ($parts[2] === 'event') { $this->handleFinishEvent($user_id); } break; case 'settings': $this->handleAdminSettings($user_id); break; case 'bet': if ($parts[2] === 'rewards') { $this->handleBetRewardsSettings($user_id); } break; } break; case 'finish': if ($parts[1] === 'event' && isset($parts[2])) { $this->handleFinishSpecificEvent($user_id, (int)$parts[2]); } break; case 'quick': if ($parts[1] === 'result' && isset($parts[2])) { $this->handleQuickResult($user_id, (int)$parts[2]); } break; case 'qr': if ($parts[1] === 'winner' && isset($parts[2], $parts[3])) { $this->handleQuickResultWinner($user_id, (int)$parts[2], $parts[3]); } elseif ($parts[1] === 'score' && isset($parts[2], $parts[3])) { $this->handleQuickResultScore($user_id, (int)$parts[2], $parts[3]); } break; case 'edit': if ($parts[1] === 'bet' && $parts[2] === 'type' && isset($parts[3])) { $this->handleEditBetType($user_id, $parts[3]); } break; case 'set': if ($parts[1] === 'reward' && isset($parts[2], $parts[3])) { $this->handleSetReward($user_id, $parts[2], (int)$parts[3]); } break; } } } ?>