
Nous continuons l'histoire du développement du bot Telegram pour la recherche de billets - HappyTicketsBot, le début se trouve
dans la première partie .
Dans la seconde, je parlerai du bot lui-même, partagerai le code, ainsi que des idées qui ne deviendront probablement pas une réalité. La plupart des fonctionnalités au moment de la création du bot étaient déjà écrites dans un format de script, la tâche principale était donc d'établir une interface d'interaction utilisateur via Telegram-messenger. Il s'est avéré moins boltologiquement que dans la 1ère partie, donc l'attention est beaucoup de code.
Spoiler: HappyTicketsBot ne s'est pas envolé pour allumer un serveur étranger, c'est local et russe, mais un jour (je crois) ça va commencer =)
MISE À JOUR: Après que le bot a été partagé entre le public du théâtre, ils ont écrit à ce sujet dans les médias. Un flot d'utilisateurs a fortement augmenté. Après quelques jours de jeu, "ramassez-le immédiatement, comment il est tombé", le bot s'est envolé vers le serveur et a connu un certain nombre d'améliorations. Je suis satisfait =)
1. Partir de zéro
Comme il n'y avait aucun mot dans la conception des robots Telegram, j'ai dû commencer par des articles de base et des tutoriels, qui sont très nombreux sur le réseau. Oui, en passant, quel est le back-end à cette époque, j'ai aussi mal imaginé))
Cet ensemble de leçons est devenu le plus informatif et appliqué. Le module qui a interagi avec Telegram était pyTelegramBotAPI (
github ).
Le plus long a pris le développement de l'idéologie des décorateurs, lisez-les dans
cet article . Il y a deux parties et très compréhensible.
2. Le script pour l'interaction du bot avec l'utilisateur. Recherche basique
Comme déjà mentionné dans la préface et
la première partie de l'article , presque tout le code d'analyse était prêt. Il restait à changer la méthode de définition des paramètres de recherche. Sur cette base, un script de comportement de bot a été créé. Les commandes disponibles pour l'utilisateur sont limitées à l'ensemble suivant:
- / Rechercher - lancer une nouvelle recherche,
- / Reset - réinitialiser les paramètres de recherche et en lancer un nouveau,
- / LastSearch - renvoie les résultats en utilisant les paramètres de la dernière requête,
- / addURL ajoute une URL de performance dans les centres d' intérêt pour suivre la réduction des prix,
- / checkURL - mise à jour des prix pour les performances d'intérêt,
- / showURL - liste toutes les URL ajoutées à la liste des centres d'intérêt
Selon le script
/ find de recherche de base
, l' utilisateur passe d'un état à un autre, en entrant séquentiellement les données nécessaires au filtre. Après avoir entré le dernier paramètre - le lieu de présentation - l'affiche est directement analysée à l'aide de dictionnaires déclarés globalement, où la clé est l'ID utilisateur et les valeurs sont les paramètres de recherche saisis.
Afin de se souvenir de l'état de l'utilisateur, ils sont stockés dans la base de données. Pour l'utiliser, les modules Vedis (un configurateur de base de données de valeurs-clés, lire la
documentation ) et Enum (travailler avec les énumérations, détails
1 ,
2 ) sont utilisés.
Dans un fichier de configuration séparé Myconfig.py, nous définissons les paramètres du bot (y compris le jeton unique reçu de Telegram) et répertorions les statuts dans lesquels l'utilisateur peut se trouver. Ils sont sortis un peu.
from enum import Enum token = "4225555:AAGmfghjuGOI4sdfsdfs5656sdfsdf_c"
En conséquence, nous obtenons une chaîne simple de transitions de statut de l'un à l'autre.

