async def load(ctx, extension): """Charge un Cog Extensions accessibles : - 'twitter' - 'moderation' - 'file' """ try: client.load_extension(extension.lower()) try: exts = tool.get_data('src/config/extension.json') if 'LIST' in exts: exts['LIST'] += [extension.lower()] else: exts['LIST'] = [extension.lower()] tool.set_data(exts, 'src/config/extension.json') await log('Cog: [{}] successfully loaded.'.format(extension.lower()), MONITOR_MAIN) except Exception as error: await log('Erreur: extension.json impossible à charger.', MONITOR_MAIN) except Exception as error: await log('{} cannot be loaded. [{}]'.format(extension.lower(), error), MONITOR_MAIN)
async def untrack(self, ctx, *compte_twitter): """Retire le compte de la liste des comptes traqués """ await log('COMMAND - UNTRACK', mnt) if not compte_twitter: return temp_data = tool.get_data('src/config/twitter/temp_data.json', default=[]) # UNTRACK ALL if compte_twitter[0] in ['all', '*']: temp_data.append({'type': 'untrack', 'account': 'all'}) tool.set_data(temp_data, 'src/config/twitter/temp_data.json') return # UNTRACK SPECIFIC ACCOUNTS for account in compte_twitter: account = account.lower() temp_data.append({'type': 'untrack', 'account': account}) temp_data.append({ 'type': 'remove', 'channel': 'tracking', 'account': account }) tool.set_data(temp_data, 'src/config/twitter/temp_data.json')
async def remove_twitter(self, ctx, *compte_twitter): """Retire le compte de la liste des comptes suivis dans ce salon """ await log('COMMAND - REMOVE', mnt) if not compte_twitter: return temp_data = tool.get_data('src/config/twitter/temp_data.json', default=[]) # UNFOLLOW ALL if compte_twitter[0] in ['all', '*']: temp_data.append({ 'type': 'remove', 'channel': ctx.channel.id, 'account': 'all' }) tool.set_data(temp_data, 'src/config/twitter/temp_data.json') return # UNFOLLOW SPECIFIC ACCOUNTS for account in compte_twitter: account = account.lower() temp_data.append({ 'type': 'remove', 'channel': ctx.channel.id, 'account': account }) tool.set_data(temp_data, 'src/config/twitter/temp_data.json')
async def unload(ctx, extension): """Enlève un Cog Extensions accessibles : - 'twitter' - 'moderation' - 'file' """ try: client.unload_extension(extension.lower()) try: exts = tool.get_data('src/config/extension.json') try: exts['LIST'].remove(extension.lower()) tool.set_data(exts, 'src/config/extension.json') await log('Cog: [{}] successfully unloaded.'.format(extension.lower()), MONITOR_MAIN) except Exception as error: await log('Cog: {} was not found in extension.json'.format(extension.lower()), MONITOR_MAIN) except Exception as error: await log('Erreur: extension.json impossible à charger.', MONITOR_MAIN) except Exception as error: await log('{} cannot be unloaded. [{}]'.format(extension.lower(), error), MONITOR_MAIN)
async def clear(self, ctx, numero_log: int): """ Supprime le log """ # Clear log logs = tool.get_data('src/config/moderation/data.json') try: logs.pop(str(numero_log)) await ctx.channel.send( ':outbox_tray: Log n°{} supprimé avec succès'.format( numero_log)) tool.set_data(logs, 'src/config/moderation/data.json') except: await ctx.channel.send( ':x: Log n°{} introuvable.'.format(numero_log))
def save(self, src): data = tool.get_data(src) data[self.num] = { "lib": self.lib, "user": self.user, "author": self.author, "time": self.time, "reason": self.reason, "message": self.message, "log_id": self.log_id, "log_channel": self.log_channel, "log_content": self.log_content } tool.set_data(data, src)
async def follow(self, ctx, *compte_twitter): """Ajoute le compte à la liste des comptes suivis dans ce salon EXEMPLE ------- > ?follow Action_Insoumis : ajoute [Action_Insoumis] à la liste des comptes suivis sur ce salon > ?follow : afficher la liste des comptes suivis sur ce salon """ await log('COMMAND - ADD', mnt) # Liste des comptes suivis sur ce salon : if not compte_twitter: data = tool.get_data('src/config/twitter/data.json') accounts = [] for element in data: if ctx.channel.id in data[element]['channel']: accounts.append(element) if not accounts: return await ctx.channel.send( "Aucun compte twitter n'est suivi ici :shrug:") else: EMB = tool.set_embed( color=0x22aaaa, author='Comptes twitters suivis', author_icon= 'https://pbs.twimg.com/profile_images/1013798240683266048/zRim1x6M_400x400.jpg', description= 'La liste ci-dessous est suivie sur ce salon, par ordre chronologique.\n?follow <nom_du_compte> : ajouter un compte\n?unfollow <nom_du_compte> : retirer un compte' ) list_accounts = [ '\n'.join(accounts[n:n + 10]) for n in range(0, len(accounts), 10) ] message, result = await tool.enhance_embed( ctx, EMB, name='COMPTES', values=list_accounts) # Ajout des comptes à follow else: temp_data = tool.get_data('src/config/twitter/temp_data.json', default=[]) for compte in compte_twitter: compte = compte.lower() temp_data.append({ 'type': 'add', 'channel': ctx.channel.id, 'account': compte }) tool.set_data(temp_data, 'src/config/twitter/temp_data.json')
async def pin(self, ctx): """ Initialize le message pin """ if self.pinnedMessage is not None: return content = ":microphone2: **SPACE TWITTER EN COURS**\n```python\n\"N'hésitez pas à partager le lien d'un Space Twitter dans ce salon !\"```\n:white_small_square: Actuellement **0** Space en cours" configPath = "src/space/config.json" msg = await ctx.channel.send(content) await msg.pin() self.pinnedMessage = msg.id config = tool.get_data(configPath) config["PINNED"] = msg.id tool.set_data(config, configPath)
async def claim(self, ctx, *text): """ Messages automatiques du bot EXEMPLE ------- > ?claim <delay> <text> : génère un message automatique tous les <delay> minutes dans le salon courant. > ?claim : affiche la liste des messages autos du salon courant > ?claim .clear : supprime tous les messages autos du salon courant. """ claim_data = tool.get_data('src/config/staff/claim.json') # Liste des annonces du salon courant if not text: await log('?claim list : [#{}], {}'.format(ctx.channel.name, str(ctx.author)), MNT) try: claim_list = claim_data[str(ctx.channel.id)] EMB = tool.set_embed(color=0xaa6622, author='Messages automatiques sur : #{}'.format(ctx.channel.name)) claim_text = [claim_list[n]['text'] + '\n\n :alarm_clock: - {}mn'.format(claim_list[n]['delay']) for n in range(0, len(claim_list))] message, result = await tool.enhance_embed(ctx, EMB, name='Texte [délai]', values=claim_text) except Exception as e: # Pas de claim dans ce salon await ctx.channel.send('Aucun message automatique trouvé :shrug:') # Ajout d'un claim dans le salon courant else: text = list(text) if text[0] == '.clear': await log('?claim clear : [#{}], {}'.format(ctx.channel.name, str(ctx.author)), MNT) claim_data.pop(str(ctx.channel.id), None) await ctx.channel.send('Messages automatiques effacés :put_litter_in_its_place:') tool.set_data(claim_data, 'src/config/staff/claim.json') return await log('?claim ajout : [#{}], {}'.format(ctx.channel.name, str(ctx.author)), MNT) claim = {'text': ' '.join(text[1::]), 'delay': int(text[0]), 'next': int(text[0])} try: channel_list = claim_data[str(ctx.channel.id)] channel_list.append(claim) except: channel_list = [claim] claim_data[str(ctx.channel.id)] = channel_list await ctx.channel.send('Message automatique enregistré :memo:') tool.set_data(claim_data, 'src/config/staff/claim.json')
async def track(self, ctx, *compte_twitter): """Collecte des données sur le compte (chaque tweet + tags publiés) """ await log('COMMAND - TRACK', mnt) #Liste des comptes écoutés : if not compte_twitter: data = tool.get_data('src/config/twitter/tweet.json') accounts = [] for element in data: accounts.append(element) if not accounts: return await ctx.channel.send( "Aucun compte twitter n'est traqué.") EMB = tool.set_embed( color=0x006a6a, author='Comptes twitters traqués', author_icon= 'https://pbs.twimg.com/profile_images/1013798240683266048/zRim1x6M_400x400.jpg', description= 'Les tweets des comptes ci-dessous sont sauvegardés et les tags de leurs publications surveillés, par ordre chronologique.\n?track <compte_twitter> : ajouter un compte\n?untrack <compte_twitter> : retirer un compte' ) list_accounts = [ '\n'.join(accounts[n:n + 10]) for n in range(0, len(accounts), 10) ] message, result = await tool.enhance_embed(ctx, EMB, name='COMPTES', values=list_accounts) return # Ajout de comptes à écouter else: temp_data = tool.get_data('src/config/twitter/temp_data.json', default=[]) for compte in compte_twitter: compte = compte.lower() temp_data.append({'type': 'track', 'account': compte}) temp_data.append({ 'type': 'add', 'channel': 'tracking', 'account': compte }) tool.set_data(temp_data, 'src/config/twitter/temp_data.json') return
async def on_member_join(self, member): """ Check if Member has been invited with a link redirecting on the specific space channel get current invites, store on member join: get and store new invites check invites to see if one has incremented if one has, that's your invite, return else: if an invite is missing, it might be it was a limited use one or expired- add it to a list of things to return check vanity invite to see if it incremented if it did, return that poll audit log to see if any invites were created recently if one was, add that to things to return, return else :mystery: """ channel = self.client.get_channel(self.spaceChannel) listInvites = await channel.invites() # Try except to ensure it works try: # Check for every invite url directing towards this channel for invite in listInvites: await log("Invitation sur le channel #{} : [{}] ({})".format(channel.name, invite.id, invite.uses), MONITOR) if invite.id in self.invite: # Check if number of uses changed if self.invite[invite.id] == invite.uses: continue # Log and update uses await log("{} used a link towards Space Twitter channel".format(member.name), MONITOR) # Update invite id / uses and save it self.invite[invite.id] = invite.uses config = tool.get_data(self.config) config["INVITE_ID"] = self.invite tool.set_data(config, self.config) except: pass
async def update_claim(self): await self.client.wait_until_ready() await asyncio.sleep(1) while True: # Get all claims claim_data = tool.get_data('src/config/staff/claim.json') for channel_ID in claim_data: # Get claims of each Textchannel update = [] for claim in claim_data[channel_ID]: claim['next'] -= 1 # Trigger claims that must be fired if claim['next'] <= 0: claim['next'] = claim['delay'] try: await self.client.get_channel(int(channel_ID)).send(claim['text']) except: await log('ALERTE : accès restreint au salon ID: {}'.format(int(channel_ID)), MNT) update.append(claim) claim_data[channel_ID] = update # Task executes every minute tool.set_data(claim_data, 'src/config/staff/claim.json') await asyncio.sleep(60)
async def checking_tags(self): await self.client.wait_until_ready() await asyncio.sleep(1) await log('TAGS TASK - INIT', mnt, time=True) # PARAMETERS FOR THE WHOLE TASK # Login await log('TAGS TASK - LOGIN API', mnt, time=True) api = await twool.login() while True: await asyncio.sleep(0) # Sleeping time sleep_time = tool.get_data( 'src/config/twitter/auth.json')['TAG_SLEEP_TIME'] max_time = tool.get_data( 'src/config/twitter/auth.json')['TAG_MAX_TIME'] # Blocking while self.task1_lock: await asyncio.sleep(10) sleep_time -= 10 self.task2_lock = True await log('TAGS TASK - RUNNING', mnt) # Tags list data = tool.get_data('src/config/twitter/temp_tags.json') for account in data: await asyncio.sleep(0) print(account) # SEARCHING TARGET target = await twool.get_target(api, account) if not target: await log('TAGS TASK - {} unreachable'.format(account), mnt) continue since_id = data[account]['since_id'] # GET RETWEETS & QUOTES while True: await asyncio.sleep(0) try: retweets, until_id = await twool.get_retweets( api, target, since_id=since_id, list_id=[ tweet for tweet in data[account]["tweets"] ]) data[account]['since_id'] = until_id break except Exception as e: await log( 'TAGS TASK - Exception thrown in RT, QT: sleep [60]s\n{}' .format(e), mnt, time=True) await asyncio.sleep(60) sleep_time -= 60 # GET FAVS favs = [] # while True: # await asyncio.sleep(0) # try: # favs = await twool.get_fav(api, target, [tweet for tweet in data[account]["tweets"]]) # break # except Exception as e: # await log('TAGS TASK - Exception thrown in FAV: SLEEP [60]s\n{}'.format(e), mnt, time=True) # traceback.print_exc() # await asyncio.sleep(60) # sleep_time -= 60 # PROCESS TWEETS for retweet in retweets: await asyncio.sleep(0) await log('{} a RT|QUOTE n°{}'.format(account, retweet), mnt) temp_data = tool.get_data( 'src/config/twitter/temp_data.json', default=[]) temp_data.append({ 'type': 'retweet', 'account': account, 'id': retweet }) tool.set_data(temp_data, 'src/config/twitter/temp_data.json') for fav in favs: await asyncio.sleep(0) await log('{} a FAV n°{}'.format(account, fav), mnt) temp_data = tool.get_data( 'src/config/twitter/temp_data.json', default=[]) temp_data.append({ 'type': 'fav', 'account': account, 'id': fav }) tool.set_data(temp_data, 'src/config/twitter/temp_data.json') for element in list(set(retweets + favs)): await asyncio.sleep(0) print(data[account]) print(data[account]["tweets"]) data[account]["tweets"].pop(element) list_to_del = [] for element in data[account]["tweets"]: await asyncio.sleep(0) if datetime.utcnow() - tool.str_to_date( data[account]["tweets"][element]) >= timedelta( 0, max_time): list_to_del.append(element) for element in list_to_del: await asyncio.sleep(0) try: data[account]["tweets"].pop(element) except Exception as e: await log( 'TAGS TASK - Exception thrown l.132 : {}'.format( e), mnt) list_to_del = [] for account in data: await asyncio.sleep(0) if not data[account]["tweets"]: list_to_del.append(account) for element in list_to_del: data.pop(element) # SAVE DATA await asyncio.sleep(0) if not data: os.remove('src/config/twitter/temp_tags.json') else: tool.set_data(data, 'src/config/twitter/temp_tags.json') # SLEEPING await asyncio.sleep(0) if sleep_time <= 0: sleep_time = 0 await log('TAGS TASK - sleeping [{}s]'.format(sleep_time), mnt, time=True) self.task2_lock = False await asyncio.sleep(sleep_time) await log('TAGS TASK - sleeping over', mnt, time=True)
async def getting_tweets(self): await self.client.wait_until_ready() await asyncio.sleep(1) await log('TWEETS TASK - INIT', mnt, time=True) # PARAMETERS FOR THE WHOLE TASK # Login await log('TWEETS TASK - LOGIN API', mnt, time=True) api = await twool.login() self.task1_lock = True while True: await asyncio.sleep(0) # Sleeping time sleep_time = tool.get_data( 'src/config/twitter/auth.json')['TWEET_SLEEP_TIME'] # Blocking while self.task2_lock: await asyncio.sleep(10) sleep_time -= 10 self.task1_lock = True await log('TWEETS TASK - running', mnt, time=True) # Merging data data = tool.get_data('src/config/twitter/data.json') data_track = tool.get_data('src/config/twitter/tweet.json') try: temp_data = tool.get_data('src/config/twitter/temp_data.json', default=[]) for element in temp_data: await asyncio.sleep(0) # ADD if element['type'] == 'add': print('add {} - {}'.format(element['account'], element['channel'])) if element['account'] not in data: print('create') data[element['account']] = { 'channel': [element['channel']], 'since_id': None, 'created_since': str(datetime.utcnow()) } else: print('append') data[element['account']]['channel'] = list( set(data[element['account']]['channel'] + [element['channel']])) # REMOVE elif element['type'] == 'remove': print('remove {} - {}'.format(element['account'], element['channel'])) if element['account'] in data: print('specific') try: data[element['account']]['channel'].remove( element['channel']) if not data[element['account']]['channel']: print('no channel anymore') data.pop(element['account']) except Exception as e: print('channel not found for this account') pass elif element['account'] == 'all': print('all') list_to_del = [] for account in data: try: data[account]['channel'].remove( element['channel']) print('{} suppr'.format(account)) if not data[account]['channel']: print('no channel anymore') list_to_del.append(account) except: continue for account in list_to_del: data.pop(account) # TRACK elif element['type'] == 'track': print('track {}'.format(element['account'])) if element['account'] not in data_track: print('track ajouté') data_track[element['account']] = {} # UNTRACK elif element['type'] == 'untrack': print('untrack {}'.format(element['account'])) if element['account'] in data_track: print('untracké') data_track.pop(element['account']) # RETWEET elif element['type'] == 'retweet': tweet_id = element['id'] retweeter = element['account'] for account in data_track: try: if 'tag_RT' in data_track[account][tweet_id]: data_track[account][tweet_id][ 'tag_RT'].append(retweeter) else: data_track[account][tweet_id]['tag_RT'] = [ retweeter ] break except Exception as e: continue # FAV elif element['type'] == 'fav': tweet_id = element['id'] favish = element['account'] for account in data_track: try: if 'tag_FAV' in data_track[account][tweet_id]: data_track[account][tweet_id][ 'tag_FAV'].append(favish) else: data_track[account][tweet_id][ 'tag_FAV'] = [favish] break except Exception as e: continue except Exception as e: print('no temp file'.format(e)) traceback.print_exc() pass # List of accounts for the current iteration accounts = [element for element in data] for account in accounts: await asyncio.sleep(0) # SEARCHING TARGET target = await twool.get_target(api, account) if not target: await log( 'TWEETS TASK - {} unreachable, check channels: {}'. format(account, [ '{} '.format(element) for element in data[account]['channel'] ]), mnt) continue since_id = data[account]['since_id'] if not since_id: created_since = tool.str_to_date( data[account]['created_since']) else: created_since = datetime.utcnow() # GET TWEETS while True: await asyncio.sleep(0) try: tweets, until_id = await twool.get_tweet( api, target, since_id=since_id, created_since=created_since) if tweets: await log( 'TWEETS TASK - {} : {} tweets found'.format( account, len(tweets)), mnt) data[account]['since_id'] = until_id break except Exception as e: await log( 'TWEETS TASK - Exception thrown ({}) : [60]s'. format(e), mnt, time=True) await asyncio.sleep(60) sleep_time -= 60 # PROCESS TWEETS for tweet in tweets: await asyncio.sleep(0) # SET EMBED try: img = tweet.entities['media'][0]['media_url'] except: img = None EMB = tool.set_embed( color=0xffffff, title='https://twitter.com/{}/status/{}'.format( tweet.user.screen_name, tweet.id_str), title_url='https://twitter.com/{}/status/{}'.format( tweet.user.screen_name, tweet.id_str), author='@{}'.format(tweet.user.screen_name), author_url='https://twitter.com/{}'.format( tweet.user.screen_name), author_icon=tweet.user.profile_image_url, timestamp=tweet.created_at, image=img, fields=[ tool.set_field(name='Nouveau tweet : ', value=tweet.full_text, inline=True) ]) # TRACK TAGS IF NECESSARY if account in data_track: await asyncio.sleep(0) # APPEND DATA data_track[account][tweet.id_str] = { 'date': str(tweet.created_at), 'link': 'https://twitter.com/{}/status/{}'.format( tweet.user.screen_name, tweet.id_str), 'text': tweet.full_text } try: tags = await twool.get_tags(tweet) data_track[account][tweet.id_str]['tags'] = tags except Exception as e: await log( 'TWEETS TASK - Exception thrown l. 299-300 ({})' .format(e), mnt, time=True) pass temp_tags = tool.get_data( 'src/config/twitter/temp_tags.json') if not temp_tags: os.remove('src/config/twitter/temp_tags.json') for tag in tags: await asyncio.sleep(0) if tag not in temp_tags: temp_tags[tag] = { "since_id": tweet.id, "tweets": { tweet.id_str: str(datetime.utcnow()) } } else: temp_tags[tag]["tweets"][tweet.id_str] = str( datetime.utcnow()) tool.set_data(temp_tags, 'src/config/twitter/temp_tags.json') # STORE DATA tool.set_data(data_track, 'src/config/twitter/tweet.json') # POST TO TEXTCHANNEL(S) textchannels = [ self.client.get_channel(element) for element in data[account]['channel'] ] for textchannel in textchannels: await asyncio.sleep(0) if not textchannel: # await log('channel not found for {}'.format(account), mnt, time=True) continue try: await textchannel.send(content=None, embed=EMB) except: await log( 'Cannot reach textchannel {}'.format( textchannel.name), mnt) # Save data await asyncio.sleep(0) tool.set_data(data, 'src/config/twitter/data.json') tool.set_data(data_track, 'src/config/twitter/tweet.json') os.remove('src/config/twitter/temp_data.json') # Sleep & unlock self.task_lock await asyncio.sleep(0) if sleep_time <= 10: sleep_time = tool.get_data( 'src/config/twitter/auth.json')['TWEET_MIN_SLEEP_TIME'] await log('TWEETS TASK - sleeping [{}s]'.format(sleep_time), mnt, time=True) self.task1_lock = False await asyncio.sleep(sleep_time) await log('TWEETS TASK - sleeping over', mnt, time=True)
async def update(self): """ TO DO : - classer les Space par popularité ? - Virer l'épingle """ await self.client.wait_until_ready() await asyncio.sleep(1) async with async_playwright() as p: browser = await p.chromium.launch() page = await browser.new_page() page.on("response", self.scraper) while True: # Get all Space url self.dataUrl = tool.get_data(self.src) totalSpace = self.dataUrl + self.newUrl self.newUrl = [] for space in (totalSpace): if (datetime.utcnow() - tool.str_to_date(space["timestamp"])).seconds < self.timedelta: continue try: await page.goto(space["url"]) except Exception as e: print(e) pass self.hasFound = False for i in range(5000): await page.wait_for_timeout(5) if self.hasFound: break # Wait to ensure every response has been catched await asyncio.sleep(10) self.catch.pop('', None) if self.catch: channel = self.client.get_channel(self.spaceChannel) for url in self.catch: matchingSpace = [space for space in self.dataUrl if space["url"] == url] if matchingSpace: self.dataUrl = [item for item in self.dataUrl if item not in matchingSpace] space = self.catch[url] # Space ending if space["state"] == "Ended" or space["state"] == "TimedOut": await channel.send(self.endMessage.format(space["title"], space["total_nb"])) else: self.dataUrl.append({"state": space["state"], "url": url, "title": space["title"], "nb": space["nb"], "timestamp": str(datetime.utcnow())}) # Suppression du message précédent self.catch = {} if self.msgID: try: message = await channel.fetch_message(self.msgID) await message.delete() except Exception as e: print(e) # Nouveau message pour les Space en cours if self.dataUrl: msgContent = "" nbRunning = 0 for space in self.dataUrl: if space["state"] == "Running": nbRunning += 1 msgContent += "{}".format(self.message.format(space["title"], space["nb"], space["url"])) if nbRunning: msg = await channel.send(":microphone2: **SPACE TWITTER EN COURS**\n```python\n\"N'hésitez pas à partager le lien d'un Space Twitter dans ce salon !\"```:o: **DIRECT** - **{}** Space en cours :{}".format(nbRunning, msgContent)) await msg.pin() self.msgID = msg.id config = tool.get_data(self.config) config["MSG"] = self.msgID tool.set_data(config, self.config) tool.set_data(self.dataUrl, self.src) await page.wait_for_timeout(5000) await asyncio.sleep(10)