Beispiel #1
0
 def from_json(cls, bot: Red, data: dict):
     members = data.get("members", [])
     new_members = []
     for m in members:
         if isinstance(m, tuple) or isinstance(m, list):
             log.debug(
                 f"Converting to new members list in {data.get('channel')}")
             new_members.append(m[0])
         else:
             new_members.append(m)
     start = data.get("start")
     if start:
         start = datetime.fromtimestamp(start, tz=timezone.utc)
     guild = data.get("guild")
     if not guild:
         chan = bot.get_channel(data.get("channel"))
         guild = chan.guild.id
     return cls(
         hoster=data.get("hoster"),
         members=new_members,
         event=data.get("event"),
         max_slots=data.get("max_slots"),
         approver=data.get("approver"),
         message=data.get("message"),
         guild=guild,
         channel=data.get("channel"),
         maybe=data.get("maybe"),
         start=start,
     )
Beispiel #2
0
async def get_channel_obj(bot: Red, channel_id: int,
                          data: dict) -> Optional[discord.TextChannel]:
    """
    Requires a bot object to access config, channel_id, and channel config data
    Returns the channel object and sets the guild ID if it's missing from config

    This is used in Game objects and Goal objects so it's here to be shared
    between the two rather than duplicating the code
    """
    if not data["guild_id"]:
        channel = bot.get_channel(id=channel_id)
        if not channel:
            await bot.get_cog("Hockey").config.channel_from_id(channel_id
                                                               ).clear()
            log.info(
                f"{channel_id} channel was removed because it no longer exists"
            )
            return None
        guild = channel.guild
        await bot.get_cog("Hockey").config.channel(channel).guild_id.set(
            guild.id)
        return channel
    guild = bot.get_guild(data["guild_id"])
    if not guild:
        await bot.get_cog("Hockey").config.channel_from_id(channel_id).clear()
        log.info(
            f"{channel_id} channel was removed because it no longer exists")
        return None
    channel = guild.get_channel(channel_id)
    if channel is None:
        await bot.get_cog("Hockey").config.channel_from_id(channel_id).clear()
        log.info(
            f"{channel_id} channel was removed because it no longer exists")
        return None
    return channel
Beispiel #3
0
    def __init__(self, bot: Red, member: discord.Member, data: dict):
        self.bot: Red = bot

        self.member: discord.Member = member
        self.guild: discord.Guild = member.guild
        self.config: dict = data  # Will contain the config of the guild.

        if not self.config["channel"]:
            raise MissingRequiredValueError(
                "Missing channel for verification.")
        self.channel: Union[discord.TextChannel, discord.DMChannel] = (
            bot.get_channel(self.config["channel"])
            if self.config.get("channel") != "dm" else self.member.dm_channel)

        self.type: str = self.config["type"]

        self.messages: dict = {}
        # bot_challenge: Message send for the challenge, contain captcha.
        # logs: The message that has been sent in the logging channel.
        # answer: Member's answer to captcha, may or may not exist.
        self.log = bot.get_cog("Captcha").send_or_update_log_message

        self.running: bool = False
        self.tasks: list = []
        self.limit: int = self.config["retry"]
        self.trynum: int = 0

        self.captcha: discapty.Captcha = discapty.Captcha(self.type)
Beispiel #4
0
    async def start_vote(self, bot: Red, vote: Vote):
        # config this vote will use
        emojis = vote.config.discord.media
        labels = vote.config.github.labels

        channel = bot.get_channel(vote.config.discord.channel_id)
        if channel is None:
            LOG.error(
                f"Error looking up channel_id found in channel conf. channel_id={vote.config.discord.channel_id}"
            )
            raise NoChannel()

        # action to start polling
        async def create_poll():
            embed = _display_vote_start(vote)

            # create msg with menu items
            poll_msg = await channel.send(embed=embed)
            await asyncio.gather(poll_msg.add_reaction(emojis.aye_vote_emoji),
                                 poll_msg.add_reaction(emojis.nay_vote_emoji),
                                 _try_pin(poll_msg, "Voting has started"))

            vote.poll = Poll(
                poll_msg, emojis.aye_vote_emoji, emojis.nay_vote_emoji
            )  # legacy, passing emojis here but should just keep that in config

        # actions needed to start vote
        actions = [
            create_poll(),
            vote.issue.remove_label(labels.needs_vote),
            vote.issue.add_label(labels.vote_in_progress)
        ]

        # remove previous vote results
        for other_label in [
                labels.vote_rejected, labels.vote_accepted,
                labels.vote_in_progress
        ]:
            if other_label in vote.issue.labels:
                actions.append(vote.issue.remove_label(other_label))

        # execute
        LOG.debug(f"Starting vote {vote}")
        try:
            await asyncio.gather(*actions)
            LOG.info(f"Started vote {vote}")
        except Exception as err:
            LOG.exception(f"Error starting vote {vote}")
            raise err

        return vote
