예제 #1
0
    async def ping_unverified(self, ctx):
        guild = self.bot.get_guild(Configuration.get_var("guild_id"))
        try:
            nonmember_role = guild.get_role(
                Configuration.get_var("nonmember_role"))
            welcome_channel = self.bot.get_config_channel(
                guild.id, Utils.welcome_channel)
            rules_channel = self.bot.get_config_channel(
                guild.id, Utils.rules_channel)

            if welcome_channel and rules_channel:
                txt = Lang.get_string(
                    "welcome/welcome_msg",
                    user=nonmember_role.mention,
                    rules_channel=rules_channel.mention,
                    accept_emoji=Emoji.get_chat_emoji('CANDLE'))

                await nonmember_role.edit(mentionable=True)
                await welcome_channel.send(txt)
                await nonmember_role.edit(mentionable=False)
                return True
        except Exception as ex:
            Logging.info(f"failed to welcome unverified role.")
            Logging.error(ex)
            raise ex
        return False
예제 #2
0
    async def send_welcome(self, member):
        guild = Utils.get_home_guild()
        if member.guild.id != guild.id or self.is_member_verified(member):
            return False

        try:
            welcome_channel = self.bot.get_config_channel(
                guild.id, Utils.welcome_channel)
            rules_channel = self.bot.get_config_channel(
                guild.id, Utils.rules_channel)

            # Send welcome message in configured language. default to english
            if welcome_channel and rules_channel:
                txt = Lang.get_locale_string(
                    "welcome/welcome_msg",
                    Configuration.get_var('broadcast_locale', 'en_US'),
                    user=member.mention,
                    rules_channel=rules_channel.mention,
                    accept_emoji=Emoji.get_chat_emoji('CANDLE'))
                if self.mute_new_members[member.guild.id]:
                    # add mute notification if mute for new members is on
                    mute_txt = Lang.get_locale_string(
                        "welcome/welcome_mute_msg",
                        Configuration.get_var('broadcast_locale', 'en_US'))
                    txt = f"{txt}\n{mute_txt}"
                await welcome_channel.send(txt)
                return True
        except Exception as ex:
            Logging.info(f"failed to welcome {member.id}")
            Logging.error(ex)
            raise ex
        return False
예제 #3
0
    async def bug_maintenance(self, ctx, active: bool):
        member_role = ctx.guild.get_role(Configuration.get_var("member_role"))

        if active:
            if len(self.in_progress) > 0:
                await ctx.send(
                    f"There are {len(self.in_progress)} report(s) in progress. Not activating maintenance mode."
                )
                return
            await ctx.send("setting bug maintenance mode **on**")
        else:
            await ctx.send("setting bug maintenance mode **off**")
        pass

        # show/hide maintenance channel
        maint_message_channel = self.bot.get_channel(
            Configuration.get_var("bug_maintenance_channel"))

        overwrite = maint_message_channel.overwrites[member_role]
        overwrite.read_messages = active
        await maint_message_channel.set_permissions(member_role,
                                                    overwrite=overwrite)

        for name, cid in Configuration.get_var("channels").items():
            # show/hide reporting channels
            channel = self.bot.get_channel(cid)
            overwrite = channel.overwrites[member_role]
            overwrite.read_messages = None if active else True
            await channel.set_permissions(member_role, overwrite=overwrite)
예제 #4
0
    def is_user_event_ignored(self, event):
        ignored_channels = Configuration.get_var('channels')
        is_ignored_channel = event.channel_id in ignored_channels.values()
        guild = self.bot.get_guild(event.guild_id)
        if not guild:
            # Don't listen to DMs
            return True
        is_bot = event.user_id == self.bot.user.id
        member = guild.get_member(event.user_id)

        if member is None:
            return True  # ignore reaction events from departing members

        is_mod = member and member.guild_permissions.ban_members
        is_admin = event.user_id in Configuration.get_var("ADMINS", [])
        has_admin = False

        for role in member.roles:
            if role in Configuration.get_var("admin_roles", []):
                has_admin = True

        # ignore bot, ignore mod, ignore admin users and admin roles
        if is_bot or is_mod or is_admin or has_admin or is_ignored_channel:
            return True
        return False
