示例#1
0
    async def countdown(self, ctx, *args):
        """Uses discord message time formatting to provide a countdown

        Usage: `~countdown September 22, 2021 9:00pm EDT`
        """
        logging_utils.log_command("countdown", ctx.channel, ctx.author)

        if len(args) < 1:
            embed = discord_utils.create_no_argument_embed("time")
            await ctx.send(embed=embed)
            return

        user_time = time_utils.parse_date(" ".join(args))

        if user_time is None:
            embed = discord_utils.create_embed()
            embed.add_field(name=f"Failed!",
                            value=f"Is {' '.join(args)} a valid time?",
                            inline=False)
            await ctx.send(embed=embed)
            return

        unix_time = int(datetime.timestamp(user_time))
        embed = discord.Embed(title=f"{' '.join(args)}",
                              description=f"<t:{unix_time}:f>\n"
                                          f"`<t:{unix_time}:R>` - <t:{unix_time}:R>\n\n"
                                          f"[Guide to format](https://discord.com/developers/docs/reference#message-formatting-formats)",
                              color=constants.EMBED_COLOR)
        await ctx.send(embed=embed)
示例#2
0
    async def showweekcalendar(self, ctx, timezone: str = constants.UTC):
        """Show the calendar for the next 7 days

        ~showweekcalendar EDT"""
        logging_utils.log_command("showweekcalendar", ctx.channel, ctx.author)

        server_calendar_results = self.activity_calendar_sheet.findall(
            ctx.guild.name,
            in_column=activity_calendar_constants.SHEET_SERVER_COLUMN)
        description = ""
        current_date = time_utils.parse_date(datetime.utcnow().strftime(
            constants.SHEET_DATETIME_FORMAT),
                                             from_tz=constants.UTC,
                                             to_tz=timezone)
        for cell in server_calendar_results:
            row = self.activity_calendar_sheet.row_values(cell.row)
            date = time_utils.parse_date(
                row[activity_calendar_constants.SHEET_TIMESTAMP_COLUMN - 1],
                from_tz=constants.UTC,
                to_tz=timezone)
            # Only show activities that are 1 week out
            if date.day - current_date.day <= 7:
                description += f"\n\n{time_utils.replace_offset(date.strftime(constants.DISPLAY_DATETIME_FORMAT))}: " \
                               f"[{row[activity_calendar_constants.SHEET_ACTIVITY_COLUMN-1]}:]({row[activity_calendar_constants.SHEET_LINK_COLUMN-1]})" \
                               f" {row[activity_calendar_constants.SHEET_DESCRIPTION_COLUMN-1]}"

        embed = discord.Embed(
            title=
            f"Activity Calendar for Week of {current_date.strftime('%B %d')}",
            description=description,
            color=constants.EMBED_COLOR)
        await ctx.send(embed=embed)
示例#3
0
    async def deleteactivity(self, ctx, *args):
        """Remove all instances of activity from the calendar

        ~deleteactivity Dueling"""
        logging_utils.log_command("deleteactivity", ctx.channel, ctx.author)
        # In general, I've been adding activities with specifics e.g. "Dueling: Helga Game"
        # If you want to delete only that instance, ~dactivity "Dueling: Helga Game"
        # If you want to delete all dueling activities, ~dactivity Dueling
        activity = ' '.join(args)
        result_cells = self.activity_calendar_sheet.findall(
            ctx.guild.name,
            in_column=activity_calendar_constants.SHEET_SERVER_COLUMN)
        num_deletions = 0
        # TODO: I think this whole num_deletions thing becomes a non-issue if we just sort the rows
        # in a descending order
        for cell in result_cells:
            row = self.activity_calendar_sheet.row_values(cell.row)
            if activity in row[
                    activity_calendar_constants.SHEET_ACTIVITY_COLUMN - 1]:
                self.activity_calendar_sheet.delete_row(cell.row -
                                                        num_deletions)
                num_deletions += 1
        embed = discord_utils.create_embed()
        embed.add_field(
            name="Success",
            value=
            f"Deleted {num_deletions} instances of {activity} from the calendar.",
            inline=False)

        await ctx.send(embed=embed)
示例#4
0
 async def endrace(self, ctx):
     """
     DONT USE PLS
     Ends the race
     Usage: ~endrace
     """
     logging_utils.log_command("endrace", ctx.channel, ctx.author)
     channel = ctx.channel.id
     if channel not in self.current_races:
         embed = discord_utils.create_embed()
         embed.add_field(
             name="No race!",
             value=
             "This channel doesn't have a race going on. You can't end something that hasn't started!",
             inline=False)
         embed.add_field(
             name="Start Race",
             value=f"To start a race, use {ctx.prefix}startrace",
             inline=False)
         await ctx.send(embed=embed)
         return
     self.current_races.pop(channel)
     embed = discord_utils.create_embed()
     embed.add_field(
         name="Race Stopped",
         value=f"To start a new race, use {ctx.prefix}startrace",
         inline=False)
     embed.add_field(
         name="Experimental",
         value=
         "ehm, this command is still in development. It actually probably didn't do anything, sorry!",
         inline=False)
     await ctx.send(embed=embed)
