Пример #1
0
 async def loa_time_input(ctx: commands.Context):
     """Handles getting Start and End Dates/Times for LOAs"""
     await ctx.maybe_send_embed(
         "When will your LOA begin? Enter as *`month/day`* or *`3d`*." +
         "\n"
         "Enter *`now`* if it will begin right now." + "\n"
         "Enter *`cancel`* to cancel submission.")
     try:
         msg = await ctx.bot.wait_for(
             "message",
             check=MessagePredicate.same_context(ctx),
             timeout=30)
     except asyncio.TimeoutError:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     if msg.content.lower().strip() in ["exit", "cancel", "stop", "no"]:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     startdate = await Time.fromString(msg.content)
     if startdate is None:
         startdate = await Date.fromString(msg.content)
     await ctx.maybe_send_embed(
         "When will your LOA end? Enter as *`month/day`* or *`3d`*." + "\n"
         "Enter *`cancel`* to cancel submission.")
     try:
         msg = await ctx.bot.wait_for(
             "message",
             check=MessagePredicate.same_context(ctx),
             timeout=30)
     except asyncio.TimeoutError:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     if msg.content.lower().strip() in ["exit", "cancel", "stop", "no"]:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     enddate = await Time.fromString(msg.content)
     if enddate is None:
         enddate = await Date.fromString(msg.content)
     if enddate is None:
         return await ctx.maybe_send_embed("Unable to parse End Date.")
     await ctx.maybe_send_embed("Enter your reason for your LOA." + "\n"
                                "Enter *`cancel`* to cancel submission.")
     try:
         msg = await ctx.bot.wait_for(
             "message",
             check=MessagePredicate.same_context(ctx),
             timeout=45)
     except asyncio.TimeoutError:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     if msg.content.lower().strip() in ["exit", "cancel", "stop", "no"]:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     reason = msg.content
     return startdate, enddate, reason
Пример #2
0
 async def loa_time_input(ctx: commands.Context):
     """Handles getting Start and End Dates/Times for LOAs"""
     await ctx.maybe_send_embed(
         "When will your LOA begin? Enter as *`month/day`* or *`3d`*." + "\n"
         "Enter *`now`* if it will begin right now." + "\n"
         "Enter *`cancel`* to cancel submission."
     )
     try:
         msg = await ctx.bot.wait_for(
             "message", check=MessagePredicate.same_context(ctx), timeout=30
         )
     except asyncio.TimeoutError:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     if msg.content.lower().strip() in ["exit", "cancel", "stop", "no"]:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     startdate = await Time.fromString(msg.content)
     if startdate is None:
         startdate = await Date.fromString(msg.content)
     await ctx.maybe_send_embed(
         "When will your LOA end? Enter as *`month/day`* or *`3d`*." + "\n"
         "Enter *`cancel`* to cancel submission."
     )
     try:
         msg = await ctx.bot.wait_for(
             "message", check=MessagePredicate.same_context(ctx), timeout=30
         )
     except asyncio.TimeoutError:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     if msg.content.lower().strip() in ["exit", "cancel", "stop", "no"]:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     enddate = await Time.fromString(msg.content)
     if enddate is None:
         enddate = await Date.fromString(msg.content)
     if enddate is None:
         return await ctx.maybe_send_embed("Unable to parse End Date.")
     await ctx.maybe_send_embed(
         "Enter your reason for your LOA." + "\n" "Enter *`cancel`* to cancel submission."
     )
     try:
         msg = await ctx.bot.wait_for(
             "message", check=MessagePredicate.same_context(ctx), timeout=45
         )
     except asyncio.TimeoutError:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     if msg.content.lower().strip() in ["exit", "cancel", "stop", "no"]:
         return await ctx.maybe_send_embed("LOA Submission Cancelled.")
     reason = msg.content
     return startdate, enddate, reason
Пример #3
0
    async def download_songs(self, ctx):
        botmsg = await ctx.send("Post Genius API token:")

        usercheck = MessagePredicate.same_context(ctx)

        try:
            msg = await self.bot.wait_for('message',
                                          timeout=15, check=usercheck)
        except asyncio.TimeoutError:
            await ctx.send("Timed out!")

        token = msg.content
        await msg.delete()
        await botmsg.delete()

        try:
            await ctx.send("Downloading songs...")
            hat_song_download.downloader(token, self.path)
            await ctx.send("Songs downloaded!")

            self.all_lyrics = self.load_lyrics()

        except ValueError as e:
            await ctx.send("Token invalid.")
            return
Пример #4
0
 async def user_remove_all(self, ctx, discord_user: discord.User):
     """Remove a user's settings for all servers."""
     config = self.config.user(discord_user)
     query = await ctx.send(
         "This action is irrevocable and will remove all of this user's"
         " settings on all servers. Only do this if the user requested it.\n"
         "Settings removal does not prevent the user from later being re-added"
         " or from accessing other bot functions. To do that, ban them with"
         f" `{ctx.clean_prefix}userlocalblocklist add`.\n\n"
         f"If you really want to remove {discord_user.mention} completely, type:\n"
         "  `I understand`"
     )
     try:
         response = await self.bot.wait_for(
             "message_without_command",
             check=MessagePredicate.same_context(
                 channel=ctx.channel, user=ctx.author
             ),
             timeout=30,
         )
     except asyncio.TimeoutError:
         with contextlib.suppress(discord.HTTPException):
             await query.delete()
             return
     if response and response.content.lower() == "i understand":
         await self._user_clear(ctx, config)
     return
Пример #5
0
    async def check_100_plus(ctx: commands.Context, number: int) -> bool:
        """
        Called when trying to delete more than 100 messages at once.

        Prompts the user to choose whether they want to continue or not.

        Tries its best to cleanup after itself if the response is positive.
        """

        prompt = await ctx.send(
            _("Are you sure you want to delete {number} messages? (y/n)").
            format(number=number))
        response = await ctx.bot.wait_for(
            "message", check=MessagePredicate.same_context(ctx))

        if response.content.lower().startswith("y"):
            await prompt.delete()
            try:
                await response.delete()
            except discord.HTTPException:
                pass
            return True
        else:
            await ctx.send(_("Cancelled."))
            return False
Пример #6
0
    async def responses(self, ctx, trigger_name: str):
        """
        Edit the responses for a trigger.
        """
        trigger_name = trigger_name.lower()
        async with self.config.guild(ctx.guild).triggers() as triggers:
            if trigger_name not in triggers:
                await ctx.send("Trigger does not exist.")
                return
            responses = []
            await ctx.send(
                "Every message you send will be counted as a response. To exit or finish adding responses, type `exit`."
            )
            while True:
                msg = await self.bot.wait_for(
                    "message", check=MessagePredicate.same_context(ctx))

                if msg.content.lower() == "exit":
                    break
                elif len(msg.content) > 2000:
                    await ctx.send(
                        "The text response you're trying to create has more than 2000 characters.\nI cannot send messages that are longer than 2000 characters, please try again."
                    )
                    continue
                await msg.add_reaction("✅")
                responses.append(msg.content)
            triggers[trigger_name]["responses"] = responses
            await self.update_trigger(ctx.guild, trigger_name,
                                      triggers[trigger_name])
        await ctx.tick()
