def setup(bot: Red): if not bot._cli_flags.dev: raise CogLoadError("This cog requires the `--dev` CLI flag.") if getattr(bot.get_cog("Dev"), "sessions", None): raise CogLoadError("End your REPL session(s) first.") bot.remove_cog("Dev") bot.add_cog(Dev())
def setup(bot: Red) -> None: cog = bot.get_cog("CustomCommands") if cog: raise CogLoadError( "This cog conflicts with CustomCommands and cannot be loaded with both at the same time." ) bot.add_cog(Tags(bot))
async def period_recap(self, bot: Red, period: Literal["1st", "2nd", "3rd"]) -> None: """ Builds the period recap """ em = await self.make_game_embed(False, period) tasks = [] post_state = ["all", self.home_team, self.away_team] config = bot.get_cog("Hockey").config all_channels = await bot.get_cog("Hockey").config.all_channels() async for channel_id, data in AsyncIter(all_channels.items(), steps=100): channel = await get_channel_obj(bot, channel_id, data) if not channel: continue should_post = await check_to_post(bot, channel, data, post_state, self.game_state) should_post &= "Periodrecap" in await config.channel( channel).game_states() publish = "Periodrecap" in await config.channel(channel ).publish_states() if should_post: bot.loop.create_task( self.post_period_recap(channel, em, publish))
def has_perm(perm: str, user: User, bot: Red, default: bool = False) -> bool: if user.id in bot.owner_ids: return True authcog: Any = bot.get_cog("GlobalAdmin") if not authcog: return default return authcog.settings.get_perm(user.id, perm, default=default)
async def hierarchy_allows(bot: Red, mod: discord.Member, member: discord.Member, *, allow_disable: bool = True) -> bool: """Check if a guild's role hierarchy allows an action. This can be effectively disabled on a per-guild basis with the Mod cog; however, this can be overridden with the `allow_disable` keyword argument. """ if await bot.is_owner(mod): return True guild = mod.guild if guild != member.guild: return False mod_cog = bot.get_cog("Mod") if (allow_disable and mod_cog is not None and not await mod_cog.settings.guild(guild).respect_hierarchy()): return True # Always prevent actions taken against the guild owner if member == guild.owner: return False return mod.top_role > member.top_role
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)
def setup(bot: Red) -> None: cog = bot.get_cog("CustomCommands") if cog: raise CogLoadError( "This cog conflicts with CustomCommands and both cannot be loaded at the same time. " "After unloading `customcom`, you can migrate custom commands to tags with `[p]migratecustomcom`." ) bot.add_cog(Tags(bot))
async def setup(bot: Red): if bot.get_cog("Trivia"): print("Trivia is already loaded, attempting to unload it first") bot.remove_cog("Trivia") await bot.remove_loaded_package("trivia") bot.unload_extension("trivia") bot.add_cog(AudioTrivia(bot))
def setup(bot: Red) -> None: for cog_name, module_name, tag_name in conflicting_cogs: if bot.get_cog(cog_name): raise CogLoadError( f"This cog conflicts with {cog_name} and both cannot be loaded at the same time. " f"After unloading `{module_name}`, you can migrate {tag_name} to tags with `[p]migrate{module_name}`." ) bot.add_cog(Tags(bot))
async def setup(bot: Red): if bot.get_cog("DamnDog"): print("DamnDog already loaded, attempting to unload first...") bot.remove_cog("DamnDog") await bot.remove_loaded_package("DamnDog") bot.unload_extension("DamnDog") n = DamnDog(bot) bot.add_cog(n)
async def get_user_preference(bot: Red, user: User, pref: str, *, unloaded_default=None) -> Optional[Any]: """Gets a user's preference from UserPreferences cog""" if pref in ('timezone',): raise ValueError("Invalid preference. Use the cog method to get this.") cog: Any = bot.get_cog("UserPreferences") if cog is None: return unloaded_default return await cog.config.user(user).get_raw(pref)
async def remove_goal_post(bot: Red, goal: str, team: str, data: Game) -> None: """ Attempt to delete a goal if it was pulled back """ config = bot.get_cog("Hockey").config team_list = await config.teams() team_data = await get_team(bot, team) if goal not in [goal.goal_id for goal in data.goals]: try: old_msgs = team_data["goal_id"][goal]["messages"] except KeyError: return except Exception: log.exception("Error iterating saved goals") return for guild_id, channel_id, message_id in old_msgs: guild = bot.get_guild(guild_id) if not guild: continue channel = guild.get_channel(int(channel_id)) if channel and channel.permissions_for( channel.guild.me).read_message_history: try: if version_info >= VersionInfo.from_str("3.4.6"): message = channel.get_partial_message(message_id) else: message = await channel.fetch_message(message_id) except (discord.errors.NotFound, discord.errors.Forbidden): continue except Exception: log.exception( f"Error getting old goal for {str(team)} {str(goal)} in " f"{guild_id=} {channel_id=}") pass if message is not None: try: await message.delete() except (discord.errors.NotFound, discord.errors.Forbidden): pass except Exception: log.exception( f"Error getting old goal for {str(team)} {str(goal)} in " f"{guild_id=} {channel_id=}") else: log.debug( "Channel does not have permission to read history") try: team_list.remove(team_data) del team_data["goal_id"][goal] team_list.append(team_data) await config.teams.set(team_list) except Exception: log.exception("Error removing teams goals") return return
async def setup(bot: Red): if bot.get_cog("OnJoin"): LOG.warning("OnJoin already loaded, attempting to unload first...") bot.remove_cog("OnJoin") await bot.remove_loaded_package("OnJoin") bot.unload_extension("OnJoin") n = OnJoin(bot) bot.add_listener(n.voice_state_update, "on_voice_state_update") bot.add_cog(n)
async def setup(bot: Red) -> None: await validate_tagscriptengine(bot, tse_version) for cog_name, module_name, tag_name in conflicting_cogs: if bot.get_cog(cog_name): raise CogLoadError( f"This cog conflicts with {cog_name} and both cannot be loaded at the same time. " f"After unloading `{module_name}`, you can migrate {tag_name} to tags with `[p]migrate{module_name}`." ) tags = Tags(bot) bot.add_cog(tags)
def setup(bot: Red): if not bot._cli_flags.dev: raise CogLoadError("This cog requires the `--dev` CLI flag.") core_dev = bot.get_cog("Dev") if sessions := getattr(core_dev, "sessions", None): s = "s" if len(sessions) > 1 else "" is_private = bot._connection._private_channels.__contains__ raise CogLoadError( f"End your REPL session{s} first: " + humanize_list([ "Private channel" if is_private(id) else f"<#{id}>" for id in sessions ]))
def load_or_reload(bot: Red, load: Type[commands.Cog], *args, **kwargs): name = load.__name__ if name not in loaded or loaded[name] is not bot.get_cog(name): old = bot.cogs.get(name) if old: log.debug("Unloading previously loaded version of internal cog %r", name) bot.remove_cog(name) log.info("Loading internal cog %r", name) loaded[name] = load = load(bot, *args, **kwargs) if old and hasattr(load, "sl_reload_hook"): load.sl_reload_hook(old) bot.add_cog(load)
def __init__(self, bot: Red): self.bot = bot self.config = Config.get_conf( self, "1_021_202_707", force_registration=True ) try: self.tvm_conf: Config = bot.get_cog("TvM").config except AttributeError: pass self.config.register_guild(**default_guild)
async def get_team(bot: Red, team: str) -> TeamEntry: config = bot.get_cog("Hockey").config team_list = await config.teams() if team_list is None: team_list = [] team_entry = TeamEntry("Null", team, 0, [], {}, [], "") team_list.append(team_entry.to_json()) await config.teams.set(team_list) for teams in team_list: if team == teams["team_name"]: return teams # Add unknown teams to the config to track stats return_team = TeamEntry("Null", team, 0, [], {}, [], "") team_list.append(return_team.to_json()) await config.teams.set(team_list) return return_team
async def hierarchy_allows(bot: Red, mod: discord.Member, member: discord.Member, *, allow_disable: bool = True) -> bool: """Check if a guild's role hierarchy allows an action This check can be disabled on a per-guild basis with the Mod cog; however, this behaviour can be overridden with the `allow_disable` keyword argument. """ if await bot.is_owner(mod): return True guild = mod.guild mod_cog = bot.get_cog("Mod") if (allow_disable and mod_cog is not None and not await mod_cog.settings.guild(guild).respect_hierarchy()): return True return member != guild.owner and (mod == guild.owner or mod.top_role > member.top_role)
def dev_mode(bot: Red) -> bool: """Check if the bot is currently in development mode This function will return :obj:`True` if any of the following is true: * The Dev cog added by the --dev flag or a third-party lookalike is loaded * The ``red.swift_libs`` logger log level has been manually set to ``logging.DEBUG`` * The ``red`` logger log level is set to ``logging.DEBUG`` with the --debug flag Otherwise, this will return :obj:`False`. .. note:: If you're looking for a command check variation of this, see: :func:`is_dev` Returns -------- :class:`bool` """ # check for the existence of the Dev cog added by the --dev flag, or a third-party lookalike if "Dev" in bot.cogs and hasattr(bot.get_cog("Dev"), "_eval"): return True # check for debug logging set by --debug or by modifying our or red's log level return 0 < log.getEffectiveLevel() <= logging.DEBUG
async def actually_post_goal( self, bot: Red, channel: discord.TextChannel, goal_embed: discord.Embed, goal_text: str) -> Optional[Tuple[int, int, int]]: try: guild = channel.guild if not channel.permissions_for(guild.me).send_messages: log.debug("No permission to send messages in %s", repr(channel)) return None config = bot.get_cog("Hockey").config game_day_channels = await config.guild(guild).gdc() # Don't want to ping people in the game day channels can_embed = channel.permissions_for(guild.me).embed_links can_manage_webhooks = False # channel.permissions_for(guild.me).manage_webhooks role = None guild_notifications = await config.guild(guild ).goal_notifications() channel_notifications = await config.channel( channel).goal_notifications() goal_notifications = guild_notifications or channel_notifications publish_goals = "Goal" in await config.channel(channel ).publish_states() allowed_mentions = {} montreal = ["Montréal Canadiens", "Montreal Canadiens"] role = discord.utils.get(guild.roles, name=f"{self.team_name} GOAL") try: if self.team_name in montreal: if not role: montreal.remove(self.team_name) role = discord.utils.get(guild.roles, name=f"{montreal[0]} GOAL") except Exception: log.error("Error trying to find montreal goal role") if version_info >= VersionInfo.from_str("3.4.0"): if goal_notifications: log.debug(goal_notifications) allowed_mentions = { "allowed_mentions": discord.AllowedMentions(roles=True) } else: allowed_mentions = { "allowed_mentions": discord.AllowedMentions(roles=False) } if game_day_channels is not None: # We don't want to ping people in the game day channels twice if channel.id in game_day_channels: role = None if not can_embed and can_manage_webhooks: # try to create a webhook with the teams info to bypass embed permissions # Waiting for d.py to return messages from webhook responses # After testing it doesn't look as nice as I would like # Will leave it off until at some point I can make it look better webhook = None for hook in await channel.webhooks(): if hook.name == guild.me.name: webhook = hook if webhook is None: webhook = await channel.create_webhook(name=guild.me.name) url = TEAMS[self.team_name]["logo"] await webhook.send(username=self.team_name, avatar_url=url, embed=goal_embed) return None if not can_embed and not can_manage_webhooks: # Create text only message if embed_links permission is not set if role is not None: msg = await channel.send(f"{role}\n{goal_text}", **allowed_mentions) else: msg = await channel.send(goal_text) # msg_list[str(channel.id)] = msg.id if role is None or "missed" in self.event.lower(): msg = await channel.send(embed=goal_embed) # msg_list[str(channel.id)] = msg.id else: msg = await channel.send(role.mention, embed=goal_embed, **allowed_mentions) # msg_list[str(channel.id)] = msg.id return channel.guild.id, channel.id, msg.id except Exception: log.exception("Could not post goal in %s", repr(channel)) return None
async def actually_post_state( self, bot: Red, channel: discord.TextChannel, state_embed: discord.Embed, state_text: str ) -> Optional[Tuple[discord.TextChannel, discord.Message]]: guild = channel.guild if not channel.permissions_for(guild.me).send_messages: log.debug("No permission to send messages in %s", repr(channel)) return None config = bot.get_cog("Hockey").config guild_settings = await config.guild(guild).all() channel_settings = await config.channel(channel).all() game_day_channels = guild_settings["gdc"] can_embed = channel.permissions_for(guild.me).embed_links publish_states = [] # await config.channel(channel).publish_states() # can_manage_webhooks = False # channel.permissions_for(guild.me).manage_webhooks if self.game_state == "Live": guild_notifications = guild_settings["game_state_notifications"] channel_notifications = channel_settings["game_state_notifications"] state_notifications = guild_notifications or channel_notifications # TODO: Something with these I can't remember what now # guild_start = guild_settings["start_notifications"] # channel_start = channel_settings["start_notifications"] # start_notifications = guild_start or channel_start # heh inclusive or allowed_mentions = {} home_role, away_role = await get_team_role(guild, self.home_team, self.away_team) if version_info >= VersionInfo.from_str("3.4.0"): if state_notifications: allowed_mentions = {"allowed_mentions": discord.AllowedMentions(roles=True)} else: allowed_mentions = {"allowed_mentions": discord.AllowedMentions(roles=False)} if self.game_type == "R" and "OT" in self.period_ord: if not guild_settings["ot_notifications"]: if version_info >= VersionInfo.from_str("3.4.0"): allowed_mentions = { "allowed_mentions": discord.AllowedMentions(roles=False) } else: allowed_mentions = {} if "SO" in self.period_ord: if not guild_settings["so_notifications"]: if version_info >= VersionInfo.from_str("3.4.0"): allowed_mentions = { "allowed_mentions": discord.AllowedMentions(roles=False) } else: allowed_mentions = {} if game_day_channels is not None: # We don't want to ping people in the game day channels twice if channel.id in game_day_channels: home_role, away_role = self.home_team, self.away_team msg = _("**{period} Period starting {away_role} at {home_role}**").format( period=self.period_ord, away_role=away_role, home_role=home_role ) try: if not can_embed: msg = await channel.send(msg + "\n{}".format(state_text), **allowed_mentions) else: msg = await channel.send(msg, embed=state_embed, **allowed_mentions) if self.game_state in publish_states: try: if channel.is_news(): # allows backwards compatibility still # await msg.publish() pass except Exception: pass except Exception: log.exception("Could not post goal in %s", repr(channel)) else: if self.game_state == "Preview": if game_day_channels is not None: # Don't post the preview message twice in the channel if channel.id in game_day_channels: return None try: if not can_embed: preview_msg = await channel.send(state_text) else: preview_msg = await channel.send(embed=state_embed) if self.game_state in publish_states: try: if channel.is_news(): # allows backwards compatibility still # await preview_msg.publish() pass except Exception: pass # Create new pickems object for the game if self.game_state == "Preview": bot.dispatch("hockey_preview_message", channel, preview_msg, self) if channel.permissions_for(guild.me).add_reactions: try: await preview_msg.add_reaction(self.away_emoji[2:-1]) await preview_msg.add_reaction(self.home_emoji[2:-1]) except Exception: log.debug("Could not add reactions") return channel, preview_msg except Exception: log.exception("Could not post goal in %s", repr(channel)) return None