示例#5
0
 async def reload(self, ctx):
     """
     Admin Command.
     Reload the Google Sheet so we can update our codes instantly.
     Usage: ~reload
     """
     logging_utils.log_command("reload", ctx.channel, ctx.author)
     self.sheet_map = {
         cipher_race_constants.HP:
         google_utils.get_dataframe_from_gsheet(
             self.spreadsheet.worksheet(
                 cipher_race_constants.HP_SHEET_TAB_NAME),
             cipher_race_constants.COLUMNS),
         cipher_race_constants.COMMON:
         google_utils.get_dataframe_from_gsheet(
             self.spreadsheet.worksheet(
                 cipher_race_constants.COMMON_SHEET_TAB_NAME),
             cipher_race_constants.COLUMNS),
         cipher_race_constants.CHALLENGE:
         google_utils.get_dataframe_from_gsheet(
             self.spreadsheet.worksheet(
                 cipher_race_constants.CHALLENGE_SHEET_TAB_NAME),
             cipher_race_constants.COLUMNS)
     }
     embed = discord_utils.create_embed()
     embed.add_field(name="Sheet Reloaded",
                     value="Google sheet successfully reloaded",
                     inline=False)
     await ctx.send(embed=embed)
示例#6
0
    async def time(self, ctx, *args):
        """Return the time in the specified location

        ~time Amsterdam"""
        logging_utils.log_command("time", ctx.channel, ctx.author)
        # No location provided
        if len(args) < 1:
            embed = discord_utils.create_no_argument_embed("location")
            await ctx.send(embed=embed)
            return
        # Allow long input (e.g. St. Louis, Missouri, USA)
        location = " ".join(args)

        timezone_dict = self.get_tz(location)
        # Unable to find the location in the geonames database
        if timezone_dict is None:
            embed = discord_utils.create_embed()
            embed.add_field(name="Error!", value=f"Cannot find {location}!", inline=False)
            await ctx.send(embed=embed)
            return

        names = ["Location (Timezone)",
                 "Current Time"]
        # The DB provides a - (GMT) for west timezones but not a + for the east
        values = [f"{location.title()} ({time_utils.format_gmt_offset(timezone_dict)})",
                  time_utils.format_time(timezone_dict['time'])]
        embed = discord_utils.populate_embed(names, values, inline=False)

        await ctx.send(embed=embed)
示例#7
0
    async def duelingcategory(self, ctx, *args):
        """Get Dueling Questions from a particular category!

        ~duelingcat"""
        logging_utils.log_command("duelingcategory", ctx.channel, ctx.author)

        categories = self.quarter_tab_get_column("B")
        user_cat = " ".join(args)
        # No supplied category -- give cats
        if len(args) < 1 or user_cat not in categories:
            embed = discord_utils.create_embed()
            embed.add_field(name="Available Categories",
                            value="\n".join(categories))
            await ctx.send(embed=embed)
            return
        # Find all questions of the given category
        # TODO: Hardcoded
        question = self.quarter_tab_get_question(user_cat, 2)
        embed = discord_utils.create_embed()
        embed.add_field(
            name=dueling_constants.THEME,
            value=question[0],
        )  #inline=False)
        embed.add_field(
            name=dueling_constants.CATEGORY,
            value=question[1],
        )  #inline=False)
        embed.add_field(name=dueling_constants.QUESTION,
                        value=question[2],
                        inline=False)
        embed.add_field(name=dueling_constants.ANSWER,
                        value=dueling_utils.format_spoiler_answer(question[3]),
                        inline=False)
        await ctx.send(embed=embed)
示例#8
0
    async def duelingtheme(self, ctx, *args):
        """Get Dueling Questions from a particular theme!

        ~duelingtheme"""
        logging_utils.log_command("duelingtheme", ctx.channel, ctx.author)
        themes = self.quarter_tab_get_column("A")
        user_theme = " ".join(args)
        # No supplied theme -- give themes
        if len(args) < 1 or user_theme not in themes:
            embed = discord_utils.create_embed()
            embed.add_field(name="Available Themes", value="\n".join(themes))
            await ctx.send(embed=embed)
            return
        question = self.quarter_tab_get_question(user_theme, 1)
        embed = discord_utils.create_embed()
        embed.add_field(
            name=dueling_constants.THEME,
            value=question[0],
        )  #inline=False)
        embed.add_field(
            name=dueling_constants.CATEGORY,
            value=question[1],
        )  #inline=False)
        embed.add_field(name=dueling_constants.QUESTION,
                        value=question[2],
                        inline=False)
        embed.add_field(name=dueling_constants.ANSWER,
                        value=dueling_utils.format_spoiler_answer(question[3]),
                        inline=False)
        await ctx.send(embed=embed)
 async def archive(self, ctx, *args):
     logging_utils.log_command("archive", ctx.channel, ctx.author)
     embed = nextcord.Embed(
         title="Error!",
         description=
         f"The command `{ctx.prefix}archive` does not exist! Did you mean `{ctx.prefix}archivechannel` instead?"
     )
     await ctx.send(embed=embed)