Beispiel #5
0
async def safe_raw_edit(
    bot: Red, channel_id: int, message_id: int, *, content: str
) -> None:
    """
    Edits the message without raising.

    This function logs information about HTTP exceptions.
    """
    channel = bot.get_channel(channel_id)
    if channel is None:
        # that should not ever happen...
        log.warning("Channel with ID %s couldn't have been found.", channel_id)
        return
    assert isinstance(channel, discord.TextChannel)

    if not can_edit_in_channel(channel):
        return

    bot_message = RawMessage(bot, channel, message_id)

    try:
        await bot_message.edit(
            content=(
                "The original message with the file has been removed."
                " Gist with that file has been deleted for privacy reasons."
            )
        )
    except discord.NotFound:
        log.debug(
            "The message with ID %s-%s couldn't have been found.",
            channel_id,
            message_id,
        )
    except discord.Forbidden as e:
        log.info(
            "Bot was forbidden to edit message with ID %s-%s.",
            channel_id,
            message_id,
            exc_info=e,
        )
    except discord.HTTPException as e:
        log.error(
            "Unexpected error occurred when trying to edit message with ID %s-%s.",
            channel_id,
            message_id,
            exc_info=e,
        )
Beispiel #6
0
 def __init__(
     self,
     bot: Red,
     dt_str: str,
     text: str,
     timezone: str,
     created_by_id: int,
     role_id: int,
     channel_id: int,
     id_: str = None,
 ):
     super(RoleReminder, self).__init__(
         bot=bot, dt_str=dt_str, text=text, timezone=timezone, created_by_id=created_by_id, id_=id_
     )
     self.role_id = role_id
     self.channel_id = channel_id
     self.channel: TextChannel = bot.get_channel(channel_id)
     self.role: Role = self.channel.guild.get_role(role_id=role_id) if self.channel is not None else None
Beispiel #7
0
async def import_data(bot: Red, mongo_uri: str):
    try:
        from motor import motor_asyncio as motor
    except ImportError:
        raise NoMotorError

    log.info("Starting v2 data migration...")
    db = motor.AsyncIOMotorClient(mongo_uri)
    for starboard in get_starboard_cache().values():
        await starboard.purge_cache(0, update_items=False)

    async with import_lock:
        async for item in db.starboard.stars.find({}):
            if not isinstance(item, dict):
                continue
            message_id = item.get("message_id")
            if message_id is None:
                continue
            channel_id = item.get("channel_id")
            channel: discord.TextChannel = bot.get_channel(int(channel_id))
            if channel is None:
                continue
            guild: discord.Guild = getattr(channel, "guild", None)
            if guild is None:
                continue
            starboard: StarboardGuild = get_starboard(guild)
            await starboard.messages.set_raw(
                str(message_id),
                value={
                    "channel_id": channel.id,
                    "author_id": None,
                    "starred_by": [item.get("starrers", [])],
                    "starboard_message": item.get("starboard_message", None),
                    "hidden": item.get("removed", False),
                },
            )

    log.info("v2 data migration complete.")
Beispiel #8
0
async def get_channel_data(bot: Red, c_id: int,
                           settings: ConfChannelSettings) -> ChannelData:
    """Get ChannelData from the raw config TypedDict ConfChannelSettings

    Parameters
    ----------
    bot : Red
        Bot
    c_id : int
        Channel ID
    settings : ConfChannelSettings
        TypedDict from config

    Returns
    -------
    ChannelData
        ChannelData obj

    Raises
    ------
    NotFound
        Channel not found
    CogDisabled
        Cog disabled in guild
    NoPermission
        No permission to send
    """
    channel: TextChannel = bot.get_channel(c_id)  # type:ignore
    if channel is None:
        # TODO: maybe remove from config
        _log.info(f"I can't find the channel with id {c_id} - skipping")
        raise NotFound

    if await bot.cog_disabled_in_guild_raw("Status", channel.guild.id):
        _log.info(
            f"Cog is disabled in guild {channel.guild.id} (trying to send to channel {c_id}) - "
            "skipping")
        raise CogDisabled

    if settings["webhook"] and not channel.permissions_for(
            channel.guild.me).manage_webhooks:
        _log.info(
            f"I don't have permission to send as a webhook in {c_id} in guild {channel.guild.id} "
            "- will send as normal message")
        settings["webhook"] = False

    if not settings.get("webhook") and not channel.permissions_for(
            channel.guild.me).send_messages:
        _log.info(
            f"Unable to send messages in channel {c_id} in guild {channel.guild.id} - skipping"
        )
        raise NoPermission

    if not settings["webhook"]:
        use_embed = await bot.embed_requested(channel, channel.guild.me)
    else:
        use_embed = True

    return ChannelData(
        channel=channel,
        mode=settings.get("mode", "latest"),
        webhook=settings.get("webhook", False),
        edit_id=settings.get("edit_id", {}),
        embed=use_embed,
    )