async def main_listening_loop(conn, analyser): await init(conn) now = dt.datetime.now(s.TIMEZONE) last_loop_execution = dt.datetime(1970, 1, 1, tzinfo=s.TIMEZONE) last_new_participants_check = now participants_info = await conn.check_for_new_participants_in_main_channel( first_time=True) # todo_f: first_time et known_participants sont redondants (y'a pas 1 sans l'autre, enfin presque...) while now < s.END_LISTENING_LOOP: last_loop_execution = await wait_for_next_iteration( last_loop_execution, s.NEW_LISTENING_LOOP_ITERATION_EVERY) try: now, last_new_participants_check, participants_info = await _loop_action( conn, analyser, now, last_new_participants_check, participants_info) except KeyboardInterrupt as e: raise e except: logging.exception( "[ERREUR AU SEIN DE LA BOUCLE] Erreur inconnue dans listening_loop" ) if now >= s.END_LISTENING_LOOP: logging.info( "Fin de la boucle LISTENING_LOOP car END_LISTENING_LOOP = %s" % s.END_LISTENING_LOOP)
async def main_suggestion_loop(conn): await init(conn) now = dt.datetime.now(s.TIMEZONE) last_loop_execution = dt.datetime(1970, 1, 1, tzinfo=s.TIMEZONE) last_new_participants_check = now # participants_info = await conn.check_for_new_participants_in_main_channel(first_time=True) while now < s.END_SUGGESTION_LOOP: last_loop_execution = await wait_for_next_iteration( last_loop_execution, s.NEW_SUGGESTION_LOOP_ITERATION_EVERY) try: # todo_es dans les 3 boucles, now n'est pas forcement modifié par _loop_action (en cas de levée d'erreur). # sortir donc le now de _llop_action now, last_new_participants_check = await _loop_action( conn, now, last_new_participants_check) except KeyboardInterrupt as e: raise e except Exception as e: logging.exception( "[ERREUR AU SEIN DE LA BOUCLE] Erreur inconnue dans suggestion_loop" ) if now >= s.END_SUGGESTION_LOOP: logging.info( "Fin de la boucle SUGGESTION_LOOP car END_SUGGESTION_LOOP = %s" % s.END_SUGGESTION_LOOP)
async def sandbox_loop(conn): await init(conn) now = dt.datetime.now(sb.TIMEZONE) last_loop_execution = dt.datetime(1970, 1, 1, tzinfo=sb.TIMEZONE) await sb.populate() # todo_es : populate ne doit s'exécuter que si la campagne est nouvelle (ou si effacement BDD) while now < END_SANDBOX_LOOP: last_loop_execution = await wait_for_next_iteration( last_loop_execution, NEW_SANDBOX_LOOP_ITERATION_EVERY) try: now = await _loop_action(conn) except KeyboardInterrupt as e: raise e except Exception: logging.exception( "[ERREUR AU SEIN DE LA BOUCLE] Erreur inconnue dans sandbox_loop" ) if now >= END_SANDBOX_LOOP: logging.info( "Fin de la boucle SANDBOX_LOOP car END_SANDBOX_LOOP = %s" % END_SANDBOX_LOOP)
async def _loop_action(conn, analyser, now, last_new_participants_check, participants_info): now = dt.datetime.now(s.TIMEZONE) logmsg = " LISTENING_LOOP - Nouvelle itération de la boucle." logging.info(logmsg) if now - last_new_participants_check >= dt.timedelta( 0, 0, 0, s.CHECK_NEW_PARTICIPANTS_EVERY): # todo_chk : la vérification des nouveaux participante.s doit elle bien ête dans cette boucle ? participants_info = await conn.check_for_new_participants_in_main_channel( known_participants_info=participants_info) last_new_participants_check = dt.datetime.now(s.TIMEZONE) for j, pi in enumerate(participants_info): participant = pi['participant'] channel = pi['1to1_channel'] if not conn.is_bot( participant ): # todo_es méthode à mettre plutot dans la classe participant msgs, updated_participant = await conn.check_for_new_messages( participant, channel) # todo_f : est ce qu'on enregistre tous les mesages dans la BDD? oui ce serait bien # todo_f : définir dans la conf un niveau d'enregsitrement (ts les messages ou juste ls infos # necessaires?) if await participant.is_scribe(): for m in msgs: updated_participant = await analyser.analyse_message_from_scribe( m, updated_participant, channel, participants_info) elif await conn.is_admin( participant ): # todo_es méthode à mettre plutot dans la classe participant for m in msgs: updated_participant = await analyser.analyse_message_from_admin( m, updated_participant, channel, participants_info) else: for m in msgs: updated_participant = \ await analyser.analyse_message_from_normal_participant(m, updated_participant, channel) participants_info[j]['participant'] = updated_participant return now, last_new_participants_check, participants_info
async def _loop_action(conn, now, last_new_participants_check): now = dt.datetime.now(s.TIMEZONE) logmsg = " SUGGESTION_LOOP - Nouvelle itération de la boucle." logging.info(logmsg) if s.USE_SANDBOX or await conn.right_time_for_suggestions(): # todo_f : faire en sorte que ce soit # dynmique le start et end (genre c'est le scribe qui envoie des signaux) participants_info = await conn.fetch_all_participants(consent=True) for j, pi in enumerate(participants_info): participant = pi['participant'] channel = pi['1to1_channel'] if not conn.is_bot( participant) and not await participant.is_scribe( ) and not await conn.is_admin(participant): now = dt.datetime.now(s.TIMEZONE) if (not s.USE_SANDBOX ) or participant.right_time_to_suggest_if_sandbox(now): delta = dt.timedelta( 0, 60 * participant.suggestions_frequency) if participant.last_suggestion_url_or_text is None or ( participant.last_suggestion_url_or_text + delta <= now): if random.choice([0, 1]): updated_participant, is_sent = await conn.send_a_tweet_url( participant, channel) if not is_sent: updated_participant, is_sent = await conn.send_suggestion( participant, channel) else: updated_participant, is_sent = await conn.send_suggestion( participant, channel) if not is_sent: updated_participant, is_sent = await conn.send_a_tweet_url( participant, channel) participants_info[j][ 'participant'] = updated_participant return now, last_new_participants_check
async def _loop_action(conn): now = dt.datetime.now(sb.TIMEZONE) logmsg = "SANDBOX_LOOP - Nouvelle itération de la boucle." logging.info(logmsg) participants_info = await conn.fetch_all_participants(consent=True) for j, pi in enumerate(participants_info): participant = sb.SandboxParticipant(pi['participant']) channel = pi['1to1_channel'] if not conn.is_bot(participant) and not await participant.is_scribe( ) and not await conn.is_admin(participant): planned_msgs = await participant.check_for_planned_message( now, PLANNED_MESSAGES) for m in planned_msgs: await conn.send(participant, channel, m['message']) await participant.record_planned_message(m) return now
async def _user_authentification(self): # Si l'utilisateur n'est pas authentifié, ... if not await self.tg_client.is_user_authorized(): # ... on lui envoie le code de validation sur son Télégram. try: logging.test(20069) await self.tg_client.send_code_request(ts.BOT_PHONE_NUMBER) except FloodWaitError as e: logging.test(20070) # Cas où le code a été saisi trop de fois de manière erronée self._manage_flood_wait_error(e) # L'utilisateur doit ensuite saisir son code ici : code_is_valide = False while not code_is_valide: logging.test(20071) code = input(s.STR_TG_ENTER_CODE.format(ts.BOT_PHONE_NUMBER)) try: logging.test(20072) await self.tg_client.sign_in(ts.BOT_PHONE_NUMBER, code) except PhoneCodeInvalidError: logging.test(20073) # Si le code est incorrect code_is_valide = False logging.info( s.STR_TG_INVALID_CODE.format(ts.BOT_PHONE_NUMBER)) except FloodWaitError as e: logging.test(20074) # Cas où le code a été saisi trop de fois de manière erronée self._manage_flood_wait_error(e) else: logging.test(20075) # Si le code est bon code_is_valide = True logging.info(s.STR_TG_AUTH_OK) else: ### logging.test(20076)
import datetime as dt import random import re import urllib from contextlib import AbstractContextManager from asgiref.sync import sync_to_async from settings import settings as s from daemon_loops.models import PostedTweet, SentTweetUrl, SentTextSuggestion import daemon_loops.modules.logging as logging from daemon_loops.modules.message_generator import MessageGenerator from daemon_loops.modules.twitterstorm_utils import get_time_before_suggesting logging.info(s.INIT_MSG_TO_LOG) @sync_to_async def quickfix3(**kwargs): SentTweetUrl( # todo_es : a déplacer dans la classe BDD **kwargs ).save() @sync_to_async def quixkfix(**kwargs): SentTextSuggestion(**kwargs).save() @sync_to_async def quifix(**kwargs): return [a for a in SentTweetUrl.objects.filter(**kwargs)]