示例#10
0
    async def search(self, ctx, *args):
        """
        Command to search the interwebs! (google)
        Usage: ~search <target_site> <[query...]>
        """
        logging_utils.log_command("search", ctx.channel, ctx.author)
        if len(args) < 2:
            await ctx.send(embed=discord_utils.create_no_argument_embed(
                "Target Site and Query"))
            return
        target_site = args[0].lower()
        if target_site in lookup_constants.REGISTERED_SITES:
            target_site = lookup_constants.REGISTERED_SITES[target_site]
        # If we do a google search, we want to return the 10 top results
        # Otherwise, we want to just send the most relevant result
        if target_site == lookup_constants.GOOGLE:
            is_google_search = True
        else:
            is_google_search = False

        original_query = ' '.join(args[1:])
        # Don't add google to the query but add any other target site for easier access/SEO
        if not is_google_search:
            query = original_query + ' ' + target_site
        else:
            query = original_query
        # Dude this loop is going to be horrible wtf
        # If google:
        #   Store all results as a list and print them out line by line in an embed
        # If not google:
        #   Find the first result that matches the target site and return that
        #   If we can't find it, return the google query I think
        embed = discord_utils.create_embed()
        results = []
        for result in googlesearch.search(query,
                                          num=lookup_constants.QUERY_NUM,
                                          stop=lookup_constants.QUERY_NUM,
                                          pause=lookup_constants.PAUSE_TIME):
            if target_site in result:
                embed.add_field(
                    name=
                    f"{target_site.capitalize()} Result for {original_query}",
                    value=result)
                await ctx.send(embed=embed)
                return
            results.append(result)
        if is_google_search:
            embed.add_field(
                name=f"{target_site.capitalize()} Result for {original_query}",
                value=f"{chr(10).join(results)}")
        else:
            embed.add_field(
                name=f"Search failed!",
                value=
                f"Sorry! We weren't able to find a {target_site.capitalize()}"
                f"link for {original_query}. However, here are the top 10 hits on Google:\n"
                f"{chr(10).join(results)}")
        await ctx.send(embed=embed)
示例#11
0
    async def google(self, ctx, *args):
        """Gets the top 10 google results for your query

        ~google The Leaning Tower of Piza"""
        logging_utils.log_command("google", ctx.channel, ctx.author)
        results = lookup_utils.search_query(' '.join(args))

        embed = discord_utils.create_embed()
        embed.add_field(name=f"Google Result for {' '.join(args)}",
                        value=f"{chr(10).join(results)}")
        await ctx.send(embed=embed)
    async def archiveserver(self, ctx):
        """Command to archive every text channel in the server. WARNING: This command will take *very* long on any reasonably aged server

        Usage: `!archiveserver`"""
        logging_utils.log_command("archiveserver", ctx.channel, ctx.author)
        # If we don't have the lock, let the user know it may take a while.
        msg = None
        if self.lock.locked():
            msg = await ctx.send(embed=archive_utils.get_delay_embed())

        # LOCK EVERYTHING
        async with self.lock:
            start_embed = await self.get_start_embed(ctx.guild,
                                                     ctx.guild.text_channels)
            if msg:
                await msg.delete()
                msg = None
            # SOMETIMES THE EMBED IS TOO LONG FOR DISCORD
            embeds = discord_utils.split_embed(start_embed)
            msgs = []
            for embed in embeds:
                msgs.append(await ctx.send(embed=embed))

            for text_channel in ctx.guild.text_channels:
                archive_utils.reset_archive_dir()
                try:
                    zip_file, zip_file_size, textfile, textfile_size = await self.archive_one_channel(
                        text_channel)
                    file, embed = self.get_file_and_embed(
                        text_channel, ctx.guild.filesize_limit, zip_file,
                        zip_file_size, textfile, textfile_size)
                    await ctx.send(file=file, embed=embed)
                except nextcord.errors.Forbidden:
                    embed = discord_utils.create_embed()
                    embed.add_field(
                        name="ERROR: No access",
                        value=
                        f"Sorry! I don't have access to {text_channel.mention}. You'll need "
                        f"to give me permission to view the channel if you want "
                        f"to archive it",
                        inline=False)
                    await ctx.send(embed=embed)
                    continue
            if msgs:
                for msg in msgs:
                    await msg.delete()
            embed = discord_utils.create_embed()
            embed.add_field(name="All Done!",
                            value=f"Successfully archived {ctx.guild}",
                            inline=False)
            await ctx.send(embed=embed)
        # Clean up the archive dir
        archive_utils.reset_archive_dir()
