async def removecog(self, ctx: commands.Context, *args: str): """Rimuove una o più cog dal bot e dal file extensions.json se presente così da non caricarla più a ogni futuro riavvio del bot. Occorre passare il nome esatto della cog da aggiungere, che deve trovarsi nella cartella cogs del bot. Sintassi: <removecog nome_cog # rimuove nome_cog dal bot e dal file extensions.json <removecog nome_cog altra_cog # più cogs separate da spazio """ if not args: await ctx.send('Devi specificare il nome della cog da rimuovere.', delete_after=5) await ctx.message.delete(delay=5) else: with open('extensions.json', 'r') as file: extensions = json.load(file) removed: str = '' for ext in args: ext = 'cogs.' + ext if ext in extensions: extensions.remove(ext) try: self.bot.unload_extension(ext) except commands.ExtensionError as e: await ctx.send('Impossibile rimuovere ' + ext) print(e) else: removed += '`' + ext + '` ' if removed != '': await self.logger.log('estensioni ' + removed + 'rimosse correttamente') await ctx.send('Estensioni ' + removed + 'rimosse correttamente.') shared_functions.update_json_file(extensions, 'extensions.json')
def adjust_vote_count(payload: discord.RawReactionActionEvent, change: int) -> None: """Aggiusta il contatore dei voti in base al parametro passato. Stabilisce in autonomia se il voto è a favore o contrario guardando il tipo di emoji cambiata. :param payload: l'evento di rimozione dell'emoji :param change: variazione del voto (+1 o -1) """ try: with open('proposals.json', 'r') as file: proposals: Dict[str, Dict[str, Any]] = json.load(file) except FileNotFoundError: print('errore nel file delle proposte') return try: proposal = proposals[str(payload.message_id)] except KeyError: print('impossibile trovare la proposta') return if str(payload.emoji.name).__eq__('\U0001F7E2'): # sarebbe :green_circle: proposal['yes'] += change if proposal['yes'] < 0: proposal['yes'] = 0 if proposal['yes'] >= proposal['threshold']: proposal['passed'] = True else: # è possibile cambiare idea, il controllo lo fa la task proposal['passed'] = False else: proposal['no'] += change if proposal['no'] < 0: proposal['no'] = 0 shared_functions.update_json_file(proposals, 'proposals.json')
def add_proposal(message: discord.Message, guild: discord.Guild) -> None: """Aggiunge la proposta al file proposals.json salvando timestamp e numero di membri attivi in quel momento. :param message: messaggio mandato nel canale proposte da aggiungere :param guild: il server discord """ proposals: Dict[str, Dict[str, Any]] = {} try: with open('proposals.json', 'r') as file: proposals = json.load(file) except FileNotFoundError: print('file non trovato, lo creo ora') with open('proposals.json', 'w+') as file: proposals = {} active_count = 2 # moderatori non hanno ruolo attivo members = guild.members active_role = guild.get_role(Config.get_config().active_role_id) for member in members: if not member.bot: if active_role in member.roles: active_count += 1 proposal = { 'timestamp': datetime.date(message.created_at).__str__(), 'total_voters': active_count, 'threshold': calculate_threshold(active_count), 'passed': False, 'yes': 0, 'no': 0, 'content': message.content } # save as string for coherency with the loading proposals[str(message.id)] = proposal shared_functions.update_json_file(proposals, 'proposals.json')
async def setprefix(self, ctx: commands.Context, prefix: str): """Imposta prefix come nuovo prefisso del bot. Viene memorizzato anche nella configurazione del bot e mantenuto in caso di riavvio. Sintassi: <setprefix ? # imposta '?' come nuovo prefisso """ self.bot.command_prefix = prefix await self.logger.log((f'prefisso cambiato in ``{prefix}``')) await ctx.send(f'Prefisso cambiato in ``{prefix}``') self.config.current_prefix = prefix with open('config.json', 'r') as file: data: Dict[str, Any] = json.load(file) data['current_prefix'] = prefix shared_functions.update_json_file(data, 'config.json')
async def blackremove(self, ctx: commands.Context, *, ban_word): """Elimina la parola passata dall'elenco delle parole bannate e aggiorna il file banned_words.json. Occorre rimuovere la parola scrivendola nello stesso modo con cui era stata inserita. Sintassi: <blackremove word # rimuove 'word' dall'elenco """ if ban_word in BannedWords.banned_words: BannedWords.remove(ban_word) shared_functions.update_json_file(BannedWords.banned_words, 'banned_words.json') await self.logger.log(f'rimossa parola bannata `{ban_word}`') await ctx.send('la parola è stata rimossa', delete_after=5) else: await ctx.send('la parola non è presente nell\'elenco', delete_after=5)
def remove_proposal(message: discord.Message) -> None: """Rimuove la proposta con id uguale al messaggio passato dal file. Se non trovata non fa nulla. :param message: messaggio della proposta """ try: with open('proposals.json', 'r') as file: proposals: Dict[str, Dict[str, Any]] = json.load(file) except FileNotFoundError: print('errore nel file delle proposte') return try: del proposals[str(message.id)] except KeyError: print('proposta non trovata') else: shared_functions.update_json_file(proposals, 'proposals.json')
async def blackadd(self, ctx: commands.Context, *, ban_word: str): """Aggiunge la stringa passata alla lista contenuta e aggiorna banned_words.json. Se si scrivono più parole queste vengono considerate come una unica entry. Per come sono controllate, non occorre mettere gli spazi tra le parole. Esempio: <blackadd seistupido # aggiunge seistupido all'elenco il controllo delle parole è poi in grado di capire quali messaggi la contengono es. 'sei stupido' 's3i stupid0' vengono tutte rilevate. Sintassi: <blackadd word # aggiunge 'word' all'elenco <blackadd aListOfWords # aggiunge 'aListOfWord' come unica entry """ if ban_word in BannedWords.banned_words: await ctx.send('la parola è già contenuta nell\'elenco') return BannedWords.add(ban_word) shared_functions.update_json_file(BannedWords.banned_words, 'banned_words.json') await self.logger.log(f'aggiunta parola bannata `{ban_word}`') await ctx.send('parola aggiunta correttamente', delete_after=5)
async def addcog(self, ctx: commands.Context, *args: str): """Aggiunge una o più cog al bot e al file extensions.json se non presente in modo da caricarla in automatico a ogni futuro riavvio. Occorre passare il nome esatto della cog da aggiungere, che deve trovarsi nella cartella cogs del bot. Sintassi: <addcog nome_cog # aggiunge nome_cog al bot e al file extensions.json <addcog nome_cog altra_cog # più cogs separate da spazio """ if not args: await ctx.send('Devi specificare il nome della cog da caricare.', delete_after=5) await ctx.message.delete(delay=5) else: with open('extensions.json', 'r') as file: extensions = json.load(file) added: str = '' for ext in args: ext = 'cogs.' + ext if ext not in extensions: try: self.bot.load_extension(ext) except commands.ExtensionError as e: await ctx.send('Impossibile caricare ' + ext) print(e) else: extensions.append(ext) added += '`' + ext + '` ' else: await ctx.send(ext + ' già presente.') if added != '': await self.logger.log('estensioni ' + added + 'aggiunte correttamente') await ctx.send('Estensioni ' + added + 'aggiunte correttamente.') shared_functions.update_json_file(extensions, 'extensions.json')
async def periodic_checks(self): """Task periodica per la gestione di: - rimozione delle proposte scadute - controllo sulle proposte passate con relativo avviso - consolidamento dei messaggi temporanei in counter se necessario - azzeramento dei messaggi conteggiati scaduti - assegnamento/rimozione ruolo attivo (i mod sono esclusi) - rimozione strike/violazioni Viene avviata tramite la on_ready quando il bot ha completato la fase di setup ed è programmata per essere eseguita ogni 24 ore da quel momento. """ await self.logger.log('controllo proposte...') try: with open('proposals.json', 'r') as file: proposals = json.load(file) except FileNotFoundError: await self.logger.log('nessun file di proposte trovato') else: to_delete = [] for key in proposals: proposal = proposals[key] if proposal['passed']: to_delete.append(key) channel = self.bot.get_channel(self.config.poll_channel_id) await self.logger.log('proposta passata: ' + proposal['content']) await channel.send( 'Raggiunta soglia per la proposta, in attesa di approvazione dai mod.\n' + '`' + proposal['content'] + '`') elif datetime.date(datetime.now() - timedelta( days=3)).__str__() == proposal['timestamp']: await self.logger.log('proposta scaduta: ' + proposal['content']) to_delete.append(key) for key in to_delete: try: message = await self.bot.get_channel( self.config.poll_channel_id).fetch_message(key) except discord.NotFound: # capita se viene cancellata dopo un riavvio o mentre è offline await self.logger.log('proposta già cancellata, ignoro') else: await message.delete() del proposals[key] shared_functions.update_json_file(proposals, 'proposals.json') await self.logger.log('controllo proposte terminato') await self.logger.log('controllo conteggio messaggi...') for id in self.archive.keys(): item = self.archive.get(id) item.clean() count = item.count_consolidated_messages() if count >= self.config.active_threshold and self.bot.get_guild( self.config.guild_id).get_member( id).top_role.id not in self.config.moderation_roles_id: item.set_active() guild = self.bot.get_guild(self.config.guild_id) await guild.get_member(id).add_roles( guild.get_role(self.config.active_role_id)) await self.logger.log('membro ' + item.nick + ' è attivo') channel = self.bot.get_channel(self.config.main_channel_id) await channel.send('membro <@!' + str(id) + '> è diventato attivo') # controllo sulla data dell'ultima violazione, ed eventuale reset item.reset_violations() # rimuovo i messaggi contati 7 giorni fa item.forget_last_week() if item.is_active_expired(): channel = self.bot.get_channel(self.config.main_channel_id) guild = self.bot.get_guild(self.config.guild_id) await guild.get_member(id).remove_roles( guild.get_role(self.config.active_role_id)) await self.logger.log('membro ' + item.nick + ' non più è attivo') await channel.send('membro <@!' + str(id) + '> non più attivo :(') item.set_inactive() await self.logger.log('controllo conteggio messaggi terminato') self.archive.save()