diff --git a/.gitignore b/.gitignore index a828f5e..d673f0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ __pycache__ .vscode/ -database.sqlitedb \ No newline at end of file +database.sqlitedb +database.sqlitedb-journal \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fece950 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +FROM python:3-alpine + +WORKDIR /usr/src/app + +COPY requirements.txt ./ + +# +# The compilation of lxml (a library required and installed by pip) requires more than 1GiB of RAM memory. +# Since I had only 1 GiB of RAM, as a workaround I made a 2GiB swap file +# THIS IS A THING TO AVOID AS MUSH AS POSSIBLE +# Commands executed: +# +# 1. dd if=/dev/zero of=/swapfile bs=2048 count=1M +# 2. chmod 0600 /swapfile +# 3. mkswap /swapfile +# 4. echo "/swapfile swap swap sw 0 0" >>/etc/fstab +# 5. swapon /swapfile +# +# 1. Creates a swapfile and fill it of 0s +# 2. Set permissions for a swap file +# 3. Sets the file a file usable as a swap file +# 4. sets the swap on startup +# 5. enables the swap "hotplugged" + + +RUN apk add py3-pip openssl py3-lxml \ + && apk add --virtual build-dependencies python3-dev build-base wget libffi-dev openssl-dev libxml2-dev libxslt-dev \ + && rm -rf /var/cache/apk/* + +RUN pip install --no-cache-dir -r requirements.txt +RUN apk del build-dependencies + + +COPY scienzati_bot.py . + +CMD [ "python", "./scienzati_bot.py" ] diff --git a/database.sqlitedb-journal b/database.sqlitedb-journal deleted file mode 100644 index 89bd3cd..0000000 Binary files a/database.sqlitedb-journal and /dev/null differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2e154ca Binary files /dev/null and b/requirements.txt differ diff --git a/scienzati_bot.py b/scienzati_bot.py index 0ef33b6..a02537d 100644 --- a/scienzati_bot.py +++ b/scienzati_bot.py @@ -4,14 +4,15 @@ import sqlite3 import random import re +import sys +import os #Settings class class Settings: - TelegramApiKey = "676490981:AAELlmTlQLD4_1HojhzWIX4yISDrVU5qDmA" - SupremeAdmins = [14092073] - ITGroup = 0 - OTGroup = -1001176680738 + SupremeAdmins = ["pandry","andreaidini"]#Lowercase username! + ITGroup = -1001068546876 + OTGroup = -1001218814107 subscriptionRows = 7 @@ -20,7 +21,11 @@ class Settings: ### #Create the bot instance -bot = telebot.TeleBot(Settings.TelegramApiKey) +if "TELEGRAM_API_KEY" in os.environ: + bot = telebot.TeleBot(os.environ["TELEGRAM_API_KEY"]) +else: + print ("Please enter the bot API key in the environment variable \"TELEGRAM_API_KEY\"") + sys.exit(1) botInfo = bot.get_me() print("Authorized on @" + botInfo.username) @@ -45,6 +50,8 @@ class Settings: #This part of the code is used to initalize the database. #It runs the "seed" query #This is the query that is used to initialize the SQLite3 database + +#TODO: add referencing message to make the bot statful initQuery= """CREATE TABLE IF NOT EXISTS `Users` ( `ID` INTEGER NOT NULL UNIQUE, `Nickname` TEXT NOT NULL, @@ -85,20 +92,59 @@ class Settings: class constResources: - intro_mex = """Questo e' il bot del gruppo @scienza, - /iscrivi iscriviti al database di utenti e a liste di interessi - /modifica visiona e modifica la propria descrizione - /liste consulta le attuali liste di interessi - /nuovalista crea nuove liste - /privs elenca i privilegi utente""" - - privs_mex = """privs =-1 -> utente non registrato - = 0 -> utente normale - = 1 -> utente abituale - = 2 -> utente assiduo - = 3 -> utente storico (puo' inoltrare al canale, puo' creare nuove liste) - = 4 -> amministratore - = 5 -> fondatore""" + intro_mex = """Ciao 😁 +Sei confuso? +Questo è il bot del gruppo @scienza e permette di usufruire di queste funzioni: +/iscriviti per iscriverti al database di utenti e per partecipare alle liste sugli interessi +/aderisci per iscriverti ad una lista, puoi usare anche: /partecipa, /registrati e /sottoscrivi +/bio per scrivere qualcosa su di te +/liste per scoprire le liste già presenti +/gdpr consulta le norme sul GDPR +/privs elenca i privilegi di un utente (richiesto come argomento) +/biografia mostra la biografia di un utente (richiesto come argomento) +/disiscrivi per cancellarti da una lista alla quale hai aderito, puoi usare pure: /esci, /rimuovi, /iscrizioni e /aderenze +/info Ottieni informazioni su di me + +Puoi anche usare il bot in modalità "inline": sarà sufficiente scrivere @scienziati_bot per avere informazioni riguardo l'utente + +In caso di problemi invece, sei pregato di conttattare @Pandry, in quanto sviluppatore del bot. +Report di problemi, come ad esempio liste non presenti, bot non responsivo ecc sono assolutamente gradite; O anche solo per proporre qualche idea e conversarne a riguardo. +A tal proposito, esiste un gruppo dedicato ai programmi scritti in comune tra i membri di @Scienza. +Chiedi ad un amministratore per ulteriori informazioni a riguardo. +Buona continuazione su @Scienza""" + + welcome_message = """Benvenuto/a 😊 +Presentati se ti va (se possibile evidenzia le tue passioni scientifiche e/o i tuoi studi), ci farebbe piacere ☺️. + +Hai interessi particolari e vuoi essere avvisato quando se ne parla nel gruppo? Utilizza il nostro bot @scienzati_bot per iscriverti e registrarti nelle liste che ti interessano! +Al fine di non "intasare" la chat con messaggi da parte mia, sei invitata/o ad avviarmi in privato. +In caso di dubbi, il comando /help o /aiuto sarà a tua disposizione. +Buona permanenza dallo staff di @Scienza 😁""" + + info_message = """Ciao! +Questo è il bot del gruppo @Scienza! +Questo bot è stato sviluppato da alcuni membri del gruppo @Scienza (@AndreaIdini, @Pandry) con lo scopo di agevolare l'intervento di persone competenti in un determinato campo e richiedere il loro aiuto riguardo le questioni e le domande poste nel gruppo. +Il bot è OSS (Open Source Software) ed è possibile trovare il codice sorgente a questo indirizzo: + +https://github.com/Scienza/scienziati_bot + +La persona che al momento si occupa dello sviluppo attivo del bot e si occupa di mantenerlo operativo è @Pandry. +Puoi contattarlo in privato per qualunque questione, tuttavia ti chiedo di contattarlo in caso di questioni riguardati problemi con me o nel caso tu voglia qualche funzionalità aggiuntiva ad esempio. + + """ + + admin_help = """Comandi admin... blabla + /nuovalista + /rimuovilista + /del delete bot message + === CA$TA THINGS === + /setadmin + /unsetadmin + /grantlist + /revokelist + """ + + version = "α0.1.2.14" gdpr_message = "Raccogliamo il numero di messaggi, nickname, ID e ultima volta che l'utente ha scritto. Per richiedere l'eliminazione dei propri dati contattare un amministratore ed uscire dal gruppo" @@ -166,28 +212,97 @@ def CanEnterBio(status): # x0xx - flag - 1 = can post to channel # class UserPermission: #Siply do an AND with the permission - ADMIN=int('1', 2) - CHANNEL=int('10', 2) - CREATE_LIST=int('100', 2) + PermissionConut = 0 + + ADMIN=int('1' + '0'*PermissionConut, 2) + PermissionConut +=1 # DO NOT FUCKING REMOVE + # THIS CRAP DOES NOT HAVE A ++ OPERATOR + # SET ONE OF THOSE FOR EVERY PERMISSION YOU CREATE + # #RAGETIME + # ~ Pandry + + #WHEN CREATING A NEW PERMISSION, JUST DUPLICATE BOTH THE LINES + CAN_ADD_ADMIN=int('1' + '0'*PermissionConut, 2) + PermissionConut +=1 + + CAN_REMOVE_ADMIN=int('1' + '0'*PermissionConut, 2) + PermissionConut +=1 + + CHANNEL=int('1' + '0'*PermissionConut, 2) + PermissionConut +=1 + + LIST=int('1' + '0'*PermissionConut, 2) + PermissionConut +=1 + + + def HasPermission(userPermission, permissiontoCheck): + if (userPermission & permissiontoCheck) == permissiontoCheck: + return True + return False + + def SetPermission(userPermission, permissiontoCheck): + return (userPermission | permissiontoCheck) + + def RemovePermission(userPermission, permissiontoCheck): + return userPermission & (not(permissiontoCheck)) + def IsAdmin(permission): if (permission & UserPermission.ADMIN) == UserPermission.ADMIN: return True return False + def SetAdminPermission(permission): + return (permission | UserPermission.ADMIN) + + def RemoveAdminPermission(permission): + return permission & (not(UserPermission.ADMIN)) + + def CanAddAdmin(permission): + if (permission & UserPermission.CAN_ADD_ADMIN) == UserPermission.CAN_ADD_ADMIN: + return True + return False + + def SetCanAddAdmin(permission): + return permission | UserPermission.CAN_ADD_ADMIN + + def RemoveCanAddAdmin(permission): + return permission & (not(UserPermission.CAN_ADD_ADMIN)) + + def CanRemoveAdmin(permission): + if (permission & UserPermission.CAN_REMOVE_ADMIN) == UserPermission.CAN_REMOVE_ADMIN: + return True + return False + + def SetCanRemoveAdmin(permission): + return permission | UserPermission.CAN_REMOVE_ADMIN + + def RemoveCanRemoveAdmin(permission): + return permission & (not(UserPermission.CAN_REMOVE_ADMIN)) + def CanForwardToChannel(permission): if (permission & UserPermission.CHANNEL) == UserPermission.CHANNEL: return True return False - def CanCreateList(permission): - if (permission & UserPermission.CREATE_LIST) == UserPermission.CREATE_LIST: + def SetForwardToChannel(permission): + return permission | UserPermission.CHANNEL + + def RemoveForwardToChannel(permission): + return permission & (not(UserPermission.CHANNEL)) + + def ListPermission(permission): + if (permission & UserPermission.LIST) == UserPermission.LIST: return True return False - - - + def SetListPermission(permission): + return permission | UserPermission.LIST + + def RemoveListPermission(permission): + return permission & (not(UserPermission.LIST)) + + ### @@ -222,7 +337,7 @@ def GetUser(userID): #It returns true in case of success, otherwise it returns false def UpdateBio(userdID, bio): dbC = dbConnection.cursor() - res = dbC.execute('INSERT INTO Users (ID, Nickname, Status) VALUES (?,?,?)', (userdID, bio, UserStatus.USER_JUST_CREATED,) ) + res = dbC.execute('INSERT INTO Users (ID, Nickname, Status) VALUES (?,?,?)', (userdID, bio, UserStatus.ACTIVE,) ) if res: CommitDb() return True @@ -236,6 +351,15 @@ def GetUserPermissionsValue(userID): #No user exist, returning Flase for now return False +# GetUserPermissionsValue takes the userID as input and returns the permission value (int) direclty from the database +def SetUserPermissionsValue(userID,newPermission): + dbC = dbConnection.cursor() + res = dbC.execute('UPDATE Users SET Permissions=? WHERE ID = ?', (newPermission, userID,) ) + if res: + CommitDb() + return True + return False + def GetUserStatusValue(userID): user = GetUser(userID) if user != False: @@ -286,14 +410,30 @@ def CreateNewList(name): try: res = dbC.execute('INSERT INTO Lists (Name) VALUES (?)', (name,) ) if res: + CommitDb() return True return False except: return False -def GetLists(): +def GetLists(limit = Settings.subscriptionRows-1, offset=0): + dbC = dbConnection.cursor() + if limit == None: + dbC.execute('SELECT * FROM Lists') + else: + dbC.execute('SELECT * FROM Lists LIMIT ? OFFSET ?', (limit, offset,)) + res = dbC.fetchall() + if len(res) >0: + return res + return False + + +def GetListsNames(limit = Settings.subscriptionRows-1, offset=0): dbC = dbConnection.cursor() - dbC.execute('SELECT `Name` FROM Lists') + if limit == None: + dbC.execute('SELECT `Name` FROM Lists') + else: + dbC.execute('SELECT `Name` FROM Lists LIMIT ? OFFSET ?', (limit, offset,)) return dbC.fetchall() def SubscribeUserToList(userID, listID): @@ -309,6 +449,7 @@ def SubscribeUserToList(userID, listID): dbC.execute('INSERT INTO Subscriptions (User, List) VALUES (?,?)', (userID, listID)) res = dbC.fetchall() if res != None: + CommitDb() return True return False @@ -318,14 +459,17 @@ def UnubscribeUserFromList(userID, listID): dbC.execute('DELETE FROM Subscriptions WHERE User=? AND List=?', (userID, listID)) res = dbC.fetchall() if res != None: - #User already subscribed + CommitDb() return True return False def AvailableListsToUser(userID, limit=Settings.subscriptionRows-1, offset=0): #If user is not in the list dbC = dbConnection.cursor() - dbC.execute('SELECT ID, Name FROM Lists WHERE Lists.ID NOT IN (SELECT List FROM Subscriptions WHERE User=?) LIMIT ? OFFSET ?', (userID, limit,offset)) + if limit == None: + dbC.execute('SELECT ID, Name FROM Lists WHERE Lists.ID NOT IN (SELECT List FROM Subscriptions WHERE User=?)') + else: + dbC.execute('SELECT ID, Name FROM Lists WHERE Lists.ID NOT IN (SELECT List FROM Subscriptions WHERE User=?) LIMIT ? OFFSET ?', (userID, limit,offset)) res = dbC.fetchall() if len(res) >0: #User already subscribed @@ -336,7 +480,10 @@ def AvailableListsToUser(userID, limit=Settings.subscriptionRows-1, offset=0): def SubscribedLists(userID, limit=Settings.subscriptionRows-1, offset=0): #If user is not in the list dbC = dbConnection.cursor() - dbC.execute('SELECT Lists.ID, Lists.Name FROM Lists INNER JOIN Subscriptions ON Subscriptions.List = Lists.ID WHERE Subscriptions.User=? LIMIT ? OFFSET ?', (userID, limit,offset)) + if limit == None: + dbC.execute('SELECT Lists.ID, Lists.Name FROM Lists INNER JOIN Subscriptions ON Subscriptions.List = Lists.ID WHERE Subscriptions.User=?', (userID,)) + else: + dbC.execute('SELECT Lists.ID, Lists.Name FROM Lists INNER JOIN Subscriptions ON Subscriptions.List = Lists.ID WHERE Subscriptions.User=? LIMIT ? OFFSET ?', (userID, limit,offset)) res = dbC.fetchall() if len(res) >0: #User already subscribed @@ -377,9 +524,22 @@ def GetListSubscribers(listID): return res return False +def DeleteList(listID): + #If user is not in the list + dbC = dbConnection.cursor() + res =dbC.execute('DELETE FROM Lists WHERE ID=?', (listID,)) + if res != None: + CommitDb() + return True + return False + def UpdateNickname(userID, nickname): dbC = dbConnection.cursor() - dbC.execute('UPDATE Users SET Nickname=? WHERE ID = ?', (nickname, userID, )) + res = dbC.execute('UPDATE Users SET Nickname=? WHERE ID = ?', (nickname.lower().replace('@',''), userID, )) + if res: + CommitDb() + return True + return False #Abort the inserting process of a new Bio #WARNING: CHECK IF USER IS BANNED BEFORE, OR HE WILL GET UNBANNED @@ -399,6 +559,14 @@ def GetUserBio(userID): return res[0] return False +def SetUserBio(userID, newBio): + dbC = dbConnection.cursor() + res = dbC.execute('UPDATE Users SET Status=?, Biography=? WHERE ID = ?', (UserStatus.ACTIVE, newBio, userID,) ) + if res != None: + CommitDb() + return True + return False + def abortNewList(userID): dbC = dbConnection.cursor() res = dbC.execute('UPDATE Users SET Status=? WHERE ID = ?', (UserStatus.ACTIVE, userID,) ) @@ -407,14 +575,85 @@ def abortNewList(userID): return True return False -def getUsersIdLike(userNick): +def getUsersIdLike(userNick, limit = 5, offset = 0): dbC = dbConnection.cursor() - dbC.execute('SELECT `ID` FROM Users WHERE `Nickname` LIKE ?;', ("%"+userNick.replace("%", ":%")+"%",)) + if limit == None: + dbC.execute('SELECT `ID` FROM Users WHERE `Nickname` LIKE ?;', ("%"+userNick.replace("%", ":%")+"%",)) + else: + dbC.execute('SELECT `ID` FROM Users WHERE `Nickname` LIKE ? LIMIT ? OFFSET ?;', ("%"+userNick.replace("%", ":%")+"%",limit, offset)) + res = dbC.fetchall() if res != None: return res return False +def getUserId(userNick): + userNick = userNick.replace('@','').lower() + dbC = dbConnection.cursor() + dbC.execute('SELECT `ID` FROM Users WHERE `Nickname`= ?;', (userNick,)) + res = dbC.fetchone() + if res != None: + return res[0] + return False + +def setNewUserStatus(userdID, statusID): + dbC = dbConnection.cursor() + #res = dbC.execute('UPDATE Users SET Status=? WHERE ID = ?;', (UserStatus.WAITING_FOR_BIOGRAPHY , message.from_user.id,) ) + res = dbC.execute('UPDATE Users SET Status=? WHERE ID = ?', (statusID , userdID,) ) + if res: + CommitDb() + return True + return False + + +def IsUserSuperadmin(userNick): + return userNick.lower() in Settings.SupremeAdmins + + +def getUserPermissionText(userid): + userPermission = GetUserPermissionsValue(userid) + msg = "Ecco i privilegi dell'utente @" + GetUserNickname(userid) + ":\n ⚙️ Ranks\nSupreme admin: " + if IsUserSuperadmin(GetUserNickname(userid)): + msg = msg + "✅ Sì" + else: + msg = msg + "❌ Nope" + msg = msg + "\n" + + msg = msg + "Admin: " + if UserPermission.IsAdmin(userPermission): + msg = msg + "✅ Sì" + else: + msg = msg + "❌ Nope" + msg = msg + "\n" + + msg = msg + "\n 📝Privileges\n" + msg = msg + "Gestione liste: " + if UserPermission.ListPermission(userPermission): + msg = msg + "✅ Sì" + else: + msg = msg + "❌ Nope" + msg = msg + "\n" + + msg = msg + "Aggiunta amministratori: " + if UserPermission.CanAddAdmin(userPermission): + msg = msg + "✅ Sì" + else: + msg = msg + "❌ Nope" + msg = msg + "\n" + + msg = msg + "Eliminazione amministratori: " + if UserPermission.CanRemoveAdmin(userPermission): + msg = msg + "✅ Sì" + else: + msg = msg + "❌ Nope" + msg = msg + "\n" + + msg = msg + "Inoltro al canale: " + if UserPermission.CanForwardToChannel(userPermission): + msg = msg + "✅ Sì" + else: + msg = msg + "❌ Nope" + return msg ### # Bot functions @@ -422,14 +661,53 @@ def getUsersIdLike(userNick): #Start command. # This is the function called when the bot is started or the help commands are sent -@bot.message_handler(commands=['start', 'help']) +@bot.message_handler(commands=['start', 'help', 'aiuto']) def send_welcome(message): - bot.reply_to(message, constResources.intro_mex) + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, constResources.intro_mex, reply_markup=markup) + +@bot.message_handler(commands=['info', 'informazioni', 'about']) +def send_info(message): + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, constResources.info_message, reply_markup=markup) + +@bot.message_handler(commands=['adminhelp']) +def send_admhelp(message): + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, constResources.admin_help, reply_markup=markup) + +@bot.message_handler(commands=['v', 'version']) +def send_version(message): + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, "V: " + constResources.version, reply_markup=markup) # Replies with the static message before @bot.message_handler(commands=['privs']) def send_privs(message): - bot.reply_to(message, constResources.privs_mex) + args = message.text.split(' ') + userid = message.from_user.id + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + + if len(args) == 2: + reqUserid = getUserId(args[1]) + if reqUserid != False: + userid = reqUserid + else: + bot.reply_to(message, "L'utente inserito non è stato trovato in database", reply_markup=markup) + return + elif len(args) > 2: + bot.reply_to(message, "Sono stati inseriti troppi parametri", reply_markup=markup) + + if GetUser(userid) == False: + bot.reply_to(message, "Non sei presente in database, perciò non è possibile conoscere il tuo livello di privilegi.", reply_markup=markup) + return + + bot.reply_to(message, getUserPermissionText(userid), reply_markup=markup) # Replies with the static message before @bot.message_handler(commands=['gdpr']) @@ -437,7 +715,7 @@ def send_gdrp(message): bot.reply_to(message, constResources.gdpr_message) ### Messaggio di Iscrizione -@bot.message_handler(commands=['iscrivi']) +@bot.message_handler(commands=['iscrivi', 'iscriviti']) def start_user_registration(message): if not message.from_user.is_bot and message.text != "" : # Tries to see @@ -453,23 +731,32 @@ def start_user_registration(message): #The user needs to be created #bot.reply_to(message, "creazione nuovo record utente...") #Insert + if message.from_user.username == None or message.from_user.username == "": + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, "Errore nella registrazione: è necessario avere un username.\nImposta un username e ritenta.", reply_markup=markup) + return + dbC = dbConnection.cursor() - res = dbC.execute('INSERT INTO Users (ID, Nickname, Status) VALUES (?,?,?)', (message.from_user.id, message.from_user.username, UserStatus.USER_JUST_CREATED,) ) + res = dbC.execute('INSERT INTO Users (ID, Nickname, Status) VALUES (?,?,?)', (message.from_user.id, message.from_user.username, UserStatus.ACTIVE,) ) dbConnection.commit() if res: msg = bot.reply_to(message, "Congratulazioni, ti sei registrato correttamente! Ora puoi procedere ad inserire la tua biografia attraverso il comando /bio") else: msg = bot.reply_to(message, "Errore nella creazione del record") - # this is to define step-by-step subscription #bot.register_next_step_handler(msg, first_registration) - - - - +@bot.message_handler(commands=['nudes', 'sendnudes']) +def sendNusedFromPandry(message): + bot.forward_message(message.chat.id, 14092073, 1895) + +@bot.message_handler(commands=['msginfo']) +def infohandler(message): + if message.reply_to_message != None: + msg = bot.reply_to(message, "ID " + str(message.reply_to_message.message_id)) ### Aggioramento/ impostaizone bio -@bot.message_handler(commands=['bio']) +@bot.message_handler(commands=['bio', 'setbio', 'impostabio', 'impostabiografia']) def setBio(message): if not message.from_user.is_bot and message.text != "" : # Gets info about the user @@ -483,11 +770,7 @@ def setBio(message): #There's only one user, as it's supposed to be #Check if the user needs to set a biography if UserStatus.CanEnterBio(user["Status"]): - #Asks for the bio - dbC = dbConnection.cursor() - #res = dbC.execute('UPDATE Users SET Status=? WHERE ID = ?;', (UserStatus.WAITING_FOR_BIOGRAPHY , message.from_user.id,) ) - res = dbC.execute('UPDATE Users SET Status=? WHERE ID = ?', (UserStatus.WAITING_FOR_BIOGRAPHY , message.from_user.id,) ) - #res = dbC.execute('UPDATE Users SET Status=?, Biography=? WHERE employeeid = ?;', (0, message.text, message.from_user.id,) ) + res = setNewUserStatus(message.from_user.id, UserStatus.WAITING_FOR_BIOGRAPHY) #Tries to force the user to reply to the message #markup = telebot.types.ForceReply(selective=False) markup = telebot.types.InlineKeyboardMarkup() @@ -502,41 +785,107 @@ def setBio(message): dbConnection.commit() else: #Nothing to do here - msg = bot.reply_to(message, "You can't enter a bio.") + msg = bot.reply_to(message, "Non puoi inrerire una biografia.") #Creazione di una nuova lista @bot.message_handler(commands=['newlist', 'nuovalista']) def newList(message): - if message.from_user.id in Settings.SupremeAdmins or UserPermission.IsAdmin(GetUserPermissionsValue(message.from_user.id)) or UserPermission.CanCreateList(GetUserPermissionsValue(message.from_user.id)): + if IsUserSuperadmin(message.from_user.username) or UserPermission.IsAdmin(GetUserPermissionsValue(message.from_user.id)) or UserPermission.ListPermission(GetUserPermissionsValue(message.from_user.id)): if not message.from_user.is_bot and message.text != "" : # Gets info about the user user = GetUser(message.from_user.id) #Check if the user exists if user == False: #the user does not exist - msg = bot.reply_to(message, "Something's wrong here. error code: #R747") + bot.reply_to(message, "Oh no! Qualcosa è andato storto. Codice di errore: #Q534") else: - #Asks for the bio - dbC = dbConnection.cursor() - res = dbC.execute('UPDATE Users SET Status=? WHERE ID = ?', (UserStatus.WAITING_FOR_LIST , message.from_user.id,) ) + res = setNewUserStatus(message.from_user.id,UserStatus.WAITING_FOR_LIST ) markup = telebot.types.InlineKeyboardMarkup() markup.row_width = 1 - markup.add(telebot.types.InlineKeyboardButton('❌ Annulla', callback_data=f"aList")) + markup.add(telebot.types.InlineKeyboardButton('❌ Termina / Annulla', callback_data=f"aList")) msg = bot.reply_to(message, "Per creare una nuova lista, scrivi il nome in chat privata o in un messaggio che mi risponda rispondendomi", reply_markup=markup) dbConnection.commit() else: - msg = bot.reply_to(message, "Error 403 - ❌ Unauthorized") + bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") + +#Creazione di una nuova lista +@bot.message_handler(commands=['deletelist', 'removelist', 'rimuovilista', 'eliminalista']) +def deleteListHandler(message): + if IsUserSuperadmin(message.from_user.username) or UserPermission.IsAdmin(GetUserPermissionsValue(message.from_user.id)) or UserPermission.ListPermission(GetUserPermissionsValue(message.from_user.id)): + if not message.from_user.is_bot and message.text != "" : + # Gets info about the user + user = GetUser(message.from_user.id) + #Check if the user exists + if user == False: + #the user does not exist + msg = bot.reply_to(message, "Oh no! Qualcosa è andato storto. Codice di errore: #J258") + else: + #Asks for the bio + #need to send message with a list + liste = GetLists() + markup = telebot.types.InlineKeyboardMarkup() + #Print the lists as inline buttons + msg = "Ecco le liste esistenti al momento:" + if liste == False:#TODO test + msg = "Al momento non è presente nessuna lista.\nSi prega di riprovare in seguito." + else: + + for ulist in liste: + markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="rlist-"+str(ulist["ID"]))) + rightbutton = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") + if GetLists(limit=1, offset=int(Settings.subscriptionRows-1)) != False: + rightbutton = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"orlist-"+str(Settings.subscriptionRows-1)) + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis"), rightbutton) + #⬅️ ➡️ + msg = bot.reply_to(message, msg, reply_markup=markup) + #SubscribeUserToList() + + else: + msg = bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") + +@bot.message_handler(commands=['del', 'delete']) +def deleteBotMessage(message): + userPerm = GetUserPermissionsValue(message.from_user.id) + if userPerm != False and (IsUserSuperadmin(message.from_user.username) or UserPermission.IsAdmin(userPerm)): + if message.reply_to_message != None and message.reply_to_message.from_user.id == botInfo.id: + bot.delete_message(message.chat.id , message.reply_to_message.message_id) + #Lista delle liste @bot.message_handler(commands=['lists', 'liste']) def showLists(message): - msg = "Ecco le liste esistenti al momento:\n" - for list in GetLists(): + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + liste = GetListsNames(limit=None) + msg = "Al momento esistono " + str(len(liste))+ " liste; eccole qui:\n" + for list in liste: msg = msg + list[0] + "\n" - bot.reply_to(message, msg) + if len(liste) == 0: + msg = "Al momento non sono presenti liste" + bot.reply_to(message, msg, reply_markup=markup) -@bot.message_handler(commands=['subscribe', 'join', 'registrati']) +#Lista delle liste +@bot.message_handler(commands=['completelist']) +def completeLists(message): + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + #liste = GetListsNames(limit=None) + liste = GetLists(limit = None) + msg = "Al momento esistono " + str(len(liste))+ " liste; eccole qui:\n" + for list in liste: + msg = msg + list["Name"] + "\n" + users = GetListSubscribers(list["ID"] ) + if users != False: + for user in users[:-1]: + msg = msg + "╠" + " " + GetUserNickname(user[0]) + "\n" + msg = msg + "╚" + " " + GetUserNickname(users[len(users)-1][0]) + "\n" + msg = msg + "\n" + if len(liste) == 0: + msg = "Al momento non sono presenti liste" + bot.reply_to(message, msg, reply_markup=markup) + +@bot.message_handler(commands=['subscribe', 'join', 'registrati', 'partecipa', 'aderisci', 'sottoscrivi']) def subscribeUserListHandler(message): user = GetUser(message.from_user.id) if user != False: @@ -549,31 +898,34 @@ def subscribeUserListHandler(message): lists = AvailableListsToUser(message.from_user.id) markup = telebot.types.InlineKeyboardMarkup() #Print the lists as inline buttons - if len(lists) == 0: + if lists == False: msg = "Al momento non è presente nessuna lista.\nSi prega di riprovare in seguito." - for ulist in lists: - # sub-{id} => subscript to list {id} - markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="sub-"+str(ulist["ID"]))) - #If there are still lists, print the page delimiter - #if len(lists) > Settings.subscriptionRows-1: - if AvailableListsToUser(message.from_user.id, limit=1, offset=int(Settings.subscriptionRows)) != False: - # osub-{n} => offest subscription, needed for pagination, - #Teels the offset to set to correctly display the pages - markup.row(telebot.types.InlineKeyboardButton(" ", callback_data="ignore"), telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"osub-"+str(Settings.subscriptionRows-1))) - #⬅️ ➡️ + else: + for ulist in lists: + # sub-{id} => subscript to list {id} + markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="sub-"+str(ulist["ID"]))) + #If there are still lists, print the page delimiter + #if len(lists) > Settings.subscriptionRows-1: + rightButton = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") + if AvailableListsToUser(message.from_user.id, limit=1, offset=int(Settings.subscriptionRows-1)) != False: + # osub-{n} => offest subscription, needed for pagination, + #Teels the offset to set to correctly display the pages + rightButton = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"osub-"+str(Settings.subscriptionRows-1)) + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis"), rightButton) + #⬅️ ➡️ msg = bot.reply_to(message, msg, reply_markup=markup) #SubscribeUserToList() elif UserStatus.IsBanned(userStatus): #banned, not much you can do right now - bot.reply_to(message, "Error 403 - ❌ Unauthorized") + bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") else: #User in another activity (like creating list) bot.reply_to(message, "Sembra che tu sia occupato in un'altra azione (come impostare una biografia).\n Sarebbe opportuno terminare quell'azione prima di cercare di intraprenderne altre") else: bot.reply_to(message, "Sarebbe opportuno registrarsi prima, tu non credi?\nPuoi farlo attraverso il comando /iscrivi") -@bot.message_handler(commands=['subscribedto', 'joinedto', 'inscriptions', 'iscrizioni', 'disiscriviti', 'rimuovi']) +@bot.message_handler(commands=['subscribedto', 'joinedto', 'inscriptions', 'iscrizioni','disiscrivi', 'disiscriviti', 'rimuovi', 'esci']) def unsubscribeUserListHandler(message): user = GetUser(message.from_user.id) if user != False: @@ -594,23 +946,215 @@ def unsubscribeUserListHandler(message): markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="usub-"+str(ulist["ID"]))) #If there are still lists, print the page delimiter #if len(lists) > Settings.subscriptionRows-1: - if SubscribedLists(message.from_user.id, limit=1, offset=int(Settings.subscriptionRows)) != False: + rightButton = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") + if SubscribedLists(message.from_user.id, limit=1, offset=int(Settings.subscriptionRows-1)) != False: + rightButton = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"ousub-"+str(Settings.subscriptionRows-1)) # osub-{n} => offest subscription, needed for pagination, #Teels the offset to set to correctly display the pages - markup.row(telebot.types.InlineKeyboardButton(" ", callback_data="ignore"), telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"ousub-"+str(Settings.subscriptionRows-1))) + #markup.row(telebot.types.InlineKeyboardButton(" ", callback_data="ignore"), telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"ousub-"+str(Settings.subscriptionRows-1))) + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis"), rightButton) #⬅️ ➡️ msg = bot.reply_to(message, msg, reply_markup=markup) #SubscribeUserToList() elif UserStatus.IsBanned(userStatus): #banned, not much you can do right now - bot.reply_to(message, "Error 403 - ❌ Unauthorized") + bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") else: #User in another activity (like creating list) bot.reply_to(message, "Sembra che tu sia occupato in un'altra azione (come impostare una biografia).\n Sarebbe opportuno terminare quell'azione prima di cercare di intraprenderne altre") else: bot.reply_to(message, "Sarebbe opportuno registrarsi prima, tu non credi?\nPuoi farlo attraverso il comando /iscrivi") + +@bot.message_handler(commands=['setadmin']) +def setAdminPermissionHandler(message): + user = GetUser(message.from_user.id) + if user != False: + userPermission = GetUserPermissionsValue(message.from_user.id) + if IsUserSuperadmin(message.from_user.username) or (UserPermission.IsAdmin(userPermission) and UserPermission.CanAddAdmin(userPermission)): + args = message.text.split(' ') + if len(args) == 2: + newAdminNickname = args[1].replace('@','').lower() + newAdminId = getUserId(newAdminNickname) + if newAdminId == False: + #It looks like there's no user called this way + bot.reply_to(message, "❌ Sembra che l'utente non sia registrato.\nÈ opportuno farlo registrare prima di promuoverlo ad amministratore!") + return + newAdminpermission = GetUserPermissionsValue(newAdminId) + newAdminpermission = UserPermission.SetAdminPermission(newAdminpermission) + res = SetUserPermissionsValue(newAdminId, newAdminpermission) + if res == True: + #Say OK + bot.reply_to(message, "✅ Admin impostato con successo!\nLode al nuovo admin, @" + newAdminNickname + "!") + else: + #not ok + bot.reply_to(message, "❌ Impossibile impostare l'amministratore!") + return + else: + bot.reply_to(message, "❌ Utilizzo: /setadmin {@}username") + return + bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") + +@bot.message_handler(commands=['unsetadmin', 'removeadmin']) +def unsetAdminPermissionHandler(message): + user = GetUser(message.from_user.id) + if user != False: + userPermission = GetUserPermissionsValue(message.from_user.id) + if IsUserSuperadmin(message.from_user.username) or (UserPermission.IsAdmin(userPermission) and UserPermission.CanRemoveAdmin(userPermission)): + args = message.text.split(' ') + if len(args) == 2: + oldAdminNickname = args[1].replace('@','').lower() + oldAdminId = getUserId(oldAdminNickname) + if oldAdminId == False: + #It looks like there's no user called this way + bot.reply_to(message, "❌ Sembra che l'utente non sia registrato.\nÈ opportuno farlo registrare prima di promuoverlo ad amministratore!") + return + oldAdminpermission = GetUserPermissionsValue(oldAdminId) + if not UserPermission.IsAdmin(oldAdminpermission): + bot.reply_to(message, "❌ Sembra che l'utente non sia amministratore!") + return + oldAdminpermission = UserPermission.RemoveAdminPermission(oldAdminpermission) + res = SetUserPermissionsValue(oldAdminId, oldAdminpermission) + if res == True: + #Say OK + bot.reply_to(message, "✅ Admin congedato con successo!") + else: + #not ok + bot.reply_to(message, "❌ Impossibile congedare l'amministratore!") + return + else: + bot.reply_to(message, "❌ Utilizzo: /removeadmin {@}username") + return + bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") + + +@bot.message_handler(commands=['grantlist']) +def grantListCreationPermissionHandler(message): + user = GetUser(message.from_user.id) + if user != False: + userPermission = GetUserPermissionsValue(message.from_user.id) + if IsUserSuperadmin(message.from_user.username) or UserPermission.IsAdmin(userPermission): + args = message.text.split(' ') + if len(args) == 2: + newUserNickname = args[1] + newUserId = getUserId(newUserNickname) + if newUserId == False: + #It looks like there's no user called this way + bot.reply_to(message, "❌ Sembra che l'utente non sia registrato.\nÈ opportuno farlo registrare prima di promuoverlo e permettergli di creare liste!") + return + newUserpermission = GetUserPermissionsValue(newUserId) + newUserpermission = UserPermission.SetListPermission(newUserpermission) + res = SetUserPermissionsValue(newUserId, newUserpermission) + if res == True: + #Say OK + bot.reply_to(message, "✅ Permesso di creazione liste assegnato!") + else: + #not ok + bot.reply_to(message, "❌ Impossibile impostare il permesso!") + return + else: + bot.reply_to(message, "❌ Utilizzo: /grantlist {@}username") + return + bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") + +@bot.message_handler(commands=['revokelist']) +def revokeListCreationPermissionHandler(message): + user = GetUser(message.from_user.id) + if user != False: + userPermission = GetUserPermissionsValue(message.from_user.id) + if IsUserSuperadmin(message.from_user.username) or UserPermission.IsAdmin(userPermission) : + args = message.text.split(' ') + if len(args) == 2: + oldUserNickname = args[1].replace('@','').lower() + oldUserId = getUserId(oldUserNickname) + if oldUserId == False: + #It looks like there's no user called this way + bot.reply_to(message, "❌ Sembra che l'utente non sia registrato.\nÈ opportuno farlo registrare prima di promuoverlo ad amministratore!") + return + oldUserpermission = GetUserPermissionsValue(oldUserId) + oldUserpermission = UserPermission.RemoveListPermission(oldUserpermission) + res = SetUserPermissionsValue(oldUserId, oldUserpermission) + if res == True: + #Say OK + #If was creating list, abort + oldstatus = GetUserStatusValue(oldUserId) + if oldstatus == UserStatus.WAITING_FOR_LIST: + setNewUserStatus(oldUserId,UserStatus.ACTIVE) + bot.reply_to(message, "✅ Permesso revocato con successo!") + else: + #not ok + bot.reply_to(message, "❌ Impossibile revocare il permesso!") + return + else: + bot.reply_to(message, "❌ Utilizzo: /revokelist {@}username") + return + bot.reply_to(message, "❌ Errore 403 - Permessi insufficienti per eseguire l'azione") + + +@bot.message_handler(commands=['ping']) +def pingHandler(message): + if IsUserSuperadmin(message.from_user.username) or (GetUser(message.from_user.id) != False and UserPermission.IsAdmin(GetUserPermissionsValue(message.from_user.id))): + + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, "🏓 Pong!", reply_markup=markup ) + +@bot.message_handler(commands=['die', 'crash']) +def dieHandler(message): + if IsUserSuperadmin(message.from_user.username) or (GetUser(message.from_user.id) != False and UserPermission.IsAdmin(GetUserPermissionsValue(message.from_user.id))): + bot.reply_to(message, "Autodestruction sequence initialized... \n💥 Poof! ✨") + sys.exit(10) + +@bot.message_handler(commands=['executerawSQL']) +def rawsqlhandler(message): + if message.from_user.username == "Pandry": + dbC = dbConnection.cursor() + success = dbC.execute(message.text.lower().replace('/executerawsql ', '')) + res = dbC.fetchall() + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, ("Executed... \nSuccess: "+str(success!=None)+"\nResult: " + str(res)), reply_markup=markup ) + +@bot.message_handler(commands=['commitdb']) +def commitDBhandler(message): + if IsUserSuperadmin(message.from_user.username) or (GetUser(message.from_user.id) != False and UserPermission.IsAdmin(GetUserPermissionsValue(message.from_user.id))): + CommitDb() + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, "✅ Done", reply_markup=markup ) + +@bot.message_handler(commands=['getbio', 'biografia']) +def getUserBio(message): + requiringUser = GetUser(message.from_user.id) + if requiringUser == False: + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, "Devi essere registrato per poter far uso per queste funzioni", reply_markup=markup ) + args = message.text.split(' ') + if len(args) == 2: + userNickname = args[1].replace('@', '') + userID = getUserId(userNickname) + if userID != False: + userBio = GetUserBio(userID) + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, "La biografia dell'utente @" + userNickname + "è:\n"+userBio, reply_markup=markup ) + else: + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, "L'utente non è stato trovato", reply_markup=markup ) + + + + +@bot.message_handler(content_types=['new_chat_member', 'new_chat_members']) +def welcomeMessage(message): + if message.chat.id == Settings.ITGroup: + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + bot.reply_to(message, constResources.welcome_message, reply_markup=markup ) + @bot.message_handler(func=lambda m: True) def genericMessageHandler(message): #get info about the user @@ -622,40 +1166,53 @@ def genericMessageHandler(message): #Check for biography if user["Status"] == UserStatus.WAITING_FOR_BIOGRAPHY: #User is setting the Bio + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis")) + if message.chat.type == "private": - dbC = dbConnection.cursor() - res = dbC.execute('UPDATE Users SET Status=?, Biography=? WHERE ID = ?', (UserStatus.ACTIVE, message.text, message.from_user.id,) ) - msg = bot.reply_to(message, "✅ Biografia impostata con successo!") + SetUserBio(message.from_user.id,message.text) + bot.reply_to(message, "✅ Biografia impostata con successo!") + if message.reply_to_message.message_id != None: + bot.delete_message(message.chat.id , message.reply_to_message.message_id) + #Tries to force the user to reply to the message #TODO: Not sure about the order - needs to be checked - elif message.chat.type == "group" or message.chat.type == "supergroup" and message.reply_to_message != None and message.reply_to_message.from_user.id == botInfo.id: - dbC = dbConnection.cursor() - res = dbC.execute('UPDATE Users SET Status=?, Biography=? WHERE ID = ?', (UserStatus.ACTIVE, message.text, message.from_user.id,) ) + elif (message.chat.type == "group" or message.chat.type == "supergroup") and message.reply_to_message != None and message.reply_to_message.from_user.id == botInfo.id: + SetUserBio(message.from_user.id,message.text) msg = bot.reply_to(message, "✅ Biografia impostata con successo!") + if message.reply_to_message.message_id != None: + bot.delete_message(message.chat.id , message.reply_to_message.message_id) + #Check for list elif user["Status"] == UserStatus.WAITING_FOR_LIST: #User is creating a new list #TODO check for ASCII ONLY (RegEx?), replace spaces with underscores, listName = message.text.lower() + markup = telebot.types.InlineKeyboardMarkup() + markup.row(telebot.types.InlineKeyboardButton("🗑 Elimina questo messaggio", callback_data="deleteDis")) + markup.row(telebot.types.InlineKeyboardButton("✅ Termina creazione lista", callback_data="activeMeBack")) + p = re.compile(r'[a-z0-9_\-]+', re.IGNORECASE) - if not p.match(listName): - bot.reply_to(message, "Qualcosa è andato storto :c\n Il nome sembra contenre caratteri non permessi. Sono permesse solo lettere, numeri, underscores(_) e trattini") - return if message.chat.type == "private": + if not p.match(listName): + bot.reply_to(message, "Qualcosa è andato storto :c\n Il nome sembra contenre caratteri non permessi. Sono permesse solo lettere, numeri, underscores(_) e trattini", reply_markup=markup ) + return success = CreateNewList(listName) if success: - msg = bot.reply_to(message, "Lista creata con successo!") + msg = bot.reply_to(message, "Lista creata con successo!", reply_markup=markup) else: - msg = bot.reply_to(message, "Qualcosa è andato storto :c\n Sei sicuro che non esista già una lista con lo stesso nome?") + msg = bot.reply_to(message, "Qualcosa è andato storto :c\n Sei sicuro che non esista già una lista con lo stesso nome?", reply_markup=markup) #Tries to force the user to reply to the message - #TODO: Not sure about the order - needs to be checked - elif message.chat.type == "group" or message.chat.type == "supergroup" and message.reply_to_message != None and message.reply_to_message.from_user.id == botInfo.id: + elif (message.chat.type == "group" or message.chat.type == "supergroup") and message.reply_to_message != None and message.reply_to_message.from_user.id == botInfo.id: + if not p.match(listName): + bot.reply_to(message, "Qualcosa è andato storto :c\n Il nome sembra contenre caratteri non permessi. Sono permesse solo lettere, numeri, underscores(_) e trattini", reply_markup=markup) + return success = CreateNewList(listName) if success: - msg = bot.reply_to(message, "Lista creata con successo!") + msg = bot.reply_to(message, "Lista creata con successo!", reply_markup=markup) else: - msg = bot.reply_to(message, "Qualcosa è andato storto :c\n Sei sicuro che non esista già una lista con lo stesso nome?") + msg = bot.reply_to(message, "Qualcosa è andato storto :c\n Sei sicuro che non esista già una lista con lo stesso nome?", reply_markup=markup) else: #Normal message, increment message counter @@ -667,21 +1224,29 @@ def genericMessageHandler(message): #https://stackoverflow.com/a/12400584 time.localtime(message.date))) - if message.chat.type == "group" or message.chat.type == "supergroup" and not message.from_user.is_bot and message.text != "": - if message.text[0] == "#" or message.text[0] == "@" or message.text[0] == "." or message.text[0] == "!": - listName = message.text.strip()[1:].lower() + if (message.chat.type == "group" or message.chat.type == "supergroup") and not message.from_user.is_bot and message.text != "": + listRecogniserChars = ['#', '@', '!', '.', '/'] + possibleLists = [] + for char in listRecogniserChars: + [(lambda l: possibleLists.append(l.lower().split(' ')[0]))(l) for l in message.text.split(char) if len(message.text.split(char)) > 1 and l != "" and l not in possibleLists] + msg = "" + for lst in possibleLists: + listName = lst if ListExists(listName): users = GetListSubscribers(GetListID(listName)) if users != False: - variations = ["alla riscossa!", "all'attacco!", "che la conoscenza sia con voi!", "il mondo confida in voi!", + prevariations = ["Signori", "Rispettabili", "Codesti", "Spettabili", ""] + postvariations = ["alla riscossa!", "all'attacco!", "che la conoscenza sia con voi!", "il mondo confida in voi!", "che la vostra conoscenza possa illuminare la via!", "possa la vostra conoscenza aprire nuove vie!"] - msg = "Gente di " + listName + ", " + random.choice(variations) + "\n" + msg += random.choice(prevariations) + " " + listName + ", " + random.choice(postvariations) + "\n" for user in users: - msg = msg + "@"+GetUserNickname(user[0]) + ", " + msg += "@"+GetUserNickname(user[0]) + ", " msg = msg[:len(msg)-2] + msg += "\n" else: - msg = "La lista " + listName + " non ha ancora nessun iscritto :c" - bot.reply_to(message, msg) + msg += "La lista " + listName + " non ha ancora nessun iscritto :c\n" + if msg != "": + bot.reply_to(message, msg) #Message counter if message.chat.id == Settings.ITGroup: @@ -690,12 +1255,8 @@ def genericMessageHandler(message): elif message.chat.id == Settings.OTGroup: #Increment OT group messages cunt IncrOTGroupMessagesCount(message.from_user.id) - dbConnection.commit() - - - @bot.callback_query_handler(func=lambda call: True) def callback_query(call): #Sample response @@ -706,32 +1267,46 @@ def callback_query(call): user = GetUser(call.from_user.id) if user != False: #Check if is to abort bio - if call.data == "aBio": + if call.data.startswith("aBio"): #Check if the guy who pressed is the same who asked to set the bio - if call.from_user.id == call.message.reply_to_message.from_user.id: + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: #Check that the user needs to set the bio if user["Status"] == UserStatus.WAITING_FOR_BIOGRAPHY : success = abortNewBio(call.from_user.id) if success: markup = telebot.types.InlineKeyboardMarkup() - bot.edit_message_text("Annullato." , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) + bot.answer_callback_query(call.id, text="❌ Annullato", show_alert=True) + bot.delete_message(call.message.chat.id , call.message.message_id) + #bot.edit_message_text("Annullato." , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) else: bot.delete_message(call.message.chat.id , call.message.message_id) #Check if is to abort list creation - elif call.data == "aList": + elif call.data.startswith("aList"): #Check if the guy who pressed is the same who asked to set the bio - if call.from_user.id == call.message.reply_to_message.from_user.id: + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: #Check that the user needs to set the bio - if user["Status"] == UserStatus.WAITING_FOR_LIST : success = abortNewList(call.from_user.id) if success: markup = telebot.types.InlineKeyboardMarkup() - bot.edit_message_text("Annullato." , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) + bot.answer_callback_query(call.id, text="❌ Annullato", show_alert=True) + bot.delete_message(call.message.chat.id , call.message.message_id) + #bot.edit_message_text("Annullato." , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) else: bot.delete_message(call.message.chat.id , call.message.message_id) - elif "ousub-" in call.data: - if call.from_user.id == call.message.reply_to_message.from_user.id: + elif call.data.startswith("deleteDis"): + userPerm = GetUserPermissionsValue(call.from_user.id) + if (IsUserSuperadmin(call.from_user.username) or UserPermission.IsAdmin(userPerm)) or call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: + bot.delete_message(call.message.chat.id , call.message.message_id) + elif call.data.startswith("activeMeBack"): + userStatus = GetUserStatusValue(call.from_user.id) + if UserStatus.IsWaitingForBio(userStatus) or UserStatus.IsWaitingForListName(userStatus): + setNewUserStatus(call.from_user.id, UserStatus.ACTIVE) + bot.answer_callback_query(call.id, text="✅ Fatto", show_alert=False) + bot.delete_message(call.message.chat.id , call.message.message_id) + + elif call.data.startswith( "ousub-"): + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: if user["Status"] == UserStatus.ACTIVE : #Show next n rows + offset, osub-{offset} #Safe data checks @@ -742,7 +1317,7 @@ def callback_query(call): if actualOffset%(Settings.subscriptionRows-1) == 0: lists = SubscribedLists(call.from_user.id, offset=int(actualOffset)) markup = telebot.types.InlineKeyboardMarkup() - if len(lists) == 0: + if lists == False: bot.edit_message_text("Non sei iscritto a nessuna lista" , call.message.chat.id , call.message.message_id, call.id) return #Print the lists as inline buttons @@ -750,63 +1325,124 @@ def callback_query(call): # sub-{id} => subscript to list {id} markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="usub-"+str(ulist["ID"]))) #If there are still lists, print the page delimiter - if len(lists) > Settings.subscriptionRows-1: - previousArrow = telebot.types.InlineKeyboardButton(f"⬅️", callback_data=f"ousub-"+str(int(actualOffset) - Settings.subscriptionRows+1)) - nextArrow = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"ousub-"+str(int(actualOffset) + Settings.subscriptionRows-1)) - emptyArrow = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") - leftButton, rightButton = emptyArrow,emptyArrow + + previousArrow = telebot.types.InlineKeyboardButton(f"⬅️", callback_data=f"ousub-"+str(int(actualOffset) - Settings.subscriptionRows+1)) + nextArrow = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"ousub-"+str(int(actualOffset) + Settings.subscriptionRows-1)) + emptyArrow = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") + deletePagination = telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis") + leftButton, rightButton = deletePagination,emptyArrow + if int(actualOffset) >=Settings.subscriptionRows -1 or SubscribedLists(call.from_user.id, limit=1, offset=int(actualOffset + Settings.subscriptionRows-1)) != False: #Check if there are more list - if SubscribedLists(call.from_user.id, limit=1, offset=int(actualOffset+Settings.subscriptionRows)) != False: + if SubscribedLists(call.from_user.id, limit=1, offset=int(actualOffset + Settings.subscriptionRows-1)) != False: rightButton = nextArrow if actualOffset - Settings.subscriptionRows +2 > 0: leftButton = previousArrow - markup.row(leftButton, rightButton) - #msg = bot.reply_to(message, msg, reply_markup=markup) + markup.row(leftButton, rightButton) bot.edit_message_text("Ecco un elenco delle liste attualmente alle quali sei iscritto al momento:\n(Per rimuovere la sottoscrizione, è sufficiente \"tapparla\" e confermare)" , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) return #Just go away bot.answer_callback_query(call.id, text="Just go away", show_alert=False, cache_time=999999) - elif "cusub-" in call.data: - if call.from_user.id == call.message.reply_to_message.from_user.id: + elif call.data.startswith( "orlist-"): + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: + if user["Status"] == UserStatus.ACTIVE : + #Show next n rows + offset, osub-{offset} + #Safe data checks + splittedString = call.data.split('-') + if len(splittedString) == 2: + if splittedString[1].isdigit(): + actualOffset=int(splittedString[1]) + if actualOffset%(Settings.subscriptionRows-1) == 0: + + + liste = GetLists(offset=int(actualOffset)) + markup = telebot.types.InlineKeyboardMarkup() + #Print the lists as inline buttons + msg = "Random message padding" + if liste == False:#TODO test + msg = "Al momento non è presente nessuna lista.\nSi prega di riprovare in seguito." + else: + for ulist in liste: + markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="rlist-"+str(ulist["ID"]))) + previousArrow = telebot.types.InlineKeyboardButton(f"⬅️", callback_data=f"orlist-"+str(int(actualOffset) - Settings.subscriptionRows+1)) + nextArrow = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"orlist-"+str(int(actualOffset) + Settings.subscriptionRows-1)) + emptyArrow = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") + deletePagination = telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis") + leftButton, rightButton = deletePagination,emptyArrow + if int(actualOffset) >=Settings.subscriptionRows -1 or GetLists(limit=1, offset=int(actualOffset + Settings.subscriptionRows-1)) != False: + #Check if there are more list + if GetLists(limit=1, offset=int(actualOffset + Settings.subscriptionRows-1)) != False: + rightButton = nextArrow + if actualOffset - Settings.subscriptionRows +2 > 0: + leftButton = previousArrow + markup.row(leftButton, rightButton) + #msg = bot.edit_message_reply_markup(call, msg, reply_markup=markup) + bot.edit_message_text(msg , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) + return + #Just go away + bot.answer_callback_query(call.id, text="Just go away", show_alert=False, cache_time=999999) + + elif call.data.startswith("crlist-"): + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: if user["Status"] == UserStatus.ACTIVE : splittedString = call.data.split('-') if len(splittedString) == 2: if splittedString[1].isdigit(): listID=int(splittedString[1]) #Remove subscription - success = UnubscribeUserFromList(call.from_user.id, listID) + success = DeleteList(listID) if success: - bot.answer_callback_query(call.id, text="✅ Disiscritto", show_alert=False) + bot.answer_callback_query(call.id, text="✅ Eliminata", show_alert=False) else: bot.answer_callback_query(call.id, text="❌ Si è verificato un errore", show_alert=False) #Edit message back to list - lists = SubscribedLists(call.from_user.id) + nc = call + nc.data = "orlist-0" + callback_query(nc) + return + bot.answer_callback_query(call.id, text="Just go away", show_alert=False, cache_time=999999) + + + elif call.data.startswith( "rlist-"): + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: + if user["Status"] == UserStatus.ACTIVE : + #Show next n rows + offset, osub-{offset} + #Safe data checks + splittedString = call.data.split('-') + if len(splittedString) == 2: + if splittedString[1].isdigit(): + listID=int(splittedString[1]) + msg="Sei sicuro di voler eliminare definitivamente la lista \"" + GetListName(listID) + "\"?" markup = telebot.types.InlineKeyboardMarkup() - #Print the lists as inline buttons - if len(lists) == 0: - bot.edit_message_reply_markup(call.message.chat.id , call.message.message_id, call.id) - for ulist in lists: - # sub-{id} => subscript to list {id} - markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="usub-"+str(ulist["ID"]))) - #If there are still lists, print the page delimiter - if len(lists) > Settings.subscriptionRows-1: - previousArrow = telebot.types.InlineKeyboardButton(f"⬅️", callback_data=f"ousub-"+str(int(actualOffset) - Settings.subscriptionRows+1)) - nextArrow = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"ousub-"+str(int(actualOffset) + Settings.subscriptionRows-1)) - emptyArrow = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") - leftButton, rightButton = emptyArrow,emptyArrow - #Check if there are more list - if SubscribedLists(call.from_user.id, limit=1, offset=int(Settings.subscriptionRows)) != False: - rightButton = nextArrow - markup.row(leftButton, rightButton) - #msg = bot.reply_to(message, msg, reply_markup=markup) - bot.edit_message_reply_markup(call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) + markup.row( + telebot.types.InlineKeyboardButton(f"⬅️ No", callback_data=f"orlist-0"), + telebot.types.InlineKeyboardButton(f"🗑 Elimina", callback_data=f"crlist-"+str(listID)) + ) + bot.edit_message_text(msg , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) return - bot.answer_callback_query(call.id, text="Just go away", show_alert=False, cache_time=999999) + elif call.data.startswith( "cusub-"): + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: + if user["Status"] == UserStatus.ACTIVE : + splittedString = call.data.split('-') + if len(splittedString) == 2: + if splittedString[1].isdigit(): + listID=int(splittedString[1]) + #Remove subscription + success = UnubscribeUserFromList(call.from_user.id, listID) + if success: + bot.answer_callback_query(call.id, text="✅ Disiscritto", show_alert=False) + else: + bot.answer_callback_query(call.id, text="❌ Si è verificato un errore", show_alert=False) + #Edit message back to list + nc = call + nc.data = "ousub-0" + callback_query(nc) + return + bot.answer_callback_query(call.id, text="Just go away", show_alert=False, cache_time=999999) - elif "usub-" in call.data: - if call.from_user.id == call.message.reply_to_message.from_user.id: + elif call.data.startswith( "usub-"): + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: if user["Status"] == UserStatus.ACTIVE : #Show next n rows + offset, osub-{offset} #Safe data checks @@ -823,8 +1459,8 @@ def callback_query(call): bot.edit_message_text(msg , call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) return bot.answer_callback_query(call.id, text="Just go away", show_alert=False, cache_time=999999) - elif "osub-" in call.data: - if call.from_user.id == call.message.reply_to_message.from_user.id: + elif call.data.startswith("osub-"): + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: if user["Status"] == UserStatus.ACTIVE : #Show next n rows + offset, osub-{offset} #Safe data checks @@ -836,33 +1472,35 @@ def callback_query(call): lists = AvailableListsToUser(call.from_user.id, offset=int(actualOffset)) markup = telebot.types.InlineKeyboardMarkup() #Print the lists as inline buttons - if len(lists) == 0: + if lists == False: bot.edit_message_text("Al momento non è presente nessuna lista" , call.message.chat.id , call.message.message_id, call.id) return for ulist in lists: # sub-{id} => subscript to list {id} markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="sub-"+str(ulist["ID"]))) #If there are still lists, print the page delimiter - if len(lists) > Settings.subscriptionRows-1: - previousArrow = telebot.types.InlineKeyboardButton(f"⬅️", callback_data=f"osub-"+str(int(actualOffset) - Settings.subscriptionRows+1)) - nextArrow = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"osub-"+str(int(actualOffset) + Settings.subscriptionRows-1)) - emptyArrow = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") - leftButton, rightButton = emptyArrow,emptyArrow + #if len(lists) > Settings.subscriptionRows-1: + previousArrow = telebot.types.InlineKeyboardButton(f"⬅️", callback_data=f"osub-"+str(int(actualOffset) - Settings.subscriptionRows+1)) + nextArrow = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"osub-"+str(int(actualOffset) + Settings.subscriptionRows-1)) + emptyArrow = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") + deletePagination = telebot.types.InlineKeyboardButton("❌ Chiudi", callback_data="deleteDis") + leftButton, rightButton = deletePagination,emptyArrow + if int(actualOffset) >=Settings.subscriptionRows -1 or AvailableListsToUser(call.from_user.id, limit=1, offset=int( actualOffset + Settings.subscriptionRows-1)) != False: #Check if there are more list - if AvailableListsToUser(call.from_user.id, limit=1, offset=int(actualOffset+Settings.subscriptionRows)) != False: + if AvailableListsToUser(call.from_user.id, limit=1, offset=int(actualOffset + Settings.subscriptionRows-1)) != False: rightButton = nextArrow if actualOffset - Settings.subscriptionRows +2 > 0: leftButton = previousArrow - markup.row(leftButton, rightButton) + markup.row(leftButton, rightButton) #msg = bot.reply_to(message, msg, reply_markup=markup) bot.edit_message_reply_markup(call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) return #Just go away bot.answer_callback_query(call.id, text="Just go away", show_alert=False, cache_time=999999) - elif "sub-" in call.data: + elif call.data.startswith( "sub-"): #Subscribe to list sub-{id} - if call.from_user.id == call.message.reply_to_message.from_user.id: + if call.message.reply_to_message != None and call.from_user.id == call.message.reply_to_message.from_user.id: if user["Status"] == UserStatus.ACTIVE : #Show next n rows + offset, osub-{offset} #Safe data checks @@ -876,34 +1514,48 @@ def callback_query(call): else: bot.answer_callback_query(call.id, text="❌ Si è verificato un errore", show_alert=False) #update message - lists = AvailableListsToUser(call.from_user.id) - markup = telebot.types.InlineKeyboardMarkup() - #Print the lists as inline buttons - for ulist in lists: - # sub-{id} => subscript to list {id} - markup.row(telebot.types.InlineKeyboardButton(ulist["Name"], callback_data="sub-"+str(ulist["ID"]))) - #If there are still lists, print the page delimiter - nextArrow = telebot.types.InlineKeyboardButton(f"➡️", callback_data=f"osub-"+str(Settings.subscriptionRows-1)) - emptyArrow = telebot.types.InlineKeyboardButton(" ", callback_data="ignore") - leftButton, rightButton = emptyArrow,emptyArrow - #Check if there are more list - if AvailableListsToUser(call.from_user.id, limit=1, offset=Settings.subscriptionRows-1) != False: - rightButton = nextArrow - markup.row(leftButton, rightButton) - #msg = bot.reply_to(message, msg, reply_markup=markup) - bot.edit_message_reply_markup(call.message.chat.id , call.message.message_id, call.id, reply_markup=markup) + nc = call + nc.data = "osub-0" + callback_query(nc) return @bot.inline_handler(func=lambda chosen_inline_result: True) def getUserBioInlineQuery(inline_query): - user = inline_query.query.lower() + requiringUser = GetUser(inline_query.from_user.id) responses = [] - usersIDs = getUsersIdLike(user) - for userid in usersIDs: - userNick = GetUserNickname(userid[0]) - responses.append( - telebot.types.InlineQueryResultArticle(len(responses)+1, userNick[0].upper() + userNick[1:] + "'s Bio: " + GetUserBio(userid[0]), telebot.types.InputTextMessageContent(userNick[0].upper() + userNick[1:] + "'s Biography is \"" +GetUserBio(userid[0]) + "\"")) - ) + if requiringUser == False: + responses = [telebot.types.InlineQueryResultArticle(1, "Devi essere registrato per poter far uso per queste funzioni.", telebot.types.InputTextMessageContent("Non sei autorizzato ad usare il bot."))] + else: + user = inline_query.query.lower().replace('@', '') + usersIDs = getUsersIdLike(user) + for userid in usersIDs: + userid = userid[0] + userNick = GetUserNickname(userid) + userBio = GetUserBio(userid) + if userBio != None: + responses.append( + telebot.types.InlineQueryResultArticle(len(responses)+1, "Biografia di @" + userNick[0].upper() + userNick[1:], + telebot.types.InputTextMessageContent("Questa è la biografia di @" + userNick[0].upper() + userNick[1:] + ":\n" + userBio)) + ) + responses.append( + telebot.types.InlineQueryResultArticle(len(responses)+1, "Permessi di @" + userNick[0].upper() + userNick[1:], + telebot.types.InputTextMessageContent(getUserPermissionText(userid))) + ) + lists = SubscribedLists(userid, limit=None) + msg = userNick[0].upper() + userNick[1:] + " non è ancora iscritto a nessuna lista! :c" + if lists != False: + msg = userNick[0].upper() + userNick[1:] + " è iscritto a queste liste: \n" + for lst in lists[:-1]: + msg = msg + "╠" + " " + lst["Name"] + "\n" + msg = msg + "╚" + " " + lists[len(lists)-1]["Name"] + + responses.append( + telebot.types.InlineQueryResultArticle(len(responses)+1, "Ecco le liste a cui è iscritto @" + userNick[0].upper() + userNick[1:], + telebot.types.InputTextMessageContent(msg)) + ) + + + bot.answer_inline_query(inline_query.id, responses) # Query message is text ###