示例#13
0
    async def errorlog(self, ctx, num_lines: int = 50):
        """Admin Command.
        Shows errors in reverse chronological order

        ~errorlog"""
        logging_utils.log_command("errorlog", ctx.channel, ctx.author)
        with open(error_constants.ERROR_LOGFILE, "r") as f:
            lines = f.readlines()
            last_n_lines = "".join(lines[-num_lines:])
            # Trim the length of the log messages
            if len(last_n_lines) > 1990:
                last_n_lines = f"...\n{last_n_lines[-1990:]}"
            await ctx.send(f"```{last_n_lines}```")
示例#14
0
    async def submissions(self, ctx):
        """Count submissions for homework and extra credit

        ~submissions"""
        logging_utils.log_command("submissions", ctx.channel, ctx.author)

        # Get HW and EC if possible
        result_cells = self.activity_calendar_sheet.findall(
            ctx.guild.name,
            in_column=activity_calendar_constants.SHEET_SERVER_COLUMN)
        activity_ids = []
        submission_counts = {}
        for cell in result_cells:
            row = self.activity_calendar_sheet.row_values(cell.row)
            if "Homework:" in row[
                    activity_calendar_constants.SHEET_ACTIVITY_COLUMN -
                    1] or "EC:" in row[
                        activity_calendar_constants.SHEET_ACTIVITY_COLUMN - 1]:
                # TODO: pls
                if row[activity_calendar_constants.SHEET_LINK_COLUMN -
                       1] not in [link[2] for link in activity_ids]:
                    activity_ids.append((
                        row[activity_calendar_constants.SHEET_ACTIVITY_COLUMN -
                            1], row[activity_calendar_constants.
                                    SHEET_DESCRIPTION_COLUMN - 1],
                        row[activity_calendar_constants.SHEET_LINK_COLUMN -
                            1]))

        HOUSES = ["Gryffindor", "Hufflepuff", "Ravenclaw", "Slytherin"]
        description = ""
        for activity in activity_ids:
            submission = asyncpraw.models.Submission(self.reddit_client,
                                                     url=activity[2])
            for comment in await submission.comments():
                for house in HOUSES:
                    if "submit" in comment.body.lower() and house.lower(
                    ) in comment.body.lower():
                        if activity[0] not in submission_counts:
                            submission_counts[activity[0]] = [0, 0, 0, 0]

                        submission_counts[activity[0]][HOUSES.index(
                            house)] = len(comment.replies)

            if activity[0] in submission_counts:
                description += f"\n\n**[{activity[0]}:]({activity[2]})** {activity[1]} \n" \
                               f"{chr(10).join([f'{house}: {submissions}' for house, submissions in zip(HOUSES, submission_counts[activity[0]])])}"
        embed = discord.Embed(title="Submission counts for HW and ECs",
                              description=description,
                              color=constants.EMBED_COLOR)

        await ctx.send(embed=embed)
示例#15
0
    async def duelingmultiplechoice(self, ctx):
        """Get A Multiple Choice Question

        ~duelingmc"""
        logging_utils.log_command("duelingmultiplechoice", ctx.channel,
                                  ctx.author)
        embed = discord_utils.create_embed()
        # Cut off header
        quarter_questions = self.quarter_tab.get_all_values()[1:]
        question = quarter_questions[np.random.randint(len(quarter_questions))]
        # TODO: Hacky way of saying there are not multiple options
        i = 0
        while question[-1] == "":
            question = quarter_questions[np.random.randint(
                len(quarter_questions))]
            i += 1
            if i >= 100:
                embed.add_field(
                    name=f"{constants.FAILED}!",
                    value=
                    f"Sorry! I was unable to find a multiple choice question. Try again later?"
                )
                await ctx.send(embed=embed)
                return

        multiple_choice = [question[3]] + question[5:]
        np.random.shuffle(multiple_choice)
        embed.add_field(
            name=dueling_constants.THEME,
            value=question[0],
        )  #inline=False)
        embed.add_field(
            name=dueling_constants.CATEGORY,
            value=question[1],
        )  #inline=False)
        embed.add_field(name=dueling_constants.QUESTION,
                        value=question[2],
                        inline=False)
        embed.add_field(
            name=dueling_constants.CHOICES,
            # TODO: woof that hardcoded formatting
            # Some of the answers are ints
            value="\n".join([
                f"{letter}.) {str(answer)}" for letter, answer in zip(
                    string.ascii_uppercase, multiple_choice)
            ]))
        embed.add_field(name=dueling_constants.ANSWER,
                        value=dueling_utils.format_spoiler_answer(question[3],
                                                                  filler=20),
                        inline=False)
        await ctx.send(embed=embed)