Пример #7
0
    async def discover_guild(
        self,
        author: discord.User,
        *,
        mod: bool = False,
        permissions: Union[discord.Permissions, dict] = None,
        prompt: str = "",
    ):
        """
        discovers which of shared guilds between the bot
        and provided user based on conditions (mod or permissions is an or)

        prompt is for providing a user prompt for selection
        """
        shared_guilds = []
        if permissions is None:
            perms = discord.Permissions()
        elif isinstance(permissions, discord.Permissions):
            perms = permissions
        else:
            perms = discord.Permissions(**permissions)

        async for guild in AsyncIter(self.bot.guilds, steps=100):
            x = guild.get_member(author.id)
            if x is not None:
                if await self.internal_filter(x, mod, perms):
                    shared_guilds.append(guild)
        if len(shared_guilds) == 0:
            raise ValueError("No Qualifying Shared Guilds")
        if len(shared_guilds) == 1:
            return shared_guilds[0]
        output = ""
        guilds = sorted(shared_guilds, key=lambda g: g.name)
        for i, guild in enumerate(guilds, 1):
            output += "{}: {}\n".format(i, guild.name)
        output += "\n{}".format(prompt)

        for page in pagify(output, delims=["\n"]):
            await author.send(box(page))

        try:
            message = await self.bot.wait_for(
                "message",
                check=MessagePredicate.same_context(channel=author.dm_channel,
                                                    user=author),
                timeout=45,
            )
        except asyncio.TimeoutError:
            await author.send(
                _("You took too long to select. Try again later."))
            return None

        try:
            message = int(message.content.strip())
            guild = guilds[message - 1]
        except (ValueError, IndexError):
            await author.send(_("That wasn't a valid choice."))
            return None
        else:
            return guild
Пример #8
0
 async def changeIcon(self, ctx):
     """Modify your SCP:SL Server's Icon as shown on discord."""
     if not await self.config.guild(ctx.guild).enabled():
         return await ctx.send(
             "SCPSL Module disabled on this server. Use `{prefix}scpsl enable` to enable the module for this server.".format(
                 prefix=ctx.prefix
             )
         )
     server = await self.config.guild(ctx.guild).server()
     global_servers = await self.config.global_servers()
     guildID = str(ctx.guild.id)
     if not guildID in global_servers and not server:
         try:
             await ctx.send(f"{ctx.guild.name} does not have a registered SCP:SL server")
         except discord.Forbidden:
             pass
         return
     await ctx.send("Enter a url to set as your Icon Thumbnail.")
     try:
         msg = await ctx.bot.wait_for(
             "message", check=MessagePredicate.same_context(ctx), timeout=25
         )
     except asyncio.TimeoutError:
         return await ctx.send("Server Registration Cancelled.")
     if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
         return await ctx.send("Server Editing Cancelled.")
     image = msg.content.strip()
     d = {"icon_url": image}
     await self.updateServer(ctx, d)
Пример #9
0
    async def newcontributors_interactive(self, ctx: GuildContext) -> None:
        """Interactively add contributors.

        Integrates with Red.
        """
        member_converter = commands.MemberConverter()
        pending_contributors = await self.__config.pending_contributors()
        new_added_contributors = {}

        early_exit = False
        for user_id, author_data in pending_contributors.items():
            discord_user_id_line = (
                f"**Discord user ID:** {discord_user_id}\n"
                if (discord_user_id := author_data.get('discord_user_id')) is not None
                else ""
            )
            bot_msg = await ctx.send(
                f"**GitHub Username:** {author_data['username']}\n"
                f"**Commit author name:** {author_data['name']}\n"
                f"**Commit author email:** {author_data['email']}\n"
                f"{discord_user_id_line}"
                "Use Red's `?assign` command or send user ID to add contributor."
                " Type `exit` to finish, use `skip` to skip the contributor."
            )

            while not early_exit:
                user_msg = await self.bot.wait_for(
                    "message_without_command", check=MessagePredicate.same_context(ctx)
                )
                content = user_msg.content

                if content == "exit":
                    early_exit = True
                    continue
                if content == "skip":
                    break

                if user_msg.content.startswith("?assign "):
                    view = StringView(user_msg.content)
                    view.skip_string("?assign ")
                    content = view.get_quoted_word()

                try:
                    member = await member_converter.convert(ctx, content)
                except commands.BadArgument as e:
                    await ctx.send(
                        f"{e}. Please try passing user ID"
                        " or using `?assign` command again."
                    )
                    continue

                author_data["discord_user_id"] = member.id
                new_added_contributors[user_id] = author_data
                break
            else:
                # early-exit by breaking out of for loop
                await safe_delete_message(bot_msg)
                break

            await safe_delete_message(bot_msg)
Пример #10
0
    async def get_responses(self, ctx):
        intro = _(
            "Welcome to the interactive random {cc} maker!\n"
            "Every message you send will be added as one of the random "
            "responses to choose from once this {cc} is "
            "triggered. To exit this interactive menu, type `{quit}`").format(
                cc="customcommand", quit="exit()")
        await ctx.send(intro)

        responses = []
        args = None
        while True:
            await ctx.send(_("Add a random response:"))
            msg = await self.bot.wait_for(
                "message", check=MessagePredicate.same_context(ctx))

            if msg.content.lower() == "exit()":
                break
            else:
                try:
                    this_args = ctx.cog.prepare_args(msg.content)
                except ArgParseError as e:
                    await ctx.send(e.args[0])
                    continue
                if args and args != this_args:
                    await ctx.send(
                        _("Random responses must take the same arguments!"))
                    continue
                args = args or this_args
                responses.append(msg.content)
        return responses
Пример #11
0
async def get_command_for_exceeded_points(ctx: commands.Context):
    """Gets the command to be executed when the user is at or exceeding
    the points threshold for the action"""
    await ctx.send(
        _(
            "Enter the command to be run when the user **exceeds the points for "
            "this action to occur.**\n**If you do not wish to have a command run, enter** "
            "`none`.\n\nEnter it exactly as you would if you were "
            "actually trying to run the command, except don't put a prefix and "
            "use `{user}` in place of any user/member arguments\n\n"
            "WARNING: The command entered will be run without regard to checks or cooldowns. "
            "Commands requiring bot owner are not allowed for security reasons.\n\n"
            "Please wait 15 seconds before entering your response."
        )
    )
    await asyncio.sleep(15)

    await ctx.send(_("You may enter your response now."))

    try:
        msg = await ctx.bot.wait_for(
            "message", check=MessagePredicate.same_context(ctx), timeout=30
        )
    except asyncio.TimeoutError:
        return None
    else:
        if msg.content == "none":
            return None

    command, m = get_command_from_input(ctx.bot, msg.content)
    if command is None:
        await ctx.send(m)
        return None

    return command
Пример #12
0
    async def char_delete(self, ctx):
        """Удалить персонажа"""

        author = ctx.author
        member_id = str(author.id)

        if not self.CharacterClass.is_member_registered(member_id):
            await ctx.send(f"{author.mention}, у вас нет персонажа. "
                           f"Введите `{ctx.prefix}char new`, чтобы создать")
            return

        await ctx.send(
            f"{author.mention}, вы уверены, что хотите удалить своего персонажа?\n"
            "\n"
            "ВНИМАНИЕ: Это действие нельзя отменить. Все ваши предметы, уровень и достижения будут "
            "потеряны безвозвратно.")

        try:
            msg = await self.Red.wait_for(
                "message",
                timeout=30.0,
                check=MessagePredicate.same_context(ctx))
        except TimeoutError:
            await ctx.send(f"{author.mention}, удаление персонажа отменено.")
            return
        if msg.content.lower() in ["да", "д", "yes", "y"]:
            self.CharacterClass.objects(member_id=member_id).delete()
            await ctx.send(
                f"{author.mention}, ваш персонаж удален. "
                f"Введите `{ctx.prefix}char new`, чтобы создать нового.")
        else:
            await ctx.send(f"{author.mention}, удаление персонажа отменено.")
