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, )
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
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)
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
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, )
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
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.")
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, )