示例#16
0
    async def monthlychecklist(self, ctx):
        """
        Prints out a list of things to do at the start of every month

        Usage: `~monthlychecklist`
        """
        logging_utils.log_command("monthlychecklist", ctx.channel, ctx.author)

        checklist = self.get_checklist()
        embed = discord_utils.create_embed()
        embed.add_field(name="Monthly Checklist",
                        value=checklist,
                        inline=False)

        await ctx.send(embed=embed)
示例#17
0
 async def reset(self, ctx):
     """
     Admin Command.
     Reset the bot as if it has just loaded up
     Usage: ~reset
     Note: Does not reload google sheet. Use ~reload for that
     """
     logging_utils.log_command("reset", ctx.channel, ctx.author)
     self.current_races = {}
     embed = discord_utils.create_embed()
     embed.add_field(
         name="Success",
         value=
         "Bot has been reset, and all races have been forcibly ended. I feel brand new!",
         inline=False)
     await ctx.send(embed=embed)
示例#18
0
    async def christmas(self, ctx):
        """Print out a countdown to Christmas

        Usage: `~christmas`"""
        logging_utils.log_command("christmas", ctx.channel, ctx.author)

        now = datetime.now(tz=pytz.UTC)
        delta_time = date(now.year, 12, 25) - now.date()
        embed = discord.Embed(
            title=f"There are {delta_time.days} sleeps until {EMOJIS[':Santa_Claus:']} Christmas {EMOJIS[':Christmas_tree:']}",
            url="https://christmascountdown.live/",
            description=f"{EMOJIS[':snowflake:']}{EMOJIS[':cloud_with_snow:']}{EMOJIS[':deer:']}{EMOJIS[':bell:']}{EMOJIS[':cloud_with_snow:']}{EMOJIS[':snowflake:']}\n"
                        f"Check out the countdown timer [here](https://christmascountdown.live/)",

            color=constants.EMBED_COLOR
        )
        await ctx.send(embed=embed)
示例#19
0
    async def duelingrandom(self, ctx):
        """Give a random question

        ~duelingrandom"""
        logging_utils.log_command("duelingrandom", ctx.channel, ctx.author)

        # Cut off headers
        possible_questions = self.quarter_tab.get_all_values(
        )[1:] + self.quotes_tab.get_all_values()[1:]
        question = possible_questions[np.random.randint(
            len(possible_questions))]
        embed = discord_utils.create_embed()
        # TODO: hardcoded hacked
        if len(question) <= 5:
            # name the quote
            embed.add_field(name=dueling_constants.QUOTE_PROMPT,
                            value=question[0],
                            inline=False)
            embed.add_field(name=dueling_constants.ANSWER,
                            value=dueling_utils.format_spoiler_answer(
                                question[4]),
                            inline=False)
            embed.add_field(name="HINT (Book)",
                            value=dueling_utils.format_spoiler_answer(
                                question[2], filler=10),
                            inline=False)
        else:
            # MC question (do not give MC)
            embed.add_field(
                name=dueling_constants.THEME,
                value=question[0],
            )  # inline=False)
            embed.add_field(
                name=dueling_constants.CATEGORY,
                value=question[1],
            )  # inline=False)
            embed.add_field(name=dueling_constants.QUESTION,
                            value=question[2],
                            inline=False)
            embed.add_field(name=dueling_constants.ANSWER,
                            value=dueling_utils.format_spoiler_answer(
                                question[3]),
                            inline=False)
        await ctx.send(embed=embed)
示例#20
0
    async def wikipedia(self, ctx, *args):
        """Gets the Wikipedia article most closely related to your search

        ~wiki Philadelphia"""
        logging_utils.log_command("wikipedia", ctx.channel, ctx.author)
        results = lookup_utils.search_query(' '.join(args),
                                            target_site=lookup_constants.WIKI)

        embed = discord_utils.create_embed()
        if len(results) > 1:
            embed.add_field(
                name=f"Search failed!",
                value=f"Sorry! We weren't able to find a Wikipedia"
                f"link for {' '.join(args)}. However, here are the top 10 hits on Google:\n"
                f"{chr(10).join(results)}")
        else:
            embed.add_field(name=f"Wikipedia Result for {' '.join(args)}",
                            value=f"{chr(10).join(results)}")
        await ctx.send(embed=embed)
