async def misctools_unload(self, ctx: commands.Context, *toolsets_: str): if not toolsets_: await ctx.send_help() return unloaded = [] output = [] for toolset in toolsets_: try: self.unload(toolset) except UnknownToolset: output.append(translate("toolset_not_found", set=toolset)) except NotLoaded: output.append(translate("toolset_already_unloaded", set=toolset)) else: unloaded.append(toolset) async with config.toolsets() as toolsets__: for ts in toolsets__.copy(): if ts.lower() == toolset.lower(): toolsets__.remove(ts) if unloaded: output.append( translate( "toolset_unloaded", count=len(unloaded), sets=Humanize([inline(x) for x in unloaded]), ) ) for page in pagify("\n".join(output)): await ctx.send(page)
def try_import(*imports: str, extra: str = None) -> None: """Try to import required modules and raise an exception if any fail to import Keyword Arguments ----------------- extra: str If this is provided, this will be logged as extra information alongside any import failures in the bot's logging. Raises ------- CogLoadError Raised if one or more given imports fail to import """ failed: List[str] = [] for import_ in imports: try: importlib.import_module(import_) except Exception as e: # pylint:disable=broad-except log.exception("Failed to import required library %r", import_, exc_info=e) failed.append(import_) if failed: if extra: log.warning( "Extra information provided for the above import failures: %s", extra) raise CogLoadError( translate("checks.import_failed", libs=Humanize([inline(x) for x in failed]), n=len(failed)))
async def remindme(self, ctx: commands.Context, in_time: str, *, to: str): if len(to) > 1000: await ctx.send(translate("content_too_long")) return in_time = FutureTime.get_seconds(in_time) if in_time is None or in_time < 60: raise commands.BadArgument(translate("invalid_time")) reminder = await Reminder.create(ctx.author, to, in_time) if await ctx.embed_requested(): embed = discord.Embed( colour=await ctx.embed_colour(), description=reminder.message, title=translate("reminder_created"), timestamp=reminder.due_on, ) embed.set_footer(text=translate("will_send_on")) await ctx.send(embed=embed) else: await ctx.send( tick( translate( "reminder_set", date=Humanize(reminder.due_on, format="long", tzinfo=get_localzone()), )))
async def snowflake_delta(self, ctx: commands.Context, starting: int, ending: int): starting, ending = ( discord.utils.snowflake_time(starting), discord.utils.snowflake_time(ending), ) now = datetime.utcnow() await ctx.send( translate( "snowflake_delta", start_delta=Humanize(starting - now, add_direction=True), start_date=Humanize(starting), end_delta=Humanize(ending - now, add_direction=True), end_date=Humanize(ending), difference=Humanize(ending - starting), ) )
def reminder_text(self): from .remindme import translate return translate( "reminder_message", set_on=Humanize(self.set_on, format="long", tzinfo=get_localzone()), message=self.message, )
async def ping(self, ctx: commands.Context): await ctx.send( translate( "ping", latency=Humanize( format_unit, dict(self.bot.latencies) [ctx.guild.shard_id if ctx.guild else 0] * 1000, "millisecond", ), ))
async def __build_xkcd_embed(ctx: commands.Context, comic: "Comic"): return ( discord.Embed( title=f"#{comic.number} \N{EM DASH} {comic.title}", colour=await ctx.embed_colour(), url=comic.link, description=translate( "description", image=comic.image, explain=comic.explain, date=Humanize(comic.timestamp), ), ).set_footer(text=comic.alt or discord.Embed.Empty) # the image may be an empty string in the case of comic #404 .set_image(url=comic.image or discord.Embed.Empty) )
async def timedmute( self, ctx: commands.Context, member: discord.Member, duration: TimeConverter, *, reason: str = None, ): from timedrole.api import TempRole if not await hierarchy_allows(self.bot, mod=ctx.author, member=member): await ctx.send(warning(translate("hierarchy_disallows"))) return role = await self.get_punished_role(ctx.guild) if role is None: tmp_msg = await ctx.send(translate("setting_up")) async with ctx.typing(): role = await self.setup_role(ctx.guild) await tmp_msg.delete() if role in member.roles: await ctx.send(warning(translate("already_muted"))) return role = await TempRole.create( member, role, duration=duration, added_by=ctx.author, reason=reason ) await role.apply_role(reason=reason) try: await modlog.create_case( bot=self.bot, guild=ctx.guild, user=member, moderator=ctx.author, reason=reason, until=role.expires_at, action_type="timedmute", created_at=role.added_at, ) except RuntimeError: pass await ctx.send(tick(translate("member_muted", member=member, duration=Humanize(duration))))
async def list(self, ctx: commands.Context): reminders = await self.config.user(ctx.author).reminders() if not reminders: await ctx.send(translate("no_set_reminders", prefix=ctx.prefix)) return pages = list(chunks(reminders, 5)) page_count = len(pages) colour = await ctx.embed_colour() # noinspection PyUnresolvedReferences for page in pages.copy(): index = pages.index(page) embed = discord.Embed(colour=colour) embed.set_author( name=translate("set_reminders", user=ctx.author), icon_url=ctx.author.avatar_url_as(format="png"), ) embed.set_footer( text=translate("page", total=page_count, current=index + 1)) for reminder in page: remind_on = datetime.utcfromtimestamp(reminder["remind_on"]) embed.add_field( name=translate( "reminder_title", id=(index * 5) + (page.index(reminder) + 1), delta=Humanize(remind_on - datetime.utcnow(), add_direction=True), ), value=shorten(reminder["message"], width=700, placeholder=" \N{HORIZONTAL ELLIPSIS}"), inline=False, ) pages[index] = embed await PaginatedMenu(pages=pages, bot=self.bot, member=ctx.author, channel=ctx.channel).prompt()
async def misctools_load(self, ctx: commands.Context, *toolsets_: str): if not toolsets_: await ctx.send_help() return loaded = [] output = [] for toolset in toolsets_: try: await self.load(toolset) except AlreadyLoaded: output.append(translate("toolset_already_loaded", set=toolset)) except UnknownToolset: output.append(translate("toolset_not_found", set=toolset)) except InternalLoadError as e: output.append(str(e.translated)) except Exception as e: # pylint:disable=broad-except log.exception("Failed to load toolset %r", toolset.lower(), exc_info=e) output.append(translate("toolset_errored", set=toolset)) else: async with config.toolsets() as toolsets__: ts = self.find(toolset).__name__ if ts not in toolsets__: toolsets__.append(ts) loaded.append(toolset) if loaded: output.append( translate( "toolset_loaded", count=len(loaded), sets=Humanize([inline(x) for x in loaded]) ) ) for page in pagify("\n".join(output)): await ctx.send(page)
def __trim_to_three(roles: List[discord.Role]) -> List[str]: new_list = [mention(x) for x in roles[:3]] if len(roles) > 3: new_list.append(translate("n_more", n=Humanize(len(roles) - 3))) return new_list
async def rndactivity_delay(self, ctx: commands.Context, *, duration: Delay): await self.config.delay.set(duration.total_seconds()) await ctx.send( tick(translate("delay_set", duration=Humanize(duration))))
async def build_description(self, member: Union[discord.Member, discord.User]) -> str: in_guild = isinstance(member, discord.Member) desc = [] if in_guild: desc.append( translate(f"status.{str(member.status)}") if f"status.{str(member.status)}" in translate else translate("status.unknown") ) for activity in member.activities: desc.append( translate( "activity", activity.type.name if not isinstance(activity, discord.Spotify) else "spotify", artists=Humanize(getattr(member.activity, "artists", [])), title=getattr(member.activity, "title", "???"), name=member.activity.name, url=getattr(member.activity, "url", None), default=None, ) ) if member.is_on_mobile(): desc.append(translate("on_mobile")) if member.voice: desc.append(translate("voice", channel=member.voice.channel.mention)) if member.bot: desc.append(translate("role.bot")) else: if await self.bot.is_owner(member): desc.append(translate("role.bot_owner")) if in_guild: if member.guild.owner.id == member.id: desc.append(translate("role.guild_owner")) elif await self.bot.is_admin(member): desc.append(translate("role.guild_admin")) elif await self.bot.is_mod(member): desc.append(translate("role.guild_mod")) else: desc.append(translate("role.guild_member")) else: desc.append(translate("role.non_member")) if in_guild: # This will only be visible on Red versions 3.1.4+ boost_since: Optional[datetime] = getattr(member, "premium_since", None) if boost_since: desc.append( translate( "nitro_boost", delta=Humanize(boost_since - datetime.utcnow()), date=Humanize(boost_since, tzinfo=get_localzone(), format=DATETIME_FORMAT), ) ) if member.nick: desc.append(translate("nickname", nick=bold(escape(member.nick, formatting=True)))) # noinspection PyTypeChecker return "\n".join(filter(bool, desc))
async def _user_info(self, ctx: commands.Context, member: Union[discord.Member, discord.User]): in_guild = isinstance(member, discord.Member) embed = discord.Embed( title=filter_invites(str(member)), colour=member.colour if member.colour.value != 0 else discord.Embed.Empty, description=await self.build_description(member), ).set_thumbnail( # discord.py 1.0.0 changes this to an Asset instance, which causes PyCharm to start # flipping the f**k out since it doesn't match the expected str type, despite # working perfectly fine. url=str(member.avatar_url_as(static_format="png")) ) now = datetime.utcnow() member_n = ( (sorted(member.guild.members, key=lambda m: m.joined_at or now).index(member) + 1) if in_guild else None ) embed.set_footer( text=translate( "member_footer" if member_n is not None else "user_footer", n=member_n, id=member.id ) ) if in_guild: if member.joined_at is None: joined_guild = translate("unknown_join_date") else: joined_guild = translate( "joined_server", delta=Humanize(member.joined_at - ctx.message.created_at, add_direction=True), absolute=Humanize(member.joined_at, DATETIME_FORMAT, tzinfo=get_localzone()), ) else: joined_guild = None joined_discord = translate( "joined_discord", delta=Humanize(member.created_at - ctx.message.created_at, add_direction=True), absolute=Humanize(member.created_at, DATETIME_FORMAT, tzinfo=get_localzone()), ) embed.add_field( name=translate("account_age"), value="\n".join(x for x in [joined_discord, joined_guild] if x is not None), ) if in_guild: roles = list(reversed([mention(x) for x in member.roles if not x.is_default()])) cap = 40 if len(roles) > cap: roles = [*roles[:cap], translate("more_roles", num=len(roles) - cap)] if roles: embed.add_field( name=translate("server_roles"), value=format_list(roles, locale=translate.locale.babel), inline=False, ) names, nicks = await self.get_names_and_nicks(member) if names: embed.add_field(name=translate("past_names"), value=", ".join(names), inline=False) if nicks: embed.add_field(name=translate("past_nicks"), value=", ".join(nicks), inline=False) await ctx.send(embed=embed)