예제 #5
0
    async def handle_reaction_change(self, t, reaction, user_id):
        roles = Configuration.get_var("roles")
        if reaction in roles:
            guild = self.bot.get_guild(Configuration.get_var("guild_id"))
            role = guild.get_role(roles[reaction])
            member_role = guild.get_role(Configuration.get_var("member_role"))
            nonmember_role = guild.get_role(
                Configuration.get_var("nonmember_role"))
            member = guild.get_member(user_id)

            if member is None:
                return

            action = getattr(member, f"{t}_roles")
            try:
                await action(role)
                # if acting on member role, toggle corresponding nonmember role
                if role is member_role:
                    if t == 'add':
                        await member.remove_roles(nonmember_role)
                    else:
                        await member.add_roles(nonmember_role)
            except Exception as ex:
                Logging.info("failed")
                Logging.error(ex)
                raise ex
예제 #6
0
 async def on_member_join(self, member):
     if member.guild.id == Configuration.get_var("guild_id"):
         txt = Configuration.get_var("welcome_msg")
         welcome_channel = self.bot.get_channel(
             Configuration.get_var('welcome_channel'))
         txt = txt.format(user=member.mention)
         if welcome_channel is not None:
             await welcome_channel.send(txt)
예제 #7
0
    async def on_member_join(self, member):
        guild = self.bot.get_guild(Configuration.get_var("guild_id"))
        if member.guild.id != guild.id:
            return

        nonmember_role = guild.get_role(
            Configuration.get_var("nonmember_role"))
        await member.add_roles(nonmember_role)
        await self.send_welcome(member)
예제 #8
0
    async def set_rules_react_message_id(self, ctx, message_id: int):
        """
        Set the message ID of the rules react-to-join message

        Setting rules message ID also clears reactions, and may be helpful if discord glitches from too many reacts

        message_id: Message id of rules react message
        """
        rules_channel = self.bot.get_config_channel(ctx.guild.id,
                                                    Utils.rules_channel)
        if message_id and not rules_channel:
            ctx.send(
                'Rules channel must be set in order to set rules message. Try `!channel_config set rules_channel [id]`'
            )

        # clear old reactions
        rules_message_id = Configuration.get_var('rules_react_message_id')
        try:
            # Un-setting rules message. Clear reactions from the old one.
            old_rules = await rules_channel.fetch_message(rules_message_id)
            await old_rules.clear_reactions()
            await ctx.send(f"Cleared reactions from:\n{old_rules.jump_url}")
            # TODO: make this guild-specific
        except Exception as e:
            await ctx.send(f"Failed to clear existing rules reactions")

        try:
            Configuration.MASTER_CONFIG['rules_react_message_id'] = message_id
            Configuration.save()
        except Exception as e:
            await ctx.send(
                f"Failed while saving configuration. Operation will continue, but check the logs..."
            )

        if message_id == 0:
            if rules_message_id == 0:
                await ctx.send(f"Rules message is already unset")
            return

        try:
            new_rules = await rules_channel.fetch_message(message_id)
            roles = Configuration.get_var("roles")
            await new_rules.clear_reactions()
            for emoji, role_id in roles.items():
                # if not Emoji.is_emoji_defined(emoji):
                #     continue
                # emoji = Emoji.get_chat_emoji(emoji)
                await new_rules.add_reaction(emoji)
            await ctx.send(
                f"Rules message set to {message_id} in channel {rules_channel.mention}"
            )
        except (discord.NotFound, discord.Forbidden,
                discord.HTTPException) as e:
            await ctx.send(
                f"Could not find message id {message_id} in channel {rules_channel.mention}"
            )
예제 #9
0
 def is_member_verified(self, member):
     try:
         guild = self.bot.get_guild(Configuration.get_var("guild_id"))
         if member.guild.id != guild.id:
             return True  # non-members are "verified" so we don't try to interact with them
         member_role = guild.get_role(Configuration.get_var("member_role"))
         if member_role not in member.roles:
             return False
         return True
     except Exception as ex:
         return True  # exceptions are "verified" so we don't try to interact with them *again*