示例#21
0
    async def remindme(self, ctx, *args):
        """
        Reminds you to do something later. Pick one of days (d), hours (h), minutes (m)

        Usage: `~remindme 24h Take out the trash`
        """
        logging_utils.log_command("remindme", ctx.channel, ctx.author)

        utctime = datetime.datetime.now(tz=pytz.UTC)

        # TODO: I'm being REALLY loose on the arguments here
        if 'd' in args[0]:
            remind_time = utctime + datetime.timedelta(days=int(args[0][:-1]))
        elif 'h' in args[0]:
            remind_time = utctime + datetime.timedelta(hours=int(args[0][:-1]))
        elif 'm' in args[0]:
            remind_time = utctime + datetime.timedelta(
                minutes=int(args[0][:-1]))
        else:
            embed = discord_utils.create_embed()
            embed.add_field(
                name=f"{constants.FAILED}!",
                value="Must supply a unit of time! (e.g. 5d, 24h, 30m)",
                inline=False)
            await ctx.send(embed=embed)
            return

        self.reminder_tab.append_row([
            ctx.guild.name, ctx.channel.name,
            str(ctx.channel.id),
            remind_time.strftime(constants.SHEET_DATETIME_FORMAT),
            ctx.author.name,
            str(ctx.author.id), ' '.join(args[1:])
        ])

        embed = discord_utils.create_embed()
        embed.add_field(
            name=f"{constants.SUCCESS}!",
            value=
            f"I will remind you to {' '.join(args[1:])} <t:{int(datetime.datetime.timestamp(remind_time))}:R>",
            inline=False)
        await ctx.send(embed=embed)
示例#22
0
    async def duelingquote(self, ctx):
        """Get a quote and answer the SPEAKER and BOOK

        ~duelingquote"""
        logging_utils.log_command("duelingquote", ctx.channel, ctx.author)
        # Cut off header
        quote_questions = self.quotes_tab.get_all_values()[1:]
        question = quote_questions[np.random.randint(len(quote_questions))]
        embed = discord_utils.create_embed()
        embed.add_field(name=dueling_constants.QUOTE_PROMPT,
                        value=question[0],
                        inline=False)
        embed.add_field(name=dueling_constants.ANSWER,
                        value=dueling_utils.format_spoiler_answer(question[4]),
                        inline=False)
        embed.add_field(name="HINT (Book)",
                        value=dueling_utils.format_spoiler_answer(question[2],
                                                                  filler=10),
                        inline=False)
        await ctx.send(embed=embed)
示例#23
0
    async def startrace(self, ctx, sheet: str = cipher_race_constants.HP):
        """
        Start your race! You will have 60 seconds per level to solve the codes
        Usage: ~startrace <optional sheet> where sheet is {hp, challenge, common}
        """
        logging_utils.log_command("startrace", ctx.channel, ctx.author)
        channel = ctx.channel.id
        if channel in self.current_races:
            print("startrace called from a channel that's already racing!!")
            embed = discord_utils.create_embed()
            embed.add_field(
                name="Already Racing!",
                value=
                f"Stop trying to start a new race while you have one going!",
                inline=False)
            await ctx.send(embed=embed)
            return
        # Create entry in current_races
        self.current_races[channel] = dict()
        self.current_races[channel][cipher_race_constants.LEVEL] = 1
        # ~startrace challenge gives you 1000 random english word sheet
        # ~startrace hp gives you the harry potter sheet
        # ~startrace common gives you 1000 very common english words
        if sheet not in self.sheet_map:
            sheet = cipher_race_constants.HP

        self.current_races[channel][
            cipher_race_constants.CODE] = self.sheet_map[sheet]
        embeds, self.current_races[channel][
            cipher_race_constants.
            ANSWERS] = cipher_race_utils.create_code_embed(
                self.current_races[channel][cipher_race_constants.LEVEL],
                self.current_races[channel][cipher_race_constants.CODE],
                ctx.prefix)

        await ctx.send(embed=cipher_race_utils.get_opening_statement(sheet))
        # In a short time, send the codes
        time = Timer(cipher_race_constants.BREAK_TIME,
                     self.start_new_level,
                     callback_args=(ctx, channel, embeds),
                     callback_async=True)
示例#24
0
	async def resend(self, ctx):
		"""Command to resend the last post again.

		~resend"""
		# log command in console
		logging_utils.log_command("resend", ctx.channel, ctx.author)
		# respond to command
		await ctx.send("Resending last announcement!")
		# check for last submission in subreddit
		subreddit = await self.reddit.subreddit()
		async for submission in subreddit.new(limit=1):
			# process submission
			subreddit, title, author, message = RedditPost(self.bot, submission).process_post()
			embed = discord.Embed(title=title,
								  description=f"By u/{author}",
								  color=constants.EMBED_COLOR)
			embed.add_field(name=f"New Post in r/{subreddit}!",
							value=message,
							inline=False)
			channel = self.bot.get_channel(reddit_feed_constants.REDDIT_ANNOUNCEMENTS_CHANNEL_ID)
			await channel.send(embed=embed)
