Example #1
0
 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()
Example #2
0
 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()
Example #3
0
    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")
Example #4
0
 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
Example #5
0
    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)
Example #6
0
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"
    )
Example #7
0
 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)
Example #8
0
 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)
Example #9
0
    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]
Example #10
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())
Example #11
0
    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
Example #12
0
    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)
Example #13
0
    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)
Example #14
0
    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
Example #15
0
 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()