Пример #13
0
        async def query_locked(msg, user, prompt, timeout):
            """Query member with user lock."""

            async def is_query_response(response):
                # so we can ignore '[p]cancel` too. doh!
                # - FIXME: for the love of Pete, why does response.content
                #   contain the cancel command? then we could remove this
                #   foolishness.
                prefixes = await self.bot.get_valid_prefixes(msg.guild)
                config = self.config.guild(msg.guild)
                other_bot_prefixes = await config.bot_prefixes()
                all_prefixes = prefixes + other_bot_prefixes
                ignore_prefixes = r"|".join(
                    re.escape(prefix) for prefix in all_prefixes
                )
                prefix_pat = re.compile(
                    r"^({prefixes})".format(prefixes=ignore_prefixes)
                )
                return not re.match(prefix_pat, response.content)

            response = None
            if member.id not in self.predicate_locks:
                self.predicate_locks[user.id] = asyncio.Lock()
            lock = self.predicate_locks[user.id]
            if lock.locked():
                # An outstanding query for this user hasn't been answered.
                # They must answer it or the timeout must expire before they
                # can start another interaction.
                return

            async with self.predicate_locks[user.id]:
                query = await msg.channel.send(prompt)
                try:
                    response = await self.bot.wait_for(
                        "message_without_command",
                        check=MessagePredicate.same_context(
                            channel=msg.channel, user=user
                        ),
                        timeout=timeout,
                    )
                except asyncio.TimeoutError:
                    with contextlib.suppress(discord.HTTPException):
                        await query.delete()
                        return

                # Cleanup messages:
                if await is_query_response(response):
                    try:
                        await msg.channel.delete_messages((query, response))
                    except (discord.HTTPException, AttributeError):
                        # In case the bot can't delete other users' messages:
                        with contextlib.suppress(discord.HTTPException):
                            await query.delete()
                else:
                    # Response was a command for another bot: just delete the prompt
                    # and discard the response.
                    with contextlib.suppress(discord.HTTPException):
                        await query.delete()
                    response = None
            return response
Пример #14
0
    async def get_responses(self, ctx):
        intro = _(
            "Welcome to the interactive random {cc} maker!\n"
            "Every message you send will be added as one of the random "
            "responses to choose from once this {cc} is "
            "triggered. To exit this interactive menu, type `{quit}`"
        ).format(cc="customcommand", quit="exit()")
        await ctx.send(intro)

        responses = []
        args = None
        while True:
            await ctx.send(_("Add a random response:"))
            msg = await self.bot.wait_for("message", check=MessagePredicate.same_context(ctx))

            if msg.content.lower() == "exit()":
                break
            else:
                try:
                    this_args = ctx.cog.prepare_args(msg.content)
                except ArgParseError as e:
                    await ctx.send(e.args[0])
                    continue
                if args and args != this_args:
                    await ctx.send(_("Random responses must take the same arguments!"))
                    continue
                args = args or this_args
                responses.append(msg.content)
        return responses
Пример #15
0
 async def trivia_upload(self, ctx: commands.Context):
     """Upload a trivia file."""
     if not ctx.message.attachments:
         await ctx.send(
             _("Supply a file with next message or type anything to cancel."
               ))
         try:
             message = await ctx.bot.wait_for(
                 "message",
                 check=MessagePredicate.same_context(ctx),
                 timeout=30)
         except asyncio.TimeoutError:
             await ctx.send(_("You took too long to upload a list."))
             return
         if not message.attachments:
             await ctx.send(_("You have cancelled the upload process."))
             return
         parsedfile = message.attachments[0]
     else:
         parsedfile = ctx.message.attachments[0]
     try:
         await self._save_trivia_list(ctx=ctx, attachment=parsedfile)
     except yaml.error.MarkedYAMLError as exc:
         await ctx.send(_("Invalid syntax: ") + str(exc))
     except yaml.error.YAMLError:
         await ctx.send(
             _("There was an error parsing the trivia list. See logs for more info."
               ))
         LOG.exception("Custom Trivia file %s failed to upload",
                       parsedfile.filename)
Пример #16
0
    async def applyset_questions(self, ctx: commands.Context):
        """Set custom application questions."""
        current_questions = "**Current questions:**"
        for question in await self.config.guild(ctx.guild).questions():
            try:
                current_questions += "\n" + question[0]
            except TypeError:
                current_questions = (
                    "Uh oh, couldn't fetch your questions.\n"
                    + await self._default_questions_string()
                )
                break
        await ctx.send(current_questions)

        same_context = MessagePredicate.same_context(ctx)
        valid_int = MessagePredicate.valid_int(ctx)

        await ctx.send("How many questions?")
        try:
            number_of_questions = await self.bot.wait_for(
                "message", timeout=60, check=valid_int
            )
        except asyncio.TimeoutError:
            return await ctx.send("You took too long. Try again, please.")

        list_of_questions = []
        for _ in range(int(number_of_questions.content)):
            question_list = []

            await ctx.send("Enter question: ")
            try:
                custom_question = await self.bot.wait_for(
                    "message", timeout=60, check=same_context
                )
            except asyncio.TimeoutError:
                return await ctx.send("You took too long. Try again, please.")
            question_list.append(custom_question.content)

            await ctx.send(
                "Enter how the question will look in final embed (f.e. Name): "
            )
            try:
                shortcut = await self.bot.wait_for(
                    "message", timeout=60, check=same_context
                )
            except asyncio.TimeoutError:
                return await ctx.send("You took too long. Try again, please.")
            question_list.append(shortcut.content)

            await ctx.send("Enter how many seconds the applicant has to answer: ")
            try:
                time = await self.bot.wait_for("message", timeout=60, check=valid_int)
            except asyncio.TimeoutError:
                return await ctx.send("You took too long. Try again, please.")
            question_list.append(int(valid_int.result))

            list_of_questions.append(question_list)

        await self.config.guild(ctx.guild).questions.set(list_of_questions)
        await ctx.send("Done!")
Пример #17
0
 async def changeIcon(self, ctx):
     """Modify your SCP:SL Server's Icon as shown on discord."""
     if not await self.config.guild(ctx.guild).enabled():
         return await ctx.send(
             "SCPSL Module disabled on this server. Use `{prefix}scpsl enable` to enable the module for this server."
             .format(prefix=ctx.prefix))
     server = await self.config.guild(ctx.guild).server()
     global_servers = await self.config.global_servers()
     guildID = str(ctx.guild.id)
     if not guildID in global_servers and not server:
         try:
             await ctx.send(
                 f"{ctx.guild.name} does not have a registered SCP:SL server"
             )
         except discord.Forbidden:
             pass
         return
     await ctx.send("Enter a url to set as your Icon Thumbnail.")
     try:
         msg = await ctx.bot.wait_for(
             "message",
             check=MessagePredicate.same_context(ctx),
             timeout=25)
     except asyncio.TimeoutError:
         return await ctx.send("Server Registration Cancelled.")
     if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
         return await ctx.send("Server Editing Cancelled.")
     image = msg.content.strip()
     d = {"icon_url": image}
     await self.updateServer(ctx, d)
Пример #18
0
async def get_command_for_exceeded_points(ctx: commands.Context):
    """Gets the command to be executed when the user is at or exceeding
    the points threshold for the action"""
    await ctx.send(
        _("Enter the command to be run when the user **exceeds the points for "
          "this action to occur.**\n**If you do not wish to have a command run, enter** "
          "`none`.\n\nEnter it exactly as you would if you were "
          "actually trying to run the command, except don't put a prefix and "
          "use `{user}` in place of any user/member arguments\n\n"
          "WARNING: The command entered will be run without regard to checks or cooldowns. "
          "Commands requiring bot owner are not allowed for security reasons.\n\n"
          "Please wait 15 seconds before entering your response."))
    await asyncio.sleep(15)

    await ctx.send(_("You may enter your response now."))

    try:
        msg = await ctx.bot.wait_for("message",
                                     check=MessagePredicate.same_context(ctx),
                                     timeout=30)
    except asyncio.TimeoutError:
        return None
    else:
        if msg.content == "none":
            return None

    command, m = get_command_from_input(ctx.bot, msg.content)
    if command is None:
        await ctx.send(m)
        return None

    return command
Пример #19
0
    async def message(self, ctx):
        """Set the response message!"""
        gconf = self.config.guild(ctx.guild)

        await ctx.send(
            '**Set your message:**\n*Format: "*[something happens]* in x days!*"'
        )

        usercheck = MessagePredicate.same_context(ctx)

        try:

            send_msg = await self.bot.wait_for('message',
                                               timeout=15,
                                               check=usercheck)

            msg_content = str(send_msg.content)
            await self.set_send_msg(gconf, msg_content)

            new_message = await self.get_send_msg(gconf)

            await ctx.send('Message set!\n{}'.format(new_message))

        except asyncio.TimeoutError:
            await ctx.send("Timed out!")