示例#25
0
    async def addactivity(self, ctx: commands.Context, *args):
        """Add an activity to the calendar
        ~addactivity "Dueling" "Harry Potter Trivia!" Tuesday, May 11, 2021 7pm EDT https://www.reddit.com/r/Dueling"""
        logging_utils.log_command("addactivity", ctx.channel, ctx.author)
        # Currently we require the args to be: Activity name, description, date, link
        # They have to use quotes if they want the name or description to be more than 1 word.
        # We pop off the name, description, and link, and what's left is the time.
        # Should we make them put the time in quotes too? Then it would just make things cleaner on the back end
        # I would prefer making it easier to use, though, I guess
        args = list(args)
        activity = args.pop(0)
        description = args.pop(0)
        link = args.pop()

        user_time = time_utils.parse_date(' '.join(args))
        # We store all our times in UTC on the spreadsheet
        spreadsheet_time = time_utils.parse_date(user_time.strftime(
            constants.SHEET_DATETIME_FORMAT),
                                                 to_tz=constants.UTC)

        embed = discord.Embed(title="Added To Activities Calendar",
                              color=constants.EMBED_COLOR)
        embed.add_field(name="Time",
                        value=user_time.strftime(
                            constants.DISPLAY_DATETIME_FORMAT),
                        inline=False)
        embed.add_field(name="Activity", value=f"{activity}", inline=False)
        embed.add_field(name="Description",
                        value=f"{description}",
                        inline=False)
        embed.add_field(name="Link", value=link, inline=False)
        await ctx.send(embed=embed)

        self.activity_calendar_sheet.append_row([
            ctx.guild.name,
            spreadsheet_time.strftime(constants.SHEET_DATETIME_FORMAT),
            activity, description, link
        ])
        self.activity_calendar_sheet.sort(
            (activity_calendar_constants.SHEET_TIMESTAMP_COLUMN, 'asc'))
示例#26
0
    async def showactivitycalendar(self, ctx, timezone: str = constants.UTC):
        """Displays the current activity calendar
        Can add a timezone to display the times in that timezone

        ~showactivitycalendar CEST"""
        logging_utils.log_command("showactivitycalendar", ctx.channel,
                                  ctx.author)
        server_calendar_results = self.activity_calendar_sheet.findall(
            ctx.guild.name,
            in_column=activity_calendar_constants.SHEET_SERVER_COLUMN)
        description = ""
        for cell in server_calendar_results:
            row = self.activity_calendar_sheet.row_values(cell.row)
            date = time_utils.parse_date(
                row[activity_calendar_constants.SHEET_TIMESTAMP_COLUMN - 1],
                from_tz=constants.UTC,
                to_tz=timezone)
            description += f"\n\n{time_utils.replace_offset(date.strftime(constants.DISPLAY_DATETIME_FORMAT))}: " \
                           f"[{row[activity_calendar_constants.SHEET_ACTIVITY_COLUMN-1]}]({row[activity_calendar_constants.SHEET_LINK_COLUMN-1]})"
        embed = discord.Embed(title="Current Activity Calendar",
                              description=description,
                              color=constants.EMBED_COLOR)
        await ctx.send(embed=embed)
示例#27
0
    async def quibbler(self, ctx):
        """
        Generic Quibbler info with links to:
            1.) r/TheQuibbler
            2.) The r/TheQuibbler submission form
            3.) The Issue profile page where all the quibbler's are stored
            4.) The Google Doc which has prompts for inspiration

        ~quib
            """
        logging_utils.log_command("quibbler", ctx.channel, ctx.author)
        description = f"The Quibbler is a light-hearted, quirky, facts-optional online magazine where creativity " \
                      f"and wit are prized over accuracy and factuality. We exist to put smiles on peoples' faces, " \
                      f"including our own! New editions are published quarterly on our [Issuu page]({quibbler_constants.ISSUU_LINK})" \
                      f"\n\nJoin [r/TheQuibbler]({quibbler_constants.SUBREDDIT_LINK})" \
                      f"\n\nAll submissions go to this [Google Form]({quibbler_constants.SUBMISSION_LINK})" \
                      f"\n\nCheck out our inspiration prompt [Google Doc]({quibbler_constants.PROMPT_LIST_LINK})" \
                      f"\n\nFor more information, take a look at r/TheQuibbler's [Wiki]({quibbler_constants.SUBREDDIT_WIKI_LINK})"
        embed = discord.Embed(title=f"r/TheQuibbler Information and Links",
                              color=constants.EMBED_COLOR,
                              description=description)

        await ctx.send(embed=embed)