예제 #10
0
 async def handle_reaction_change(self, t, reaction, user_id):
     roles = Configuration.get_var("roles")
     if reaction in roles:
         guild = self.bot.get_guild(Configuration.get_var("guild_id"))
         role = guild.get_role(roles[reaction])
         member = guild.get_member(user_id)
         action = getattr(member, f"{t}_roles")
         try:
             await action(role)
         except Exception as ex:
             Logging.info("failed")
             Logging.error(ex)
             raise ex
예제 #11
0
 async def unload(self, ctx, cog: str):
     if cog in ctx.bot.cogs:
         self.bot.unload_extension(f"cogs.{cog}")
         if cog in Configuration.MASTER_CONFIG["cogs"]:
             Configuration.get_var("cogs").remove(cog)
             Configuration.save()
         await ctx.send(f'**{cog}** has been unloaded.')
         await Logging.bot_log(
             f'**{cog}** has been unloaded by {ctx.author.name}')
         Logging.info(f"{cog} has been unloaded")
     else:
         await ctx.send(
             f"{Emoji.get_chat_emoji('NO')} I can't find that cog.")
예제 #12
0
 async def permission_manage_bot(self, ctx):
     db_admin = BotAdmin.get_or_none(userid=ctx.author.id) is not None
     # Logging.info(f"db_admin: {'yes' if db_admin else 'no'}")
     owner = await ctx.bot.is_owner(ctx.author)
     # Logging.info(f"owner: {'yes' if owner else 'no'}")
     in_admins = ctx.author.id in Configuration.get_var("ADMINS", [])
     # Logging.info(f"in_admins: {'yes' if in_admins else 'no'}")
     has_admin_role = False
     if ctx.guild:
         for role in ctx.author.roles:
             if role in Configuration.get_var("admin_roles", []):
                 has_admin_role = True
     # Logging.info(f"has_admin_role: {'yes' if has_admin_role else 'no'}")
     return db_admin or owner or in_admins or has_admin_role
예제 #13
0
    async def count_shadows(self, ctx):
        """
        Count members who have shadow role
        """
        members = self.bot.get_all_members()
        nonmember_role = ctx.guild.get_role(
            Configuration.get_var("nonmember_role"))

        await ctx.send(f"counting members who have the shadow role...")
        count = 0
        multi_role_count = 0
        no_role_count = 0
        for member in members:
            if member.bot or member.guild.id != ctx.guild.id:
                # Don't count bots or members of other guilds
                continue

            if len(member.roles) == 0:
                no_role_count = no_role_count + 1

            if nonmember_role in member.roles:
                count = count + 1
                if len(member.roles) > 1:
                    # count members who have shadow role AND other role(s)
                    multi_role_count = multi_role_count + 1

        content = f"There are {count} members with \"{nonmember_role.name}\" role.\n"
        content += f"Among them, {multi_role_count} members have \"{nonmember_role.name}\" role *and* 1 or more other roles.\n"
        content += f"There are {no_role_count} members with no roles assigned."
        await ctx.send(content)
예제 #14
0
    async def give_shadow(self,
                          ctx,
                          time_delta: typing.Optional[int] = 1,
                          add_role: bool = False):
        """
        Add non-member role to members with no role

        time_delta: how far back (in hours) to search for members with no roles
        add_role:
        """
        recent = self.fetch_non_role(time_delta)
        string_name = 'welcome/darkness' if (len(
            recent['unverified']) == 1) else 'welcome/darkness_plural'
        await ctx.send(
            Lang.get_string(string_name,
                            unverified=len(recent['unverified']),
                            time_delta=time_delta,
                            too_old=len(recent['too_old'])))
        if add_role:
            nonmember_role = ctx.guild.get_role(
                Configuration.get_var("nonmember_role"))
            # slowly add roles, since this may be a large number of members
            count = 0
            try:
                for member in recent['unverified']:
                    await member.add_roles(nonmember_role)
                    count += 1
                    await asyncio.sleep(0.3)
            except Exception as ex:
                await Utils.handle_exception("problem adding nonmember role",
                                             self, ex)
            string_name = 'welcome/darkened' if count == 1 else 'welcome/darkened_plural'
            await ctx.send(Lang.get_string(string_name, count=count))
