Esempio n. 1
0
 async def update_setting(self, ctx, setting_key: str, setting_value: str):
     """*(admin) Update guild setting: !update_setting key value*"""
     guild_id = ctx.guild.id
     settings = GuildSettingsDb.get(guild_id)
     if hasattr(settings, setting_key):
         old_value = getattr(settings, setting_key)
         setattr(settings, setting_key, setting_value)
         GuildSettingsDb.commit(settings)
         await ctx.send(f":white_check_mark: Updated `{setting_key}={setting_value}` from old value: `{old_value}`")
     else:
         await ctx.send(f":exclamation: Unrecognized setting key: `{setting_key}`. Use `!show_settings` for more info.")
    async def create_puzzle_spreadsheet(self,
                                        text_channel: discord.TextChannel,
                                        puzzle: PuzzleData):
        guild_id = text_channel.guild.id
        name = self.cap_name(puzzle.name)
        round_name = self.cap_name(puzzle.round_name)
        if name == "meta":
            # Distinguish metas between different rounds
            name = f"{name} ({round_name})"

        settings = GuildSettingsDb.get(guild_id)
        if not settings.drive_parent_id:
            return

        try:
            # create drive folder if needed
            round_folder = await get_or_create_folder(
                name=round_name, parent_id=settings.drive_parent_id)
            round_folder_id = round_folder["id"]

            spreadsheet = await create_spreadsheet(agcm=self.agcm,
                                                   title=name,
                                                   folder_id=round_folder_id)
            puzzle.google_folder_id = round_folder_id
            puzzle.google_sheet_id = spreadsheet.id
            PuzzleJsonDb.commit(puzzle)

            # inform spreadsheet creation
            puzzle_url = puzzle.hunt_url
            sheet_url = urls.spreadsheet_url(spreadsheet.id)
            emoji = GuildSettingsDb.get_cached(guild_id).discord_bot_emoji
            embed = discord.Embed(
                description=
                f"{emoji} I've created a spreadsheet for you at {sheet_url}. "
                f"Check out the `Quick Links` tab for more info! "
                # NOTE: This next sentence might be better elsewhere, for now easy enough to add message here.
                f"I've assumed the puzzle page is {puzzle_url}, use `!link` to update if needed."
            )
            await text_channel.send(embed=embed)

            # add some helpful links
            await self.add_quick_links_worksheet(spreadsheet, puzzle, settings)

        except Exception as exc:
            logger.exception(
                f"Unable to create spreadsheet for {round_name}/{name}")
            await text_channel.send(
                f":exclamation: Unable to create spreadsheet for {round_name}/{name}: {exc}"
            )
            return

        return spreadsheet
 async def refresh_nexus(self):
     """Ref: https://discordpy.readthedocs.io/en/latest/ext/tasks/"""
     for guild in self.bot.guilds:
         settings = GuildSettingsDb.get_cached(guild.id)
         if settings.drive_nexus_sheet_id:
             puzzles = PuzzleJsonDb.get_all(guild.id)
             await update_nexus(agcm=self.agcm,
                                file_id=settings.drive_nexus_sheet_id,
                                puzzles=puzzles)
Esempio n. 4
0
    async def check_is_bot_channel(self, ctx) -> bool:
        """Check if command was sent to bot channel configured in settings"""
        settings = GuildSettingsDb.get_cached(ctx.guild.id)
        if not settings.discord_bot_channel:
            # If no channel is designated, then all channels are fine
            # to listen to commands.
            return True

        if ctx.channel.name == settings.discord_bot_channel:
            # Channel name matches setting (note, channel name might not be unique)
            return True

        await ctx.send(f":exclamation: Most bot commands should be sent to #{settings.discord_bot_channel}")
        return False
Esempio n. 5
0
    async def create_puzzle_channel(self, ctx, round_name: str, puzzle_name: str):
        """Create new text channel for puzzle, and optionally a voice channel

        Save puzzle metadata to data_dir, send initial messages to channel, and
        create corresponding Google Sheet if GoogleSheets cog is set up.
        """
        guild = ctx.guild
        category_name = self.clean_name(round_name)
        category = discord.utils.get(guild.categories, name=category_name)
        if category is None:
            raise ValueError(f"Round {category_name} not found")

        channel_name = self.clean_name(puzzle_name)
        text_channel, created_text = await self.get_or_create_channel(
            guild=guild, category=category, channel_name=channel_name, channel_type="text", reason=self.PUZZLE_REASON
        )
        settings = GuildSettingsDb.get_cached(guild.id)
        if created_text:
            puzzle_data = PuzzleData(
                name=channel_name,
                round_name=category_name,
                round_id=category.id,
                guild_name=guild.name,
                guild_id=guild.id,
                channel_mention=text_channel.mention,
                channel_id=text_channel.id,
                start_time=datetime.datetime.now(tz=pytz.UTC),
            )
            if settings.hunt_url:
                # NOTE: this is a heuristic and may need to be updated!
                # This is based on last year's URLs, where the URL format was
                # https://<site>/puzzle/puzzle_name
                hunt_url_base = settings.hunt_url.rstrip("/")
                if channel_name == "meta":
                    # Use the round name in the URL
                    hunt_name = category_name.lower().replace("-", settings.hunt_url_sep)
                else:
                    hunt_name = channel_name.replace("-", settings.hunt_url_sep)
                puzzle_data.hunt_url = f"{hunt_url_base}/{hunt_name}"
            PuzzleJsonDb.commit(puzzle_data)
            await self.send_initial_puzzle_channel_messages(text_channel)

            gsheet_cog = self.bot.get_cog("GoogleSheets")
            # print("google sheets cog:", gsheet_cog)
            if gsheet_cog is not None:
                # update google sheet ID
                await gsheet_cog.create_puzzle_spreadsheet(text_channel, puzzle_data)
        else:
            puzzle_data = self.get_puzzle_data_from_channel(text_channel)

        created_voice = False
        if settings.discord_use_voice_channels:
            voice_channel, created_voice = await self.get_or_create_channel(
                guild=guild, category=category, channel_name=channel_name, channel_type="voice", reason=self.PUZZLE_REASON
            )
            if created_voice:
                puzzle_data.voice_channel_id = voice_channel.id
                PuzzleJsonDb.commit(puzzle_data)

        created = created_text or created_voice
        if created:
            if created_text and created_voice:
                created_desc = "text and voice"  # I'm sure there's a more elegant way to do this ..
            elif created_text:
                created_desc = "text"
            elif created_voice:
                created_desc = "voice"

            await ctx.send(
                f":white_check_mark: I've created new puzzle {created_desc} channels for {category.mention}: {text_channel.mention}"
            )
        else:
            await ctx.send(
                f"I've found an already existing puzzle channel for {category.mention}: {text_channel.mention}"
            )
        return (text_channel, voice_channel, created)
Esempio n. 6
0
 async def show_settings(self, ctx):
     """*(admin) Show guild-level settings*"""
     guild_id = ctx.guild.id
     settings = GuildSettingsDb.get(guild_id)
     await ctx.channel.send(f"```json\n{settings.to_json()}```")
Esempio n. 7
0
 def get_guild_settings_from_ctx(cls, ctx, use_cached: bool = True) -> GuildSettings:
     guild_id = ctx.guild.id
     if use_cached:
         return GuildSettingsDb.get_cached(guild_id)
     else:
         return GuildSettingsDb.get(guild_id)