async def show_results(): text = _("Banned {num} users from the server.").format( num=humanize_number(len(banned)) ) if errors: text += _("\nErrors:\n") text += "\n".join(errors.values()) if upgrades: text += _( "\nFollowing user IDs have been upgraded from a temporary to a permanent ban:\n" ) text += humanize_list(upgrades) for p in pagify(text): await ctx.send(p)
async def _send_startup_msg(self): list_names = [] for idx, tup in enumerate(self.settings["lists"].items()): name, (author, count) = tup if author: title = _( "{trivia_list} ({count} entries by {author})").format( trivia_list=name, author=author, count=count) else: title = _("{trivia_list} ({count} entries)").format( trivia_list=name, count=count) list_names.append(title) await self.ctx.send( _("Starting Trivia: {list_names}").format( list_names=humanize_list(list_names)))
async def initialize(self): agent = await self.config.agent() if not agent: await self.bot.wait_until_red_ready() if not self.bot.owner_ids: # always False but forces owner_ids to be filled await self.bot.is_owner(discord.Object(id=None)) owner_ids = self.bot.owner_ids # only make the user_info request if necessary agent = humanize_list( [str(self.bot.get_user(id) or await self.bot.fetch_user(id)) for id in owner_ids] ) Api.agent = f"{agent} Red-DiscordBot/{red_version}" self.db_cache = await self.config.custom("NATION").all() self.cog_ready.set()
async def get_commands(self): returning = [] downloader = self.bot.get_cog("Downloader") for name, cog in self.bot.cogs.copy().items(): stripped = [] for c in cog.__cog_commands__: if not c.parent: stripped.append(c) cmds = await self.build_cmd_list(stripped) if not cmds: continue author = "Unknown" repo = "Unknown" # Taken from Trusty's downloader fuckery, https://gist.github.com/TrustyJAID/784c8c32dd45b1cc8155ed42c0c56591 if name not in self.cog_info_cache: if downloader: module = downloader.cog_name_from_instance(cog) installed, cog_info = await downloader.is_installed(module) if installed: author = humanize_list( cog_info.author) if cog_info.author else "Unknown" try: repo = (cog_info.repo.clean_url if cog_info.repo.clean_url else "Unknown") except AttributeError: repo = "Unknown (Removed from Downloader)" elif cog.__module__.startswith("redbot."): author = "Cog Creators" repo = "https://github.com/Cog-Creators/Red-DiscordBot" self.cog_info_cache[name] = {} self.cog_info_cache[name]["author"] = author self.cog_info_cache[name]["repo"] = repo else: author = self.cog_info_cache[name]["author"] repo = self.cog_info_cache[name]["repo"] returning.append({ "name": name, "desc": cog.__doc__, "cmds": cmds, "author": author, "repo": repo }) returning = sorted(returning, key=lambda k: k["name"]) return returning
async def send_testing_msg(self, ctx, bot=False, msg=None, leave=False): # log.info(leave) guild = ctx.message.guild guild_settings = await self.config.guild(guild).get_raw() # log.info(guild_settings) channel = guild.get_channel(guild_settings["CHANNEL"]) if leave: channel = guild.get_channel(guild_settings["LEAVE_CHANNEL"]) rand_msg = msg or rand_choice(guild_settings["GREETING"]) if leave: rand_msg = msg or rand_choice(guild_settings["GOODBYE"]) if bot: rand_msg = guild_settings["BOTS_MSG"] is_embed = guild_settings["EMBED"] member = ctx.message.author whisper_settings = guild_settings["WHISPER"] if channel is None and whisper_settings not in ["BOTH", True]: msg = _("I can't find the specified channel. It might have been deleted.") await ctx.send(msg) return if channel is None: await ctx.send(_("`Sending a testing message to ") + "` DM") else: await ctx.send(_("`Sending a testing message to ") + "`{0.mention}".format(channel)) if not bot and guild_settings["WHISPER"]: if is_embed: em = await self.make_embed(member, guild, rand_msg) await ctx.author.send(embed=em, delete_after=60) else: await ctx.author.send(await self.convert_parms(member, guild, rand_msg), delete_after=60) if bot or whisper_settings is not True: if guild_settings["GROUPED"]: member = [ctx.author, ctx.me] if is_embed and channel.permissions_for(guild.me).embed_links: em = await self.make_embed(member, guild, rand_msg) if await self.config.guild(guild).EMBED_DATA.mention(): if guild_settings["GROUPED"]: await channel.send( humanize_list([m.mention for m in member]), embed=em, delete_after=60 ) else: await channel.send(member.mention, embed=em, delete_after=60) else: await channel.send(embed=em, delete_after=60) else: await channel.send( await self.convert_parms(member, guild, rand_msg), delete_after=60 )
async def _set_event_emoji( self, ctx: commands.Context, emoji: Union[discord.Emoji, str], *events: EventChooser, ) -> None: """ Set the emoji used in text modlogs. `new_emoji` can be any discord emoji or unicode emoji the bot has access to use. `[events...]` must be one of the following options (more than one event can be provided at once): `message_edit` `message_delete` `user_change` `role_change` `role_create` `role_delete` `voice_change` `user_join` `user_left` `channel_change` `channel_create` `channel_delete` `guild_change` `emoji_change` `commands_used` **Requires Red 3.3 and discord.py 1.3** `invite_created` `invite_deleted` """ if len(events) == 0: return await ctx.send( _("You must provide which events should be included.")) if ctx.guild.id not in self.settings: self.settings[ctx.guild.id] = inv_settings if isinstance(emoji, str): try: await ctx.message.add_reaction(emoji) except discord.errors.HTTPException: return await ctx.send( _("{emoji} is not a valid emoji.").format(emoji=emoji)) new_emoji = str(emoji) for event in events: self.settings[ctx.guild.id][event]["emoji"] = new_emoji await self.config.guild(ctx.guild).set_raw( event, value=self.settings[ctx.guild.id][event]) await ctx.send( _("{event} emoji has been set to {new_emoji}").format( event=humanize_list(events), new_emoji=str(new_emoji)))
async def _set_event_colours(self, ctx: commands.Context, colour: discord.Colour, *events: EventChooser): """ Set custom colours for modlog events `colour` must be a hex code or a [built colour.](https://discordpy.readthedocs.io/en/latest/api.html#colour) `[events...]` must be any of the following options (more than one event can be provided at once): `channel_change` - Updates to channel name, etc. `channel_create` `channel_delete` `commands_used` - Bot command usage `emoji_change` - Emojis added or deleted `guild_change` - Server settings changed `message_edit` `message_delete` `member_change` - Member changes like roles added/removed and nicknames `role_change` - Role updates like permissions `role_create` `role_delete` `voice_change` - Voice channel join/leave `member_join` `member_left` **Requires Red 3.3+ and discord.py 1.3+** `invite_created` `invite_deleted` """ if len(events) == 0: return await ctx.send( _("You must provide which events should be included.")) if ctx.guild.id not in self.settings: self.settings[ctx.guild.id] = inv_settings if colour: new_colour = colour.value else: new_colour = colour for event in events: self.settings[ctx.guild.id][event]["colour"] = new_colour await self.config.guild(ctx.guild).set_raw( event, value=self.settings[ctx.guild.id][event]) await ctx.send( _("{event} has been set to {colour}").format( event=humanize_list( [e.replace("user_", "member_") for e in events]), colour=str(colour), ))
async def blacklist(self, ctx: commands.Context, guild_id: int = None): """Blacklist the bot from joining a server.""" if not guild_id: e = discord.Embed( color=await ctx.embed_color(), title="Baron Blacklist", description=humanize_list(await self.config.blacklist()), ) await ctx.send(embed=e) else: if guild_id in await self.config.blacklist(): await ctx.send("This server is already blacklisted.") return async with self.config.blacklist() as b: b.append(guild_id) await ctx.tick()
async def whitelist(self, ctx: commands.Context, guild_id: int = None): """Whitelist a server from Baron actions.""" if not guild_id: e = discord.Embed( color=await ctx.embed_color(), title="Baron Whitelist", description=humanize_list(await self.config.whitelist()), ) await ctx.send(embed=e) else: if guild_id in await self.config.whitelist(): await ctx.send("This server is already whitelisted.") return async with self.config.whitelist() as w: w.append(guild_id) await ctx.tick()
def humanize_roles(roles: List[discord.Role], *, mention: bool = False, bold: bool = True) -> Optional[str]: if not roles: return None role_strings = [] for role in roles: role_name = escape_mentions(role.name) if mention: role_strings.append(role.mention) elif bold: role_strings.append(f"**{role_name}**") else: role_strings.append(role_name) return humanize_list(role_strings)
async def blacklist(self, ctx: commands.Context, user_id: int = None): """Blacklist receiving messages from a user.""" if not user_id: e = discord.Embed( color=await ctx.embed_color(), title="Forward Blacklist", description=humanize_list(await self.config.blacklist()), ) await ctx.send(embed=e) else: if user_id in await self.config.blacklist(): await ctx.send("This user is already blacklisted.") return async with self.config.blacklist() as b: b.append(user_id) await ctx.tick()
async def alert_new_letter(self, user_id: int, letter: Letter, letter_id: int): user = self.bot.get_user(user_id) if user is None: # User not found raise discord.NotFound("User cannot be contacted.") if not await self.allow_service(user): raise StopService("User stopped using the service.") message = str() prefix = await self.bot._config.prefix() first_time = await self.config.user(user).first_usage() if first_time: message += (( f"Hello {user.name}, this is the first time you're receiving a letter in your " "letterbox, so let me introduce you to the service.\n\nLetters is a service that " "allows you to send and receive letters from members of Discord, as long as I " "share a server with you and I can contact you. When you receive a letter, the " "letter gets into your letterbox where all your letters are stocked, so you can " "open a letter whenever you want. When you have read a letter, it is marked as " "read.\n\nYou can disable this service. **However, this system is meant for " "receiving letters over Discord from others, from your friends, from the past or " "of today, every letters deserve to be delivered.** It would be hurtful " "for you to disable it.\n\n Now that you are familiar with the concept, here are " "2 commands you should know:\n- `[p]letterbox` to check your letterbox;\n- " "`[p]letterset` to set your settings for the letter service;\n\n You will not " "receive this message again. From now on, you will only receive regular alerts " "about new letters.\n\n📩 You have received a new letter from {authors}! Check " "it out in your letterbox!").format(authors=humanize_list( list(letter.authors.values()))).replace("[p]", prefix[0])) else: message += ( f"📩 You have received a new letter from {letter.author}! Check it out in your " "letterbox! (`[p]letterbox`)").replace("[p]", prefix[0]) if [ i for i in list(letter.authors.values()) if i in await self.config.user(user).blocklist() ]: message += ( "\n⚠The author of this letter as been marked as blocked, you still " "receiving this letter in your letterbox, open it if you want or delete " "it. Letter ID: " + str(letter_id)) try: await user.send(message) if first_time: await self.config.user(user).first_usage.set(False) return True except discord.HTTPException: return False
async def _set_event_colours( self, ctx: commands.Context, colour: discord.Colour, *events: EventChooser ): """ Set custom colours for modlog events `colour` must be a hex code or a [built colour.](https://discordpy.readthedocs.io/en/latest/api.html#colour) `event` must be one of the following options (more than one event can be provided at once.): `message_edit` `message_delete` `user_change` `role_change` `role_create` `role_delete` `voice_change` `user_join` `user_left` `channel_change` `channel_create` `channel_delete` `guild_change` `emoji_change` `commands_used` **Requires Red 3.3 and discord.py 1.3** `invite_created` `invite_deleted` """ if len(events) == 0: return await ctx.send(_("You must provide which events should be included.")) if ctx.guild.id not in self.settings: self.settings[ctx.guild.id] = inv_settings if colour: new_colour = colour.value else: new_colour = colour for event in events: self.settings[ctx.guild.id][event]["colour"] = new_colour await self.config.guild(ctx.guild).set_raw( event, value=self.settings[ctx.guild.id][event] ) await ctx.send( _("{event} has been set to {colour}").format( event=humanize_list(events), colour=str(colour) ) )
async def _set_event_on_or_off( self, ctx: commands.Context, true_or_false: bool, *events: EventChooser, ) -> None: """ Turn on and off specific modlog actions `<true_or_false>` Either on or off. `[events...]` must be any of the following options (more than one event can be provided at once): `channel_change` - Updates to channel name, etc. `channel_create` `channel_delete` `commands_used` - Bot command usage `emoji_change` - Emojis added or deleted `guild_change` - Server settings changed `message_edit` `message_delete` `member_change` - Member changes like roles added/removed and nicknames `role_change` - Role updates like permissions `role_create` `role_delete` `voice_change` - Voice channel join/leave `member_join` `member_left` **Requires Red 3.3+ and discord.py 1.3+** `invite_created` `invite_deleted` """ if len(events) == 0: return await ctx.send( _("You must provide which events should be included.")) if ctx.guild.id not in self.settings: self.settings[ctx.guild.id] = inv_settings for event in events: self.settings[ctx.guild.id][event]["enabled"] = true_or_false await self.config.guild(ctx.guild).set_raw( event, value=self.settings[ctx.guild.id][event]) await ctx.send( _("{event} logs have been set to {true_or_false}").format( event=humanize_list( [e.replace("user_", "member_") for e in events]), true_or_false=str(true_or_false), ))
async def _set_event_channel( self, ctx: commands.Context, channel: discord.TextChannel, *events: EventChooser, ) -> None: """ Set the channel for modlogs. `<channel>` The text channel to send the events to. `[events...]` must be any of the following options (more than one event can be provided at once): `channel_change` - Updates to channel name, etc. `channel_create` `channel_delete` `commands_used` - Bot command usage `emoji_change` - Emojis added or deleted `guild_change` - Server settings changed `message_edit` `message_delete` `member_change` - Member changes like roles added/removed and nicknames `role_change` - Role updates like permissions `role_create` `role_delete` `voice_change` - Voice channel join/leave `member_join` `member_left` **Requires Red 3.3+ and discord.py 1.3+** `invite_created` `invite_deleted` """ if len(events) == 0: return await ctx.send( _("You must provide which events should be included.")) if ctx.guild.id not in self.settings: self.settings[ctx.guild.id] = inv_settings for event in events: self.settings[ctx.guild.id][event]["channel"] = channel.id await self.config.guild(ctx.guild).set_raw( event, value=self.settings[ctx.guild.id][event]) await ctx.send( _("{event} logs have been set to {channel}").format( event=humanize_list( [e.replace("user_", "member_") for e in events]), channel=channel.mention, ))
async def post_standings( self, ctx: commands.Context, standings_type: str, channel: Optional[discord.TextChannel] = None, ) -> None: """ Posts automatic standings when all games for the day are done `<standings_type>` can be a division name or all `[channel]` The channel you want standings to be posted into, if not provided this will use the current channel. """ guild = ctx.message.guild if channel is None: channel = ctx.message.channel channel_perms = channel.permissions_for(ctx.me) if not (channel_perms.send_messages and channel_perms.embed_links and channel_perms.read_message_history): return await ctx.send( _("I require permission to send messages, embed " "links, and read message history in {channel}.").format( channel=channel.mention)) if standings_type.lower() not in DIVISIONS + CONFERENCES + ["all"]: await ctx.send( _("You must choose from: {standings_types}.").format( standings_types=humanize_list(DIVISIONS + CONFERENCES + ["all"]))) return standings, page = await Standings.get_team_standings( standings_type.lower(), session=self.session) if standings_type.lower() != "all": em = await Standings.build_standing_embed(standings, page) else: em = await Standings.all_standing_embed(standings) await self.config.guild(guild).standings_type.set(standings_type) await self.config.guild(guild).standings_channel.set(channel.id) await ctx.send( _("Sending standings to {channel}").format(channel=channel.mention) ) message = await channel.send(embed=em) await self.config.guild(guild).standings_msg.set(message.id) await ctx.send( _("{standings_type} standings will now be automatically updated in {channel}." ).format(standings_type=standings_type, channel=channel.mention)) await self.config.guild(guild).post_standings.set(True)
async def blacklist_remove(self, ctx: commands.Context, *channel_user_role: ChannelUserRole): """ Remove a channel, user, or role from translation blacklist """ if len(channel_user_role) < 1: return await ctx.send( _("You must supply 1 or more channels, users, " "or roles to be removed from the blacklist")) for obj in channel_user_role: if obj.id in await self.config.guild(ctx.guild).blacklist(): async with self.config.guild( ctx.guild).blacklist() as blacklist: blacklist.remove(obj.id) msg = _("`{list_type}` removed from translation blacklist.") list_type = humanize_list([c.name for c in channel_user_role]) await ctx.send(msg.format(list_type=list_type))
async def blacklist_add(self, ctx: commands.Context, *channel_user_role: ChannelUserRole): """ Add a channel, user, or role to translation blacklist """ if len(channel_user_role) < 1: return await ctx.send( _("You must supply 1 or more channels users or roles to be blacklisted." )) for obj in channel_user_role: if obj.id not in await self.config.guild(ctx.guild).blacklist(): async with self.config.guild( ctx.guild).blacklist() as blacklist: blacklist.append(obj.id) msg = _("`{list_type}` added to translation blacklist.") list_type = humanize_list([c.name for c in channel_user_role]) await ctx.send(msg.format(list_type=list_type))
async def convert(self, ctx, argument): bot = ctx.bot possible_results = { "allpvp": { "code": "allPvP", "alt": ["pvp"] }, "patrol": { "code": "patrol", "alt": [] }, "raid": { "code": "raid", "alt": ["all"] }, "story": { "code": "story", "alt": [] }, "allstrikes": { "code": "allStrikes", "alt": ["strikes", "strike"] }, "allpve": { "code": "allPvE", "alt": ["pve"] }, "allpvecompetitive": { "code": "allPvECompetitive", "alt": ["gambit"] }, } result = None argument = argument.lower() if argument in possible_results: result = possible_results[argument]["code"] else: for k, v in possible_results.items(): if argument in v["alt"]: result = v["code"] if not result: raise BadArgument( _("That is not an available stats page, pick from these: {activity_list}" ).format(activity_list=humanize_list( list(possible_results.keys())))) return result
async def get_heist_message(self, ctx, flags, sleep_time, early_time, role): heist_message = "" early_heist_message = "" if flags["ping"]: pingrole = await self.config.guild(ctx.guild).pingrole() pingrole = ctx.guild.get_role(pingrole) heist_message += f"{pingrole.mention}: " if flags["early_roles"]: roles = humanize_list([r.name for r in flags["early_roles"]]) early_heist_message += f"Channel Unlocked for **{roles}**! Unlocking in {self.display_time(early_time)} " heist_message += f"Channel Unlocked for {role.name}! Locking in {self.display_time(sleep_time)} " return heist_message, early_heist_message
async def _global_list(self, ctx: commands.Context): """Send a list of this server's filtered words.""" server = ctx.guild author = ctx.author word_list = await self.config.guild(server).filter() if not word_list: await ctx.send( _("There are no current words setup to be filtered in this server." )) return words = humanize_list(word_list) words = _("Filtered in this server:") + "\n\n" + words try: for page in pagify(words, delims=[" ", "\n"], shorten_by=8): await author.send(page) except discord.Forbidden: await ctx.send(_("I can't send direct messages to you."))
async def _set_event_channel( self, ctx: commands.Context, channel: discord.TextChannel, *events: EventChooser, ) -> None: """ Set the channel for modlogs. `channel` The text channel to send the events to. `[events...]` must be one of the following options (more than one event can be provided at once): `message_edit` `message_delete` `user_change` `role_change` `role_create` `role_delete` `voice_change` `user_join` `user_left` `channel_change` `channel_create` `channel_delete` `guild_change` `emoji_change` `commands_used` **Requires Red 3.3 and discord.py 1.3** `invite_created` `invite_deleted` """ if len(events) == 0: return await ctx.send(_("You must provide which events should be included.")) if ctx.guild.id not in self.settings: self.settings[ctx.guild.id] = inv_settings for event in events: self.settings[ctx.guild.id][event]["channel"] = channel.id await self.config.guild(ctx.guild).set_raw( event, value=self.settings[ctx.guild.id][event] ) await ctx.send( _("{event} logs have been set to {channel}").format( event=humanize_list(events), channel=channel.mention ) )
async def cancel(self): await self._cancel() file = None if self.fails: text = "" for member, e in self.fails: text += f"{str(member)} ({member.id}): {type(e)} {e.args[0]}\n" file = text_to_file(text, filename="erreurs.txt") if len(self.roles) > 1: text = "Rôles " + humanize_list([x.name for x in self.roles]) else: text = "Rôle " + self.roles[0].name await self.ctx.send( f"{text} {'ajouté' if self.add_roles else 'retiré'} " f"à {self.current}/{self.limit} membres.", file=file, )
async def _set_event_on_or_off( self, ctx: commands.Context, set_to: bool, *events: EventChooser, ) -> None: """ Turn on and off specific modlog actions `set_to` Either on or off. `[events...]` must be one of the following options (more than one event can be provided at once): `message_edit` `message_delete` `user_change` `role_change` `role_create` `role_delete` `voice_change` `user_join` `user_left` `channel_change` `channel_create` `channel_delete` `guild_change` `emoji_change` `commands_used` ** requires manage_channel permissions** `invite_created` `invite_deleted` """ if len(events) == 0: return await ctx.send(_("You must provide which events should be included.")) if ctx.guild.id not in self.settings: self.settings[ctx.guild.id] = inv_settings for event in events: self.settings[ctx.guild.id][event]["enabled"] = set_to await self.config.guild(ctx.guild).set_raw( event, value=self.settings[ctx.guild.id][event] ) await ctx.send( _("{event} logs have been set to {set_to}").format( event=humanize_list(events), set_to=str(set_to) ) )
async def _command_level(self, ctx, *level: CommandPrivs): """ Set the level of commands to be logged `[level...]` must include all levels you want from: MOD, ADMIN, BOT_OWNER, GUILD_OWNER, and NONE These are the basic levels commands check for in permissions. `NONE` is a command anyone has permission to use, where as `MOD` can be `mod or permissions` """ if len(level) == 0: return await ctx.send_help() guild = ctx.message.guild msg = _("Command logs set to: ") await self.config.guild(guild).commands_used.privs.set(list(level)) await ctx.send(msg + humanize_list(level))
async def _channel_list(self, ctx: commands.Context): """Send the list of the channel's filtered words.""" channel = ctx.channel author = ctx.author word_list = await self.config.channel(channel).filter() if not word_list: await ctx.send( _("There is no current words setup to be filtered in this channel." )) return words = humanize_list(word_list) words = _("Filtered in this channel:") + "\n\n" + words try: for page in pagify(words, delims=[" ", "\n"], shorten_by=8): await author.send(page) except discord.Forbidden: await ctx.send(_("I can't send direct messages to you."))
async def exes(self, ctx: commands.Context, member: typing.Optional[discord.Member]): """Display your or someone else's exes.""" conf = await self._get_conf_group(ctx.guild) if not await conf.toggle(): return await ctx.send("Marriage is not enabled!") if not member: member = ctx.author m_conf = await self._get_user_conf(member) exes_ids = await m_conf.exes() exes = list() for ex_id in exes_ids: ex = self.bot.get_user(ex_id) if ex: exes.append(ex.name) ex_text = "None" if exes == [] else humanize_list(exes) await ctx.send(f"{member.mention}'s exes are: {ex_text}")
async def rift_open(self, ctx, *rifts: RiftConverter(_, globally=True)): """ Opens a rift to the specified destination. The destination may be any channel or user that both you and the bot are connected to, even across servers. """ if not rifts: return await ctx.send_help() rifts = set(rifts) self.open_rifts.update(((rift, {}) for rift in rifts)) for rift in rifts: ctx.bot.loop.create_task( rift.destination.send( _("{} has opened a rift to here.").format(rift.author))) await ctx.send( _("A rift has been opened to {}! Everything you say will be relayed there.\nResponses will be relayed here.\nType `exit` to quit." ).format(humanize_list([str(rift.destination) for rift in rifts])))
async def get_info(self, ctx: commands.Context) -> discord.Embed: desc = [ f"Author: {self.author.mention if self.author else self.author_id}", f"Uses: **{self.uses}**", f"Length: **{hn(len(self))}**", ] if self.aliases: desc.append(humanize_list([inline(alias) for alias in self.aliases])) e = discord.Embed( color=await ctx.embed_color(), title=f"{self.name_prefix} `{self}` Info", description="\n".join(desc), ) if self.guild_id: e.set_author(name=ctx.guild, icon_url=ctx.guild.icon_url) else: e.set_author(name=ctx.me, icon_url=ctx.me.avatar_url) return e
async def rift_open(self, ctx, *rifts: RiftConverter(_, globally=True)): """ Opens a rift to the specified destination. The destination may be any channel or user that both you and the bot are connected to, even across servers. """ if not rifts: return await ctx.send_help() rifts = set(rifts) create_queue = [] for rift in rifts: if not await self.rift_exists(rift): if ctx.guild is None or rift.destination not in ctx.guild.channels: accepted, reason = await self.request_access(ctx, rift) if not accepted: continue dest_open_embed = await self.create_simple_embed(ctx.author, _(rift.mention()), "A Rift has been opened." ) #ctx.bot.loop.create_task( # rift.destination.send(embed=dest_open_embed) #) await rift.destination.send(embed=dest_open_embed) create_queue.append(rift) with suppress(NameError): if reason is not None: await ctx.maybe_send_embed(reason) if not accepted: return if not create_queue: return await ctx.maybe_send_embed("Rift(s) already exist.") # add new rifts self.open_rifts.update(((rift, {}) for rift in create_queue)) for rift in create_queue: await self.save_rift(rift) open_embed = await self.create_simple_embed(ctx.author, _("A rift has been opened to {}! Everything you say will be relayed there.\n" "Responses will be relayed here.\nType `exit` here to quit." ).format(humanize_list([str(rift.destination) for rift in create_queue])) , "Rift Opened!") await ctx.send(embed=open_embed)
async def _image_upload_command_logic(self, ctx: commands.Context): # Getting image and upload try: image = await ctx.message.attachments[0].read() except IndexError: await ctx.send("You must upload an image.") ctx.command.reset_cooldown(ctx) return try: result = await self.image_upload(image) except (RuntimeError, AttributeError) as error: await ctx.send(error) return except (SubWrongToken, SubNeedToken) as error: await ctx.send( "I was unable to send your file: `{error}`".format(error=error) ) ctx.command.reset_cooldown(ctx) return except UnallowedFileType as error: available_file_type = [ ".png", ".jpg/.jpeg", ".tif/.tiff", ".gif", ".ico", ".bmp", ".webm", ] await ctx.send( str(error) + "\nRemember that the only available file type are:\n" + humanize_list(available_file_type)) return # Sending image, if everthing is okay url = result[0] deletion_url = result[1] thumbnail = result[2] user_dmed = await self._try_send_private_message_deletion( await ctx.embed_color(), ctx.author, url, deletion_url) raw_message, maybe_embed = await self._make_embed_and_raw_message( ctx, url, deletion_url if not user_dmed else None, thumbnail) await ctx.send(raw_message, embed=maybe_embed or None)
async def _cog_update(self, ctx, cog_name: InstalledCog = None): """Update all cogs, or one of your choosing.""" installed_cogs = set(await self.installed_cogs()) async with ctx.typing(): if cog_name is None: updated = await self._repo_manager.update_all_repos() else: try: updated = await self._repo_manager.update_repo(cog_name.repo_name) except KeyError: # Thrown if the repo no longer exists updated = {} updated_cogs = set(cog for repo in updated for cog in repo.available_cogs) installed_and_updated = updated_cogs & installed_cogs if installed_and_updated: await self._reinstall_requirements(installed_and_updated) await self._reinstall_cogs(installed_and_updated) await self._reinstall_libraries(installed_and_updated) message = _("Cog update completed successfully.") cognames = {c.name for c in installed_and_updated} message += _("\nUpdated: ") + humanize_list(tuple(map(inline, cognames))) else: await ctx.send(_("All installed cogs are already up to date.")) return await ctx.send(message) cognames &= set(ctx.bot.extensions.keys()) # only reload loaded cogs if not cognames: return await ctx.send( _("None of the updated cogs were previously loaded. Update complete.") ) message = _("Would you like to reload the updated cogs?") can_react = ctx.channel.permissions_for(ctx.me).add_reactions if not can_react: message += " (y/n)" query: discord.Message = await ctx.send(message) if can_react: # noinspection PyAsyncCall start_adding_reactions(query, ReactionPredicate.YES_OR_NO_EMOJIS, ctx.bot.loop) pred = ReactionPredicate.yes_or_no(query, ctx.author) event = "reaction_add" else: pred = MessagePredicate.yes_or_no(ctx) event = "message" try: await ctx.bot.wait_for(event, check=pred, timeout=30) except asyncio.TimeoutError: await query.delete() return if pred.result is True: if can_react: with contextlib.suppress(discord.Forbidden): await query.clear_reactions() await ctx.invoke(ctx.bot.get_cog("Core").reload, *cognames) else: if can_react: await query.delete() else: await ctx.send(_("OK then."))