예제 #15
0
    async def on_member_update(self, before, after):
        try:
            if before.pending and not after.pending:
                # member just accepted rules

                # don't add a role or this defeats the cool-down.
                # wait for member to talk, then add a role.

                # TODO: metrics logging

                # member_role = after.guild.get_role(Configuration.get_var("member_role"))
                # await after.add_roles(member_role)
                # print(f"{after.display_name} is a member now")
                pass
        except Exception as e:
            pass

        try:
            # Enforce member role on any role changes - in case other bot assigns a role.
            # TODO: should this be configurable on|off?
            member_role = before.guild.get_role(
                Configuration.get_var("member_role"))
            member_before = member_role in before.roles
            member_after = member_role in after.roles

            if before.roles != after.roles:
                if (not member_before
                        and not member_after) or (member_before
                                                  and not member_after):
                    await after.add_roles(member_role)
        except Exception as e:
            pass
예제 #16
0
파일: journey.py 프로젝트: e-a-h/journeybot
    async def on_ready(self):
        if not self.loaded:
            Logging.BOT_LOG_CHANNEL = self.get_channel(
                Configuration.get_var("log_channel"))
            Emoji.initialize(self)

            for cog in Configuration.get_var("cogs"):
                try:
                    self.load_extension("cogs." + cog)
                except Exception as e:
                    await Utils.handle_exception(f"Failed to load cog {cog}",
                                                 self, e)
            Logging.info("Cogs loaded")
            self.loop.create_task(self.keepDBalive())
            self.loaded = True

        await Logging.bot_log("Journey bot surfing through the dunes!")
예제 #17
0
파일: Bugs.py 프로젝트: e-a-h/That-Sky-Bot
            async def send_report():
                # save report in the database
                br = BugReport.create(reporter=user.id, platform=platform, deviceinfo=deviceinfo,
                                      platform_version=platform_version, branch=branch, app_version=app_version,
                                      app_build=app_build, title=title, steps=steps, expected=expected, actual=actual,
                                      additional=additional_text)
                for url in attachment_links:
                    Attachments.create(report=br, url=url)

                # send report
                channel_name = f"{platform}_{branch}".lower()

                report_id_saved = False
                attachment_id_saved = False
                user_reported_channels = list()
                all_reported_channels = list()
                selected_platform = BugReportingPlatform.get(platform=platform, branch=branch)

                for row in BugReportingChannel.select().where(BugReportingChannel.platform == selected_platform):
                    report_channel = self.bot.get_channel(row.channelid)
                    message = await report_channel.send(
                        content=Lang.get_locale_string("bugs/report_header", ctx, id=br.id, user=user.mention),
                        embed=report)
                    attachment = None
                    if len(attachment_links) != 0:
                        key = "attachment_info" if len(attachment_links) == 1 else "attachment_info_plural"
                        attachment = await report_channel.send(
                            Lang.get_locale_string(f"bugs/{key}", ctx, id=br.id, links="\n".join(attachment_links)))

                    if report_channel.guild.id == Configuration.get_var('guild_id'):
                        # Only save report and attachment IDs for posts in the official server
                        if not report_id_saved and not attachment_id_saved:
                            if attachment is not None:
                                br.attachment_message_id = attachment.id
                                attachment_id_saved = True
                            br.message_id = message.id
                            report_id_saved = True
                            br.save()
                            user_reported_channels.append(report_channel.mention)
                    else:
                        # guild is not the official server. if author is member, include user_reported_channels
                        this_guild = self.bot.get_guild(report_channel.guild.id)
                        if this_guild.get_member(user.id) is not None:
                            user_reported_channels.append(report_channel.mention)

                    all_reported_channels.append(report_channel)

                channels_mentions = []
                channels_ids = set()
                if not all_reported_channels:
                    await Logging.bot_log(f"no report channels for bug report #{br.id}")

                for report_channel in all_reported_channels:
                    channels_mentions.append(report_channel.mention)
                    channels_ids.add(report_channel.id)
                await channel.send(
                    Lang.get_locale_string("bugs/report_confirmation", ctx, channel_info=', '.join(channels_mentions)))
                await self.send_bug_info(*channels_ids)