Пример #20
0
    async def edit(
        self,
        ctx: commands.Context,
        command: str,
        *,
        response=None,
        cooldowns: Mapping[str, int] = None,
        ask_for: bool = True,
    ):
        """Edit an already existing custom command"""
        ccinfo = await self.db(ctx.guild).commands.get_raw(command, default=None)

        # Check if this command is registered
        if not ccinfo:
            raise NotFound()

        author = ctx.message.author

        if ask_for and not response:
            await ctx.send(_("Do you want to create a 'randomized' custom command? (y/n)"))

            pred = MessagePredicate.yes_or_no(ctx)
            try:
                await self.bot.wait_for("message", check=pred, timeout=30)
            except TimeoutError:
                await ctx.send(_("Response timed out, please try again later."))
                return
            if pred.result is True:
                response = await self.get_responses(ctx=ctx)
            else:
                await ctx.send(_("What response do you want?"))
                try:
                    resp = await self.bot.wait_for(
                        "message", check=MessagePredicate.same_context(ctx), timeout=180
                    )
                except TimeoutError:
                    await ctx.send(_("Response timed out, please try again later."))
                    return
                response = resp.content

        if response:
            # test to raise
            ctx.cog.prepare_args(response if isinstance(response, str) else response[0])
            ccinfo["response"] = response

        if cooldowns:
            ccinfo.setdefault("cooldowns", {}).update(cooldowns)
            for key, value in ccinfo["cooldowns"].copy().items():
                if value <= 0:
                    del ccinfo["cooldowns"][key]

        if author.id not in ccinfo["editors"]:
            # Add the person who invoked the `edit` coroutine to the list of
            # editors, if the person is not yet in there
            ccinfo["editors"].append(author.id)

        ccinfo["edited_at"] = self.get_now()

        await self.db(ctx.guild).commands.set_raw(command, value=ccinfo)
Пример #21
0
    async def steps(self, ctx):
        """
        Change the text/images provided by the verify command
        """
        steps = await self.config.verify_steps()
        embed_list = []
        pred_continue = MessagePredicate.yes_or_no(ctx)
        pred_steps = MessagePredicate.same_context(ctx)

        for info in steps.values():
            embed=discord.Embed(title=f"{info[0]}", description=f"{info[1]}", color=0xf99437)
            embed.set_image(url=f"{info[2]}")
            embed_list.append(embed)
        
            for embed in embed_list:
                try:
                    await ctx.send(embed=embed)
                except discord.errors.HTTPException:
                    warn_embed=discord.Embed(title="Warning!", description="Unable to display step. This is most likely caused by a bad image URL. Please contact an Admin.", color=0xFF0000)
                    await ctx.send(embed=warn_embed)

        await ctx.send("Would you like to change the above?")
        await self.bot.wait_for("message", check=pred_continue)
        if pred_continue.result is True:
            continue_steps = True
            step_count = 1
            while continue_steps is True:
                await ctx.send(f"Give me a title for step {step_count}")
                msg = await self.bot.wait_for("message", check=pred_steps)
                steps[f'step{step_count}'][0] = msg.content
                await ctx.send(f"Give me a description for step {step_count}")
                msg = await self.bot.wait_for("message", check=pred_steps)
                steps[f'step{step_count}'][1] = msg.content
                await ctx.send(f"Give me an image for step {step_count}")
                msg = await self.bot.wait_for("message", check=pred_steps)
                if msg.attachments:
                    steps[f'step{step_count}'][2] = msg.attachments[0].url
                else:
                    steps[f'step{step_count}'][2] = msg.content
                
                await ctx.send("Add more steps?")
                await self.bot.wait_for("message", check=pred_continue)
                if pred_continue.result is False:
                    continue_steps = False
                else:
                    step_count += 1
            
            await self.config.verify_steps.set(steps)
            await ctx.send("Your new steps are now..")
            embed_list = []
            for info in steps.values():
                embed=discord.Embed(title=f"{info[0]}", description=f"{info[1]}", color=0xf99437)
                embed.set_image(url=f"{info[2]}")
                embed_list.append(embed)
            
            for embed in embed_list:
                await ctx.send(embed=embed)
        else:
            await ctx.send("Understood! The steps will remain unchanged")
Пример #22
0
    async def edit(
        self,
        ctx: commands.Context,
        command: str,
        *,
        response=None,
        cooldowns: Mapping[str, int] = None,
        ask_for: bool = True,
    ):
        """Edit an already existing custom command"""
        ccinfo = await self.db(ctx.guild).commands.get_raw(command, default=None)

        # Check if this command is registered
        if not ccinfo:
            raise NotFound()

        author = ctx.message.author

        if ask_for and not response:
            await ctx.send(_("Do you want to create a 'randomized' custom command? (y/n)"))

            pred = MessagePredicate.yes_or_no(ctx)
            try:
                await self.bot.wait_for("message", check=pred, timeout=30)
            except TimeoutError:
                await ctx.send(_("Response timed out, please try again later."))
                return
            if pred.result is True:
                response = await self.get_responses(ctx=ctx)
            else:
                await ctx.send(_("What response do you want?"))
                try:
                    resp = await self.bot.wait_for(
                        "message", check=MessagePredicate.same_context(ctx), timeout=180
                    )
                except TimeoutError:
                    await ctx.send(_("Response timed out, please try again later."))
                    return
                response = resp.content

        if response:
            # test to raise
            ctx.cog.prepare_args(response if isinstance(response, str) else response[0])
            ccinfo["response"] = response

        if cooldowns:
            ccinfo.setdefault("cooldowns", {}).update(cooldowns)
            for key, value in ccinfo["cooldowns"].copy().items():
                if value <= 0:
                    del ccinfo["cooldowns"][key]

        if author.id not in ccinfo["editors"]:
            # Add the person who invoked the `edit` coroutine to the list of
            # editors, if the person is not yet in there
            ccinfo["editors"].append(author.id)

        ccinfo["edited_at"] = self.get_now()

        await self.db(ctx.guild).commands.set_raw(command, value=ccinfo)
Пример #23
0
    async def enter_article(self, ctx, selected_domain):

        message = await ctx.send(content="Enter the wikia article for " + selected_domain["name"] + ":", delete_after=10)
        response = await ctx.bot.wait_for("message", check=MessagePredicate.same_context(ctx))

        response = str(response.content).replace(" ", "+")

        return response
Пример #24
0
    async def discover_guild(
        self,
        author: discord.User,
        *,
        mod: bool = False,
        permissions: Union[discord.Permissions, dict] = None,
        prompt: str = "",
    ):
        """
        discovers which of shared guilds between the bot
        and provided user based on conditions (mod or permissions is an or)

        prompt is for providing a user prompt for selection
        """
        shared_guilds = []
        if permissions is None:
            perms = discord.Permissions()
        elif isinstance(permissions, discord.Permissions):
            perms = permissions
        else:
            perms = discord.Permissions(**permissions)

        for guild in self.bot.guilds:
            x = guild.get_member(author.id)
            if x is not None:
                if await self.internal_filter(x, mod, perms):
                    shared_guilds.append(guild)
        if len(shared_guilds) == 0:
            raise ValueError("No Qualifying Shared Guilds")
        if len(shared_guilds) == 1:
            return shared_guilds[0]
        output = ""
        guilds = sorted(shared_guilds, key=lambda g: g.name)
        for i, guild in enumerate(guilds, 1):
            output += "{}: {}\n".format(i, guild.name)
        output += "\n{}".format(prompt)

        for page in pagify(output, delims=["\n"]):
            await author.send(box(page))

        try:
            message = await self.bot.wait_for(
                "message",
                check=MessagePredicate.same_context(channel=author.dm_channel, user=author),
                timeout=45,
            )
        except asyncio.TimeoutError:
            await author.send(_("You took too long to select. Try again later."))
            return None

        try:
            message = int(message.content.strip())
            guild = guilds[message - 1]
        except (ValueError, IndexError):
            await author.send(_("That wasn't a valid choice."))
            return None
        else:
            return guild
