async def on_member_update(self, before: discord.Member, after: discord.Member): """Impedisce ai membri del server di modificare il proprio username includendo parole offensive. Quando un membro riceve il ruolo AFL si occupa di creare la entry nel file di archivio salvando il nickname e la data. Quest'ultima serve per gestire il cambio di nickname periodico concesso agli AFL. """ guild = self.bot.get_guild(self.config.guild_id) afl_role = guild.get_role(self.config.afl_role_id) if afl_role not in before.roles: if afl_role in after.roles: # appena diventato AFL, crea entry e salva nickname await self.logger.log('nuova entry nell\'archivio: ' + after.display_name) afler = Afler.new_entry(after.display_name) self.archive.add(after.id, afler) self.archive.save() else: # non è ancora AFL, libero di cambiare nick a patto che non contenga parole vietate if BannedWords.contains_banned_words(after.display_name): await self.logger.log( 'nickname' + after.display_name + 'contiene parole vietate, ripristino a ' + before.display_name) await after.edit(nick=before.display_name) else: # era già AFL, ripristino il nickname dal file if before.display_name != after.display_name: try: old_nick = self.archive.get(after.id).nick except KeyError: old_nick = before.display_name await self.logger.log('ripristino nickname a ' + old_nick) await after.edit(nick=old_nick)
async def on_message_edit(self, before: discord.Message, after: discord.Message): """Controlla che i messaggi non vengano editati per inserire parole della lista banned_words. Se viene trovata una parola bannata dopo l'edit il messaggio viene cancellato. """ if BannedWords.contains_banned_words(after.content): await after.delete()
async def blacklist(self, ctx: commands.Context): """Stampa l'elenco delle parole attualmente bannate. Sintassi: <blacklist # stampa la lista alias: black, bl """ await ctx.send(BannedWords.to_string())
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)
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 on_member_join(self, member: discord.Member): """Invia il messaggio di benvenuto all'utente entrato nel server e controlla che l'username sia adeguato. Se l'username contiene parole offensive l'utente viene kickato dal server con un messaggio che lo invita a modificare il proprio nome prima di unirsi nuovamente. """ if member.bot: return await self.logger.log('nuovo membro ' + member.display_name) channel = await member.create_dm() await channel.send(self.config.greetings) if BannedWords.contains_banned_words(member.display_name): await self.logger.log('nuovo membro ' + member.display_name + 'kickato per username improprio') await member.kick(reason="ForbiddenUsername") await channel.send( 'Il tuo username non è consentito, ritenta l\'accesso dopo averlo modificato' )
async def on_message(self, message: discord.Message): """Elimina i messaggi inappropriati dai canali e aggiunge un warn all'utente. Ignora i messaggi da: - il bot stesso - altri bot - canali di chat privata - canali ignorati (vedi config.template) """ if message.author == self.bot.user or message.author.bot or message.guild is None: return if BannedWords.contains_banned_words( message.content ) and message.channel.id not in self.config.exceptional_channels_id: await message.delete() await self.logger.log('aggiunto warn a ' + message.author.display_name + ' per linguaggio inappropriato: `' + message.content + '`') await self._add_warn(message.author, 'linguaggio inappropriato', 1)
async def setbio(self, ctx: commands.Context, *, bio: str): """Permette di impostare una biografia visibile agli altri membri. Non sono ovviamente ammesse parole vietate e gli admin si riservano il diritto di editare quelle ritenute offensive. Sintassi: <setbio mia bio # imposta *mia bio* come bio """ if len(bio) > self.config.bio_length_limit: await ctx.send('Bio troppo lunga, il limite è ' + str(self.config.bio_length_limit) + ' caratteri.') return if BannedWords.contains_banned_words(bio): return try: item: Afler = self.archive.get(ctx.author.id) except KeyError: await ctx.send('Non tovato nel file :(', delete_after=5) return item.bio = bio self.archive.save() await self.logger.log('aggiunta bio di ' + ctx.author.display_name) await ctx.send('Bio aggiunta correttamente.')
async def setnick(self, ctx: commands.Context, *, new_nick: str): """Permette di cambiare il proprio nickname periodicamente. La frequenza con cui è possibile farlo è definita nel config. Impedisce che due membri abbiano lo lo stesso nickname. Sintassi: <setnick afler # cambia il nickname in afler <setnick due aflers # può contenere anche più parole """ try: item: Afler = self.archive.get(ctx.author.id) except KeyError: await ctx.send('Non tovato nel file :(', delete_after=5) return last_change = item.last_nick_change() difference = datetime.date(datetime.now()) - last_change if difference.days < self.config.nick_change_days: renewal = last_change + \ timedelta(days=self.config.nick_change_days) days_until_renewal = renewal - datetime.date(datetime.now()) await ctx.send('Prossimo cambio tra ' + str(days_until_renewal.days) + ' giorni') elif BannedWords.contains_banned_words(new_nick): await ctx.send('Il nickname non può contenere parole offensive') elif len(new_nick) > 32: await ctx.send( 'La lunghezza massima del nickname è di 32 caratteri') else: for member in self.archive.values(): if member.nick == new_nick: await ctx.send('Questo nickname è già in uso') return item.nick = new_nick self.archive.save() await ctx.author.edit(nick=new_nick) await ctx.send('Nickname cambiato in ' + new_nick)
from utils import shared_functions from utils.shared_functions import Archive, BannedWords, BotLogger, Config # logging di base sul terminale logging.basicConfig(level=logging.INFO) # carico il token dal .env load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN') # carica la configurazione, ricorda di modificare config.json seguendo indicazioni del template if not Config.get_config().load(): print('controlla di avere creato correttamente config.json') exit() # carica le parole bannate BannedWords.load() # carica l'archivio dati Archive.load_archive() # per poter ricevere le notifiche sull'unione di nuovi membri e i ban intents = discord.Intents.default() intents.members = True intents.bans = True # istanziare il bot (avvio in fondo al codice) bot = commands.Bot( command_prefix=Config.get_config().current_prefix, intents=intents) # setup del logging nel canale dedicato logger = BotLogger.create_instance(bot)
async def on_message(self, message: discord.Message): """Azioni da eseguire ad ogni messaggio. Ignora i messaggi provenienti da: - il bot stesso - altri bot - canali di chat privata Il messaggio 'ping' ritorna l'intervallo di tempo tra un HEARTBEAT e il suo ack in ms.' Se il messaggio è nel canale di presentazione, ammette il membro automaticamente assegnandogli il ruolo AFL. Invoca la funzione update_counter per aggiornare il conteggio. """ if message.author == self.bot.user or message.author.bot or message.guild is None: return if message.content.lower() == 'ping': response = 'pong in ' f'{round(self.bot.latency * 1000)} ms' await message.channel.send(response) return if re.match('^(420|69|\s)+$', message.content.lower()): response = 'nice' await message.channel.send(response) return if BannedWords.contains_banned_words( message.content ) and message.channel.id not in self.config.exceptional_channels_id: # cancellazione e warn fatto nella cog ModerationCog, qua serve solo per non contare il messaggio return if message.channel.id == self.config.presentation_channel_id: # non deve rispondere a eventuali messaggi di moderatori nel canale, solo a nuovi membri for role in message.author.roles: if role.id in self.config.moderation_roles_id: return # il controllo della validità è ancora manuale await message.author.add_roles( self.bot.get_guild(self.config.guild_id).get_role( self.config.afl_role_id)) await message.channel.send('Formidabile') channel = self.bot.get_channel(self.config.welcome_channel_id) welcomeMessage = discord.Embed( title=f'Diamo il benvenuto a {message.author.display_name}!', colour=discord.Colour.dark_theme().value) welcomeMessage.set_thumbnail(url=message.author.avatar_url) welcomeMessage.add_field(name='Presentazione:', value=message.content, inline=False) await channel.send(embed=welcomeMessage) return link = shared_functions.link_to_clean(message.content) if link is not None: await message.delete() await message.channel.send('Link da ' + message.author.display_name + ':\n' + link) return if message.channel.id == self.config.poll_channel_id: guild = self.bot.get_guild(self.config.guild_id) await self.logger.log('membro ' + message.author.display_name + ' ha aggiunto una proposta') add_proposal(message, guild) await self.logger.log('proposta aggiunta al file: `' + message.content + '`') # controlla se il messaggio è valido if not does_it_count(message): return # controlla se il membro è già registrato nell'archivio, in caso contrario lo aggiunge if message.author.id in self.archive.keys(): afler = self.archive.get(message.author.id) else: afler = Afler.new_entry(message.author.display_name) self.archive.add(message.author.id, afler) # incrementa il conteggio afler.increase_counter() self.archive.save()