예제 #18
0
    async def sweep_trash(self, user):
        await asyncio.sleep(
            Configuration.get_var("bug_trash_sweep_minutes") * 60)
        if user.id in self.in_progress:
            if not self.in_progress[user.id].done() or not self.in_progress[
                    user.id].cancelled():
                await user.send(Lang.get_string("bugs/sweep_trash"))

            await self.delete_progress(user.id)
예제 #19
0
def permission_official(member_id, permission_name):
    # ban permission on official server - sort of a hack to propagate perms
    # TODO: better permissions model
    try:
        official_guild = BOT.get_guild(Configuration.get_var("guild_id"))
        official_member = official_guild.get_member(member_id)
        return getattr(official_member.guild_permissions, permission_name)
    except Exception:
        return False
예제 #20
0
    async def on_ready(self):
        Logging.info(f"Skybot... {'RECONNECT!' if self.loaded else 'STARTUP!'}")
        if self.loaded:
            Logging.info("Skybot reconnect")
            return

        Logging.BOT_LOG_CHANNEL = self.get_channel(Configuration.get_var("log_channel"))
        Emoji.initialize(self)

        for cog in Configuration.get_var("cogs"):
            try:
                self.load_extension("cogs." + cog)
            except Exception as e:
                await Utils.handle_exception(f"Failed to load cog {cog}", self, e)
        Logging.info("Cogs loaded")
        self.db_keepalive = self.loop.create_task(self.keepDBalive())
        self.loaded = True

        await Logging.bot_log("Skybot soaring through the skies!")
예제 #21
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)
예제 #22
0
    async def on_member_remove(self, member):
        # clear rules reactions
        roles = Configuration.get_var("roles")
        guild = self.bot.get_guild(member.guild.id)

        self.remove_member_from_cooldown(guild.id, member.id)

        rules_channel = self.bot.get_config_channel(guild.id,
                                                    Utils.rules_channel)
        rules_message_id = Configuration.get_var('rules_react_message_id')
        try:
            rules = await rules_channel.fetch_message(rules_message_id)
        except Exception as e:
            return

        for reaction, role_id in roles.items():
            try:
                await rules.remove_reaction(reaction, member)
            except Exception as e:
                pass
예제 #23
0
파일: artbot.py 프로젝트: e-a-h/artbot
    async def on_ready(self):
        if self.loaded:
            Logging.info(f"{self.my_name} reconnect")
            return

        Logging.BOT_LOG_CHANNEL = self.get_channel(
            Configuration.get_var("log_channel"))
        Emoji.initialize(self)

        for cog in Configuration.get_var("cogs"):
            try:
                self.load_extension("cogs." + cog)
            except Exception as e:
                await Utils.handle_exception(f"Failed to load cog {cog}", self,
                                             e)
        Logging.info("Cogs loaded")
        self.db_keepalive = self.loop.create_task(self.keepDBalive())
        self.loaded = True

        await Logging.bot_log(f"{self.my_name} has started. Time to bot!")
예제 #24
0
 def is_member_unverified(self, member):
     try:
         guild = Utils.get_home_guild()
         if member.guild.id != guild.id:
             return True  # non-members are "verified" so we don't try to interact with them
         nonmember_role = guild.get_role(
             Configuration.get_var("nonmember_role"))
         if nonmember_role not in member.roles:
             return False
         return True
     except Exception as ex:
         return True  # exceptions are "verified" so we don't try to interact with them *again*
예제 #25
0
    async def on_member_join(self, member):
        if self.mute_new_members and not self.discord_verification_flow:
            self.bot.loop.create_task(self.mute_new_member(member))

        if self.discord_verification_flow:
            # do not welcome new members when using discord verification
            # set entry_channel to use discord verification
            return

        # Only send welcomes for configured guild i.e. sky official
        # TODO: retool to allow any guild to welcome members?
        guild = self.bot.get_guild(Configuration.get_var("guild_id"))
        if member.guild.id != guild.id:
            return

        # add the nonmember role
        nonmember_role = guild.get_role(
            Configuration.get_var("nonmember_role"))
        await member.add_roles(nonmember_role)

        # send the welcome message
        await self.send_welcome(member)