Пример #25
0
 async def ticketset_case_add(self, ctx: commands.Context,
                              emoji: typing.Union[discord.Emoji, str]):
     """Add a support case type."""
     if await self.config.guild(ctx.guild).enabled():
         return await ctx.send(
             "Uh oh, you cannot add nor remove cases while support is enabled."
         )
     cases = await self.config.guild(ctx.guild).cases.get_raw()
     try:
         if cases[emoji]:
             return await ctx.send(
                 "Uh oh, that emoji is already registered.")
     except KeyError:
         pass
     try:
         await ctx.message.add_reaction(emoji)
     except discord.HTTPException:
         return await ctx.send("Uh oh, I cannot use that emoji.")
     await ctx.send(
         "What is the title of this case? (e.g. Role change requested)")
     try:
         title = await self.bot.wait_for(
             "message",
             timeout=60,
             check=MessagePredicate.same_context(ctx))
     except asyncio.TimeoutError:
         return await ctx.send("You took too long.")
     await ctx.send(
         "What's the message in the reaction message? (e.g. to request a role change)"
     )
     try:
         desc = await self.bot.wait_for(
             "message",
             timeout=60,
             check=MessagePredicate.same_context(ctx))
     except asyncio.TimeoutError:
         return await ctx.send("You took too long.")
     await self.config.guild(ctx.guild).cases.set_raw(emoji,
                                                      value={
                                                          "title":
                                                          title.content,
                                                          "desc":
                                                          desc.content
                                                      })
     await ctx.send(f"{title.content} was assigned to {emoji}.")
Пример #26
0
    async def conversation(self, ctx: commands.Context):
        """Start a conversation with Cleverbot
        You don't need to use a prefix or the command using this mode."""

        if ctx.author.id in self.conversation:
            await ctx.send("There's already a conversation running. Say `close` to stop it.")
            return

        session = await self._make_cleverbot_session()
        self.conversation[ctx.author.id] = {
            "session": session,
            "task": None,
        }

        # Handled when the cog is restarted/unloaded, which we will let the user know.

        await ctx.send(
            "Starting a new Cleverbot session!\n\nSay `close` to stop the conversation"
            " with me !\n\nYour conversation will be automatically closed if CleverBot"
            " receive no answer.\nThis conversation is only available in this channel."
        )

        prefixes = tuple(await self.bot.get_valid_prefixes())

        try:
            while True:
                self.conversation[ctx.author.id]["task"] = task = asyncio.Task(
                    self.bot.wait_for(
                        "message", check=MessagePredicate.same_context(ctx), timeout=300
                    )
                )
                try:
                    message = await task.get_coro()  # Wait for user message...
                except asyncio.TimeoutError:
                    await ctx.send(
                        "You haven't answered me! \N{PENSIVE FACE}\nI'm closing our session..."
                    )
                    break
                except asyncio.CancelledError:
                    await ctx.send("Our session has been cancelled due to cog unload! Closing...")
                    break
                if message.content.startswith(prefixes):
                    continue
                if message.content.lower() in ("close", "c"):
                    await ctx.send("Alright, bye then. \N{WAVING HAND SIGN}")
                    break
                async with ctx.typing():
                    answer, answered = await self.ask_question(
                        session, message.content, message.author.id
                    )
                await message.reply(answer)
                if not answered:
                    break
                continue
        finally:
            await self.conversation[ctx.author.id]["session"].close()
            del self.conversation[ctx.author.id]
Пример #27
0
        async def get_input(timeout=30):
            pred = await ctx.bot.wait_for(
                "message",
                check=MessagePredicate.same_context(ctx),
                timeout=timeout)
            if pred.content.strip().lower() == "cancel":
                raise CancellationError

            return pred.content.strip()
Пример #28
0
    async def race_select(
        self,
        ctx: commands.Context,
        embed: Embed,
        message: discord.Message,
        do_once: bool = True,
    ) -> bool:
        """Requests information from the member about the race of the
        character being registered.

        Args:
            ctx (commands.Context): Same as `RegisterSession.ctx`
            embed (Embed): Same as `RegisterSession.embed`
            message (discord.Message): Same as `RegisterSession.message`
            do_once (bool): The parameter allows not to perform actions that
                are not needed during a recursive method call.

        Returns:
            bool: Whether the correct information is received or not.

        """
        _config = config.humanize
        races = _config.races.values()
        if do_once:
            embed.description = (
                "**Выберите расу персонажа**\n\n"
                f"**Возможные варианты:** {', '.join(races)}.")
            await message.edit(embed=embed)
            do_once = False
        try:
            race = await self.ctx.bot.wait_for(
                "message",
                timeout=60.0,
                check=MessagePredicate.same_context(ctx))
            race_content = race.content.lower()
            await race.delete()
            if race_content not in races:
                incorrect = await ctx.send("Недопустимый ввод!")
                race_select = await self.race_select(ctx, embed, message,
                                                     do_once)
                await incorrect.delete()
                if race_select:
                    return True
                else:
                    await self.cancel(embed, message)
                    return False
            self.char["race"] = list(_config.races.keys())[list(
                _config.races.values()).index(race_content)]
            embed.add_field(name="Раса",
                            value=race_content.title(),
                            inline=True)
            await message.edit(embed=embed)
            return True
        except asyncio.TimeoutError:
            await self.cancel(embed, message)
            return False
Пример #29
0
 async def wait_for_message(self, ctx: commands.Context, content: str):
     msg = await ctx.send(content)
     pred = MessagePredicate.same_context(ctx)
     try:
         message = await self.bot.wait_for("message", check=pred, timeout=60)
     except AsyncTimeoutError:
         return None
     finally:
         await msg.delete()
     return message.content
Пример #30
0
    async def desc_select(
        self,
        ctx: commands.Context,
        embed: Embed,
        message: discord.Message,
        do_once: bool = True,
    ) -> bool:
        """Requests information from the member about the description of the
        character being registered.

        Args:
            ctx (commands.Context): Same as `RegisterSession.ctx`
            embed (Embed): Same as `RegisterSession.embed`
            message (discord.Message): Same as `RegisterSession.message`
            do_once (bool): The parameter allows not to perform actions that
                are not needed during a recursive method call.

        Returns:
            bool: Whether the correct information is received or not.

        """
        if do_once:
            embed.description = (
                "**Опишите своего персонажа**\n\n"
                "В описании персонажа должно быть **не менее 50** и **не более 2000 символов**.\n"
                "Описание персонажа должно состоять из символов **латинского алфавита** или **кириллицы.**"
            )
            await message.edit(embed=embed)
            do_once = False
        try:
            desc = await self.ctx.bot.wait_for(
                "message",
                timeout=600.0,
                check=MessagePredicate.same_context(ctx))
            desc_content = desc.content
            await desc.delete()
            if not re.match(
                    """[a-zа-яA-ZА-ЯёЁ\d\s!.,%*'";:()\[\]<>\-«»—]{50,2000}""",
                    desc_content):
                incorrect = await ctx.send("Недопустимый ввод!")
                desc_select = await self.desc_select(ctx, embed, message,
                                                     do_once)
                await incorrect.delete()
                if desc_select:
                    return True
                else:
                    await self.cancel(embed, message)
                    return False
            self.char["desc"] = desc_content
            embed.description = italics(desc_content)
            await message.edit(embed=embed)
            return True
        except asyncio.TimeoutError:
            await self.cancel(embed, message)
            return False
