async def startup_cleanup(self): self.join_cooldown = Configuration.get_persistent_var( "join_cooldown", dict()) for guild in self.bot.guilds: self.set_verification_mode(guild) self.mute_minutes_old_account = Configuration.get_persistent_var( f"{guild.id}_mute_minutes_old_account", 10) self.mute_minutes_new_account = Configuration.get_persistent_var( f"{guild.id}_mute_minutes_new_account", 20) self.welcome_talkers[guild.id] = dict() if str(guild.id) not in self.join_cooldown: self.join_cooldown[str(guild.id)] = dict() self.check_cooldown.start()
def init_guild(self, guild): self.set_verification_mode(guild) self.mute_minutes_old_account[ guild.id] = Configuration.get_persistent_var( f"{guild.id}_mute_minutes_old_account", 10) self.mute_minutes_new_account[ guild.id] = Configuration.get_persistent_var( f"{guild.id}_mute_minutes_new_account", 20) self.mute_new_members[guild.id] = Configuration.get_persistent_var( f"{guild.id}_mute_new_members", False) self.welcome_talkers[guild.id] = dict() if str(guild.id) not in self.join_cooldown: self.join_cooldown[str(guild.id)] = dict()
async def periodic_task(self): # periodic task to run while cog is loaded # remove expired cooldowns now = datetime.now().timestamp() cooldown = Configuration.get_persistent_var(f"mischief_cooldown", dict()) try: # key for loaded dict is a string updated_cooldown = {} for str_uid, member_last_access_time in cooldown.items(): if (now - member_last_access_time) < self.cooldown_time: updated_cooldown[str_uid] = member_last_access_time Configuration.set_persistent_var(f"mischief_cooldown", updated_cooldown) except: Logging.info("can't clear cooldown") # update role count storage (because it's slow) try: guild = Utils.get_home_guild() for role_id in self.role_map.values(): my_role = guild.get_role(role_id) if my_role is not None: self.role_counts[str(role_id)] = len(my_role.members) except: Logging.info("can't update role counts")
async def startup_cleanup(self): restart_mid = Configuration.get_persistent_var("bot_restart_message_id") restart_cid = Configuration.get_persistent_var("bot_restart_channel_id") author_id = Configuration.get_persistent_var("bot_restart_author_id") Configuration.del_persistent_var("bot_restart_message_id", True) Configuration.del_persistent_var("bot_restart_channel_id", True) Configuration.del_persistent_var("bot_restart_author_id", True) # TODO: write pop_persistent_var if restart_cid and restart_mid: try: channel = self.bot.get_channel(restart_cid) message = await channel.fetch_message(restart_mid) author = self.bot.get_user(author_id) await message.edit(content=f"Restart complete {author.mention}") except Exception: pass
async def startup_cleanup(self): Logging.info("starting bugs") # TODO: find out what the condition is we need to wait for instead of just sleep # await asyncio.sleep(20) # for name, cid in Configuration.get_var("channels").items(): reporting_channel_ids = [] for row in BugReportingChannel.select(): cid = row.channelid name = f"{row.platform.platform}_{row.platform.branch}" guild_id = row.guild.serverid channel = self.bot.get_channel(cid) shutdown_key = f"{guild_id}_{name}_shutdown" shutdown_id = Configuration.get_persistent_var(shutdown_key) if shutdown_id is not None: Configuration.del_persistent_var(shutdown_key) try: message = await channel.fetch_message(shutdown_id) await message.delete() except (NotFound, HTTPException) as e: pass reporting_channel_ids.append(cid) try: await self.send_bug_info(*reporting_channel_ids) except Exception as e: await Utils.handle_exception("bug startup failure", self.bot, e)
def run_db_migrations(): dbv = int(Configuration.get_persistent_var('db_version', 0)) Logging.info(f"db version is {dbv}") dbv_list = [f for f in glob.glob("db_migrations/db_migrate_*.py")] dbv_pattern = re.compile(r'db_migrations/db_migrate_(\d+)\.py', re.IGNORECASE) migration_count = 0 for filename in sorted(dbv_list): # get the int version number from filename version = int(re.match(dbv_pattern, filename)[1]) if version > dbv: try: Logging.info( f"--- running db migration version number {version}") spec = importlib.util.spec_from_file_location( f"migrator_{version}", filename) dbm = importlib.util.module_from_spec(spec) spec.loader.exec_module(dbm) Configuration.set_persistent_var('db_version', version) migration_count = migration_count + 1 except Exception as e: # throw a fit if it doesn't work raise e Logging.info( f"--- {migration_count if migration_count else 'no'} db migration{'' if migration_count == 1 else 's'} run" )
def set_verification_mode(self, guild): # TODO: enforce channel permissions for entry_channel? # verification flow is on if entry channel is set self.discord_verification_flow = bool( self.bot.get_config_channel(guild.id, Utils.entry_channel)) # Do not mute new members if verification flow is on. # Otherwise, mute new members UNLESS it's manually overridden self.mute_new_members = False if self.discord_verification_flow else \ Configuration.get_persistent_var(f"{guild.id}_mute_new_members", True)
async def startup_cleanup(self): for name, cid in Configuration.get_var("channels").items(): channel = self.bot.get_channel(cid) shutdown_id = Configuration.get_persistent_var(f"{name}_shutdown") if shutdown_id is not None: message = await channel.fetch_message(shutdown_id) if message is not None: await message.delete() Configuration.set_persistent_var(f"{name}_shutdown", None) await self.send_bug_info(name)
def init_guild(self, guild_id): watch = ReactWatch.get_or_create(serverid=guild_id)[0] self.mutes[guild_id] = Configuration.get_persistent_var(f"react_mutes_{guild_id}", dict()) self.min_react_lifespan[guild_id] = Configuration.get_persistent_var(f"min_react_lifespan_{guild_id}", 0.5) self.mute_duration[guild_id] = watch.muteduration # track react add/remove per guild self.recent_reactions[guild_id] = dict() self.react_removers[guild_id] = dict() self.react_adds[guild_id] = dict() # list of emoji to watch self.emoji[guild_id] = dict() for e in watch.emoji: self.emoji[guild_id][e.emoji] = e # enable listening if set in db if watch.watchremoves: self.activate_react_watch(guild_id) self.guilds[guild_id] = Guild.get_or_create(serverid=guild_id)[0]
async def mischief(self, ctx): if ctx.guild and not Utils.can_mod_official(ctx): return member_counts = Configuration.get_persistent_var(f"mischief_usage", dict()) max_member_id = max(member_counts, key=member_counts.get) wishes_granted = sum(member_counts.values()) guild = Utils.get_home_guild() max_user: discord.Member = guild.get_member(int(max_member_id)) await ctx.send(f"{len(member_counts)} people have gotten mischief roles.\n" f"I have granted {wishes_granted} wishes.\n" f"{max_user.mention} has wished the most, with {member_counts[max_member_id]} wishes granted.", allowed_mentions=AllowedMentions.none())
async def startup_cleanup(self): self.krilled = Configuration.get_persistent_var("krilled", dict()) """ for user_id, expiry in self.krilled.items(): user = self.bot.get_user(user_id) # expiry = date(expiry) print(f"krilled: {user_id}") # if date gt expiry, unkrill, else schedule unkrilling """ # Load channels for guild in self.bot.guilds: my_channels = set() for row in KrillChannel.select(KrillChannel.channelid).where( KrillChannel.serverid == guild.id): my_channels.add(row.channelid) self.channels[guild.id] = my_channels self.loaded = True
async def send_bug_info(self, key): channel = self.bot.get_channel(Configuration.get_var("channels")[key]) bug_info_id = Configuration.get_persistent_var(f"{key}_message") if bug_info_id is not None: try: message = await channel.fetch_message(bug_info_id) except NotFound: pass else: await message.delete() if message.id in self.bug_messages: self.bug_messages.remove(message.id) bugemoji = Emoji.get_emoji('BUG') message = await channel.send( Lang.get_string("bugs/bug_info", bug_emoji=bugemoji)) await message.add_reaction(bugemoji) self.bug_messages.add(message.id) Configuration.set_persistent_var(f"{key}_message", message.id)
async def send_bug_info(self, *args): for channel_id in args: channel = self.bot.get_channel(channel_id) if channel is None: await Logging.bot_log(f"can't send bug info to nonexistent channel {channel_id}") continue bug_info_id = Configuration.get_persistent_var(f"{channel.guild.id}_{channel_id}_bug_message") ctx = None tries = 0 while not ctx and tries < 5: tries += 1 # this API call fails on startup because connection is not made yet. # TODO: properly wait for connection to be initialized try: last_message = await channel.send('preparing bug reporting...') ctx = await self.bot.get_context(last_message) if bug_info_id is not None: try: message = await channel.fetch_message(bug_info_id) except (NotFound, HTTPException): pass else: await message.delete() if message.id in self.bug_messages: self.bug_messages.remove(message.id) bugemoji = Emoji.get_emoji('BUG') message = await channel.send(Lang.get_locale_string("bugs/bug_info", ctx, bug_emoji=bugemoji)) self.bug_messages.add(message.id) await message.add_reaction(bugemoji) Configuration.set_persistent_var(f"{channel.guild.id}_{channel_id}_bug_message", message.id) Logging.info(f"Bug report message sent in channel #{channel.name} ({channel.id})") await last_message.delete() except Exception as e: await self.bot.guild_log(channel.guild.id, f'Having trouble sending bug message in {channel.mention}') await Utils.handle_exception( f"Bug report message failed to send in channel #{channel.name} ({channel.id})", self.bot, e) await asyncio.sleep(0.5)
async def on_message(self, message: discord.Message): if message.author.bot: return uid = message.author.id try: guild = Utils.get_home_guild() my_member: discord.Member = guild.get_member(uid) if my_member is None or len(message.content) > 60: return except: return # try to create DM channel try: channel = await my_member.create_dm() except: # Don't message member because creating DM channel failed channel = None now = datetime.now().timestamp() triggers = [ "i wish i was", "i wish i were", "i wish i could be", "i wish to be", "i wish to become", "i wish i could become", "i wish i could turn into", "i wish to turn into", "i wish you could make me", "i wish you would make me", "i wish you could turn me into", "i wish you would turn me into", ] remove = False pattern = re.compile(f"(skybot,? *)?({'|'.join(triggers)}) (.*)", re.I) result = pattern.match(message.content) if result is None: # no match. don't remove or add roles return # get selection out of matching message selection = result.group(3).lower().strip() if selection in ["myself", "myself again", "me"]: selection = "me again" if selection not in self.role_map: return # Selection is now validated # Check Cooldown cooldown = Configuration.get_persistent_var(f"mischief_cooldown", dict()) member_last_access_time = 0 if str(uid) not in cooldown else cooldown[str(uid)] cooldown_elapsed = now - member_last_access_time remaining = self.cooldown_time - cooldown_elapsed ctx = await self.bot.get_context(message) if not Utils.can_mod_official(ctx) and (cooldown_elapsed < self.cooldown_time): try: remaining_time = Utils.to_pretty_time(remaining) await channel.send(f"wait {remaining_time} longer before you make another wish...") except: pass return # END cooldown if selection == "me again": remove = True # remove all roles for key, role_id in self.role_map.items(): try: old_role = guild.get_role(role_id) if old_role in my_member.roles: await my_member.remove_roles(old_role) except: pass try: member_counts = Configuration.get_persistent_var(f"mischief_usage", dict()) member_count = 0 if str(uid) not in member_counts else member_counts[str(uid)] member_counts[str(uid)] = member_count + 1 Configuration.set_persistent_var("mischief_usage", member_counts) cooldown = Configuration.get_persistent_var("mischief_cooldown", dict()) cooldown[str(uid)] = now Configuration.set_persistent_var("mischief_cooldown", cooldown) except Exception as e: await Utils.handle_exception("mischief role tracking error", self.bot, e) if not remove: # add the selected role new_role = guild.get_role(self.role_map[selection]) await my_member.add_roles(new_role) if channel is not None: try: if remove: await channel.send("fine, you're demoted!") else: await channel.send(f"""Congratulations, you are now **{selection}**!! You can wish again in my DMs if you want! You can also use the `!team_mischief` command right here to find out more""") except: pass
async def startup_cleanup(self): self.join_cooldown = Configuration.get_persistent_var( "join_cooldown", dict()) for guild in self.bot.guilds: self.init_guild(guild) self.check_cooldown.start()