def runUpdates(long_fetch=False, sendMessages=True): childThreads = [] if not updateLock.acquire(blocking=True, timeout=60): return runDatetime = datetime.now() pendingUsers = helpers.isAdmin() if restrictedMode else select( user.chatId for user in User if user.password != "")[:] for currentUser in pendingUsers: t = Thread(target=runUserUpdate, name=f"upd_{currentUser}", args=[currentUser, long_fetch, runDatetime, sendMessages]) childThreads.append(t) t.start() while any(t.is_alive() for t in childThreads): sleep(2) updateLock.release()
def runDailyUpdates(runDatetime): childThreads = [] if not updateLock.acquire(blocking=True, timeout=60): return isSaturday = runDatetime.isoweekday() == 6 dayString = "lunedì" if isSaturday else "domani" pendingUsers = helpers.isAdmin() if restrictedMode else select( user.chatId for user in User if user.password != "")[:] for currentUser in pendingUsers: t = Thread(target=runUserDaily, name=f"mem_{currentUser}", args=[currentUser, runDatetime, dayString]) childThreads.append(t) t.start() while any(t.is_alive() for t in childThreads): sleep(2) updateLock.release()
def button_press(msg): chatId = msg['message']['chat']['id'] msgId = msg['message']['message_id'] text = msg['data'] msgIdent = (chatId, msgId) user = User.get(chatId=chatId) settings = Settings.get(chatId=chatId) def editNotif(): bot.editMessageText( msgIdent, "<b>Preferenze notifiche</b>\n" "- Stato attuale: {0}\n\n" "Vuoi che ti mandi notifiche se trovo novità?\n" "<b>Nota</b>: Se non vuoi riceverle di notte, puoi impostarlo a parte." "".format( "🔔 Attivo" if settings.wantsNotifications else "🔕 Spento"), parse_mode="HTML", reply_markup=keyboards.settings_notifications( settings.wantsNotifications)) def editNotifDaily(): bot.editMessageText( msgIdent, "<b>Preferenze notifiche giornaliere</b>\n" "- Stato attuale: {0}\n" "- Orario notifiche: {1}\n\n" "Vuoi che ti dica ogni giorno i compiti per il giorno successivo e le lezioni svolte?" "".format("🔔 Attiva" if settings.wantsDailyUpdates else "🔕 Spenta", settings.dailyUpdatesHour), parse_mode="HTML", reply_markup=keyboards.settings_dailynotif( settings.wantsDailyUpdates)) def editNotifNight(): bot.editMessageText( msgIdent, "<b>Preferenze modalità notturna</b>\n" "- Stato attuale: {0}\n\n" "Vuoi che silenzi le notifiche nella fascia oraria notturna (21:00 - 7:00)?" "".format("😴 Attivo" if settings.doNotDisturb else "🔔 Suona"), parse_mode="HTML", reply_markup=keyboards.settings_donotdisturb( settings.doNotDisturb)) def editNotifSelection(): stats = [ "🔔 Attivo" if type in settings.activeNews else "🔕 Spento" for type in ["didattica", "note", "voti", "agenda", "circolari"] ] bot.editMessageText( msgIdent, f"📲 <b>Selezione notifiche</b>\n\n" f"📚 Didattica: {stats[0]}\n" f"❗️ Note: {stats[1]}\n" f"📝 Voti: {stats[2]}\n" f"📆 Agenda: {stats[3]}\n" f"📩 Circolari: {stats[4]}\n\n" "Quali notifiche vuoi ricevere? (Clicca per cambiare)", parse_mode="HTML", reply_markup=keyboards.settings_selectnews()) if (not restrictedMode) or helpers.isAdmin(chatId): if text == "settings_main": bot.editMessageText( msgIdent, "🛠 <b>Impostazioni</b>\n" "Ecco le impostazioni del bot. Cosa vuoi modificare?", parse_mode="HTML", reply_markup=keyboards.settings_menu()) elif text == "settings_close": bot.editMessageText(msgIdent, "✅ Impostazioni salvate.", reply_markup=None) elif text == "settings_notifications": editNotif() elif text == "settings_donotdisturb": editNotifNight() elif text == "settings_dailynotif": editNotifDaily() elif text == "settings_selectnews": editNotifSelection() elif text.startswith("news_"): cat = text.split("_", 1)[1] if cat in settings.activeNews: settings.activeNews.remove(cat) else: settings.activeNews.append(cat) editNotifSelection() elif text.startswith("settings_notif_"): ans = text.endswith("yes") settings.wantsNotifications = ans editNotif() elif text.startswith("settings_night_"): ans = text.endswith("yes") settings.doNotDisturb = ans editNotifNight() elif text.startswith("settings_daily_"): if text.endswith("yes") or text.endswith("no"): ans = text.endswith("yes") settings.wantsDailyUpdates = ans else: seltime = datetime.strptime(settings.dailyUpdatesHour, "%H:%M") if text.endswith("plus"): seltime += timedelta(minutes=30) else: seltime -= timedelta(minutes=30) settings.dailyUpdatesHour = seltime.strftime("%H:%M") editNotifDaily() elif text.startswith("logout"): if text.endswith("yes"): helpers.clearUserData(chatId) bot.editMessageText(msgIdent, "😯 Fatto, sei stato disconnesso!\n" "Premi /login per entrare di nuovo.\n\n" "Premi /help se serve aiuto.", reply_markup=None) else: bot.editMessageText(msgIdent, "<i>Logout annullato.</i>", parse_mode="HTML", reply_markup=None) elif text.startswith("lezioni"): api = ClasseVivaAPI() if helpers.userLogin(chatId, api): newDay = int(text.split("#")[1]) dateformat = "del " + (datetime.now() + timedelta(days=newDay)).strftime("%d/%m/%Y") \ if newDay != 0 else "di oggi" try: apiRes = api.lezioni(newDay) data = parsers.parseLezioni(apiRes) bot.editMessageText(msgIdent, f"📚 <b>Lezioni {dateformat}</b>:\n\n" f"{data}", parse_mode="HTML", reply_markup=keyboards.lezioni(newDay), disable_web_page_preview=True) except ApiServerError: bot.editMessageText( msgIdent, "⚠️ I server di ClasseViva non sono raggiungibili.\n" "Riprova tra qualche minuto.", reply_markup=None) elif text.startswith("orario"): if text.endswith("del"): doc = Document.get(chatId=chatId, type="orario") doc.delete() bot.editMessageCaption(msgIdent, "🗑 Orario eliminato.", reply_markup=None) elif text.endswith("mod"): user.status = "sending_orario" bot.editMessageReplyMarkup(msgIdent, None) bot.sendMessage( chatId, "🕑 <b>Impostazione orario</b>\n" "Inviami un documento (PDF oppure foto) da impostare come nuovo orario.\n\n" "Usa /annulla per annullare la modifica.", parse_mode="HTML", reply_markup=None) elif user.status == "memo_date" and text.startswith("memo"): when = int(text[-1]) memoDate = (datetime.now() + timedelta(days=when)).strftime("%d/%m/%Y") user.status = f"memo_text#{memoDate}" bot.editMessageText( msgIdent, f"💡 <b>Data memo: {memoDate}</b>\n" f"Inviami il testo del memo, o premi /annulla per annullare.", parse_mode="HTML", reply_markup=None) else: bot.sendMessage( chatId, "ℹ️ <b>Bot in manutenzione</b>\n" "Il bot è attualmente in manutenzione per problemi con ClasseViva, e tutte le sue " "funzioni sono temporaneamente disabilitate.\n" "Non eliminare questa chat: se vuoi puoi archiviarla su Telegram, così appena " "ci saranno notizie arriverà un messaggio qui.\n\n" "/moreinfo", parse_mode="HTML")
def reply(msg): global restrictedMode chatId = msg['chat']['id'] name = msg['from']['first_name'] text = msg.get("text", "") if chatId < 0: return if not User.exists(lambda u: u.chatId == chatId): User(chatId=chatId) if not Data.exists(lambda u: u.chatId == chatId): Data(chatId=chatId) if not ParsedData.exists(lambda u: u.chatId == chatId): ParsedData(chatId=chatId) if not Settings.exists(lambda u: u.chatId == chatId): Settings(chatId=chatId) user = User.get(chatId=chatId) userdata = Data.get(chatId=chatId) stored = ParsedData.get(chatId=chatId) if (not restrictedMode) or helpers.isAdmin(chatId): if text == "/about": bot.sendMessage( chatId, "ℹ️ <b>Informazioni sul bot</b>\n" "ClasseVivaBot è un bot creato e sviluppato da Filippo Pesavento, che ti può aiutare " "durante l'anno scolastico mandando notifiche per le novità del registro e molto altro.\n" "Prova ad usarlo per scoprire quanto è comodo!\n\n" "<b>Sviluppo:</b> <a href=\"https://t.me/pesaventofilippo\">Filippo Pesavento</a> e Francesco De Benedittis\n" "<b>Contributori:</b> Gianluca Parri e PolpOnline\n" "<b>Hosting:</b> Filippo Pesavento\n\n" "<b>Info sicurezza:</b> /aboutprivacy", parse_mode="HTML", disable_web_page_preview=True) elif text == "/aboutprivacy": bot.sendMessage( chatId, "ℹ️ <b>Informazioni sulla privacy</b>\n" "La mia password è al sicuro? 🤔\n\n" "🔐 <b>Sì: la tua password viene criptata.</b>\n" "Il bot conserva la tua password in maniera sicura, salvandola in un formato non leggibile da " "persone estranee. Sei al sicuro: i tuoi dati non verranno visti nè rubati da nessuno!\n\n" "🔐 <b>Spiegazione dettagliata:</b>\n" "Tecnicamente potrei decriptare a mano le password e vederle, ma sostanzialmente è complicato, " "perchè il bot genera una chiave per l'algoritmo (visto che il cripting deve essere reversibile, " "per poter mandare le notifiche automatiche) prendendo come dati una chiave comune (che salvo nella RAM, " "per evitare che qualcuno che non sia io possa leggere il database e i dati degli utenti) " "e anche l'username dell'utente. Quindi ogni utente ha la propria password criptata con una chiave diversa da tutti " "gli altri, e sarebbe difficile anche per me risalire alla password, dovendo sapere di chi è l'username collegato a " "quella password specifica.\n" "Questo non vuol dire che non possa farlo: con un po' di lavoro ci riuscirei. Quindi alla fine devi decidere tu: " "io ti posso assicurare che non leggerò mai nè proverò mai a decriptare le password, sia per un discorso di etica " "che per scelta personale, ma non sono tuo amico nè tuo conoscente: quindi se decidi di non fidarti di uno sconosciuto " "che ti scrive su Telegram (ti posso capire benissimo) sei libero di non usare il bot 🙂\n\n" "<a href=\"https://kutt.it/botinfo\">Altre info & Privacy Policy</a>\n" "<a href=\"https://t.me/pesaventofilippo\">Contattami</a>\n\n" "<i>Se sei venuto qui prima di digitare la password per il login, scrivila adesso!</i>", parse_mode="HTML", disable_web_page_preview=True) elif user.status != "normal": if text == "/annulla": user.status = "normal" bot.sendMessage(chatId, "Comando annullato!") elif user.status == "login_0": if len(text) < 5: bot.sendMessage( chatId, "⚠️ Errore: l'username è troppo corto. Riprova!") return user.username = text user.status = "login_1" bot.sendMessage( chatId, "👍 Ottimo. Adesso inviami la password.\n" "Ricorda che la password viene salvata solo per te e viene criptata, nessuno potrà leggerla.\n\n" "Sei preoccupato per la sicurezza della password? /aboutprivacy" ) elif user.status == "login_1": user.password = crypt_password(text, chatId) user.status = "normal" commit() api = ClasseVivaAPI() try: api.login(user.username, decrypt_password(chatId)) except ApiServerError: try: bot.sendMessage( chatId, "⚠️ I server di ClasseViva non sono raggiungibili.\n" "Riprova tra qualche minuto.") except (TelegramError, BotWasBlockedError): pass return except Exception: helpers.clearUserData(chatId) try: bot.sendMessage( chatId, "😯 Le tue credenziali di accesso sono errate.\n" "Effettua nuovamente il /login per favore.") except (TelegramError, BotWasBlockedError): pass return bot.sendMessage( chatId, "Fatto 😊\n" "Premi /help per vedere la lista dei comandi disponibili.") sent = bot.sendMessage(chatId, "🔍 Aggiorno il profilo...") data = helpers.fetchStrict(api) helpers.updateUserdata(chatId, data) helpers.fetchAndStore(chatId, api, data, fetch_long=True) bot.editMessageText((chatId, sent['message_id']), "✅ Profilo aggiornato!") elif user.status == "calling_support": user.status = "normal" for a in helpers.isAdmin(): bot.sendMessage( a, "🆘 <b>Richiesta di aiuto</b>\n" "Da: <a href=\"tg://user?id={0}\">{1}</a>\n\n" "<i>Rispondi al messaggio per parlare con l'utente.</i>" .format(chatId, name), parse_mode="HTML") if "reply_to_message" in msg: bot.forwardMessage( a, chatId, msg["reply_to_message"]["message_id"]) bot.forwardMessage(a, chatId, msg['message_id'], disable_notification=True) bot.sendMessage(chatId, "<i>Richiesta inviata.</i>\n" "Un admin ti risponderà il prima possibile.", parse_mode="HTML") elif user.status == "sending_orario": if msg.get("photo"): fileId = msg.get("photo")[0]["file_id"] ext = "photo" elif msg.get("document"): fileId = msg.get("document")["file_id"] ext = "document" else: bot.sendMessage( chatId, "🤔 Documento non valido. Invia una foto o un file.\n" "Premi /annulla per annullare.") return if not Document.exists( lambda d: (d.chatId == chatId and d.type == "orario")): Document(chatId=chatId, type="orario", data={ "fileId": fileId, "ext": ext }) else: doc = Document.get(chatId=chatId, type="orario") doc.data = {"fileId": fileId, "ext": ext} bot.sendMessage( chatId, "✅ Orario impostato!\n" "Richiamalo con /orario.") user.status = "normal" elif user.status == "memo_date": if not text: bot.sendMessage( chatId, "Inviami la data in formato GG/MM.\n" "Premi /annulla per annullare.") return try: now = datetime.now() when = datetime.strptime(text, "%d/%m") when.replace(year=now.year) if when < now: when.replace(year=now.year + 1) if when > now + timedelta(days=28): bot.sendMessage( chatId, "⚠️ Data non valida.\n" "La data non può essere oggi, nel passato oppure fra più di 4 settimane.\n" "Premi /annulla per annullare.") return memoDate = when.strftime("%d/%m/%Y") user.status = f"memo_text#{memoDate}" bot.sendMessage( chatId, f"💡 <b>Data memo: {memoDate}</b>\n" f"Inviami il testo del memo, o premi /annulla per annullare.", parse_mode="HTML") except ValueError: bot.sendMessage( chatId, "⚠️ Data non valida.\n" "Inviami la data in formato GG/MM.\n" "Premi /annulla per annullare.") elif user.status.startswith("memo_text"): if not text or len(text) > 400: bot.sendMessage( chatId, "⚠️ Inviami il testo della memo (max. 400 caratteri).\n" "Premi /annulla per annullare.") return memoDate = user.status.split("#")[1] memo = Document(chatId=chatId, type="memo", data={ "date": memoDate, "text": text }) user.status = "normal" stored.agenda = parsers.parseAgenda(userdata.agenda, chatId) stored.domani = parsers.parseDomani(userdata.agenda, chatId) bot.sendMessage( chatId, f"✅ Ho creato la memo per il <b>{memo.data['date']}</b>:\n" f"\"{memo.data['text']}\"\n\n" f"Vedilo in /agenda!", parse_mode="HTML") elif text == "/help": bot.sendMessage( chatId, "Ciao, sono il bot di <b>ClasseViva</b>! 👋🏻\n" "Posso aiutarti a <b>navigare</b> nel registro e posso mandarti <b>notifiche</b> quando hai nuovi avvisi.\n\n" "<b>Lista dei comandi</b>:\n" "- /login - Effettua il login\n" "- /aggiorna - Aggiorna manualmente tutti i dati, per controllare se ci sono nuovi avvisi.\n" "Oppure, puoi lasciarlo fare a me ogni mezz'ora :)\n" "- /agenda - Visualizza agenda (compiti e verifiche)\n" "- /domani - Vedi i compiti che hai per domani\n" "- /promemoria - Vedi un promemoria con i compiti da fare per domani e le lezioni svolte oggi.\n" "- /memo - Aggiungi un memo all'agenda\n" "- /voti - Visualizza la lista dei voti\n" "- /lezioni - Visualizza la lista delle lezioni\n" "- /didattica - Visualizza la lista dei file in didattica\n" "- /circolari - Visualizza le circolari da leggere\n" "- /orario - Imposta o visualizza l'orario delle lezioni\n" "- /settings - Modifica le impostazioni personali del bot\n" "- /assenze - Visualizza assenze, ritardi e uscite anticipate\n" "- /note - Visualizza la lista delle note\n" "- /info - Visualizza le tue info utente\n" "- /prof - Visualizza la lista delle materie e dei prof\n" "- /about - Informazioni sul bot\n" "- /aboutprivacy - Più informazioni sulla privacy\n" "- /logout - Disconnettiti\n" "- /support - Contatta lo staff (emergenze)\n\n" "<b>Notifiche</b>: ogni mezz'ora, se vuoi, ti invierò un messaggio se ti sono arrivati nuovi voti, note, compiti, materiali, avvisi o circolari.\n" "<b>Impostazioni</b>: con /settings puoi cambiare varie impostazioni, tra cui l'orario delle notifiche, quali notifiche ricevere e se riceverle di notte." "", parse_mode="HTML") elif text.startswith("/broadcast ") and helpers.isAdmin(chatId): bdText = text.split(" ", 1)[1] pendingUsers = select(u.chatId for u in User)[:] userCount = len(pendingUsers) for u in pendingUsers: try: bot.sendMessage(u, bdText, parse_mode="HTML", disable_web_page_preview=True) except (TelegramError, BotWasBlockedError): userCount -= 1 bot.sendMessage( chatId, "📢 Messaggio inviato correttamente a {0} utenti!".format( userCount)) elif text.startswith("/sendmsg ") and helpers.isAdmin(chatId): selId = int(text.split(" ", 2)[1]) selText = str(text.split(" ", 2)[2]) bot.sendMessage(selId, selText, parse_mode="HTML") bot.sendMessage(chatId, selText + "\n\n- Messaggio inviato!", parse_mode="HTML") elif text == "/globalupdate" and helpers.isAdmin(chatId): bot.sendMessage(chatId, "🕙 Inizio aggiornamento globale...") runUpdates(long_fetch=True) bot.sendMessage(chatId, "✅ Aggiornamento globale completato!") elif text == "/silentupdate" and helpers.isAdmin(chatId): bot.sendMessage(chatId, "🕙 [BG] Inizio aggiornamento globale...") runUpdates(long_fetch=True, sendMessages=False) bot.sendMessage(chatId, "✅ [BG] Aggiornamento globale completato!") elif text == "/users" and helpers.isAdmin(chatId): totalUsers = len(select(u for u in User)[:]) loggedUsers = len(select(u for u in User if u.password != "")[:]) bot.sendMessage(chatId, "👤 Utenti totali: <b>{}</b>\n" "👤 Utenti loggati: <b>{}</b>".format( totalUsers, loggedUsers), parse_mode="HTML") elif text == "/restrict" and helpers.isAdmin(chatId): restrictedMode = True bot.sendMessage(chatId, "<i>Modalità ristretta attiva.\n" "Solo gli admin possono usare il bot.</i>", parse_mode="HTML") elif text == "/unrestrict" and helpers.isAdmin(chatId): restrictedMode = False bot.sendMessage(chatId, "<i>Modalità ristretta disattivata.\n" "Tutti gli utenti potranno usare il bot.</i>", parse_mode="HTML") elif "reply_to_message" in msg: if helpers.isAdmin(chatId): try: userId = msg['reply_to_message']['forward_from']['id'] bot.sendMessage(userId, "💬 <b>Risposta dello staff</b>\n" "{0}".format(text), parse_mode="HTML") bot.sendMessage(chatId, "Risposta inviata!") except Exception: bot.sendMessage(chatId, "Errore nell'invio.") else: if text.lower() == "no": bot.sendMessage(chatId, "<i>Ah ok, scusa.</i>", parse_mode="HTML") else: bot.sendMessage( chatId, "Scrivi /support per parlare con lo staff.") elif text == "/annulla": bot.sendMessage(chatId, "😴 Nessun comando da annullare!") elif helpers.hasStoredCredentials(chatId): if text == "/start": bot.sendMessage(chatId, "Bentornato, <b>{0}</b>!\n" "Cosa posso fare per te? 😊".format(name), parse_mode="HTML") elif text == "/login": bot.sendMessage( chatId, "Sei già loggato.\n" "Premi /logout per uscire.") elif text == "/logout": bot.sendMessage( chatId, "Tutti i tuoi dati scolastici e le credenziali verranno eliminate dal bot.\n" "Sei <b>veramente sicuro</b> di voler uscire?", parse_mode="HTML", reply_markup=keyboards.logout()) elif text == "/didattica": helpers.sendLongMessage( chatId, "📚 <b>Files caricati in didattica</b>:\n\n" "{0}".format(stored.didattica), parse_mode="HTML", disable_web_page_preview=True) elif text == "/info": bot.sendMessage(chatId, "ℹ️ <b>Ecco le tue info</b>:\n\n" "{0}".format(stored.info), parse_mode="HTML") elif text == "/prof": helpers.sendLongMessage(chatId, "📚 <b>Lista materie e prof</b>:\n\n" "{0}".format(stored.prof), parse_mode="HTML") elif text == "/note": helpers.sendLongMessage(chatId, "❗️<b>Le tue note</b>:\n\n" "{0}".format(stored.note), parse_mode="HTML") elif text == "/voti": helpers.sendLongMessage(chatId, "📝 <b>I tuoi voti</b>:\n\n" "{0}".format(stored.voti), parse_mode="HTML") elif text == "/assenze": helpers.sendLongMessage(chatId, "{0}".format(stored.assenze), parse_mode="HTML") elif text == "/agenda": bot.sendMessage( chatId, "📆 <b>Agenda compiti per le prossime 2 settimane</b>:\n\n" "{0}".format(stored.agenda), parse_mode="HTML", disable_web_page_preview=True) elif text == "/domani": isSaturday = datetime.now().isoweekday() == 6 dayString = "lunedì" if isSaturday else "domani" bot.sendMessage(chatId, "📆 <b>Compiti e verifiche per {0}</b>:\n\n" "{1}".format(dayString, stored.domani), parse_mode="HTML", disable_web_page_preview=True) elif text == "/circolari": bot.sendMessage(chatId, "📩 <b>Circolari da leggere</b>:\n\n" "{0}".format(stored.circolari), parse_mode="HTML", disable_web_page_preview=True) elif text == "/lezioni": bot.sendMessage(chatId, "📚 <b>Lezioni di oggi</b>:\n\n" "{0}".format(stored.lezioni), parse_mode="HTML", disable_web_page_preview=True, reply_markup=keyboards.lezioni()) elif text == "/settings": bot.sendMessage( chatId, "🛠 <b>Impostazioni</b>\n" "Ecco le impostazioni del bot. Cosa vuoi modificare?", parse_mode="HTML", reply_markup=keyboards.settings_menu()) elif text == "/promemoria": bot.sendMessage(chatId, "🕙 <b>Promemoria!</b>\n\n" "📆 <b>Cosa devi fare per domani</b>:\n\n" "{0}\n\n\n" "📚 <b>Le lezioni di oggi</b>:\n\n" "{1}".format(stored.domani, stored.lezioni), parse_mode="HTML", disable_web_page_preview=True) elif text == "/aggiorna": if (user.remainingCalls > 0) or (helpers.isAdmin(chatId)): if not updateLock.acquire(blocking=False): bot.sendMessage( chatId, "ℹ️ <b>Aspetta!</b>\n" "Il bot sta già eseguendo degli aggiornamenti globali per tutti gli utenti.", parse_mode="HTML") return sent = bot.sendMessage(chatId, "📙📙📙 Cerco aggiornamenti... 0%") user.remainingCalls -= 1 commit() updateLock.release() bot.editMessageText((chatId, sent['message_id']), "📗📙📙 Cerco aggiornamenti... 10%") api = ClasseVivaAPI() bot.editMessageText((chatId, sent['message_id']), "📗📙📙 Cerco aggiornamenti... 20%") if helpers.userLogin(chatId, api): bot.editMessageText((chatId, sent['message_id']), "📗📙📙 Cerco aggiornamenti... 35%") try: data = helpers.fetchStrict(api) except ApiServerError: bot.editMessageText(( chatId, sent['message_id'] ), "⚠️ I server di ClasseViva non sono raggiungibili.\n" "Riprova tra qualche minuto.") return bot.editMessageText((chatId, sent['message_id']), "📗📗📙 Cerco aggiornamenti... 50%") dataDidattica = parsers.parseNewDidattica( userdata.didattica, data['didattica']) bot.editMessageText((chatId, sent['message_id']), "📗📗📙 Cerco aggiornamenti... 60%") dataNote = parsers.parseNewNote( userdata.note, data['note']) bot.editMessageText((chatId, sent['message_id']), "📗📗📙 Cerco aggiornamenti... 70%") dataVoti = parsers.parseNewVoti( userdata.voti, data['voti'], chatId) bot.editMessageText((chatId, sent['message_id']), "📗📗📙 Cerco aggiornamenti... 80%") dataAgenda = parsers.parseNewAgenda( userdata.agenda, data['agenda'], chatId) bot.editMessageText((chatId, sent['message_id']), "📗📗📙 Cerco aggiornamenti... 90%") dataCircolari = parsers.parseNewCircolari( userdata.circolari, data['circolari']) bot.editMessageText((chatId, sent['message_id']), "📗📗📗 Cerco aggiornamenti... 100%") if dataDidattica is not None: bot.sendMessage( chatId, "🔔 <b>Nuovi file caricati!</b>{0}".format( dataDidattica), parse_mode="HTML", disable_web_page_preview=True) if dataNote is not None: bot.sendMessage( chatId, "🔔 <b>Hai nuove note!</b>{0}".format(dataNote), parse_mode="HTML") if dataVoti is not None: bot.sendMessage( chatId, "🔔 <b>Hai nuovi voti!</b>{0}".format(dataVoti), parse_mode="HTML") if dataAgenda is not None: bot.sendMessage( chatId, "🔔 <b>Hai nuovi impegni!</b>\n{0}".format( dataAgenda), parse_mode="HTML", disable_web_page_preview=True) if dataCircolari is not None: bot.sendMessage( chatId, "🔔 <b>Hai nuove circolari!</b>{0}".format( dataCircolari), parse_mode="HTML", disable_web_page_preview=True) if not any([ dataDidattica, dataNote, dataVoti, dataAgenda, dataCircolari ]): bot.editMessageText((chatId, sent['message_id']), "📗 Dati aggiornati!\n" "📗 Nessuna novità!") else: bot.deleteMessage((chatId, sent['message_id'])) helpers.updateUserdata(chatId, data) helpers.fetchAndStore(chatId, api, data, fetch_long=True) else: bot.sendMessage( chatId, "⛔️ Hai usato troppi /aggiorna recentemente. Aspetta un po'!" ) elif (text == "/support") or (text == "/start support"): user.status = "calling_support" bot.sendMessage( chatId, "🆘 <b>Richiesta di supporto</b>\n" "Se hai qualche problema che non riesci a risolvere, scrivi qui un messaggio, e un admin " "ti contatterà il prima possibile.\n\n" "<i>Per annullare, premi</i> /annulla.", parse_mode="HTML") elif text == "/orario": if not Document.exists( lambda d: (d.chatId == chatId and d.type == "orario")): user.status = "sending_orario" bot.sendMessage( chatId, "🕑 <b>Impostazione orario</b>\n" "Inviami un documento (PDF oppure foto) per salvarlo e richiamarlo " "quando serve con /orario!", parse_mode="HTML") else: doc = Document.get(chatId=chatId, type="orario") sendFunc = bot.sendPhoto if doc.data[ "ext"] == "photo" else bot.sendDocument sendFunc(chatId, doc.data["fileId"], reply_markup=keyboards.mod_orario()) elif text == "/memo": user.status = "memo_date" today = datetime.now().weekday() bot.sendMessage( chatId, "💡 <b>Memo personale</b>\n" "Crea un memo personale per aggiungere i compiti da fare all'agenda!\n" "Inviami <b>la data</b> di consegna, nel formato GG/MM, oppure scegli un'opzione " "da quelle qui sotto.\n\n" "Premi /annulla per annullare.", parse_mode="HTML", reply_markup=keyboards.create_memo(today)) elif text == "/resetmemo": memos = select(m for m in Document if m.chatId == chatId and m.type == "memo")[:] for memo in memos: memo.delete() bot.sendMessage(chatId, "✅ Ho eliminato tutte le memo!") # Custom Start Parameters elif text.startswith("/start "): param = text.split(' ')[1] if param.startswith("circ"): evtCode = param.split("-")[0].replace("circ", "") pubId = int(param.split("-")[1]) sendFile(chatId, "circolare", evtCode, pubId) elif param.startswith("file"): intId = int(param[4:]) sendFile(chatId, "file", intId) elif param.startswith("link"): intId = int(param[4:]) sendFile(chatId, "link", intId) elif text == "⬆️⬆️⬇️⬇️⬅️➡️⬅️➡️🅱️🅰️" or text == "⬆️⬆️⬇️⬇️⬅️➡️⬅️➡️🅱🅰": from random import choice today = datetime.today().strftime("%d/%m/%Y") subject = choice( ["MATEMATICA", "ITALIANO", "INGLESE", "STORIA"]) bot.sendMessage(chatId, "🔔 <b>Hai nuovi voti!</b>\n\n" "📚 <b>{}</b>\n\n" "📗 <b>Voto 10</b> • Scritto • {}\n" "<i>Start!</i>".format(subject, today), parse_mode="HTML") # Text is not a keyword else: bot.sendMessage( chatId, "Non ho capito...\n" "Serve aiuto? Premi /help") # User not logged in else: if text == "/login": user.status = "login_0" bot.sendMessage( chatId, "Per favore, inviami il tuo <b>username</b> (quello che usi per accedere al registro).\n" "Usa /annulla se serve.", parse_mode="HTML") else: bot.sendMessage(chatId, "Benvenuto, <b>{0}</b>!\n" "Per utilizzarmi devi eseguire il /login.\n\n" "Premi /help se serve aiuto.".format(name), parse_mode="HTML") # Normal user with restricted mode else: if text == "/moreinfo": bot.sendMessage( chatId, "❓ <b>Che genere di problemi?</b>\n" "ClasseViva ha recentemente imposto un limite alle sue API, che questo bot utilizza, " "anche se è nascosto e non sempre uguale. Con l'aumentare degli utenti, il bot doveva fare " "sempre più richieste e una volta raggiunto il limite ha cominciato a non funzionare più.\n" "La soluzione sarebbe avere una lista di minimo 20 proxy da utilizzare per fare le richieste " "(si tratta di max. 200KB di traffico ogni 30 minuti, non è quello il problema), che " "però è molto difficile da trovare senza pagare qualche servizio, che al momento non posso permettermi.\n\n" "❔ <b>Posso contattarti?</b>\n" "Certo, puoi scrivermi per qualsiasi motivo <a href=\"https://t.me/pesaventofilippo\">qui</a> " "o mandarmi una mail a [email protected].\n" "Non sono un bot, quindi magari non rispondo subito 🙂", parse_mode="HTML", disable_web_page_preview=True) else: bot.sendMessage( chatId, "ℹ️ <b>Bot in manutenzione</b>\n" "Il bot è attualmente in manutenzione per problemi con ClasseViva, e tutte le sue " "funzioni sono temporaneamente disabilitate.\n" "Non eliminare questa chat: se vuoi puoi archiviarla su Telegram, così appena " "ci saranno notizie ti manderò un messaggio.\n\n" "/moreinfo", parse_mode="HTML")
async def add_twillio_creds(ctx, sid, token, phonenumber): if helpers.isAdmin(ctx): DB.addAuth(str(ctx.guild.id), sid, token, phonenumber) await ctx.send("Twillio credentials + phone number noted!") else: await ctx.send("Only Admins can do that")
def reply(msg): chatId = msg['chat']['id'] name = msg['from']['first_name'] if "text" in msg: text = msg['text'] else: bot.sendMessage(chatId, "🤨 Formato file non supportato. /help") return if not User.exists(lambda u: u.chatId == chatId): User(chatId=chatId) if not Data.exists(lambda d: d.chatId == chatId): Data(chatId=chatId) user = User.get(chatId=chatId) data = Data.get(chatId=chatId) if text == "/about": bot.sendMessage(chatId, "ℹ️ <b>Informazioni sul bot</b>\n" "IliadInfoBot è un bot creato e sviluppato da Filippo Pesavento, che ti permette " "di visualizzare tutte le info sul tuo account Iliad in mancanza dell'app.\n" "Prova ad usarlo per scoprire quanto è comodo!\n\n" "<b>Sviluppo:</b> Filippo Pesavento\n" "<b>Hosting:</b> Filippo Pesavento\n" "<b>Info sicurezza:</b> /aboutprivacy\n\n" "<i>IliadInfoBot non è in alcun modo affiliato con Iliad Italia S.p.A ed è una creazione " "esclusiva di Filippo Pesavento.</i>", parse_mode="HTML") elif text == "/aboutprivacy": bot.sendMessage(chatId, "ℹ️ <b>Informazioni sulla privacy</b>\n" "La mia password è al sicuro? 🤔\n\n" "🔐 <b>Sì: la tua password viene criptata.</b>\n" "Il bot conserva la tua password in maniera sicura, salvandola in un formato non leggibile da " "persone estranee. Sei al sicuro: i tuoi dati non verranno visti nè rubati da nessuno!\n\n" "🔐 <b>Spiegazione dettagliata:</b>\n" "Tecnicamente potrei decriptare a mano le password e vederle, ma sostanzialmente è complicato, " "perchè il bot genera una chiave per l'algoritmo (visto che il cripting deve essere reversibile, " "per poter mandare le notifiche automatiche) prendendo come dati una chiave comune (che salvo nella RAM " "e inserisco ad ogni avvio, per evitare che qualcuno che non sia io possa leggere il database e i dati degli utenti) " "e anche l'username dell'utente. Quindi ogni utente ha la propria password criptata con una chiave diversa da tutti " "gli altri, e sarebbe difficile anche per me risalire alla password, dovendo sapere di chi è l'username collegato a " "quella password specifica.\n" "Questo non vuol dire che non possa farlo: con un po' di lavoro ci riuscirei. Quindi alla fine devi decidere tu: " "io ti posso assicurare che non leggerò mai nè proverò mai a decriptare le password, sia per un discorso di etica " "che per scelta personale, ma non sono tuo amico nè tuo conoscente: quindi se decidi di non fidarti di uno sconosciuto " "che ti scrive su Telegram (ti posso capire benissimo) sei libero di non usare il bot 🙂\n\n" "<a href=\"https://t.me/pesaventofilippo\">Contattami</a>\n\n" "<i>Se sei venuto qui prima di digitare la password per il login, scrivila adesso!</i>", parse_mode="HTML", disable_web_page_preview=True) elif user.status != "normal": if text == "/annulla": user.status = "normal" bot.sendMessage(chatId, "Comando annullato!") elif user.status == "login_0": if len(text) != 8 or not text.isdigit(): bot.sendMessage(chatId, "⚠️ Errore: l'username deve essere un numero 8 cifre. Riprova!") return user.username = text user.status = "login_1" bot.sendMessage(chatId, "👍 Ottimo. Adesso inviami la password.\n" "Ricorda che la password viene salvata solo per te e viene criptata, nessuno potrà leggerla.\n\n" "Sei preoccupato per la sicurezza della password? /aboutprivacy") elif user.status == "login_1": user.password = crypt_password(text, chatId) user.status = "normal" commit() api = IliadApi(user.username, decrypt_password(chatId)) try: api.load() except AuthenticationFailedError: helpers.clearUserData(chatId) try: bot.sendMessage(chatId, "😯 Le tue credenziali di accesso sono errate.\n" "Controlla i dati inseriti e rieffettua il /login.") except (TelegramError, BotWasBlockedError): pass return bot.sendMessage(chatId, "Fatto 😊\n" "Premi /help per vedere la lista dei comandi disponibili.\n\n" "<i>Se vuoi, puoi eliminare il messaggio che mi hai mandato contenente la password: "******"non mi serve più!</i>", parse_mode="HTML") sent = bot.sendMessage(chatId, "🔍 Aggiorno il profilo...") helpers.fetchAndStore(api, chatId) bot.editMessageText((chatId, sent['message_id']), "✅ Profilo aggiornato!") elif user.status == "calling_support": user.status = "normal" for a in helpers.isAdmin(): bot.sendMessage(a, "🆘 <b>Richiesta di aiuto</b>\n" "Da: <a href=\"tg://user?id={0}\">{1}</a>\n\n" "<i>Rispondi al messaggio per parlare con l'utente.</i>".format(chatId, name), parse_mode="HTML") if "reply_to_message" in msg: bot.forwardMessage(a, chatId, msg["reply_to_message"]["message_id"]) bot.forwardMessage(a, chatId, msg['message_id'], disable_notification=True) bot.sendMessage(chatId, "<i>Richiesta inviata.</i>\n" "Un admin ti risponderà il prima possibile.", parse_mode="HTML") elif text == "/help": bot.sendMessage(chatId, "Ciao, sono il bot di <b>Iliad</b>! 👋🏻\n" "Posso aiutarti a <b>controllare</b> il tuo piano dati e posso mandarti <b>notifiche</b> (in futuro).\n\n" "<b>Lista dei comandi</b>:\n" "- /start - Avvia bot\n" "- /login - Effettua il login\n" "- /profilo - Informazioni sul profilo Iliad\n" "- /overview - Riepilogo generale dei consumi\n" "- /credito - Credito residuo\n" "- /internet - Visualizza piano dati\n" "- /chiamate - Visualizza piano chiamate\n" "- /sms - Visualizza piano SMS\n" "- /mms - Visualizza piano MMS\n" "- /logout - Disconnettiti\n" "- /aggiorna - Aggiorna tutti i dati. <b>Nota</b>: lo faccio già in automatico ogni mezz'ora per te!\n" "- /help - Mostra questa lista\n" "- /about - Informazioni sul bot\n" "- /aboutprivacy - Più informazioni sulla privacy\n" "- /support - Contatta lo staff (emergenze)\n\n" "<i>IliadInfoBot non è in alcun modo affiliato con Iliad Italia S.p.A ed è una creazione " "esclusiva di Filippo Pesavento.</i>", parse_mode="HTML") elif text == "/users" and helpers.isAdmin(chatId): totalUsers = len(select(u for u in User)[:]) loggedUsers = len(select(u for u in User if u.password != "")[:]) bot.sendMessage(chatId, "👤 Utenti totali: <b>{}</b>\n" "👤 Utenti loggati: <b>{}</b>".format(totalUsers, loggedUsers), parse_mode="HTML") elif text == "/globalupdate" and helpers.isAdmin(chatId): bot.sendMessage(chatId, "🕙 Inizio aggiornamento globale...") runUpdates() bot.sendMessage(chatId, "✅ Aggiornamento globale completato!") elif text.startswith("/broadcast ") and helpers.isAdmin(chatId): bdText = text.split(" ", 1)[1] pendingUsers = select(u.chatId for u in User)[:] userCount = len(pendingUsers) for u in pendingUsers: try: bot.sendMessage(u, bdText, parse_mode="HTML", disable_web_page_preview=True) except (TelegramError, BotWasBlockedError): userCount -= 1 bot.sendMessage(chatId, "📢 Messaggio inviato correttamente a {0} utenti!".format(userCount)) elif text.startswith("/sendmsg ") and helpers.isAdmin(chatId): selId = int(text.split(" ", 2)[1]) selText = str(text.split(" ", 2)[2]) bot.sendMessage(selId, selText, parse_mode="HTML") bot.sendMessage(chatId, selText + "\n\n- Messaggio inviato!", parse_mode="HTML") elif "reply_to_message" in msg: if helpers.isAdmin(chatId): try: userId = msg['reply_to_message']['forward_from']['id'] bot.sendMessage(userId, "💬 <b>Risposta dello staff</b>\n" "{0}".format(text), parse_mode="HTML") bot.sendMessage(chatId, "Risposta inviata!") except Exception: bot.sendMessage(chatId, "Errore nell'invio.") else: bot.sendMessage(chatId, "Scrivi /support per parlare con lo staff.") elif text == "/annulla": bot.sendMessage(chatId, "😴 Nessun comando da annullare!") elif helpers.hasStoredCredentials(chatId): if text == "/start": bot.sendMessage(chatId, "Bentornato, <b>{0}</b>!\n" "Cosa posso fare per te? 😊".format(name), parse_mode="HTML") elif text == "/login": bot.sendMessage(chatId, "Sei già loggato.\n" "Premi /logout per uscire.") elif text == "/logout": sent = bot.sendMessage(chatId, "Tutti i tuoi dati relativi all'account e le credenziali verranno eliminate dal bot.\n" "Sei <b>veramente sicuro</b> di voler uscire?", parse_mode="HTML") bot.editMessageReplyMarkup((chatId, sent['message_id']), keyboards.logout(sent['message_id'])) elif text == "/profilo": bot.sendMessage(chatId, f"👤 <b>Info profilo</b>\n\n" f"ℹ️ Nome: <b>{data.nome}</b>\n" f"📞 Numero: <b>{data.numero}</b>\n" f"🆔 ID Account: <b>{data.accountId}</b>\n\n" f"💶 Credito residuo: <b>{data.credito:.2f}€</b>\n" f"📅 Data rinnovo: <b>{data.dataRinnovo}</b>", parse_mode="HTML") elif text == "/overview": costo = data.costoChiamate + data.costoGiga + data.costoSms + data.costoMms sent = bot.sendMessage(chatId, f"ℹ️ <b>Riepilogo piano</b>\n\n" f"📞 Chiamate: <b>{data.totChiamate}</b>\n" f"🌐 Dati consumati: <b>{data.totGiga['count']}{data.totGiga['unit']}</b> su <b>" f"{data.pianoGiga['count']}{data.pianoGiga['unit']}</b>\n" f"✉️ SMS Inviati: <b>{data.totSms}</b>\n" f"📧 MMS Inviati: <b>{data.totMms}</b>\n\n" f"💸 Costi extra: {costo:.2f}€", parse_mode="HTML") bot.editMessageReplyMarkup((chatId, sent['message_id']), keyboards.overviewExt(sent['message_id'])) elif text == "/credito": bot.sendMessage(chatId, f"Il tuo credito residuo è di <b>{data.credito:.2f} euro</b>.", parse_mode="HTML") elif text == "/chiamate": bot.sendMessage(chatId, f"🇮🇹 <b>Chiamate in Italia</b>\n" f"🕙 Tempo: <b>{data.totChiamate}</b>\n" f"💸 Costi extra: <b>{data.costoChiamate:.2f}€</b>\n\n" f"🇪🇺 <b>Chiamate in Europa</b>\n" f"🕙 Tempo: <b>{data.ext_totChiamate}</b>\n" f"💸 Costi extra: <b>{data.ext_costoChiamate:.2f}€</b>", parse_mode="HTML") elif text == "/sms": bot.sendMessage(chatId, f"🇮🇹 <b>SMS in Italia</b>\n" f"✉️ Inviati: <b>{data.totSms} SMS</b>\n" f"💸 Costi extra: <b>{data.costoSms:.2f}€</b>\n\n" f"🇪🇺 <b>SMS in Europa</b>\n" f"✉️ Inviati: <b>{data.ext_totSms} SMS</b>\n" f"💸 Costi extra: <b>{data.ext_costoSms:.2f}€</b>", parse_mode="HTML") elif text == "/mms": bot.sendMessage(chatId, f"🇮🇹 <b>MMS in Italia</b>\n" f"📧 Inviati: <b>{data.totMms} MMS</b>\n" f"💸 Costi extra: <b>{data.costoSms:.2f}€</b>\n\n" f"🇪🇺 <b>MMS in Europa</b>\n" f"📧 Inviati: <b>{data.ext_totMms} MMS</b>\n" f"💸 Costi extra: <b>{data.ext_costoMms:.2f}€</b>", parse_mode="HTML") elif text == "/internet": bot.sendMessage(chatId, f"🇮🇹 <b>Piano dati in Italia</b>\n" f"📶 Consumati: <b>{data.totGiga['count']}{data.totGiga['unit']}</b> su <b>" f"{data.pianoGiga['count']}{data.pianoGiga['unit']}</b>\n" f"💸 Costi extra: <b>{data.costoGiga:.2f}€</b>\n\n" f"🇪🇺 <b>Piano dati in Europa</b>\n" f"📶 Consumati: <b>{data.ext_totGiga['count']}{data.ext_totGiga['unit']}</b> su <b>" f"{data.ext_pianoGiga['count']}{data.ext_pianoGiga['unit']}</b>\n" f"💸 Costi extra: <b>{data.ext_costoGiga:.2f}€</b>", parse_mode="HTML") elif text == "/support": user.status = "calling_support" bot.sendMessage(chatId, "🆘 <b>Richiesta di supporto</b>\n" "Se hai qualche problema che non riesci a risolvere, scrivi qui un messaggio, e un admin " "ti contatterà il prima possibile.\n\n" "<i>Per annullare, premi</i> /annulla.", parse_mode="HTML") elif text == "/aggiorna": if user.remainingCalls > 0: user.remainingCalls -= 1 commit() sent = bot.sendMessage(chatId, "📙📙📙 Aggiorno il profilo... 0%") api = IliadApi(user.username, decrypt_password(chatId)) bot.editMessageText((chatId, sent['message_id']), "📗📙📙 Cerco aggiornamenti... 10%") try: api.load() except AuthenticationFailedError: helpers.clearUserData(chatId) bot.editMessageText((chatId, sent['message_id']), "⚠️ Le tue credenziali non sono corrette.\n" "Rieffettua il /login!.") return bot.editMessageText((chatId, sent['message_id']), "📗📙📙 Cerco aggiornamenti... 50%") helpers.fetchAndStore(api, chatId) bot.editMessageText((chatId, sent['message_id']), "📗📗📗 Cerco aggiornamenti... 100%") bot.editMessageText((chatId, sent['message_id']), "✅ Profilo aggiornato!") else: bot.sendMessage(chatId, "⛔️ Hai usato troppi /aggiorna recentemente. Aspetta un po'!") else: bot.sendMessage(chatId, "Non ho capito...\n" "Serve aiuto? Premi /help") else: if text == "/login": user.status = "login_0" bot.sendMessage(chatId, "Per favore, inviami il tuo <b>username</b> (il codice da 8 cifre che usi per accedere " "all'Area Personale).\n" "Usa /annulla se serve.", parse_mode="HTML") else: bot.sendMessage(chatId, "Benvenuto, <b>{0}</b>!\n" "Per favore, premi /login per utilizzarmi.\n\n" "Premi /help se serve aiuto.".format(name), parse_mode="HTML")
def reply(msg): chatId = msg['chat']['id'] name = msg['from']['first_name'] if "text" in msg: text = msg['text'] elif "caption" in msg: text = msg['caption'] else: text = "" if not Category.exists(lambda c: c.name == "General"): Category(name="General") if not User.exists(lambda u: u.chatId == chatId): User(chatId=chatId) user = User.get(chatId=chatId) ## Text Message if msg.get('text'): if user.status.endswith("uploading_file"): if text == "/cancel": user.status = "normal" bot.sendMessage(chatId, "📕 File upload cancelled.") else: bot.sendMessage( chatId, "❓ Please upload an ebook file.\n" "Type /cancel to abort.") elif user.status.startswith("selecting_category"): book_id = int(user.status.split('#', 1)[1]) book = Book.get(id=book_id) if text == "/cancel": book.category = Category.get(name="General") user.status = "normal" bot.sendMessage(chatId, "📗 Book moved to category <b>General</b>.", parse_mode="HTML") return categories = [ cat.name.lower() for cat in select(c for c in Category)[:] ] if text.lower() not in categories: cat = Category(name=text) commit() book.category = cat user.status = "normal" bot.sendMessage( chatId, f"📗 New category <b>{text}</b> successfully added!\n" f"I also added the book to the new category for you.", parse_mode="HTML") else: bot.sendMessage( chatId, f"📙 Category <b>{text}</b> already exists!\n" f"Try with a different name, or select one from the list above.", parse_mode="HTML") elif text == "/getusers" and isAdmin(chatId): users = len(select(u for u in User)[:]) bot.sendMessage( chatId, f"👥 There currently are <b>{users}</b> registered users.", parse_mode="HTML") elif text == "/getbooks" and isAdmin(chatId): books = len(select(b for b in Book)[:]) bot.sendMessage(chatId, f"📚 There currently are <b>{books}</b> books.", parse_mode="HTML") elif text == "/movebook" and isAdmin(chatId): sent = bot.sendMessage( chatId, "📦 Please choose the book you want to move:") bot.editMessageReplyMarkup( (chatId, sent['message_id']), keyboards.manageBooks("move", sent['message_id'])) elif text == "/delbook" and isAdmin(chatId): sent = bot.sendMessage(chatId, "🗑 Please choose the book to delete:") bot.editMessageReplyMarkup( (chatId, sent['message_id']), keyboards.manageBooks("del", sent['message_id'])) elif text == "/bulkupload": user.status = "bulk_uploading_file" bot.sendMessage( chatId, "📎 <b>Bulk Upload mode active.</b> Type /cancel to abort.\n" "<i>Only PDF files are supported.</i>", parse_mode="HTML") # General user commands elif text == "/start": bot.sendMessage( chatId, f"Hey <b>{name}</b>! I'm the Free Books Bot 👋🏻\n" f"I'm currently in <b>Beta Version</b>, but you can already use me to find some books: " f"type /search to find a book by category, or type /help if you have any question.", parse_mode="HTML") elif text == "/help": bot.sendMessage(chatId, "<b>Commands List</b>\n\n" "/start - Start bot\n" "/help - Show this page\n" "/search - Search books by category\n" "/submit - Send a new ebook for everyone to read\n" "/cancel - Reset current action", parse_mode="HTML") elif text == "/search": sent = bot.sendMessage(chatId, "🔍 <b>Book Search</b>\n" "Pick a category from the list below:", parse_mode="HTML") bot.editMessageReplyMarkup( (chatId, sent['message_id']), keyboards.search_cat(sent['message_id'])) elif text == "/submit": user.status = "uploading_file" bot.sendMessage( chatId, "📎 Ok, please send me the new ebook, or type /cancel to abort.\n" "<i>Only PDF files are supported.</i>", parse_mode="HTML") elif text == "/cancel": bot.sendMessage( chatId, "Operation cancelled!\n" "I was doing nothing, by the way... 😴") elif text.startswith("/start getbook"): book_id = int(text.split('_')[1]) book = Book.get(id=book_id) bot.sendDocument( chatId, book.telegramFileId, f"<b>Book Name:</b> {book.name}\n" f"<b>Category:</b> {book.category.name}", "HTML") # Unknown command else: bot.sendMessage(chatId, "😕 Sorry, I didn't understand.\n" "Need /help?") ## File Document elif msg.get('document') and supportedFile(msg): if not user.status.endswith("uploading_file"): bot.sendMessage( chatId, "📕 Sorry, you're currently not uploading a file.\n" "Type /submit if you would like to submit a new book.") return fileId = msg['document']['file_id'] fileSize = msg['document']['file_size'] fileName = msg['document']['file_name'] if fileSize > 50000000: # 50MB Telegram Limit (in bytes) bot.sendMessage( chatId, "📕 Sorry, the file size must be lower than <b>50MB</b>.", parse_mode="HTML") return if not Book.exists(lambda b: b.name == fileName): book = Book(name=fileName, telegramFileId=fileId) commit() if (not isAdmin(chatId)) or (user.status == "bulk_uploading_file"): book.category = Category.get(name="General") if user.status != "bulk_uploading_file": user.status = "normal" bot.sendMessage(chatId, f"📗 <b>{fileName}</b> successfully uploaded!", parse_mode="HTML") else: user.status = f"selecting_category#{book.id}" if not select(c for c in Category if c.name != "General")[:]: bot.sendMessage( chatId, f"📗 <b>{fileName}</b> successfully uploaded!\n" f"Please type a name to create a new category:", parse_mode="HTML") else: sent = bot.sendMessage( chatId, f"📗 <b>{fileName}</b> successfully uploaded!\n" f"Please select a category for the book, or type a name to create a new one:", parse_mode="HTML") bot.editMessageReplyMarkup( (chatId, sent['message_id']), keyboards.category(book.id, sent['message_id'])) # Book with same name already exists else: bot.sendMessage( chatId, f"📙 Warning: \"<b>{fileName}</b>\" already exists! If you think this is an error, please " f"change the file name and reupload it.", parse_mode="HTML") # Filetype not supported else: bot.sendMessage( chatId, "🤨 I'm sorry, but this is not a supported file type...\n" "Are you lost? Press /help")
def reply(msg): chatId = int(msg['chat']['id']) msgId = int(msg['message_id']) name = msg['from']['first_name'] if "last_name" in msg['from']: name += " " + msg['from']['last_name'] if "text" in msg: text = msg['text'] elif "caption" in msg: text = msg['caption'] else: text = "" # Rename it-m.banggood.com to desktop banggood.com if "it-m.banggood.com" in text: text = text.replace("it-m.banggood.com", "banggood.com") # Rename m.banggood.com to desktop banggood.com if "m.banggood.com" in text: text = text.replace("m.banggood.com", "banggood.com") ## Messaggio da canale interno if chatId == -1001298078411: print(msg) ## Messaggio da chat normali elif chatId > 0: # Genera entry nel database if not User.exists(lambda u: u.chatId == chatId): isNewUser = True user = User(chatId=chatId, name=name) else: isNewUser = False user = User.get(chatId=chatId) user.name = name # Comandi bot if text == "/listmuted" and helpers.isAdmin(chatId): mutedUsers = select(u for u in User if u.muted)[:] mutedList = "" for u in mutedUsers: mutedList += "- <a href=\"tg://user?id={}\">{}</a>\n".format( u.chatId, u.name) if mutedList: bot.sendMessage(chatId, "ЪћЄ <b>Lista utenti mutati:</b>\n" "{}".format(mutedList), parse_mode="HTML") else: bot.sendMessage(chatId, "ЪћЄ <b>Nessun utente mutato!</b>", parse_mode="HTML") elif text.startswith("/annuncio ") and helpers.isAdmin(chatId): bdText = "ЪЊб <b>Annuncio dallo staff</b>\n" + text.split(" ", 1)[1] pendingUsers = select(u.chatId for u in User)[:] userCount = len(pendingUsers) for uid in pendingUsers: try: bot.sendMessage(uid, bdText, parse_mode="HTML", disable_web_page_preview=True) except (TelegramError, BotWasBlockedError): userCount -= 1 bot.sendMessage( chatId, "ЪЊб Messaggio inviato correttamente a {0} utenti!".format( userCount)) elif text == "/start": if isNewUser: bot.sendMessage(chatId, messages["help"], parse_mode="HTML") else: bot.sendMessage(chatId, messages["start"].format( msg['from']['first_name']), parse_mode="HTML") elif text == "/help": bot.sendMessage(chatId, messages["help"], parse_mode="HTML") ## Admin ha risposto ad un messaggio di testo elif "reply_to_message" in msg and helpers.isAdmin(chatId): try: quotedMessage = msg['reply_to_message'] # Cerca i dati del messaggio dal database origMsg = None dbQuery = select(m for m in Message if m.sentIds[str(chatId)] == int(quotedMessage['message_id']))[:] if len(dbQuery) > 0: origMsg = dbQuery[0] userId = origMsg.fromUser.chatId userName = origMsg.fromUser.name else: # Cerca di capire le informazioni da Telegram if "forward_from" in quotedMessage: userId = quotedMessage['forward_from']['id'] userName = quotedMessage['forward_from']['first_name'] if "last_name" in quotedMessage['forward_from']: userName += " " + msg['reply_to_message'][ 'forward_from']['last_name'] else: bot.sendMessage( chatId, "Ъўћ <b>Errore nell'invio.</b>\n\n" "L'utente ha attivato la privacy per i messaggi inoltrati, e il " "messaggio non ├е nel database.", parse_mode="HTML") return # Controlla se ├е un comando di servizio if text.startswith("/"): if text == "/mute": origMsg.fromUser.muted = True bot.sendMessage( chatId, "ЪћЄ Utente mutato.\n" "Usa /unmute per smutarlo.") bot.sendMessage(origMsg.fromUser.chatId, "ЪћЄ Sei stato mutato da un admin.") elif text == "/unmute": origMsg.fromUser.muted = False bot.sendMessage( chatId, "ЪћЅ Utente smutato.\n" "Usa /mute per mutarlo di nuovo.") bot.sendMessage( origMsg.fromUser.chatId, "ЪћЅ Puoi nuovamente inviare messaggi al bot!") else: bot.sendMessage(chatId, messages["command_ukn"], parse_mode="HTML") # Altrimenti, invia risposta a utente else: replyToId = origMsg.fromMsgId if origMsg else None bot.sendMessage(userId, "Ъњг <b>Risposta dello staff</b>\n" "{}".format(text), parse_mode="HTML", reply_to_message_id=replyToId) bot.sendMessage(chatId, "Risposta inviata!") # Segnala ad altri admin la risposta data otherAdmins = [a for a in helpers.isAdmin() if a != chatId] for a in otherAdmins: try: replyToId = origMsg.sentIds[str( a)] if origMsg else None if replyToId: bot.deleteMessage((a, replyToId)) bot.sendMessage( a, "<a href=\"tg://user?id={}\">{}</a> ha risposto a <a href=\"tg://user?id={}\">{}</a>:\n" "<i>{}</i>".format(chatId, name, userId, userName, text), parse_mode="HTML") except (TelegramError, BotWasBlockedError, KeyError): pass bot.deleteMessage((chatId, quotedMessage['message_id'])) except Exception as e: bot.sendMessage(chatId, "Ъўћ <b>Errore nell'invio.</b>\n\n" "<i>Debug Info:</i>\n" "<code>{}</code>".format(e), parse_mode="HTML") return ## Messaggio non contiene un link: modalit├а limitatibot elif not helpers.getLink(msg): if user.muted: bot.sendMessage(chatId, messages["muted"], parse_mode="HTML") return if text.startswith("/"): bot.sendMessage(chatId, messages["command_ukn"], parse_mode="HTML") return sentIdsCache = {} for a in helpers.isAdmin(): try: sentMsg = bot.forwardMessage(a, chatId, msg['message_id']) sentIdsCache[str(a)] = int(sentMsg['message_id']) except (TelegramError, BotWasBlockedError): pass # Se non c'├е il messaggio nel database, ├е nuovo: salvalo if not Message.exists(fromUser=user, fromMsgId=msgId): Message(fromUser=user, fromMsgId=msgId, sentIds=sentIdsCache) # Se esiste gi├а il messaggio nel database, aggiorna i vecchi ID else: oldMessage = Message.get(fromUser=user, fromMsgId=msgId) oldMessage.sentIds = sentIdsCache bot.sendMessage(chatId, messages["msg_sent"], parse_mode="HTML") ## Messaggio contiene link: logga offerta e rispondi else: if user.muted: bot.sendMessage(chatId, messages["muted"], parse_mode="HTML") return link = helpers.getLink(msg) sent = bot.sendMessage( forwardChannel, "<b>Nuovo messaggio!</b>\n" "<i>Da:</i> <a href=\"tg://user?id={}\">{}</a>\n\n" "{}".format(chatId, name, text), parse_mode="HTML", disable_web_page_preview=True, reply_markup=None) Message(fromUser=user, fromMsgId=msgId, sentIds={str(forwardChannel): int(sent['message_id'])}) if helpers.short(link): bot.editMessageReplyMarkup( (forwardChannel, sent['message_id']), keyboards.link_prenota(helpers.short(link), sent['message_id'])) else: bot.editMessageReplyMarkup( (forwardChannel, sent['message_id']), keyboards.error_prenota(sent['message_id'])) bot.sendMessage(chatId, choice(messages["thanks"]), parse_mode="HTML")