Пример #31
0
    async def create(self, ctx, trigger_name: str, *, triggered_by: str):
        """
        Create a trigger.

        Variables can be used within the responses.
        user: The user that triggered the trigger.
        channel: The channel the trigger was triggered in.
        message: The message that triggered the trigger.
        guild: The guild the trigger was triggered in.
        uses: The number of times the trigger has been used.
        trigger: The name of the trigger that was triggered.

        Example: `{user} has triggered the trigger {trigger} in {channel} {uses} times.`
        """
        trigger_name = trigger_name.lower()
        triggers = await self.config.guild(ctx.guild).triggers()
        if trigger_name in triggers:
            await ctx.send("Trigger already exists.")
            return
        responses = []
        await ctx.send(
            "Every message you send will be counted as a response. To exit or finish adding responses, type `exit`."
        )
        while True:
            msg = await self.bot.wait_for(
                "message", check=MessagePredicate.same_context(ctx))

            if msg.content.lower() == "exit":
                break
            elif len(msg.content) > 2000:
                await ctx.send(
                    "The text response you're trying to create has more than 2000 characters.\nI cannot send messages that are longer than 2000 characters, please try again."
                )
                continue
            await msg.add_reaction("✅")
            responses.append(msg.content)
        async with self.config.guild(ctx.guild).triggers() as triggers:
            triggers[trigger_name] = {
                "trigger": triggered_by,
                "responses": responses,
                "owner": ctx.author.id,
                "guild": ctx.guild.id,
                "cooldown": 0,
                "timestamp": None,
                "uses": 0,
                "toggle": True,
                "case_sensitive": False,
                "word_boundary": False,
            }
            await self.update_trigger(ctx.guild, trigger_name,
                                      triggers[trigger_name])

        await ctx.send("Trigger created.")
Пример #32
0
    async def name_select(
        self,
        ctx: commands.Context,
        embed: Embed,
        message: discord.Message,
        do_once: bool = True,
    ) -> bool:
        """Requests information from the member about the name of the
        character being registered.

        Args:
            ctx (commands.Context): Same as `RegisterSession.ctx`
            embed (Embed): Same as `RegisterSession.embed`
            message (discord.Message): Same as `RegisterSession.message`
            do_once (bool): The parameter allows not to perform actions that
                are not needed during a recursive method call.

        Returns:
            bool: Whether the correct information is received or not.

        """
        if do_once:
            embed.description = (
                "**Выберите имя персонажа**\n\n"
                "В имени персонажа должно быть **не менее 3** и **не более 25 символов**.\n"
                "Имя персонажа должно состоять из символов **латинского алфавита** или **кириллицы.**"
            )
            await message.edit(embed=embed)
            do_once = False
        try:
            name = await self.ctx.bot.wait_for(
                "message",
                timeout=60.0,
                check=MessagePredicate.same_context(ctx))
            name_content = name.content
            await name.delete()
            if not re.match("""^[a-zа-яA-ZА-ЯёЁ\s'-]{3,25}$""", name_content):
                incorrect = await ctx.send("Недопустимый ввод!")
                name_select = await self.name_select(ctx, embed, message,
                                                     do_once)
                await incorrect.delete()
                if name_select:
                    return True
                else:
                    await self.cancel(embed, message)
                    return False
            self.char["name"] = name_content
            embed.add_field(name="Имя", value=name_content, inline=True)
            await message.edit(embed=embed)
            return True
        except asyncio.TimeoutError:
            await self.cancel(embed, message)
            return False
Пример #33
0
    async def send(self, ctx: commands.Context, *rifts: Messageable):
        """
        Send a message to the specified destinations.

        Editing or deleting the message you send will still forward
        to the bot's reposts, as in normal rifts.
        """
        if not rifts:
            raise commands.UserInputError()
        unique_rifts = deduplicate_iterables(rifts)
        await ctx.send("What would you like to say?")
        p = MessagePredicate.same_context(ctx=ctx)
        message = await ctx.bot.wait_for("message", check=p)
        await self._send(message, unique_rifts)
Пример #34
0
    async def dataconversioncommand(self, ctx: commands.Context, v2path: str):
        """Interactive prompt for importing data from Red V2.

        Takes the path where the V2 install is, and overwrites
        values which have entries in both V2 and v3; use with caution.
        """
        resolver = SpecResolver(Path(v2path.strip()))

        if not resolver.available:
            return await ctx.send(
                _(
                    "There don't seem to be any data files I know how to "
                    "handle here. Are you sure you gave me the base "
                    "installation path?"
                )
            )
        while resolver.available:
            menu = _("Please select a set of data to import by number, or 'exit' to exit")
            for index, entry in enumerate(resolver.available, 1):
                menu += "\n{}. {}".format(index, entry)

            menu_message = await ctx.send(box(menu))

            try:
                message = await self.bot.wait_for(
                    "message", check=MessagePredicate.same_context(ctx), timeout=60
                )
            except asyncio.TimeoutError:
                return await ctx.send(_("Try this again when you are ready."))
            else:
                if message.content.strip().lower() in ["quit", "exit", "-1", "q", "cancel"]:
                    return await ctx.tick()
                try:
                    message = int(message.content.strip())
                    to_conv = resolver.available[message - 1]
                except (ValueError, IndexError):
                    await ctx.send(_("That wasn't a valid choice."))
                    continue
                else:
                    async with ctx.typing():
                        await resolver.convert(self.bot, to_conv)
                    await ctx.send(_("{} converted.").format(to_conv))
            await menu_message.delete()
        else:
            return await ctx.send(
                _(
                    "There isn't anything else I know how to convert here.\n"
                    "There might be more things I can convert in the future."
                )
            )
Пример #35
0
    async def start(self, ctx: commands.Context):
        """
        Begin a game session with Aikanator.

        To answer a question, you can use the following terms:
        - "yes" OR "y" OR "0" for answering "Yes".
        - "no" OR "n" OR "1" for answer "No".
        - "i" OR "idk" OR "i dont know" OR "i don't know" OR "2" for answer "I don't know".
        - "probably" OR "p" OR "3" for answering "Probably".
        - "probably not" OR "pn" OR "4" for answering "Probably not".

        You can also say "b" or "back" to change your last question.
        """

        await ctx.send_help()
        await ctx.send(_("Are you ready to answer Akinator's questions? (y/n)")
                       )
        check = MessagePredicate.yes_or_no(ctx=ctx)
        try:
            await self.bot.wait_for("message", timeout=60, check=check)
        except TimeoutError:
            check.result = False
        if not check.result:
            await ctx.send(_("See you later then! \N{WAVING HAND SIGN}"))
            return
        game_class = UserGame(ctx.author, ctx.channel, self.bot)
        self.ongoing_games[ctx.author.id] = game_class
        await ctx.send(
            _("Do you wish to set a specific language? If so, please specify it now (Find all "
              "available language at "
              "<https://github.com/NinjaSnail1080/akinator.py#functions>) else just say 'no'."
              ))
        try:
            res = await self.bot.wait_for(
                "message",
                timeout=60,
                check=MessagePredicate.same_context(ctx=ctx))
        except asyncio.TimeoutError:
            await ctx.send(_("You didn't answered in time... \N{PENSIVE FACE}")
                           )
            return
        res = res.content.lower()
        lang = res if res not in ("no", "n") else "en"

        try:
            await game_class.start_akinator_game(language=lang)
        finally:
            with suppress(KeyError):
                del self.ongoing_games[ctx.author.id]
Пример #36
0
    async def dataconversioncommand(self, ctx: commands.Context, v2path: str):
        """Interactive prompt for importing data from Red V2.

        Takes the path where the V2 install is, and overwrites
        values which have entries in both V2 and v3; use with caution.
        """
        resolver = SpecResolver(Path(v2path.strip()))

        if not resolver.available:
            return await ctx.send(
                _("There don't seem to be any data files I know how to "
                  "handle here. Are you sure you gave me the base "
                  "installation path?"))
        while resolver.available:
            menu = _(
                "Please select a set of data to import by number, or 'exit' to exit"
            )
            for index, entry in enumerate(resolver.available, 1):
                menu += "\n{}. {}".format(index, entry)

            menu_message = await ctx.send(box(menu))

            try:
                message = await self.bot.wait_for(
                    "message",
                    check=MessagePredicate.same_context(ctx),
                    timeout=60)
            except asyncio.TimeoutError:
                return await ctx.send(_("Try this again when you are ready."))
            else:
                if message.content.strip().lower() in [
                        "quit", "exit", "-1", "q", "cancel"
                ]:
                    return await ctx.tick()
                try:
                    message = int(message.content.strip())
                    to_conv = resolver.available[message - 1]
                except (ValueError, IndexError):
                    await ctx.send(_("That wasn't a valid choice."))
                    continue
                else:
                    async with ctx.typing():
                        await resolver.convert(self.bot, to_conv)
                    await ctx.send(_("{} converted.").format(to_conv))
            await menu_message.delete()
        else:
            return await ctx.send(
                _("There isn't anything else I know how to convert here.\n"
                  "There might be more things I can convert in the future."))
