async def member_join(self, member): if not self.settings["log_member_join"]: return guild = member.guild if guild != self.bot.discord_bot.guild: return out_channel = self.bot.filters.get_channel( [int(self.settings["output_channel"])], None, {} )[0] users = len(guild.members) created_at = member.created_at.replace(tzinfo=datetime.timezone.utc) since_created = (utils.now() - created_at).days user_created = created_at.strftime("%d %b %Y %H:%M") created_on = f"{user_created}\n({since_created} days ago)" embed = discord.Embed( description=f"@{member}", colour=await self.get_event_colour(guild, "user_join"), timestamp=member.joined_at if member.joined_at else utils.now(), ) embed.add_field(name="Total Users:", value=str(users), inline=False) embed.add_field(name="Account created on:", value=created_on, inline=False) embed.set_footer(text="User ID: " + str(member.id)) embed.set_author( name=f"{member} ({member.id}) has joined the guild", url=member.avatar_url, icon_url=member.avatar_url, ) embed.set_thumbnail(url=member.avatar_url) await self.bot.say(channel=out_channel, embed=embed)
async def vroom(self, bot, author, channel, message, args): if len(self.vroom_races) < self.settings["max_vroom_races"]: start_time = utils.now() m = await self.bot.say(channel=channel, message="﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏") self.vroom_races.append(m) await asyncio.sleep(0.5) await m.edit( content=f"{self.settings['emote_for_vroom']}﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏﹏" ) for _ in range(19): newtick = m.content[:-1] newtick = "﹏" + newtick await asyncio.sleep(random.randint(5, 30) / 10) await m.edit(content=newtick) elapsed_time = utils.now() - start_time await m.edit( content= f"{author.mention} finished in {round(elapsed_time.total_seconds(), 2)}s" ) self.vroom_races.remove(m) else: await self.bot.say( channel=channel, message= f"{author.mention} there can only be up to {self.settings['max_vroom_races']} races at the same time. Try later...", ignore_escape=True, )
def should_run(self): if self.paused: return False if self.run_type == "date": return self.run_date < utils.now() else: return ((utils.now() - self.last_run).total_seconds() > self.interval if self.last_run else True)
async def role_update(self, before, after): if not self.settings["log_role_update"]: return guild = before.guild if guild != self.bot.discord_bot.guild: return out_channel = self.bot.filters.get_channel( [int(self.settings["output_channel"])], None, {} )[0] perp = None reason = None action = discord.AuditLogAction.role_update async for _log in guild.audit_logs(limit=5, action=action): if _log.target.id == before.id: perp = _log.user if _log.reason: reason = _log.reason break if perp == self.bot.discord_bot.client.user: return embed = discord.Embed( description=after.mention, colour=after.colour, timestamp=utils.now() ) if after is guild.default_role: embed.set_author(name="Updated @everyone role ") else: embed.set_author(name=f"Updated {before.name} ({before.id}) role ") if perp: embed.add_field(name="Updated by ", value=perp.mention, inline=False) if reason: embed.add_field(name="Reason ", value=reason, inline=False) role_updates = { "name": "Name:", "color": "Colour:", "mentionable": "Mentionable:", "hoist": "Is Hoisted:", } worth_updating = False for attr, name in role_updates.items(): before_attr = getattr(before, attr) after_attr = getattr(after, attr) if before_attr != after_attr: worth_updating = True if before_attr == "": before_attr = "None" if after_attr == "": after_attr = "None" embed.add_field( name="Before " + name, value=str(before_attr), inline=False ) embed.add_field( name="After " + name, value=str(after_attr), inline=False ) p_msg = await self.get_role_permission_change(before, after) if p_msg != "": worth_updating = True embed.add_field(name="Permissions", value=p_msg[:1024], inline=False) if not worth_updating: return await self.bot.say(channel=out_channel, embed=embed)
async def role_delete(self, role): if not self.settings["log_role_create"]: return guild = role.guild if guild != self.bot.discord_bot.guild: return out_channel = self.bot.filters.get_channel( [int(self.settings["output_channel"])], None, {} )[0] perp = None reason = None action = discord.AuditLogAction.role_create async for _log in guild.audit_logs(limit=5, action=action): if _log.target.id == role.id: perp = _log.user if _log.reason: reason = _log.reason break embed = discord.Embed( description=role.name, colour=role.colour, timestamp=utils.now(), ) embed.set_author(name=f"Role deleted {role.name} ({role.id})") if perp: embed.add_field(name="Deleted by", value=perp.mention, inline=False) if reason: embed.add_field(name="Reason ", value=reason, inline=False) await self.bot.say(channel=out_channel, embed=embed)
async def initial_unbans(self): try: data = json.loads(self.redis.get(f"{self.bot.bot_name}:timeouts-discord")) for user in data: unban_date = utils.parse_date(data[user]["unban_date"]) time_now = utils.now() resp_timeout = data.get("resp_timeout", "") resp_timeout += " after " if resp_timeout else "" if unban_date < time_now: ScheduleManager.execute_now( method=self.unban, args=[ data[user]["discord_id"], f"Unbanned by timer{resp_timeout}", ], ) continue ScheduleManager.execute_delayed( delay=(unban_date - time_now).seconds, method=self.unban, args=[data[user]["discord_id"], f"Unbanned by timer{resp_timeout}"], ) except Exception as e: log.exception(e) self.redis.set(f"{self.bot.bot_name}:timeouts-discord", json.dumps({})) with DBManager.create_session_scope() as db_session: unnamed_users = db_session.query(User).filter_by(user_name="").all() for user in unnamed_users: member = self.get_member(int(user.discord_id)) if not member: db_session.delete(user) continue user.user_name = str(member)
def enable(self, bot): if not bot: return try: reminders_list = json.loads(self.redis.get("remind-me-reminders")) """ { user_id: { "message_id": message_id, "message": message, "date_of_reminder": date_of_reminder, }, } """ except: self.redis.set("remind-me-reminders", json.dumps({})) reminders_list = {} new_reminders_list = {} for user in reminders_list: user_reminders = reminders_list[user] new_user_reminders = [] for reminder in user_reminders: salt = random_string() date_of_reminder = reminder["date_of_reminder"] if ":" in date_of_reminder[-5:]: date_of_reminder = f"{date_of_reminder[:-5]}{date_of_reminder[-5:-3]}{date_of_reminder[-2:]}" date_of_reminder = datetime.strptime(date_of_reminder, "%Y-%m-%d %H:%M:%S.%f%z") if date_of_reminder < utils.now(): continue new_user_reminders.append(reminder) self.reminder_tasks[salt] = ScheduleManager.execute_delayed((date_of_reminder-utils.now()).seconds, self.execute_reminder, args=[salt, reminder])
async def channel_delete(self, channel): if not self.settings["log_channel_delete"]: return guild = channel.guild if guild != self.bot.discord_bot.guild: return out_channel = self.bot.filters.get_channel( [int(self.settings["output_channel"])], None, {} )[0] channel_type = str(channel.type).title() embed = discord.Embed( description=channel.name, timestamp=utils.now(), colour=await self.get_event_colour(guild, "channel_delete"), ) embed.set_author( name=f"{channel_type} Channel Deleted {channel.name} ({channel.id})" ) perp = None reason = None action = discord.AuditLogAction.channel_delete async for _log in guild.audit_logs(limit=5, action=action): if _log.target.id == channel.id: perp = _log.user if _log.reason: reason = _log.reason break embed.add_field(name="Type", value=channel_type, inline=False) if perp: embed.add_field(name="Deleted by ", value=perp.mention, inline=False) if reason: embed.add_field(name="Reason ", value=reason, inline=False) await self.bot.say(channel=out_channel, embed=embed)
def _get_week_count_user(db_session, user_id): return ( db_session.query(func.count(Message.message_id)) .filter(Message.user_id == str(user_id)) .filter(Message.time_sent > utils.now() - timedelta(days=7)) .scalar() )
def _get_last_hour(db_session): return ( db_session.query(Message) .filter_by(credited=False) .filter(Message.time_sent > utils.now() - timedelta(hours=1)) .all() )
async def _ban( self, user, timeout_in_seconds=0, reason=None, delete_message_days=0 ): delete_message_days = ( 7 if delete_message_days > 7 else (0 if delete_message_days < 0 else delete_message_days) ) if not self.guild: return if not user: return try: ban = await self.guild.fetch_ban(user) if ban: return except: pass if timeout_in_seconds > 0: reason = f"{reason} for {timeout_in_seconds} seconds" timeouts = json.loads(self.redis.get("timeouts-discord")) timeouts[str(user.id)] = { "discord_id": str(user.id), "unban_date": str(utils.now() + timedelta(seconds=timeout_in_seconds)), "reason": str(reason) } self.redis.set("timeouts-discord", json.dumps(timeouts)) ScheduleManager.execute_delayed(delay=timeout_in_seconds, method=self.unban, args=[user.id, "Unbanned by timer"]) await self.guild.ban( user=user, reason=reason, delete_message_days=delete_message_days )
async def guild_update(self, before, after): if not self.settings["log_guild_update"]: return if after != self.bot.discord_bot.guild: return out_channel = self.bot.filters.get_channel( [int(self.settings["output_channel"])], None, {} )[0] embed = discord.Embed( timestamp=utils.now(), colour=await self.get_event_colour(after, "guild_change"), ) embed.set_author(name="Updated Guild", icon_url=str(after.icon_url)) embed.set_thumbnail(url=str(after.icon_url)) guild_updates = { "name": "Name:", "region": "Region:", "afk_timeout": "AFK Timeout:", "afk_channel": "AFK Channel:", "icon_url": "Server Icon:", "owner": "Server Owner:", "splash": "Splash Image:", "system_channel": "Welcome message channel:", "verification_level": "Verification Level:", } worth_updating = False for attr, name in guild_updates.items(): before_attr = getattr(before, attr) after_attr = getattr(after, attr) if before_attr != after_attr: worth_updating = True embed.add_field( name="Before " + name, value=str(before_attr), inline=False ) embed.add_field( name="After " + name, value=str(after_attr), inline=False ) if not worth_updating: return perps = [] reasons = [] action = discord.AuditLogAction.guild_update async for _log in self.bot.discord_bot.guild.audit_logs( limit=int(len(embed.fields) / 2), action=action ): perps.append(_log.user) if _log.reason: reasons.append(_log.reason) if perps: embed.add_field( name="Updated by", value=", ".join(p.mention for p in perps), inline=False, ) if reasons: embed.add_field( name="Reasons ", value=", ".join(str(r) for r in reasons), inline=False ) await self.bot.say(channel=out_channel, embed=embed)
def execute_now(method, args=[], kwargs={}): job = ScheduledJob("date", method, run_date=utils.now(), args=args, kwargs=kwargs) ScheduleManager.schedules.append(job) return job
def _filter_time_since_dt(var, args): try: ts = utils.time_since(utils.now().timestamp(), var.timestamp()) if ts: return ts return "0 seconds" except: return "never FeelsBadMan ?"
def no_cache(*args, **kwargs): response = make_response(view(*args, **kwargs)) response.headers["Last-Modified"] = utils.now() response.headers[ "Cache-Control" ] = "no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0" response.headers["Pragma"] = "no-cache" response.headers["Expires"] = "-1" return response
def execute_delayed(delay, method, args=[], kwargs={}): run_date = utils.now() + datetime.timedelta(seconds=delay) job = ScheduledJob("date", method, run_date=run_date, args=args, kwargs=kwargs) ScheduleManager.schedules.append(job) return job
def _create(db_session, message_id, user_id, channel_id, content): user = Message( message_id=str(message_id), user_id=str(user_id), channel_id=str(channel_id), content=content, time_sent=utils.now(), ) db_session.add(user) return user
def _get_week_count_by_user(db_session): query = (db_session.query( Message.user_id.label("user_id"), func.count(Message.message_id).label("count")).filter( Message.time_sent > utils.now() - timedelta(days=7)).group_by( Message.user_id).all()) return_dict = {} for row in query: return_dict[row.user_id] = int(row.count) return return_dict
def add_entry(entry_type, source, message, data={}): with DBManager.create_session_scope() as db_session: entry_object = AdminLogEntry( type=entry_type, user_id=source, message=message, created_at=utils.now(), data=data, ) db_session.add(entry_object)
def _create(db_session, user_id, giveaway_id, tickets): if GiveawayEntry.is_entered(db_session, user_id, giveaway_id): return None giveaway_entry = GiveawayEntry(user_id=user_id, giveaway_id=giveaway_id, date_entered=utils.now(), tickets=tickets) db_session.add(giveaway_entry) return giveaway_entry
def enable(self, bot): if not bot: return try: reminders_list = json.loads( self.redis.get(f"{self.bot.bot_name}:remind-me-reminders")) """ { user_id: [ { "message_id": message_id, "channel_id": channel_id, "salt": salt, "message": message, "date_of_reminder": date_of_reminder, "date_reminder_set": date_reminder_set }, ], } """ except: self.redis.set(f"{self.bot.bot_name}:remind-me-reminders", json.dumps({})) reminders_list = {} new_reminders_list = {} for user_id in reminders_list: user_reminders = reminders_list[user_id] new_user_reminders = [] for reminder in user_reminders: salt = reminder["salt"] date_of_reminder = utils.parse_date( reminder["date_of_reminder"]) if date_of_reminder < utils.now(): continue new_user_reminders.append(reminder) self.reminder_tasks[salt] = ScheduleManager.execute_delayed( (date_of_reminder - utils.now()).total_seconds(), self.execute_reminder, args=[salt, user_id, reminder], ) new_reminders_list[user_id] = new_user_reminders self.redis.set(f"{self.bot.bot_name}:remind-me-reminders", json.dumps(new_reminders_list))
def _create(db_session, user_id, issued_by_id, until, ban_reason): timeout = Timeout( active=True, user_id=user_id, issued_by_id=issued_by_id, until=until, created_at=utils.now(), ban_reason=ban_reason, ) db_session.add(timeout) return timeout
async def message_edit(self, payload): if not self.settings["log_edit_message"]: return out_channel = self.bot.filters.get_channel( [int(self.settings["output_channel"])], None, {} )[0] sent_in_channel = self.bot.filters.get_channel([int(payload.data["channel_id"])], None, {})[0] channels = ( self.settings["ingore_channels"].split(" ") if self.settings["ingore_channels"] != "" else [] ) if not sent_in_channel or (len(channels) > 0 and str(sent_in_channel.id) in channels): return message_id = payload.message_id guild_id = payload.data.get("guild_id", None) message = await sent_in_channel.fetch_message(int(message_id)) if not guild_id or self.bot.discord_bot.guild.id != int(guild_id): return with DBManager.create_session_scope() as db_session: db_message = Message._get(db_session, str(message_id)) if not db_message: return content = json.loads(db_message.content) author_id = db_message.user_id author = self.bot.discord_bot.get_member(int(author_id)) if int(author_id) == self.bot.discord_bot.client.user.id: return embed = discord.Embed( description=f"{author} updated their message in {sent_in_channel}", colour=await self.get_event_colour(author.guild, "message_edit"), timestamp=utils.now(), ) embed.add_field(name="Now:", value=f"{content[-1]}" if content[-1] else "None", inline=False) embed.add_field(name="Previous:", value=f"{content[-2]}" if content[-2] else "None", inline=False) embed.add_field( name="Channel:", value=f"{sent_in_channel.mention} ({sent_in_channel})\n[Jump to message]({message.jump_url})", inline=False, ) embed.add_field( name="ID", value=f"```User ID = {author.id}\nMessage ID = {message.id}\nChannel ID = {sent_in_channel.id}```", inline=False, ) embed.set_author( name=f"{author} ({author.id})", icon_url=str(author.avatar_url), ) await self.bot.say(out_channel, embed=embed)
def execute_now(method, args=[], kwargs={}, scheduler=None): if scheduler is None: scheduler = ScheduleManager.base_scheduler if scheduler is None: raise ValueError("No scheduler available") job = scheduler.add_job(method, "date", run_date=utils.now(), args=args, kwargs=kwargs) return ScheduledJob(job)
def _create(db_session, message_id, user_id, channel_id, content): # Content is an array if Message._get(db_session, message_id): return None user = Message( message_id=str(message_id), user_id=str(user_id), channel_id=str(channel_id), content=json.dumps(content), time_sent=utils.now(), ) db_session.add(user) return user
async def message_delete(self, payload): if not self.settings["log_delete_message"]: return out_channel = self.bot.filters.get_channel( [int(self.settings["output_channel"])], None, {} )[0] message_id = payload.message_id with DBManager.create_session_scope() as db_session: db_message = Message._get(db_session, message_id) if not db_message: return content = json.loads(db_message.content) author_id = db_message.user_id sent_in_channel = self.bot.filters.get_channel([int(payload.channel_id)], None, {})[0] channels = ( self.settings["ingore_channels"].split(" ") if self.settings["ingore_channels"] != "" else [] ) if not sent_in_channel or (len(channels) > 0 and str(sent_in_channel.id) in channels): return author = self.bot.discord_bot.get_member(int(author_id)) if author == self.bot.discord_bot.client.user: return embed = discord.Embed( colour=await self.get_event_colour(author.guild, "message_delete"), timestamp=utils.now(), ) embed.add_field(name="Message", value=content[-1] if content[-1] else "None", inline=False) embed.add_field(name="Channel", value=sent_in_channel, inline=False) embed.add_field( name="ID", value=f"```Message ID: {message_id}\nUser ID: {author_id}\nChannel ID: {sent_in_channel.id}```", inline=False, ) action = discord.AuditLogAction.message_delete perp = None async for _log in self.bot.discord_bot.guild.audit_logs(limit=2, action=action): same_chan = _log.extra.channel.id == sent_in_channel.id if _log.target.id == int(author_id) and same_chan: perp = f"{_log.user}({_log.user.id})" break if perp: embed.add_field(name="Deleted by", value=perp, inline=False) embed.set_footer(text="User ID: " + str(author_id)) embed.set_author( name=f"{author} ({author.id})- Deleted Message", icon_url=str(author.avatar_url), ) await self.bot.say(out_channel, embed=embed)
def execute_delayed(delay, method, args=[], kwargs={}, scheduler=None): if scheduler is None: scheduler = ScheduleManager.base_scheduler if scheduler is None: raise ValueError("No scheduler available") job = scheduler.add_job( method, "date", run_date=utils.now() + datetime.timedelta(seconds=delay), args=args, kwargs=kwargs, ) return ScheduledJob(job)
def __init__(self, run_type, method, interval=1, run_date=utils.now(), args=[], kwargs={}): self.run_type = run_type self.method = method self.run_date = run_date self.interval = interval self.args = args self.kwargs = kwargs self.paused = False self.last_run = None
async def ban(self, user, timeout_in_seconds=0, reason=None, delete_message_days=0): delete_message_days = ( 7 if delete_message_days > 7 else (0 if delete_message_days < 0 else delete_message_days) ) if not self.guild: return False if not user: return False try: ban = await self.guild.fetch_ban(user) if ban: return False except: return False try: resp_timeout = utils.seconds_to_resp(timeout_in_seconds) reason += ( f" for {resp_timeout}!" if timeout_in_seconds > 0 else " Permanently!" ) await self.guild.ban( user=user, reason=reason, delete_message_days=delete_message_days ) if timeout_in_seconds > 0: timeouts = json.loads( self.redis.get(f"{self.bot.bot_name}:timeouts-discord") ) timeouts[str(user.id)] = { "discord_id": str(user.id), "unban_date": str( utils.now() + timedelta(seconds=timeout_in_seconds) ), "resp_timeout": resp_timeout, "reason": str(reason), } self.redis.set( f"{self.bot.bot_name}:timeouts-discord", json.dumps(timeouts) ) ScheduleManager.execute_delayed( delay=timeout_in_seconds, method=self.unban, args=[user.id, f"Unbanned by timer after {resp_timeout}"], ) except: return False return True
def initial_unbans(self): try: data = json.loads(self.redis.get("timeouts-discord")) for user in data: unban_date = data[user]["unban_date"] if ":" in unban_date[-5:]: unban_date = f"{unban_date[:-5]}{unban_date[-5:-3]}{unban_date[-2:]}" unban_date = datetime.strptime(unban_date, "%Y-%m-%d %H:%M:%S.%f%z") time_now = utils.now() if unban_date < time_now: ScheduleManager.execute_now(method=self.unban, args=[data[user]["discord_id"], "Unbanned by timer"]) continue ScheduleManager.execute_delayed(delay=(unban_date - time_now).seconds, method=self.unban, args=[data[user]["discord_id"], "Unbanned by timer"]) except Exception as e: log.exception(e) self.redis.set("timeouts-discord", json.dumps({}))