async def anti_links(self, message): link = LINKS.findall(message.content) invites = INVITE.search(message.content) current = message.created_at.replace(tzinfo=timezone.utc).timestamp() reason = _('Spamming links') automod = cm.get(self.bot, 'automod', message.guild.id) antilinks = cm.get(self.bot, 'links', message.guild.id) if not antilinks: return if invites: # invites and links are different things return if link: # was unable to figure out how to add links without multiplying. # if link_whitelist: # for li in link_whitelist: # if li in link: # return # else: # pass content_bucket = self.link_cooldown.get_bucket(message) retry = content_bucket.update_rate_limit(current) if automod['delete_messages'] and message.channel.permissions_for(message.guild.me).manage_messages: await message.delete(silent=True) if retry: content_bucket.reset() await self.execute_punishment(antilinks['level'], message, reason, btime.FutureTime(antilinks['time']))
async def anti_spam(self, message): current = message.created_at.replace(tzinfo=timezone.utc).timestamp() reason = _("Spam (sending multiple messages in a short time span)") automod = cm.get(self.bot, 'automod', message.guild.id) antispam = cm.get(self.bot, 'spam', message.guild.id) if not antispam: return content_bucket = self.messages_cooldown.get_bucket(message) if content_bucket.update_rate_limit(current): content_bucket.reset() await self.execute_punishment(antispam['level'], message, reason, btime.FutureTime(antispam['time'])) user_bucket = self.user_cooldowns.get_bucket(message) if user_bucket.update_rate_limit(current): user_bucket.reset() await self.execute_punishment(antispam['level'], message, reason, btime.FutureTime(antispam['time']))
async def anti_mentions(self, message): current = message.created_at.replace(tzinfo=timezone.utc).timestamp() reason = _('Spamming mentions') automod = cm.get(self.bot, 'automod', message.guild.id) massmention = cm.get(self.bot, 'massmention', message.guild.id) if not massmention: return limit = massmention['limit'] if len(message.mentions) > limit: content_bucket = self.mentions_limit.get_bucket(message) retry = content_bucket.update_rate_limit(current) if automod['delete_messages'] and message.channel.permissions_for(message.guild.me).manage_messages: await message.delete() if retry: content_bucket.reset() await self.execute_punishment(massmention['level'], message, reason, btime.FutureTime(massmention['time']))
async def anti_caps(self, message): cap = CAPS.findall(message.content) current = message.created_at.replace(tzinfo=timezone.utc).timestamp() reason = _('Spamming caps') automod = cm.get(self.bot, 'automod', message.guild.id) masscaps = cm.get(self.bot, 'masscaps', message.guild.id) if not masscaps: return perc = masscaps['percentage'] / 100 if len(cap) >= len(message.content) * perc and len(message.content) > 10: content_bucket = self.caps_content.get_bucket(message) retry = content_bucket.update_rate_limit(current) if automod['delete_messages'] and message.channel.permissions_for(message.guild.me).manage_messages: await message.delete() if retry: content_bucket.reset() await self.execute_punishment(masscaps['level'], message, reason, btime.FutureTime(masscaps['time']))
async def anti_invite(self, message): invites = INVITE.findall(message.content) current = message.created_at.replace(tzinfo=timezone.utc).timestamp() reason = _('Advertising') automod = cm.get(self.bot, 'automod', message.guild.id) antiinvite = cm.get(self.bot, 'invites', message.guild.id) if invites and antiinvite: content_bucket = self.invite_cooldown.get_bucket(message) the_invite = invites[0] try: invite = await self.bot.fetch_invite(the_invite) if invite.guild.id == message.guild.id and len(invites) == 1: return if automod['delete_messages'] and message.channel.permissions_for(message.guild.me).manage_messages: await message.delete() except Exception as e: return retry = content_bucket.update_rate_limit(current) if retry: content_bucket.reset() await self.execute_punishment(antiinvite['level'], message, reason, btime.FutureTime(antiinvite['time']))
async def poll(self, ctx, *, data: str = None): """ creates a poll that allows your community to vote on whatever you are polling! requires the `Community Manager` role to create a poll, use the following format: ``` !poll --title MyTitle --desc this is for a test --add :MyEmoji: - blue is better --add :MyOtherEmoji: - red is better +timer 1m ``` all fields are optional. one field per line. you may add as many emojis as you wish. for info on the timer formatting, see the ``!help time`` command." """ if not data: await ctx.send_help(ctx.command) return pdb = {"queries": {}, "end": 0, "endtxt": "", "title": "", "desc": "", "channel": ctx.channel.id, "msg": None} parser = Arguments() parser.add_argument("--title", "-t", nargs="+") parser.add_argument("--add", "-a", "--append", nargs="+", action="append") parser.add_argument("--timer", "-timer", nargs="+") parser.add_argument("--description", "--desc", "-d", nargs="+") try: parsed = parser.parse_args(parse.split(data)) except Exception as e: return await ctx.send(str(e)) if not parsed.add: return await ctx.send(f"No options passed!") for i in parsed.add: i = i[0] c = i.split() emoji = c[0] r = " ".join(c[1:]) try: emoji = await commands.EmojiConverter().convert(ctx, emoji) except commands.BadArgument: if ":" in emoji: return await ctx.send("unusable emoji!") pdb['queries'][emoji] = r if parsed.timer: c = btime.FutureTime(" ".join(parsed.timer)) end = btime.human_timedelta(c.dt, brief=True) pdb['endtxt'] = end pdb['end'] = round(c.dt.timestamp()) if parsed.description: pdb['desc'] = " ".join(parsed.description) if parsed.title: pdb['title'] = " ".join(parsed.title) e = discord.Embed() if pdb['end'] != 0 and pdb['desc']: e.description = pdb['desc'] + f"\n*poll will close after* "+pdb['endtxt'] elif pdb['end'] != 0: e.description = f"*poll will close after* {pdb['endtxt']}" e.colour = discord.Color.purple() e.title = pdb['title'] e.timestamp = datetime.datetime.utcnow() for emoji, desc in pdb['queries'].items(): try: emoj = str(self.bot.get_emoji(int(emoji))) except: emoj = emoji e.add_field(name=desc, value=f"*react with* {emoj}", inline=False) v = await ctx.send(embed=e) pdb['msg'] = v.id id = str(uuid.uuid4()) if pdb['end'] != 0: await self.db.execute("INSERT INTO polls " "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", (ctx.guild.id, id, pdb['end'], pdb['endtxt'], pdb['title'], pdb['desc'], pdb['channel'], pdb['msg'])) for emoji, desc in pdb['queries'].items(): await self.db.execute("INSERT INTO poll_nodes VALUES (?, ?, ?, ?)", (ctx.guild.id, id, str(emoji.id), desc)) for emote in pdb['queries'].keys(): try: r = self.bot.get_emoji(int(emote)) except Exception: r = emote await v.add_reaction(r)