Пример #37
0
 async def forge(ctx, item1, item2):
     newslot = random.choice([item1['slot'],item2['slot']])
     roll = random.randint(1,20)
     if roll == 1:
         modifier = 0.4
     if roll > 1 and roll <= 10:
         modifier = 0.5
     if roll > 10 and roll <= 15:
         modifier = 0.6
     if roll > 15 and roll <= 17:
         modifier = 0.7
     if roll == 18:
         modifier = 0.8
     if roll == 19:
         modifier = 1
     if roll == 20:
         modifier = 1.2
     newatt = round((int(item1['att'])+int(item2['att']))*modifier)
     newdip = round((int(item1['cha'])+int(item2['cha']))*modifier)
     newslot = random.choice([item1['slot'],item2['slot']])
     if len(newslot) == 2: # two handed weapons add their bonuses twice
         hand = "two handed"
     else:
         if newslot[0] == "right" or newslot[0] == "left":
             hand = newslot[0] + " handed"
         else:
             hand = newslot[0] + " slot"
     if len(newslot) == 2:
         await ctx.send('Your forging roll was 🎲({}).\nThe device you tinkered will have {}🗡 and {}🗨 and be {}.'.format(roll,newatt*2,newdip*2,hand))
     else:
         await ctx.send('Your forging roll was 🎲({}).\nThe device you tinkered will have {}🗡 and {}🗨 and be {}.'.format(roll,newatt,newdip,hand))
     await ctx.send('Please respond with a name for your creation within 30s.\n(You will not be able to change it afterwards. 40 characters maximum.)')
     reply = None
     try:
         reply = await ctx.bot.wait_for("message", check=MessagePredicate.same_context(ctx), timeout=30)
     except asyncio.TimeoutError:
         reply = "Unnamed Artifact"
     if reply == None:
         name = "{.:'Unnamed Artifact':.}"
     else:
         if hasattr(reply, 'content'):
             if len(reply.content) > 40:
                 name = "{.:'Long-winded Artifact':.}"
             else:
                 name = "{.:'" + reply.content + "':.}"
         else:
             name = "{.:'" + reply + "':.}"
     item = {"itemname": name,"item": {"slot":newslot,"att":newatt,"cha":newdip}}
     return item
Пример #38
0
 async def changeName(self, ctx):
     """Modify your SCP:SL Server's Name as appeared on discord."""
     if not await self.config.guild(ctx.guild).enabled():
         return await ctx.send(
             "SCPSL Module disabled on this server. Use `{prefix}scpsl enable` to enable the module for this server.".format(
                 prefix=ctx.prefix
             )
         )
     server = await self.config.guild(ctx.guild).server()
     global_servers = await self.config.global_servers()
     guildID = str(ctx.guild.id)
     endport = startport = None
     if not guildID in global_servers and not server:
         try:
             await ctx.send(f"{ctx.guild.name} does not have a registered SCP:SL server")
         except discord.Forbidden:
             pass
         return
     name = None
     while name is None:
         await ctx.send(
             "Enter a name to be displayed for your SCP:SL Server." + "\n"
             "__*Type `default` to use the discord server's name by default.*__"
         )
         try:
             msg = await ctx.bot.wait_for(
                 "message", check=MessagePredicate.same_context(ctx), timeout=25
             )
         except asyncio.TimeoutError:
             return await ctx.send("Server Editing Cancelled.")
         if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
             return await ctx.send("Server Editing Cancelled.")
         name = msg.content[:40]  # 40 Character Limit
         try:
             await self.verifyName(name)
         except AliasTaken as e:
             await ctx.send(str(e))
             name = None
             continue
         else:
             ip = msg.content.strip()
     d = {"name": name}
     await self.updateServer(ctx, d)
Пример #39
0
    async def check_100_plus(ctx: commands.Context, number: int) -> bool:
        """
        Called when trying to delete more than 100 messages at once.

        Prompts the user to choose whether they want to continue or not.

        Tries its best to cleanup after itself if the response is positive.
        """

        prompt = await ctx.send(
            _("Are you sure you want to delete {number} messages? (y/n)").format(number=number)
        )
        response = await ctx.bot.wait_for("message", check=MessagePredicate.same_context(ctx))

        if response.content.lower().startswith("y"):
            await prompt.delete()
            try:
                await response.delete()
            except discord.HTTPException:
                pass
            return True
        else:
            await ctx.send(_("Cancelled."))
            return False
Пример #40
0
 async def changeIP(self, ctx):
     """Modify your SCP:SL Server's IP Address."""
     if not await self.config.guild(ctx.guild).enabled():
         return await ctx.send(
             "SCPSL Module disabled on this server. Use `{prefix}scpsl enable` to enable the module for this server.".format(
                 prefix=ctx.prefix
             )
         )
     server = await self.config.guild(ctx.guild).server()
     global_servers = await self.config.global_servers()
     guildID = str(ctx.guild.id)
     if not guildID in global_servers and not server:
         try:
             await ctx.send(f"{ctx.guild.name} does not have a registered SCP:SL server")
         except discord.Forbidden:
             pass
         return
     ip = None
     while ip is None:
         await ctx.send("Enter the IP Address of your SCP:SL Server.")
         try:
             msg = await ctx.bot.wait_for(
                 "message", check=MessagePredicate.same_context(ctx), timeout=25
             )
         except asyncio.TimeoutError:
             return await ctx.send("Server Registration Cancelled.")
         if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
             return await ctx.send("Server Editing Cancelled.")
         test = await IPconvert(msg.content)
         if test is None:
             await ctx.send("Invalid IP Address.")
             continue
         else:
             ip = msg.content.strip()
     d = {"ip": ip}
     await self.updateServer(ctx, d)
Пример #41
0
    async def registration_input(self, ctx):
        """Handles getting required input for registering SCPSL servers to the bot."""
        attempt = 0
        ip = endport = startport = aliases = None
        while ip is None:
            await ctx.send(
                "Enter the IP Address of your SCP:SL Server." + "\n"
                "__*Type `cancel` to Cancel at any moment.*__"
            )
            try:
                msg = await ctx.bot.wait_for(
                    "message", check=MessagePredicate.same_context(ctx), timeout=25
                )
            except asyncio.TimeoutError:
                return await ctx.send("Server Registration Cancelled.")
            if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
                return await ctx.send("Server Registration Cancelled.")
            ipAddress = await IPconvert(msg.content)
            if ipAddress is None:
                await ctx.send("Invalid IP Address.")
                continue
            else:
                ip = msg.content.strip()
        while endport is None or startport is None:
            await ctx.send(
                f"Enter a port range to track at {ip}. Serpate with `-`" + "\n"
                '*Ex.  "7777 - 7780"*'
            )
            try:
                msg = await ctx.bot.wait_for(
                    "message", check=MessagePredicate.same_context(ctx), timeout=25
                )
            except asyncio.TimeoutError:
                return await ctx.send("Server Registration Cancelled.")
            if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
                return await ctx.send("Server Registration Cancelled.")
            if "-" in msg.content:
                startport, endport = msg.content.split("-")
                try:
                    startport = int(startport)
                    endport = int(endport)
                except ValueError:
                    await ctx.send("Invalid Port Range.")
                    continue
            else:
                startport = 7777
                if len(msg.content.strip()) <= 4:
                    try:
                        endport = int(msg.content.strip())
                    except ValueError:
                        await ctx.send("Invalid Port Range.")
                        continue
                else:
                    await ctx.send("Invalid Port Range. Expected a 4 digit port.")
                    continue
            if startport > endport:
                await ctx.send(
                    f'Invalid port range. Startport "{startport}" cannot be higher than Endport "{endport}"'
                )
                startport = endport = None
                continue

        while aliases is None:
            await ctx.send(
                "Enter a list of Aliases to use `!status <alias>` to view your Server status. *Max. 3 Aliases*"
            )
            try:
                msg = await ctx.bot.wait_for(
                    "message", check=MessagePredicate.same_context(ctx), timeout=35
                )
            except asyncio.TimeoutError:
                return await ctx.send("Server Registration Cancelled.")
            if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
                return await ctx.send("Server Registration Cancelled.")
            aliases = msg.content.strip().split(" ")
            if not aliases:
                aliases = []
            else:
                try:
                    await self.verifyAlias(aliases)
                    # aliases = [alias.lower() for alias in aliases[:3] if await self.verifyAlias(alias)]
                except AliasTaken as e:
                    await ctx.send(str(e))
                    aliases = None
                    continue
                else:
                    aliases = [alias.lower() for alias in aliases[:3]]
            return ip, endport, startport, aliases