示例#28
0
    async def unixtime(self, ctx, *args):
        """Return the time given (or current time if no argument) in Unix format (1626206635)

        Usage: `~unixtime Tuesday, September 27, 2021 9pm EDT"""
        logging_utils.log_command("time", ctx.channel, ctx.author)
        embed = discord_utils.create_embed()
        if len(args) < 1:
            curr_time = int(datetime.timestamp(datetime.now()))
            embed.add_field(name="Success!", value=f"Current time is `{curr_time}`", inline=False)
        else:
            user_time = time_utils.parse_date(" ".join(args))
            if user_time is None:
                embed.add_field(name=f"{constants.FAILED}!",
                                value=f"Is {' '.join(args)} a valid time?",
                                inline=False)
                await ctx.send(embed=embed)
                return
            unix_time = int(datetime.timestamp(user_time))
            embed.add_field(name=f"{constants.SUCCESS}!",
                            value=f"The Unix Time at {' '.join(args)} is `{unix_time}`",
                            inline=False)

        await ctx.send(embed=embed)
示例#29
0
    async def dueling(self, ctx):
        """Get info for dueling

        ~dueling"""
        logging_utils.log_command("dueling", ctx.channel, ctx.author)
        embed = discord.Embed(
            title="Welcome to Discord Dueling!",
            color=constants.EMBED_COLOR,
            description=
            f"Get your Harry Potter trivia fill during no-points month right here!\n"
            f"We have several commands to give you full control over what kind of question "
            f"you want!\n\n"
            f"**Multiple Choice**: `{ctx.prefix}duelingmc`\n"
            f"**Name the BOOK and SPEAKER**: `{ctx.prefix}duelingquote`\n"
            f"**Random Question**: `{ctx.prefix}duelingrandom`\n"
            f"**Question from specific CATEGORY**:`{ctx.prefix}duelingcat <category>` "
            f"(use `{ctx.prefix}duelingcat` for available categories)\n"
            f"**Question from specific THEME**:`{ctx.prefix}duelingtheme <theme>` "
            f"(use `{ctx.prefix}duelingtheme` for available themes)\n\n"
            f"For now, I will always include the answer at the end in spoiler text so you "
            f"can check your answer. Feel free to put your answer in here, but be sure to "
            f"cover it with spoiler text! To use spoiler text, surround your answer "
            f"with \|\| e.g. \|\|answer\|\|")
        await ctx.send(embed=embed)
示例#30
0
    async def answer(self, ctx, *args):
        """
        Check your  answer
        Usage: ~answer <your answer>
        """
        channel = ctx.channel.id
        logging_utils.log_command("answer", ctx.channel, ctx.author)

        # if the team isn't puzzling then we need to instruct them to use startpuzzle command first.
        if channel not in self.current_races:
            embed = discord_utils.create_embed()
            embed.add_field(
                name="No race!",
                value=
                "This channel doesn't have a race going on. You can't answer anything!",
                inline=False)
            embed.add_field(
                name="Start Race",
                value=f"To start a race, use {ctx.prefix}startrace",
                inline=False)
            await ctx.send(embed=embed)
            return
        print(
            f"All current answers: {self.current_races[channel][cipher_race_constants.ANSWERS]}"
        )

        # Remove the command and whitespace from the answer.
        user_answer = ''.join(args)
        result = cipher_race_utils.get_answer_result(
            user_answer,
            self.current_races[channel][cipher_race_constants.ANSWERS])

        if result == cipher_race_constants.CORRECT:
            await ctx.message.add_reaction(
                EMOJIS[cipher_race_constants.CORRECT_EMOJI])
        else:
            await ctx.message.add_reaction(
                EMOJIS[cipher_race_constants.INCORRECT_EMOJI])

        # We pop off the correct answers as they are given, so at some point current_answers will be an empty list.
        # If there are more answers left, don't do any of that level complete nonsense.
        if len(self.current_races[channel][
                cipher_race_constants.ANSWERS]) >= 1:
            return
        # If there are no answers left for the round, then the team has completed the level
        # Create the next level prep embed
        embed = cipher_race_utils.create_level_prep_embed(
            self.current_races[channel][cipher_race_constants.LEVEL])
        # Proceed to next level. Perform computation ahead of time.
        self.current_races[channel][cipher_race_constants.LEVEL] += 1
        # Creates all cipher_race embeds, updates used cipher_race IDS, and refreshes current answers for the next level.
        if cipher_race_constants.CODE in self.current_races[channel]:
            embeds, self.current_races[channel][
                cipher_race_constants.
                ANSWERS] = cipher_race_utils.create_code_embed(
                    self.current_races[channel][cipher_race_constants.LEVEL],
                    self.current_races[channel][cipher_race_constants.CODE],
                    ctx.prefix)
        else:
            embeds, self.current_races[channel][
                cipher_race_constants.
                ANSWERS] = cipher_race_utils.create_code_embed(
                    self.current_races[channel][cipher_race_constants.LEVEL],
                    self.codes, ctx.prefix)

        await ctx.send(embed=embed)
        Timer(cipher_race_constants.BREAK_TIME,
              self.start_new_level,
              callback_args=(ctx, channel, embeds),
              callback_async=True)