Pour le stockage, nous utilisons la base de données Vedis. L'initialisation de l'utilisateur qui a envoyé le message se fait toujours via message.chat.id.
Le code du fichier dbwoker.py, qui décrit l'interaction avec la base de données from vedis import Vedis import Myconfig as config
Voici un exemple de gestionnaire activé par la commande / find. Comme vous pouvez le voir, dans cet exemple, il n'y a pas de saisie de données - il n'y a qu'un changement d'état à "S_ENTER_MONTH". Après avoir vu le message en entrant le numéro, l'utilisateur le saisit et envoie un message. Lors de la réception d'un message avec le statut S_ENTER_MONTH, l'étape suivante est lancée. En cas d'erreur de saisie, l'état ne change pas.
Si le bot reçoit un message d'un utilisateur avec le statut S_ENTER_MONTH, alors le gestionnaire suivant est lancé. Idéologiquement, cela se produit également à d'autres étapes du script de recherche de base.
@bot.message_handler(func=lambda message: dbworker.get_current_state(message.chat.id) == config.States.S_ENTER_MONTH.value) def user_entering_month(message): if not message.text.isdigit(): bot.send_message(message.chat.id, ", ") return # 1 num[message.chat.id]=message.text # if int(num[message.chat.id])>12 or int(num[message.chat.id])<1: bot.send_message(message.chat.id, " 1 12. ") # 2 return url_list[message.chat.id]=take_url(num[message.chat.id]) # URL- if url_list[message.chat.id]==[]: # bot.send_message(message.chat.id, " , . ") return bot.send_message(message.chat.id, "! .") dbworker.set_state(message.chat.id, config.States.S_ENTER_PRICE.value) #
En plus de la recherche standard, il est possible de sauvegarder des performances intéressantes.
3. Suivi des changements de prix
L'utilisateur peut ajouter des URL à la liste des centres d'intérêt pour recevoir une alerte lorsque le prix baisse. Nous nous souvenons que nous avions toujours un statut non répertorié dans la recherche de base - S_ENTER_URL. Dans
@bot.message_handler(commands=["addURL"]) def cmd_add_url(message): bot.send_message(message.chat.id, " url, . https://") dbworker.set_state(message.chat.id, config.States.S_ENTER_URL.value) # @bot.message_handler(func=lambda message: dbworker.get_current_state(message.chat.id) == config.States.S_ENTER_URL.value) def user_entering_URL(message): perf_url=message.text user_id=message.chat.id try: add_new_URL(user_id,perf_url) bot.send_message(message.chat.id, ' !') dbworker.set_state(message.chat.id, config.States.S_START.value) # except: bot.send_message(message.chat.id, 'URL ! !') dbworker.set_state(message.chat.id, config.States.S_ENTER_URL.value)
Pour stocker la liste, utilisez le fichier .csv. Pour interagir avec lui, vous avez besoin de quelques fonctions - écriture et lecture avec vérification des changements de prix. S'il change, prévenez l'utilisateur.
def add_new_URL(user_id,perf_url): WAITING_FILE = "waiting_list.csv" with open(WAITING_FILE, "a", newline="") as file: curent_url='https://'+perf_url text=get_text(curent_url)
Le code de fonction de mise à jour des prix est légèrement plus long def update_prices(bot): WAITING_FILE = "waiting_list.csv" with open(WAITING_FILE, "r", newline="") as file: reader = csv.reader(file) waitingList=[] for row in reader: waitingList.append(list(row)) L=len(waitingList) lowest={} with open(WAITING_FILE, "w", newline="") as fl: writer = csv.writer(fl) for i in range(L): lowest[waitingList[i][1]]=waitingList[i][2]
En conséquence, par la commande
/ checkURL, l' utilisateur peut obtenir un tel résultat (maintenant je comprends qu'il serait également nécessaire d'afficher le nom de la performance, mais ce sont des choses de la série «qui ne sont pas parvenues aux mains»).