Пример #42
0
 async def range(self, ctx):
     """Modify your SCP:SL Server's portrange to track."""
     if not await self.config.guild(ctx.guild).enabled():
         return await ctx.send(
             "SCPSL Module disabled on this server. Use `{prefix}scpsl enable` to enable the module for this server.".format(
                 prefix=ctx.prefix
             )
         )
     server = await self.config.guild(ctx.guild).server()
     global_servers = await self.config.global_servers()
     guildID = str(ctx.guild.id)
     endport = startport = None
     if not guildID in global_servers and not server:
         try:
             await ctx.send(f"{ctx.guild.name} does not have a registered SCP:SL server")
         except discord.Forbidden:
             pass
         return
     while endport is None or startport is None:
         await ctx.send(
             "Enter a port range to track. Serpate with `-`. Enter single port to set endport"
             + "\n"
             '*Ex.  Range : "7777 - 7780"*   *Endport : 7778*'
         )
         try:
             msg = await ctx.bot.wait_for(
                 "message", check=MessagePredicate.same_context(ctx), timeout=25
             )
         except asyncio.TimeoutError:
             return await ctx.send("Server Editing Cancelled.")
         if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
             return await ctx.send("Server Editing Cancelled.")
         if "-" in msg.content:
             startport, endport = msg.content.split("-")
             try:
                 startport = int(startport)
                 endport = int(endport)
             except ValueError:
                 await ctx.send("Invalid Port Range.")
                 continue
         else:
             if server:
                 startport = server["startport"]
             elif guildID in global_servers:
                 async with self.config.global_servers() as global_servers:
                     server = global_servers[guildID]
                     startport = server["startport"]
             if len(msg.content.strip()) <= 4:
                 try:
                     endport = int(msg.content.strip())
                 except ValueError:
                     await ctx.send("Invalid Port Range.")
                     continue
             else:
                 await ctx.send("Invalid Port Range. Expected a 4 digit port.")
                 continue
         if startport > endport:
             await ctx.send(
                 f'Invalid port range. Startport "{startport}" cannot be higher than Endport "{endport}"'
             )
             startport = endport = None
             continue
     d = {
         "endport": endport,
         "startport": startport,
         "portrange": list(
             range(startport, endport + 1) if endport >= startport else range(7777, 7778)
         ),
     }
     await self.updateServer(ctx, d)
Пример #43
0
 async def _aliases(self, ctx):
     """Modify your SCP:SL Server's aliases. Will overwrite previous aliases."""
     if not await self.config.guild(ctx.guild).enabled():
         return await ctx.send(
             "SCPSL Module disabled on this server. Use `{prefix}scpsl enable` to enable the module for this server.".format(
                 prefix=ctx.prefix
             )
         )
     server = await self.config.guild(ctx.guild).server()
     global_servers = await self.config.global_servers()
     guildID = str(ctx.guild.id)
     if not guildID in global_servers and not server:
         try:
             await ctx.send(f"{ctx.guild.name} does not have a registered SCP:SL server")
         except discord.Forbidden:
             pass
         return
     if (
         server
     ):  # Remove and Store Aliases to bypass Alias Verification from checking own server's aliases
         temp_aliases = server.pop("aliases")
         await self.config.guild(ctx.guild).server.set(server)
     elif guildID in global_servers:
         async with self.config.global_servers() as global_servers:
             svr = global_servers[ctx.guild.id]
             temp_aliases = svr.pop("aliases")
     d = {"aliases": temp_aliases}
     aliases = None
     while aliases is None:
         await ctx.send(
             "Enter a list of Aliases to use `!status <alias>` to view your Server status. *Max. 3 Aliases*"
             + "\n"
             "*Type `cancel` to Cancel.*"
         )
         try:
             msg = await ctx.bot.wait_for(
                 "message", check=MessagePredicate.same_context(ctx), timeout=35
             )
         except asyncio.TimeoutError:
             if server:  # Readd temp stored aliases
                 server.update(d)
                 await self.config.guild(ctx.guild).server.set(server)
             elif guildID in global_servers:
                 async with self.config.global_servers() as global_servers:
                     server = global_servers[ctx.guild.id]
                     server.update(d)
                     global_servers[ctx.guild.id] = server
             return await ctx.send("Server Editing Cancelled.")
         if msg.content.strip().lower() in ["cancel", "exit", "stop"]:
             if server:  # Readd temp stored aliases
                 server.update(d)
                 await self.config.guild(ctx.guild).server.set(server)
             elif guildID in global_servers:
                 async with self.config.global_servers() as global_servers:
                     server = global_servers[ctx.guild.id]
                     server.update(d)
                     global_servers[ctx.guild.id] = server
             return await ctx.send("Server Editing Cancelled.")
         aliases = msg.content.strip().split(" ")
         if not aliases:
             aliases = []
         else:
             try:
                 await self.verifyAlias(aliases)
             except AliasTaken as e:
                 await ctx.send(str(e))
                 aliases = None
                 continue
             else:
                 aliases = [alias.lower() for alias in aliases[:3]]
     d = {"aliases": list(aliases)}
     await self.updateServer(ctx, d)
Пример #44
0
    async def report(self, ctx: commands.Context, *, _report: str = ""):
        """Send a report.

        Use without arguments for interactive reporting, or do
        `[p]report <text>` to use it non-interactively.
        """
        author = ctx.author
        guild = ctx.guild
        if guild is None:
            guild = await self.discover_guild(
                author, prompt=_("Select a server to make a report in by number.")
            )
        if guild is None:
            return
        g_active = await self.config.guild(guild).active()
        if not g_active:
            return await author.send(_("Reporting has not been enabled for this server"))
        if guild.id not in self.antispam:
            self.antispam[guild.id] = {}
        if author.id not in self.antispam[guild.id]:
            self.antispam[guild.id][author.id] = AntiSpam(self.intervals)
        if self.antispam[guild.id][author.id].spammy:
            return await author.send(
                _(
                    "You've sent too many reports recently. "
                    "Please contact a server admin if this is important matter, "
                    "or please wait and try again later."
                )
            )
        if author.id in self.user_cache:
            return await author.send(
                _(
                    "Please finish making your prior report before trying to make an "
                    "additional one!"
                )
            )
        self.user_cache.append(author.id)

        if _report:
            _m = copy(ctx.message)
            _m.content = _report
            _m.content = _m.clean_content
            val = await self.send_report(_m, guild)
        else:
            try:
                await author.send(
                    _(
                        "Please respond to this message with your Report."
                        "\nYour report should be a single message"
                    )
                )
            except discord.Forbidden:
                return await ctx.send(_("This requires DMs enabled."))

            try:
                message = await self.bot.wait_for(
                    "message",
                    check=MessagePredicate.same_context(ctx, channel=author.dm_channel),
                    timeout=180,
                )
            except asyncio.TimeoutError:
                return await author.send(_("You took too long. Try again later."))
            else:
                val = await self.send_report(message, guild)

        with contextlib.suppress(discord.Forbidden, discord.HTTPException):
            if val is None:
                await author.send(
                    _("There was an error sending your report, please contact a server admin.")
                )
            else:
                await author.send(_("Your report was submitted. (Ticket #{})").format(val))
                self.antispam[guild.id][author.id].stamp()