diff --git a/joinleave/__init__.py b/joinleave/__init__.py deleted file mode 100644 index 6d961dd..0000000 --- a/joinleave/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .joinleave import JoinLeave - - -def setup(bot): - bot.add_cog(JoinLeave(bot)) diff --git a/joinleave/joinleave.py b/joinleave/joinleave.py deleted file mode 100644 index b227f66..0000000 --- a/joinleave/joinleave.py +++ /dev/null @@ -1,256 +0,0 @@ -import asyncio -import datetime -import discord -import re -from redbot.core import Config, commands, checks -from redbot.core.utils.chat_formatting import bold - -BaseCog = getattr(commands, "Cog", object) - - -class JoinLeave(BaseCog): - """Report users that join and leave quickly, with new accounts.""" - def __init__(self, bot): - self.bot = bot - self.config = Config.get_conf(self, 2713731002, force_registration=True) - - default_global = { - "announce_channel": None, - "join_days": 7, - "toggle": False, - "cooldown": 120, - "pingrole": None, - "pingserver": None, - } - - default_user = {"last_join": "2018-01-01 00:00:00.000001", "new": True} - - self.config.register_user(**default_user) - self.config.register_global(**default_global) - - @commands.group() - @commands.guild_only() - @checks.is_owner() - async def joinleave(self, ctx): - """Main joinleave commands.""" - pass - - @joinleave.command() - async def channel(self, ctx, channel: discord.TextChannel): - """Sets the announcement channel.""" - await self.config.announce_channel.set(channel.id) - announce_channel_id = await self.config.announce_channel() - await ctx.send( - f"User announcement channel set to: {self.bot.get_channel(announce_channel_id).mention}." - ) - - @joinleave.command() - async def cooldown(self, ctx, cooldown_time: int = 0): - """Set the time window in seconds for a valid join/leave flag. - - Leave time blank to reset to default (2m).""" - cooldown = await self.config.cooldown() - if not cooldown_time: - await self.config.cooldown.set(120) - await ctx.send("Join/leave time window reset to 2m.") - else: - await self.config.cooldown.set(cooldown_time) - await ctx.send( - f"Join/leave time window set to {self._dynamic_time(int(cooldown_time))}." - ) - - @joinleave.command() - async def days(self, ctx, days: int): - """Set how old an account needs to be a trusted user.""" - await self.config.join_days.set(days) - await ctx.send(f"Users must have accounts older than {days} day(s) to be ignored.") - - @joinleave.command() - async def role(self, ctx, *, role_name: discord.Role = None): - """Set the role to ping on a first sighting. Leave blank to turn off.""" - if not role_name: - await self.config.pingrole.set(None) - await self.config.pingserver.set(None) - return await ctx.send( - "Role has been removed. No pinging will occur on a first sighting." - ) - - await self.config.pingserver.set(ctx.guild.id) - await self.config.pingrole.set(role_name.id) - role_obj = discord.utils.get(ctx.guild.roles, id=await self.config.pingrole()) - await ctx.send(f"Pingable role set to: {role_obj.name}.") - - @joinleave.command() - async def settings(self, ctx): - """Show the current settings.""" - data = await self.config.all() - - try: - achannel = self.bot.get_channel(data["announce_channel"]).name - except AttributeError: - achannel = None - joinleave_enabled = data["toggle"] - join_days = data["join_days"] - cooldown = data["cooldown"] - pingrole_id = data["pingrole"] - ping_guild = self.bot.get_guild(data["pingserver"]) - if not pingrole_id: - pingrole = "None" - else: - try: - pingrole_obj = discord.utils.get(ping_guild.roles, id=pingrole_id) - pingrole = pingrole_obj.name - except AttributeError: - pingrole = "None" - - msg = ( - "```ini\n---JoinLeave Settings--- \n" - f"Announce Channel: [{achannel}]\n" - f"Join/Leave Span: [{self._dynamic_time(int(cooldown))}]\n" - f"Day Threshold: [{str(join_days)}]\n" - f"Ping role: [{pingrole}]\n" - f"JoinLeave Active: [{joinleave_enabled}]\n```" - ) - - embed = discord.Embed(colour=ctx.guild.me.top_role.colour, description=msg) - return await ctx.send(embed=embed) - - @joinleave.command() - async def toggle(self, ctx): - """Toggle the joinleave on or off. This is global.""" - joinleave_enabled = await self.config.toggle() - announce_channel = await self.config.announce_channel() - if not announce_channel: - await self.config.announce_channel.set(ctx.message.channel.id) - await self.config.toggle.set(not joinleave_enabled) - await ctx.send(f"JoinLeave enabled: {not joinleave_enabled}.") - if not announce_channel: - await ctx.send(f"JoinLeave report channel set to: {ctx.message.channel.mention}.") - - async def on_member_join(self, member): - global_data = await self.config.all() - if not global_data["toggle"]: - return - - join_date = datetime.datetime.strptime(str(member.created_at), "%Y-%m-%d %H:%M:%S.%f") - now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None) - since_join = now - join_date - - if since_join.days < global_data["join_days"]: - await self.config.user(member).last_join.set(str(now)) - - async def on_member_remove(self, member): - user_data = await self.config.user(member).all() - global_data = await self.config.all() - if not global_data["toggle"]: - return - - channel_obj = self.bot.get_channel(global_data["announce_channel"]) - - if not channel_obj: - print("joinleave.py: toggled on but no announce channel") - return - - last_time = datetime.datetime.strptime(str(user_data["last_join"]), "%Y-%m-%d %H:%M:%S.%f") - - join_date = datetime.datetime.strptime(str(member.created_at), "%Y-%m-%d %H:%M:%S.%f") - now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None) - since_join = now - join_date - - if int((now - last_time).total_seconds()) < global_data["cooldown"]: - await channel_obj.send(f"**{member.id}**") - msg = f"User: {member} ({member.id})\nServer: {member.guild.name} ({member.guild.id})\nAccount is {self._dynamic_time(int(since_join.total_seconds()))} old" - if user_data["new"]: - await self.config.user(member).new.set(False) - if not global_data["pingrole"]: - return await channel_obj.send(f"\N{WARNING SIGN} First sighting\n{msg}") - else: - ping_guild = self.bot.get_guild(await self.config.pingserver()) - role_obj = discord.utils.get(ping_guild.roles, id=global_data["pingrole"]) - try: - await role_obj.edit(mentionable=True) - await channel_obj.send( - f"{role_obj.mention}\n\N{WARNING SIGN} First sighting\n{msg}" - ) - return await role_obj.edit(mentionable=False) - except AttributeError: - return await channel_obj.send( - f"I can't find the role that's set to ping (is it on another server?)\n\N{WARNING SIGN} First sighting\n{msg}" - ) - except discord.errors.Forbidden: - return await channel_obj.send( - f"I tried to ping for this alert but I don't have permissions to manage roles!\n\N{WARNING SIGN} First sighting\n{msg}" - ) - else: - await channel_obj.send(msg) - - async def on_message(self, message): - global_data = await self.config.all() - if not global_data["toggle"]: - return - channel_obj = self.bot.get_channel(global_data["announce_channel"]) - if not channel_obj: - return - if message.author.bot: - return - date_join = datetime.datetime.strptime(str(message.author.created_at), "%Y-%m-%d %H:%M:%S.%f") - date_now = datetime.datetime.now(datetime.timezone.utc) - date_now = date_now.replace(tzinfo=None) - since_join = date_now - date_join - if since_join.days < global_data["join_days"]: - sentence = message.content.split() - for word in sentence: - if self._match_url(word): - await channel_obj.send(bold(f"{message.author.id}")) - msg = "**Message posted in** {} ({})\n".format(message.guild.name, message.guild.id) - msg += "**Message posted in** {} ({})\n".format(message.channel.mention, message.channel.id) - msg += "**Message sent by**: {} ({})\n".format(message.author.name, message.author.id) - msg += "**Message content**:\n{}".format(message.content) - - if not global_data["pingrole"]: - return await channel_obj.send(f"\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}") - else: - ping_guild = self.bot.get_guild(await self.config.pingserver()) - try: - role_obj = discord.utils.get(ping_guild.roles, id=global_data["pingrole"]) - await role_obj.edit(mentionable=True) - await channel_obj.send( - f"{role_obj.mention}\n\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}" - ) - return await role_obj.edit(mentionable=False) - except AttributeError: - return await channel_obj.send( - f"I can't find the role that's set to ping (is it on another server?)\n\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}" - ) - except discord.errors.Forbidden: - return await channel_obj.send( - f"I tried to ping for this alert but I don't have permissions to manage roles!\n\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}" - ) - - @staticmethod - def _dynamic_time(time): - m, s = divmod(time, 60) - h, m = divmod(m, 60) - d, h = divmod(h, 24) - - if d > 0: - msg = "{0}d {1}h" - elif d == 0 and h > 0: - msg = "{1}h {2}m" - elif d == 0 and h == 0 and m > 0: - msg = "{2}m {3}s" - elif d == 0 and h == 0 and m == 0 and s > 0: - msg = "{3}s" - else: - msg = "" - return msg.format(d, h, m, s) - - @staticmethod - def _match_url(url): - regex = re.compile( - "(([\w]+:)?//)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,63}(:[\d]+)?(/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?" - ) - if regex.match(url): - return True - else: - return False