D'accord, d'accord. Nous pouvons rechercher, nous pouvons suivre. Un couple d'amis a commencé à utiliser le bot, je voulais savoir qui ils étaient et ce qu'ils cherchaient. Ces informations sont bonnes à écrire dans les journaux.
4. Nous écrivons l'activité et les erreurs dans les journaux
Le module de journalisation nous y aidera. Les informations ne sont enregistrées qu'au stade de l'achèvement de la recherche de base, dans le gestionnaire, dans lequel le statut d'utilisateur passe de S_ENTER_PLACE à S_START. L'enregistrement d'erreur, à son tour, se produit lorsqu'ils se produisent.
Je ne peux pas en dire beaucoup sur le fonctionnement du module, il est donc préférable de se tourner vers les informations
extérieures .

Description de l'enregistreur def save_logs(str): loggerInfo.info(str)
En raison d'une connexion déconnectée, le bot se bloquait périodiquement, donc une erreur de connexion Internet a été détectée et le bot a redémarré automatiquement après 10 secondes. Mais il n’a pas toujours été sauvegardé, alors j’ai gardé TeamViewer en marche, afin de l’augmenter si nécessaire.
5. Non réalisé
Nous avons obtenu un bot qui remplace la fonctionnalité du script, mais vous permet de recevoir des informations sous une forme pratique à l'intérieur du messager. Il a fermé mes besoins de base.
Le démontage avec les modules et l'écriture de gestionnaires élancés a duré environ un mois dans le mode de travail le week-end et parfois le soir. À la fin de cette période, l'intérêt a commencé à s'estomper et la fonctionnalité a été bloquée au point de départ. Il n'a pas été possible de percer les principes de travail sur les webhook-ahs, puis Telegram a été bloqué. Avant cela, il y avait un plan pour tirer le back-end vers un serveur qui fonctionne, mais ... vpn ne sera pas mis là pour ça =)
Voici ce qui reste dans les plans, dont certains peuvent et seront réalisés une fois sur une soirée d'été / hiver langoureuse:
- test de charge avec un grand nombre d'utilisateurs. Il n'est pas encore clair si le bot fonctionnera de manière stable et ne confondra pas les utilisateurs;
- notification de l'apparition d'une nouvelle représentation dans le programme de l'artiste. J'ai beaucoup de "lapins blancs" préférés, je ne peux pas garder une trace de tout le monde (mais j'aimerais bien);
- Notification de l'apparition à la vente de billets d'une certaine catégorie. Il y avait une connaissance, un amateur de la première rangée de stalles, qui était difficile à attraper manuellement;
- vérification automatique régulière des URL d'intérêt pour une réduction de prix par minuterie. Maintenant, cela se fait sur commande, le minuteur n'a pas pu être réglé rapidement, il a donc été laissé de manière simple;
- préservation de son histoire de visites de spectacles. Quelque part dans le fichier .csv, date-nom-line-up-d'artistes-votre commentaire afin de ne pas perdre;
- rechercher une catégorie donnée de billets. Fixer non seulement le prix, mais aussi le secteur (rez-de-chaussée, etc.);
- tout transférer dans une compétence pour Alice. pourquoi pas
- créer une application mobile avec les mêmes fonctionnalités. pourquoi pas
Il y a eu un appel au Théâtre du Bolchoï. Pour attraper les billets pour Noureev, mais je ne pouvais pas ramasser les affiches html en deux soirées, donc il a également été rayé de la liste des affiches non réalisées.
TOTAL
La paresse était le moteur du progrès et cela l'a arrêté. Les choses ne sont pas venues à télécharger le bot sur un serveur tiers, mais cela nécessite néanmoins des compétences et des connaissances plus larges dans le domaine du Web. Le projet s'est avéré intéressant et a permis d'apprendre un peu mieux le Python, d'en voir une autre facette (en plus du Machine Learning habituel), et a également présenté de nombreuses soirées merveilleuses au théâtre à prix d'aubaine. Grâce à lui pour cela, il a clôturé les tâches avec fracas.
Peu importe comment j'ai essayé, l'article contenait toujours beaucoup de code et un peu de texte. Je serai heureux d'expliquer l'incompréhensible ou peu décrit dans les commentaires =)