2022-10-24 15:34:18 +03:00
from datetime import datetime
2022-10-25 15:18:51 +03:00
from threading import Thread
2022-10-24 15:34:18 +03:00
from dateutil . relativedelta import relativedelta
2022-10-20 16:08:46 +03:00
from time import time
2022-10-23 12:48:34 +03:00
from os import getpid , path
2022-10-25 15:18:51 +03:00
from modules . birthdays import check_birthdays
2022-10-17 00:30:07 +03:00
from modules . utils import *
2022-10-25 15:18:51 +03:00
from schedule import run_pending , every
2022-10-17 00:30:07 +03:00
from pyrogram . client import Client
from pyrogram import filters
2022-10-23 01:27:54 +03:00
from pyrogram . enums . parse_mode import ParseMode
2022-10-24 15:34:18 +03:00
from pyrogram . enums . chat_action import ChatAction
2022-10-23 20:20:33 +03:00
from pyrogram . types import InlineKeyboardMarkup , InlineKeyboardButton , BotCommand , BotCommandScopeChat , ReplyKeyboardMarkup , ForceReply , ReplyKeyboardRemove , ChatPermissions
2022-10-17 00:30:07 +03:00
from pyrogram import idle # type: ignore
from pyrogram . errors . exceptions import bad_request_400
2022-10-21 15:00:03 +03:00
pid = getpid ( )
2022-10-17 00:30:07 +03:00
app = Client ( " holochecker " , bot_token = configGet ( " bot_token " , " bot " ) , api_id = configGet ( " api_id " , " bot " ) , api_hash = configGet ( " api_hash " , " bot " ) )
2022-10-21 15:00:03 +03:00
2022-10-26 13:54:55 +03:00
for entry in [ f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " ] :
mode = ' r ' if path . exists ( entry ) else ' w '
with open ( entry , mode ) as f :
try :
f . write ( " {} " )
except :
pass
2022-10-24 15:34:18 +03:00
async def isAnAdmin ( admin_id ) :
if admin_id == configGet ( " owner " ) or admin_id in configGet ( " admins " ) :
return True
async for member in app . get_chat_members ( configGet ( " admin_group " ) ) :
if member . user . id == admin_id :
return True
return False
2022-10-21 15:00:03 +03:00
# Start command ================================================================================================================
@app.on_message ( ~ filters . scheduled & filters . private & filters . command ( [ " start " ] , prefixes = [ " / " ] ) )
2022-10-20 13:24:32 +03:00
async def cmd_start ( app , msg ) :
try :
2022-10-20 15:43:13 +03:00
user_stage = configGet ( " stage " , file = str ( msg . from_user . id ) )
if user_stage != 0 :
2022-10-20 13:24:32 +03:00
return
except FileNotFoundError :
2022-10-22 10:45:02 +03:00
jsonSave ( jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } user_default.json " ) , f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { msg . from_user . id } .json " )
2022-10-20 15:43:13 +03:00
user_stage = configGet ( " stage " , file = str ( msg . from_user . id ) )
2022-10-20 16:08:46 +03:00
configSet ( " telegram_id " , str ( msg . from_user . username ) , file = str ( msg . from_user . id ) )
configSet ( " telegram_name " , f " { msg . from_user . first_name } { msg . from_user . last_name } " , file = str ( msg . from_user . id ) )
configSet ( " telegram_phone " , str ( msg . from_user . phone_number ) , file = str ( msg . from_user . id ) )
configSet ( " telegram_locale " , str ( msg . from_user . language_code ) , file = str ( msg . from_user . id ) )
2022-10-20 13:24:32 +03:00
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } started bot interaction " )
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( " start " , " message " ) , reply_markup = ReplyKeyboardMarkup ( locale ( " welcome " , " keyboard " ) , resize_keyboard = True ) ) # type: ignore
2022-10-21 15:00:03 +03:00
# ==============================================================================================================================
2022-10-20 13:24:32 +03:00
2022-10-21 15:00:03 +03:00
# Shutdown command =============================================================================================================
@app.on_message ( ~ filters . scheduled & filters . private & filters . command ( [ " kill " , " die " , " reboot " ] , prefixes = [ " " , " / " ] ) )
2022-10-17 00:30:07 +03:00
async def cmd_kill ( app , msg ) :
2022-10-24 15:34:18 +03:00
if await isAnAdmin ( msg . from_user . id ) :
2022-10-17 00:30:07 +03:00
logWrite ( f " Shutting down bot with pid { pid } " )
await msg . reply_text ( f " Вимкнення бота з підом ` { pid } ` " )
killProc ( pid )
2022-10-21 15:00:03 +03:00
# ==============================================================================================================================
2022-10-17 00:30:07 +03:00
2022-10-24 15:34:18 +03:00
# Applications command =========================================================================================================
@app.on_message ( ~ filters . scheduled & filters . private & filters . command ( [ " applications " ] , prefixes = [ " " , " / " ] ) )
async def cmd_applications ( app , msg ) :
if await isAnAdmin ( msg . from_user . id ) :
await app . send_chat_action ( msg . chat . id , ChatAction . UPLOAD_DOCUMENT )
await msg . reply_document ( document = f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
# ==============================================================================================================================
2022-10-25 14:36:16 +03:00
# Reapply command ==============================================================================================================
@app.on_message ( ~ filters . scheduled & filters . private & filters . command ( [ " reapply " ] , prefixes = [ " " , " / " ] ) )
async def cmd_reapply ( app , msg ) :
if configGet ( " approved " , file = str ( msg . from_user . id ) ) or configGet ( " refused " , file = str ( msg . from_user . id ) ) :
if ( configGet ( " stage " , file = str ( msg . from_user . id ) ) == 10 ) and not ( configGet ( " sent " , file = str ( msg . from_user . id ) ) ) :
configSet ( " reapply " , True , file = str ( msg . from_user . id ) )
configSet ( " confirmed " , False , file = str ( msg . from_user . id ) )
await welcome_pass ( app , msg , once_again = True )
else :
await msg . reply_text ( locale ( " reapply_in_progress " , " message " ) . format ( locale ( " confirm " , " keyboard " ) [ 1 ] [ 0 ] ) )
else :
if configGet ( " sent " , file = str ( msg . from_user . id ) ) :
await msg . reply_text ( locale ( " reapply_forbidden " , " message " ) )
else :
await msg . reply_text ( locale ( " reapply_in_progress " , " message " ) . format ( locale ( " confirm " , " keyboard " ) [ 1 ] [ 0 ] ) )
# ==============================================================================================================================
2022-10-21 15:00:03 +03:00
# Welcome check ================================================================================================================
@app.on_message ( ~ filters . scheduled & filters . private & ( filters . regex ( locale ( " welcome " , " keyboard " ) [ 0 ] [ 0 ] ) | filters . regex ( locale ( " return " , " keyboard " ) [ 0 ] [ 0 ] ) ) )
2022-10-20 22:19:37 +03:00
async def welcome_pass ( app , msg , once_again : bool = True ) :
2022-10-20 13:24:32 +03:00
2022-10-20 22:19:37 +03:00
if not once_again :
await msg . reply_text ( locale ( " privacy_notice " , " message " ) )
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } confirmed starting the application " )
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( " question1 " , " message " ) , reply_markup = ForceReply ( placeholder = locale ( " question1 " , " force_reply " ) ) ) # type: ignore
2022-10-20 15:43:13 +03:00
configSet ( " stage " , 1 , file = str ( msg . from_user . id ) )
2022-10-25 14:36:16 +03:00
configSet ( " sent " , False , file = str ( msg . from_user . id ) )
2022-10-20 15:43:13 +03:00
2022-10-21 15:00:03 +03:00
@app.on_message ( ~ filters . scheduled & filters . private & ( filters . regex ( locale ( " welcome " , " keyboard " ) [ 1 ] [ 0 ] ) ) )
2022-10-20 15:43:13 +03:00
async def welcome_reject ( app , msg ) :
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } refused to start the application " )
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( " goodbye " , " message " ) , reply_markup = ReplyKeyboardMarkup ( locale ( " return " , " keyboard " ) , resize_keyboard = True ) ) # type: ignore
2022-10-21 15:00:03 +03:00
# ==============================================================================================================================
2022-10-20 16:08:46 +03:00
2022-10-21 15:00:03 +03:00
# Confirmation =================================================================================================================
@app.on_message ( ~ filters . scheduled & filters . private & ( filters . regex ( locale ( " confirm " , " keyboard " ) [ 0 ] [ 0 ] ) ) )
2022-10-20 22:19:37 +03:00
async def confirm_yes ( app , msg ) :
user_stage = configGet ( " stage " , file = str ( msg . from_user . id ) )
if user_stage == 10 :
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
if not configGet ( " sent " , file = str ( msg . from_user . id ) ) :
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
await msg . reply_text ( locale ( " application_sent " , " message " ) , reply_markup = ReplyKeyboardRemove ( ) )
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
applications = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
applications [ str ( msg . from_user . id ) ] = {
" approved " : False ,
" approved_by " : None ,
" approval_date " : None ,
" refused " : False ,
" refused_by " : False ,
" refusal_date " : False ,
" application_date " : int ( time ( ) ) ,
" application " : configGet ( " application " , file = str ( msg . from_user . id ) )
}
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
jsonSave ( applications , f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
application_content = [ ]
i = 1
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
for question in configGet ( " application " , file = str ( msg . from_user . id ) ) :
2022-10-24 15:34:18 +03:00
if i == 2 :
age = relativedelta ( datetime . now ( ) , datetime . strptime ( configGet ( ' application ' , file = str ( msg . from_user . id ) ) [ ' 2 ' ] , ' %d . % m. % Y ' ) )
application_content . append ( f " { locale ( ' question ' + str ( i ) , ' message ' , ' question_titles ' ) } { configGet ( ' application ' , file = str ( msg . from_user . id ) ) [ ' 2 ' ] } ( { age . years } р .) " )
else :
application_content . append ( f " { locale ( ' question ' + str ( i ) , ' message ' , ' question_titles ' ) } { configGet ( ' application ' , file = str ( msg . from_user . id ) ) [ question ] } " )
2022-10-23 13:28:15 +03:00
i + = 1
2022-10-25 14:36:16 +03:00
if configGet ( " reapply " , file = str ( msg . from_user . id ) ) :
await app . send_message ( chat_id = configGet ( " admin_group " ) , text = ( locale ( " reapply_got " , " message " ) ) . format ( str ( msg . from_user . id ) , msg . from_user . first_name , msg . from_user . last_name , msg . from_user . username , " \n " . join ( application_content ) ) , parse_mode = ParseMode . MARKDOWN , reply_markup = InlineKeyboardMarkup ( # type: ignore
2022-10-23 13:28:15 +03:00
[
2022-10-25 14:36:16 +03:00
[
InlineKeyboardButton ( text = str ( locale ( " reapply_yes " , " button " ) ) , callback_data = f " reapply_yes_ { msg . from_user . id } " )
] ,
[
InlineKeyboardButton ( text = str ( locale ( " reapply_no " , " button " ) ) , callback_data = f " reapply_no_ { msg . from_user . id } " )
]
]
)
)
else :
await app . send_message ( chat_id = configGet ( " admin_group " ) , text = ( locale ( " application_got " , " message " ) ) . format ( str ( msg . from_user . id ) , msg . from_user . first_name , msg . from_user . last_name , msg . from_user . username , " \n " . join ( application_content ) ) , parse_mode = ParseMode . MARKDOWN , reply_markup = InlineKeyboardMarkup ( # type: ignore
2022-10-23 13:28:15 +03:00
[
2022-10-25 14:36:16 +03:00
[
InlineKeyboardButton ( text = str ( locale ( " sub_yes " , " button " ) ) , callback_data = f " sub_yes_ { msg . from_user . id } " )
] ,
[
InlineKeyboardButton ( text = str ( locale ( " sub_no " , " button " ) ) , callback_data = f " sub_no_ { msg . from_user . id } " )
] ,
[
InlineKeyboardButton ( text = str ( locale ( " sub_no_aggressive " , " button " ) ) , callback_data = f " sub_no_aggresive_ { msg . from_user . id } " )
] ,
[
InlineKeyboardButton ( text = str ( locale ( " sub_no_russian " , " button " ) ) , callback_data = f " sub_no_russian_ { msg . from_user . id } " )
]
2022-10-23 13:28:15 +03:00
]
2022-10-25 14:36:16 +03:00
)
2022-10-23 13:28:15 +03:00
)
2022-10-21 15:00:03 +03:00
2022-10-23 13:28:15 +03:00
logWrite ( f " User { msg . from_user . id } sent his application and it will now be reviewed " )
2022-10-23 12:56:28 +03:00
2022-10-23 13:28:15 +03:00
configSet ( " sent " , True , file = str ( msg . from_user . id ) )
configSet ( " confirmed " , True , file = str ( msg . from_user . id ) )
2022-10-20 22:19:37 +03:00
2022-10-21 15:00:03 +03:00
@app.on_message ( ~ filters . scheduled & filters . private & ( filters . regex ( locale ( " confirm " , " keyboard " ) [ 1 ] [ 0 ] ) ) )
2022-10-20 22:19:37 +03:00
async def confirm_no ( app , msg ) :
user_stage = configGet ( " stage " , file = str ( msg . from_user . id ) )
if user_stage == 10 :
2022-10-22 10:45:02 +03:00
jsonSave ( jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } user_default.json " ) , f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { msg . from_user . id } .json " )
2022-10-20 22:19:37 +03:00
configSet ( " telegram_id " , str ( msg . from_user . username ) , file = str ( msg . from_user . id ) )
configSet ( " telegram_name " , f " { msg . from_user . first_name } { msg . from_user . last_name } " , file = str ( msg . from_user . id ) )
configSet ( " telegram_phone " , str ( msg . from_user . phone_number ) , file = str ( msg . from_user . id ) )
configSet ( " telegram_locale " , str ( msg . from_user . language_code ) , file = str ( msg . from_user . id ) )
await welcome_pass ( app , msg , once_again = True )
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } restarted the application due to typo in it " )
2022-10-21 15:00:03 +03:00
# ==============================================================================================================================
2022-10-24 00:40:43 +03:00
# Callbacks application ========================================================================================================
2022-10-22 10:41:58 +03:00
@app.on_callback_query ( filters . regex ( " sub_yes_[ \ s \ S]* " ) ) # type: ignore
2022-10-21 15:00:03 +03:00
async def callback_query_accept ( app , clb ) :
fullclb = clb . data . split ( " _ " )
2022-10-23 01:27:54 +03:00
await app . send_message ( configGet ( " admin_group " ) , locale ( " approved_by " , " message " ) . format ( clb . from_user . first_name , fullclb [ 2 ] ) , disable_notification = True ) # type: ignore
2022-10-23 12:56:28 +03:00
logWrite ( f " User { fullclb [ 2 ] } got approved by { clb . from_user . id } " )
2022-10-21 16:11:13 +03:00
2022-10-24 15:34:18 +03:00
need_link = True
2022-10-21 16:11:13 +03:00
2022-10-24 15:34:18 +03:00
async for member in app . get_chat_members ( configGet ( " destination_group " ) ) :
if member . user . id == int ( fullclb [ 2 ] ) :
need_link = False
if need_link :
link = await app . create_chat_invite_link ( configGet ( " destination_group " ) , name = f " Invite for { fullclb [ 2 ] } " , member_limit = 1 ) #, expire_date=datetime.now()+timedelta(days=1))
2022-10-21 15:00:03 +03:00
2022-10-24 15:34:18 +03:00
await app . send_message ( int ( fullclb [ 2 ] ) , locale ( " approved " , " message " ) , reply_markup = InlineKeyboardMarkup (
[ [
InlineKeyboardButton ( str ( locale ( " join " , " button " ) ) , url = link . invite_link )
] ]
) )
configSet ( " link " , link . invite_link , file = fullclb [ 2 ] )
logWrite ( f " User { fullclb [ 2 ] } got an invite link { link . invite_link } " )
else :
await app . send_message ( int ( fullclb [ 2 ] ) , locale ( " approved_joined " , " message " ) )
2022-10-23 01:27:54 +03:00
2022-10-24 15:34:18 +03:00
configSet ( " approved " , True , file = fullclb [ 2 ] )
2022-10-25 14:36:16 +03:00
configSet ( " sent " , False , file = fullclb [ 2 ] )
2022-10-23 12:56:28 +03:00
2022-10-23 01:27:54 +03:00
application = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
application [ fullclb [ 2 ] ] [ " approved " ] = True
application [ fullclb [ 2 ] ] [ " approved_by " ] = clb . from_user . id
application [ fullclb [ 2 ] ] [ " approval_date " ] = int ( time ( ) )
jsonSave ( application , f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
2022-10-22 10:41:58 +03:00
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " accepted " , " button " ) ) , callback_data = " nothing " ) ] ]
2022-10-20 16:08:46 +03:00
2022-10-21 15:00:03 +03:00
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
2022-10-22 10:41:58 +03:00
await clb . answer ( text = locale ( " sub_accepted " , " callback " ) . format ( fullclb [ 2 ] ) , show_alert = True ) # type: ignore
2022-10-21 15:00:03 +03:00
2022-10-23 01:27:54 +03:00
@app.on_callback_query ( filters . regex ( " sub_no_aggressive_[ \ s \ S]* " ) ) # type: ignore
async def callback_query_refuse_aggressive ( app , clb ) :
2022-10-21 15:00:03 +03:00
fullclb = clb . data . split ( " _ " )
2022-10-23 01:27:54 +03:00
await app . send_message ( configGet ( " admin_group " ) , locale ( " refused_by_agr " , " message " ) . format ( clb . from_user . first_name , fullclb [ 3 ] ) , disable_notification = True ) # type: ignore
await app . send_message ( int ( fullclb [ 3 ] ) , locale ( " refused " , " message " ) )
2022-10-23 12:56:28 +03:00
logWrite ( f " User { fullclb [ 3 ] } got refused by { clb . from_user . id } due to being aggressive " )
2022-10-23 01:27:54 +03:00
configSet ( " refused " , True , file = fullclb [ 3 ] )
2022-10-25 14:36:16 +03:00
configSet ( " sent " , False , file = fullclb [ 3 ] )
2022-10-23 01:27:54 +03:00
application = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
application [ fullclb [ 3 ] ] [ " refused " ] = True
application [ fullclb [ 3 ] ] [ " refused_by " ] = clb . from_user . id
application [ fullclb [ 3 ] ] [ " refusal_date " ] = int ( time ( ) )
jsonSave ( application , f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
2022-10-21 15:00:03 +03:00
2022-10-22 10:41:58 +03:00
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " declined " , " button " ) ) , callback_data = " nothing " ) ] ]
2022-10-21 15:00:03 +03:00
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
2022-10-23 01:27:54 +03:00
await clb . answer ( text = locale ( " sub_no_aggressive " , " callback " ) . format ( fullclb [ 3 ] ) , show_alert = True ) # type: ignore
2022-10-21 15:00:03 +03:00
2022-10-23 01:27:54 +03:00
@app.on_callback_query ( filters . regex ( " sub_no_russian_[ \ s \ S]* " ) ) # type: ignore
async def callback_query_refuse_russian ( app , clb ) :
2022-10-21 15:00:03 +03:00
fullclb = clb . data . split ( " _ " )
2022-10-23 01:27:54 +03:00
await app . send_message ( configGet ( " admin_group " ) , locale ( " refused_by_rus " , " message " ) . format ( clb . from_user . first_name , fullclb [ 3 ] ) , disable_notification = True ) # type: ignore
await app . send_message ( int ( fullclb [ 3 ] ) , locale ( " refused " , " message " ) )
await app . send_message ( int ( fullclb [ 3 ] ) , locale ( " refused_russian " , " message " ) )
2022-10-23 12:56:28 +03:00
logWrite ( f " User { fullclb [ 3 ] } got refused by { clb . from_user . id } due to being russian " )
2022-10-23 01:27:54 +03:00
configSet ( " refused " , True , file = fullclb [ 3 ] )
2022-10-25 14:36:16 +03:00
configSet ( " sent " , False , file = fullclb [ 3 ] )
2022-10-23 01:27:54 +03:00
application = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
application [ fullclb [ 3 ] ] [ " refused " ] = True
application [ fullclb [ 3 ] ] [ " refused_by " ] = clb . from_user . id
application [ fullclb [ 3 ] ] [ " refusal_date " ] = int ( time ( ) )
jsonSave ( application , f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
2022-10-21 15:00:03 +03:00
2022-10-22 10:41:58 +03:00
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " declined " , " button " ) ) , callback_data = " nothing " ) ] ]
2022-10-21 15:00:03 +03:00
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
2022-10-23 01:27:54 +03:00
await clb . answer ( text = locale ( " sub_no_russian " , " callback " ) . format ( fullclb [ 3 ] ) , show_alert = True ) # type: ignore
2022-10-21 15:00:03 +03:00
2022-10-23 01:27:54 +03:00
@app.on_callback_query ( filters . regex ( " sub_no_[ \ s \ S]* " ) ) # type: ignore
async def callback_query_refuse ( app , clb ) :
2022-10-21 15:00:03 +03:00
fullclb = clb . data . split ( " _ " )
2022-10-23 01:27:54 +03:00
await app . send_message ( configGet ( " admin_group " ) , locale ( " refused_by " , " message " ) . format ( clb . from_user . first_name , fullclb [ 2 ] ) , disable_notification = True ) # type: ignore
2022-10-22 10:41:58 +03:00
await app . send_message ( int ( fullclb [ 2 ] ) , locale ( " refused " , " message " ) )
2022-10-23 12:56:28 +03:00
logWrite ( f " User { fullclb [ 2 ] } got refused by { clb . from_user . id } " )
2022-10-21 15:00:03 +03:00
2022-10-23 01:27:54 +03:00
configSet ( " refused " , True , file = fullclb [ 2 ] )
2022-10-25 14:36:16 +03:00
configSet ( " sent " , False , file = fullclb [ 2 ] )
application = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
application [ fullclb [ 2 ] ] [ " refused " ] = True
application [ fullclb [ 2 ] ] [ " refused_by " ] = clb . from_user . id
application [ fullclb [ 2 ] ] [ " refusal_date " ] = int ( time ( ) )
jsonSave ( application , f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " declined " , " button " ) ) , callback_data = " nothing " ) ] ]
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
await clb . answer ( text = locale ( " sub_refused " , " callback " ) . format ( fullclb [ 2 ] ) , show_alert = True ) # type: ignore
# ==============================================================================================================================
# Callbacks application ========================================================================================================
@app.on_callback_query ( filters . regex ( " reapply_yes_[ \ s \ S]* " ) ) # type: ignore
async def callback_query_accept ( app , clb ) :
fullclb = clb . data . split ( " _ " )
await app . send_message ( configGet ( " admin_group " ) , locale ( " approved_by " , " message " ) . format ( clb . from_user . first_name , fullclb [ 2 ] ) , disable_notification = True ) # type: ignore
logWrite ( f " User { fullclb [ 2 ] } got their reapplication approved by { clb . from_user . id } " )
await app . send_message ( int ( fullclb [ 2 ] ) , locale ( " approved_joined " , " message " ) )
configSet ( " approved " , True , file = fullclb [ 2 ] )
configSet ( " sent " , False , file = fullclb [ 2 ] )
application = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
application [ fullclb [ 2 ] ] [ " approved " ] = True
application [ fullclb [ 2 ] ] [ " approved_by " ] = clb . from_user . id
application [ fullclb [ 2 ] ] [ " approval_date " ] = int ( time ( ) )
jsonSave ( application , f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " accepted " , " button " ) ) , callback_data = " nothing " ) ] ]
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
await clb . answer ( text = locale ( " sub_accepted " , " callback " ) . format ( fullclb [ 2 ] ) , show_alert = True ) # type: ignore
@app.on_callback_query ( filters . regex ( " reapply_no_[ \ s \ S]* " ) ) # type: ignore
async def callback_query_refuse ( app , clb ) :
fullclb = clb . data . split ( " _ " )
await app . send_message ( configGet ( " admin_group " ) , locale ( " refused_by " , " message " ) . format ( clb . from_user . first_name , fullclb [ 2 ] ) , disable_notification = True ) # type: ignore
await app . send_message ( int ( fullclb [ 2 ] ) , locale ( " refused " , " message " ) )
logWrite ( f " User { fullclb [ 2 ] } got their reapplication refused by { clb . from_user . id } " )
configSet ( " refused " , True , file = fullclb [ 2 ] )
configSet ( " sent " , False , file = fullclb [ 2 ] )
2022-10-23 01:27:54 +03:00
application = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
application [ fullclb [ 2 ] ] [ " refused " ] = True
application [ fullclb [ 2 ] ] [ " refused_by " ] = clb . from_user . id
application [ fullclb [ 2 ] ] [ " refusal_date " ] = int ( time ( ) )
jsonSave ( application , f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " )
2022-10-22 10:41:58 +03:00
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " declined " , " button " ) ) , callback_data = " nothing " ) ] ]
2022-10-21 15:00:03 +03:00
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
2022-10-23 01:27:54 +03:00
await clb . answer ( text = locale ( " sub_refused " , " callback " ) . format ( fullclb [ 2 ] ) , show_alert = True ) # type: ignore
2022-10-21 15:00:03 +03:00
# ==============================================================================================================================
2022-10-23 01:27:54 +03:00
2022-10-24 00:40:43 +03:00
# Callbacks sus users ==========================================================================================================
@app.on_callback_query ( filters . regex ( " sus_allow_[ \ s \ S]* " ) ) # type: ignore
async def callback_query_sus_allow ( app , clb ) :
fullclb = clb . data . split ( " _ " )
await app . send_message ( configGet ( " admin_group " ) , locale ( " sus_allowed_by " , " message " ) . format ( clb . from_user . first_name , fullclb [ 2 ] ) , disable_notification = True ) # type: ignore
logWrite ( f " User { fullclb [ 2 ] } was allowed to join with another link by { clb . from_user . id } " )
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " sus_allowed " , " button " ) ) , callback_data = " nothing " ) ] ]
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
await clb . answer ( text = locale ( " sus_allowed " , " callback " ) . format ( fullclb [ 2 ] ) , show_alert = True ) # type: ignore
await app . restrict_chat_member ( configGet ( " destination_group " ) , int ( fullclb [ 2 ] ) , permissions = ChatPermissions (
can_send_messages = True ,
can_send_media_messages = True ,
can_send_other_messages = True ,
can_send_polls = True
)
)
@app.on_callback_query ( filters . regex ( " sus_refuse_[ \ s \ S]* " ) ) # type: ignore
async def callback_query_sus_refuse ( app , clb ) :
fullclb = clb . data . split ( " _ " )
await app . send_message ( configGet ( " admin_group " ) , locale ( " sus_refused_by " , " message " ) . format ( clb . from_user . first_name , fullclb [ 2 ] ) , disable_notification = True ) # type: ignore
logWrite ( f " User { fullclb [ 2 ] } was refused to join with another link by { clb . from_user . id } " )
edited_markup = [ [ InlineKeyboardButton ( text = str ( locale ( " sus_refused " , " button " ) ) , callback_data = " nothing " ) ] ]
await clb . message . edit ( text = clb . message . text , reply_markup = InlineKeyboardMarkup ( edited_markup ) )
await clb . answer ( text = locale ( " sus_refused " , " callback " ) . format ( fullclb [ 2 ] ) , show_alert = True ) # type: ignore
await app . ban_chat_member ( configGet ( " destination_group " ) , int ( fullclb [ 2 ] ) )
jsonSave ( jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } user_default.json " ) , f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { fullclb [ 2 ] } .json " )
configSet ( " stage " , 10 , file = fullclb [ 2 ] )
configSet ( " refused " , True , file = fullclb [ 2 ] )
configSet ( " refused_by " , clb . from_user . id , file = fullclb [ 2 ] )
# ==============================================================================================================================
# Callback empty ===============================================================================================================
@app.on_callback_query ( filters . regex ( " nothing " ) ) # type: ignore
async def callback_query_nothing ( app , clb ) :
await clb . answer ( text = locale ( " nothing " , " callback " ) )
# ==============================================================================================================================
2022-10-23 01:42:21 +03:00
# Contact getting ==============================================================================================================
2022-10-23 12:48:34 +03:00
@app.on_message ( ~ filters . scheduled & filters . contact & filters . private )
2022-10-23 01:27:54 +03:00
async def get_contact ( app , msg ) :
2022-10-24 15:34:18 +03:00
if ( path . exists ( f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { msg . from_user . id } .json " ) and jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { msg . from_user . id } .json " ) [ " approved " ] ) or ( await isAnAdmin ( msg . from_user . id ) ) :
2022-10-23 01:27:54 +03:00
if msg . contact . user_id != None :
try :
user_data = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { msg . contact . user_id } .json " )
application_content = [ ]
i = 1
2022-10-24 15:34:18 +03:00
for question in configGet ( " application " , file = str ( msg . from_user . id ) ) :
if i == 2 :
age = relativedelta ( datetime . now ( ) , datetime . strptime ( configGet ( ' application ' , file = str ( msg . contact . user_id ) ) [ ' 2 ' ] , ' %d . % m. % Y ' ) )
application_content . append ( f " { locale ( ' question ' + str ( i ) , ' message ' , ' question_titles ' ) } { configGet ( ' application ' , file = str ( msg . contact . user_id ) ) [ ' 2 ' ] } ( { age . years } р .) " )
else :
application_content . append ( f " { locale ( ' question ' + str ( i ) , ' message ' , ' question_titles ' ) } { configGet ( ' application ' , file = str ( msg . contact . user_id ) ) [ question ] } " )
2022-10-23 01:27:54 +03:00
i + = 1
2022-10-25 14:36:16 +03:00
application = jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } applications.json " ) [ str ( msg . contact . user_id ) ]
2022-10-23 01:27:54 +03:00
if user_data [ " sent " ] :
if user_data [ " approved " ] :
2022-10-23 12:48:34 +03:00
application_status = locale ( " application_status_accepted " , " message " ) . format ( ( await app . get_users ( application [ " approved_by " ] ) ) . first_name , datetime . fromtimestamp ( application [ " approval_date " ] ) . strftime ( " %d . % m. % Y, % H: % M " ) ) # type: ignore
2022-10-23 01:27:54 +03:00
elif application [ " refused " ] :
2022-10-23 12:48:34 +03:00
application_status = locale ( " application_status_refused " , " message " ) . format ( ( await app . get_users ( application [ " refused_by " ] ) ) . first_name , datetime . fromtimestamp ( application [ " refusal_date " ] ) . strftime ( " %d . % m. % Y, % H: % M " ) ) # type: ignore
2022-10-23 01:27:54 +03:00
else :
application_status = locale ( " application_status_on_hold " , " message " )
else :
2022-10-25 14:36:16 +03:00
if user_data [ " approved " ] :
application_status = locale ( " application_status_accepted " , " message " ) . format ( ( await app . get_users ( application [ " approved_by " ] ) ) . first_name , datetime . fromtimestamp ( application [ " approval_date " ] ) . strftime ( " %d . % m. % Y, % H: % M " ) ) # type: ignore
elif application [ " refused " ] :
application_status = locale ( " application_status_refused " , " message " ) . format ( ( await app . get_users ( application [ " refused_by " ] ) ) . first_name , datetime . fromtimestamp ( application [ " refusal_date " ] ) . strftime ( " %d . % m. % Y, % H: % M " ) ) # type: ignore
else :
application_status = locale ( " application_status_not_send " , " message " )
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } requested application of { msg . contact . user_id } " )
2022-10-23 01:27:54 +03:00
await msg . reply_text ( locale ( " contact " , " message " ) . format ( str ( msg . contact . user_id ) , " \n " . join ( application_content ) , application_status ) ) # type: ignore
except FileNotFoundError :
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } requested application of { msg . contact . user_id } but user does not exists " )
2022-10-23 01:27:54 +03:00
await msg . reply_text ( locale ( " contact_invalid " , " message " ) )
else :
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } requested application of someone but user is not telegram user " )
2022-10-23 01:27:54 +03:00
await msg . reply_text ( locale ( " contact_not_member " , " message " ) )
2022-10-23 01:42:21 +03:00
# ==============================================================================================================================
2022-10-23 01:27:54 +03:00
2022-10-21 15:00:03 +03:00
# Any other input ==============================================================================================================
@app.on_message ( ~ filters . scheduled & filters . private )
2022-10-20 16:08:46 +03:00
async def any_stage ( app , msg ) :
user_stage = configGet ( " stage " , file = str ( msg . from_user . id ) )
if user_stage == 1 :
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( f " question { user_stage + 1 } " , " message " ) , reply_markup = ForceReply ( placeholder = str ( locale ( f " question { user_stage + 1 } " , " force_reply " ) ) ) )
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } completed stage { user_stage } of application " )
2022-10-20 16:08:46 +03:00
configSet ( str ( user_stage ) , str ( msg . text ) , " application " , file = str ( msg . from_user . id ) )
configSet ( " stage " , user_stage + 1 , file = str ( msg . from_user . id ) )
2022-10-24 15:34:18 +03:00
2022-10-20 16:24:31 +03:00
elif user_stage == 2 :
2022-10-24 15:34:18 +03:00
2022-10-20 16:24:31 +03:00
try :
2022-10-24 15:34:18 +03:00
configSet ( str ( user_stage ) , str ( msg . text ) , " application " , file = str ( msg . from_user . id ) )
input_dt = datetime . strptime ( msg . text , " %d . % m. % Y " )
if datetime . now ( ) < = input_dt :
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } failed stage { user_stage } due to joking " )
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( " question2_joke " , " message " ) , reply_markup = ForceReply ( placeholder = str ( locale ( " question2 " , " force_reply " ) ) ) )
2022-10-24 15:34:18 +03:00
elif ( ( datetime . now ( ) - input_dt ) . days ) < ( ( datetime . now ( ) - datetime . now ( ) . replace ( year = datetime . now ( ) . year - configGet ( " age_allowed " ) ) ) . days ) :
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } failed stage { user_stage } due to being underage " )
2022-10-23 01:27:54 +03:00
await msg . reply_text ( locale ( " question2_underage " , " message " ) . format ( str ( configGet ( " age_allowed " ) ) ) , reply_markup = ForceReply ( placeholder = str ( locale ( " question2 " , " force_reply " ) ) ) ) # type: ignore
2022-10-24 15:34:18 +03:00
2022-10-21 15:00:03 +03:00
else :
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } completed stage { user_stage } of application " )
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( f " question { user_stage + 1 } " , " message " ) , reply_markup = ForceReply ( placeholder = str ( locale ( f " question { user_stage + 1 } " , " force_reply " ) ) ) )
2022-10-21 15:00:03 +03:00
configSet ( " stage " , user_stage + 1 , file = str ( msg . from_user . id ) )
2022-10-24 15:34:18 +03:00
2022-10-20 16:24:31 +03:00
except ValueError :
2022-10-24 15:34:18 +03:00
logWrite ( f " User { msg . from_user . id } failed stage { user_stage } due to sending invalid date format " )
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( f " question2_invalid " , " message " ) , reply_markup = ForceReply ( placeholder = str ( locale ( f " question { user_stage } " , " force_reply " ) ) ) )
2022-10-24 15:34:18 +03:00
2022-10-20 16:08:46 +03:00
else :
if user_stage < = 9 :
2022-10-23 12:56:28 +03:00
logWrite ( f " User { msg . from_user . id } completed stage { user_stage } of application " )
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( f " question { user_stage + 1 } " , " message " ) , reply_markup = ForceReply ( placeholder = str ( locale ( f " question { user_stage + 1 } " , " force_reply " ) ) ) )
2022-10-20 16:08:46 +03:00
configSet ( str ( user_stage ) , str ( msg . text ) , " application " , file = str ( msg . from_user . id ) )
configSet ( " stage " , user_stage + 1 , file = str ( msg . from_user . id ) )
else :
if not configGet ( " sent " , file = str ( msg . from_user . id ) ) :
2022-10-20 22:19:37 +03:00
if not configGet ( " confirmed " , file = str ( msg . from_user . id ) ) :
2022-10-23 13:32:10 +03:00
configSet ( str ( user_stage ) , str ( msg . text ) , " application " , file = str ( msg . from_user . id ) )
2022-10-21 15:00:03 +03:00
application_content = [ ]
i = 1
for question in configGet ( " application " , file = str ( msg . from_user . id ) ) :
application_content . append ( f " { locale ( ' question ' + str ( i ) , ' message ' , ' question_titles ' ) } { configGet ( ' application ' , file = str ( msg . from_user . id ) ) [ question ] } " )
i + = 1
2022-10-22 10:41:58 +03:00
await msg . reply_text ( locale ( " confirm " , " message " ) . format ( " \n " . join ( application_content ) ) , reply_markup = ReplyKeyboardMarkup ( locale ( " confirm " , " keyboard " ) , resize_keyboard = True ) ) # type: ignore
2022-10-20 22:19:37 +03:00
#configSet("sent", True, file=str(msg.from_user.id))
#configSet("application_date", int(time()), file=str(msg.from_user.id))
else :
2022-10-25 14:36:16 +03:00
if not configGet ( " approved " , file = str ( msg . from_user . id ) ) and not configGet ( " refused " , file = str ( msg . from_user . id ) ) :
await msg . reply_text ( locale ( " already_sent " , " message " ) )
2022-10-20 16:08:46 +03:00
else :
2022-10-23 01:27:54 +03:00
if not configGet ( " approved " , file = str ( msg . from_user . id ) ) and not configGet ( " refused " , file = str ( msg . from_user . id ) ) :
2022-10-23 01:42:21 +03:00
await msg . reply_text ( locale ( " already_sent " , " message " ) )
2022-10-21 15:00:03 +03:00
# ==============================================================================================================================
2022-10-20 13:24:32 +03:00
2022-10-17 00:30:07 +03:00
2022-10-23 17:22:38 +03:00
# Filter users on join =========================================================================================================
2022-10-24 00:40:43 +03:00
@app.on_chat_member_updated ( group = configGet ( " destination_group " ) )
#@app.on_message(filters.new_chat_members, group=configGet("destination_group"))
2022-10-23 17:22:38 +03:00
async def filter_join ( app , member ) :
2022-10-24 00:40:43 +03:00
if member . invite_link != None :
2022-10-24 15:34:18 +03:00
if ( path . exists ( f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { member . from_user . id } .json " ) and jsonLoad ( f " { configGet ( ' data ' , ' locations ' ) } { sep } users { sep } { member . from_user . id } .json " ) [ " approved " ] ) or ( await isAnAdmin ( member . from_user . id ) ) :
2022-10-24 00:40:43 +03:00
if configGet ( " link " , file = str ( member . from_user . id ) ) == member . invite_link . invite_link :
return
2022-10-24 15:34:18 +03:00
if await isAnAdmin ( member . invite_link . creator . id ) :
return
2022-10-24 00:40:43 +03:00
await app . send_message ( configGet ( " admin_group " ) , f " User ** { member . from_user . first_name } ** (` { member . from_user . id } `) joined the chat not with his personal link " , reply_markup = InlineKeyboardMarkup (
2022-10-23 20:20:33 +03:00
[
2022-10-24 00:40:43 +03:00
[
InlineKeyboardButton ( text = str ( locale ( " sus_allow " , " button " ) ) , callback_data = f " sus_allow_ { member . from_user . id } " )
] ,
[
InlineKeyboardButton ( text = str ( locale ( " sus_refuse " , " button " ) ) , callback_data = f " sus_refuse_ { member . from_user . id } " )
]
2022-10-23 20:20:33 +03:00
]
2022-10-24 00:40:43 +03:00
) )
await app . restrict_chat_member ( member . chat . id , member . from_user . id , permissions = ChatPermissions (
can_send_messages = False ,
can_send_media_messages = False ,
can_send_other_messages = False ,
can_send_polls = False
)
2022-10-23 20:20:33 +03:00
)
2022-10-23 17:22:38 +03:00
# ==============================================================================================================================
2022-10-17 00:30:07 +03:00
if __name__ == " __main__ " :
logWrite ( f " Starting up with pid { pid } " )
# Yes, it should be in some kind of async main() function but I don't give a shit.
2022-10-20 13:24:32 +03:00
# I did compare performance, almost no difference and it's much more useful this way. Change my mind.
2022-10-17 00:30:07 +03:00
app . start ( ) # type: ignore
2022-10-25 15:18:51 +03:00
if configGet ( " birthdays_notify " ) :
every ( ) . day . at ( configGet ( " birthdays_time " ) ) . do ( check_birthdays , app )
# Background tasks checker
def background_task ( ) :
try :
while True :
try :
run_pending ( )
#print('Checked')
time . sleep ( 1 )
except :
pass
except KeyboardInterrupt :
print ( ' \n Shutting down ' )
killProc ( pid )
t = Thread ( target = background_task )
t . start ( )
2022-10-17 00:30:07 +03:00
app . send_message ( configGet ( " owner " ) , f " Starting up with pid ` { pid } ` " ) # type: ignore
2022-10-25 14:36:16 +03:00
# Registering user commands
commands_list = [ ]
for command in configGet ( " commands " ) :
commands_list . append ( BotCommand ( command , configGet ( " commands " ) [ command ] ) )
app . set_bot_commands ( commands_list ) # type: ignore
2022-10-17 00:30:07 +03:00
# Registering admin commands
commands_admin_list = [ ]
2022-10-25 14:36:16 +03:00
for command in configGet ( " commands " ) :
commands_admin_list . append ( BotCommand ( command , configGet ( " commands " ) [ command ] ) )
2022-10-17 00:30:07 +03:00
for command in configGet ( " commands_admin " ) :
commands_admin_list . append ( BotCommand ( command , configGet ( " commands_admin " ) [ command ] ) )
for admin in configGet ( " admins " ) :
try :
app . set_bot_commands ( commands_admin_list , scope = BotCommandScopeChat ( chat_id = admin ) ) # type: ignore
except bad_request_400 . PeerIdInvalid :
pass
app . set_bot_commands ( commands_admin_list , scope = BotCommandScopeChat ( chat_id = configGet ( " owner " ) ) ) # type: ignore
idle ( )
app . send_message ( configGet ( " owner " ) , f " Shutting with pid ` { pid } ` " ) # type: ignore
app . stop ( ) # type: ignore
killProc ( pid )