예제 #26
0
    async def create_site(self):
        port = Configuration.get_var('METRICS_PORT', 8080)

        await asyncio.sleep(10)
        print("starting metrics server")
        metrics_app = web.Application()
        metrics_app.add_routes([web.get("/metrics", self.serve_metrics)])

        runner = web.AppRunner(metrics_app)
        await self.bot.loop.create_task(runner.setup())
        site = web.TCPSite(runner, port=port, host='localhost')
        await site.start()

        self.metric_server = site
예제 #27
0
    async def on_message(self, message: discord.Message):
        if message.author.bot or message.author.guild_permissions.mute_members:
            return

        member_role = message.guild.get_role(
            Configuration.get_var("member_role"))
        if member_role in message.author.roles:
            return

        welcome_channel = self.bot.get_config_channel(message.guild.id,
                                                      Utils.welcome_channel)
        rules_channel = self.bot.get_config_channel(message.guild.id,
                                                    Utils.rules_channel)
        log_channel = self.bot.get_config_channel(message.guild.id,
                                                  Utils.log_channel)
        if not welcome_channel or not rules_channel:
            # ignore when channels not configured
            return

        if message.channel.id != welcome_channel.id:
            return

        now = datetime.now().timestamp()
        then = 0
        grace_period = 10 * 60  # 3 minutes

        try:
            was_welcomed = self.welcome_talkers[message.guild.id][
                message.author.id]
            then = was_welcomed + grace_period
        except Exception as ex:
            pass

        if then > now:
            # print("it hasn't been 10 minutes...")
            return

        # record the time so member won't be pinged again too soon if they keep talking
        self.welcome_talkers[message.guild.id][message.author.id] = now
        await welcome_channel.send(
            Lang.get_string("welcome/welcome_help",
                            author=message.author.mention,
                            rules_channel=rules_channel.mention))
        # ping log channel with detail
        if log_channel:
            await log_channel.send(
                f"{message.author.mention} spoke in {welcome_channel.mention} ```{message.content}```"
            )
예제 #28
0
 async def on_message(self, message: discord.Message):
     if message.author.bot:
         return
     if not hasattr(message.channel,
                    "guild") or message.channel.guild is None:
         return
     prefix = Configuration.get_var("bot_prefix")
     if message.content.startswith(prefix, 0):
         for trigger in self.commands[message.guild.id]:
             if message.content.lower() == prefix + trigger or (
                     message.content.lower().startswith(
                         trigger, len(prefix)) and
                     message.content.lower()[len(prefix + trigger)] == " "):
                 command_content = self.commands[
                     message.guild.id][trigger].replace("@", "@\u200b")
                 await message.channel.send(command_content)
예제 #29
0
    async def on_message(self, message: discord.Message):
        prefix = Configuration.get_var("bot_prefix")
        is_boss = await self.cog_check(message)
        command_context = message.content.startswith(prefix, 0) and is_boss
        not_in_guild = not hasattr(message.channel,
                                   "guild") or message.channel.guild is None

        if message.author.bot or command_context or not_in_guild:
            return

        m = self.bot.metrics
        pattern = re.compile(self.words[message.guild.id], re.IGNORECASE)
        # find all matches and reduce to unique set
        words = set(pattern.findall(message.content))
        for word in words:
            # increment counters
            word = str(word).lower()
            m.word_counter.labels(word=word).inc()
예제 #30
0
파일: Bugs.py 프로젝트: e-a-h/That-Sky-Bot
 async def reset_active(self, ctx):
     """Reset active bug reports. Bot will attempt to DM users whose reports are cancelled."""
     to_kill = len(self.in_progress)
     active_keys = [key for key in self.in_progress.keys()]
     for uid in active_keys:
         try:
             await self.delete_progress(uid)
             user = self.bot.get_user(uid)
             await user.send(Lang.get_locale_string('bugs/user_reset',
                                                    Configuration.get_var('broadcast_locale', 'en_US')))
             await ctx.send(Lang.get_locale_string('bugs/reset_success', uid=uid))
         except Exception as e:
             await ctx.send(Lang.get_locale_string('bugs/reset_fail', uid=uid))
     self.in_progress = dict()
     await ctx.send(Lang.get_locale_string('bugs/dead_bugs_cleaned',
                                           ctx,
                                           active_keys=len(active_keys),
                                           in_progress=len(self.in_progress)))