async def modset_showsettings(self, ctx: commands.Context): """Show the current server administration settings.""" guild = ctx.guild data = await self.config.guild(guild).all() delete_repeats = data["delete_repeats"] warn_mention_spam = data["mention_spam"]["warn"] kick_mention_spam = data["mention_spam"]["kick"] ban_mention_spam = data["mention_spam"]["ban"] strict_mention_spam = data["mention_spam"]["strict"] respect_hierarchy = data["respect_hierarchy"] delete_delay = data["delete_delay"] reinvite_on_unban = data["reinvite_on_unban"] dm_on_kickban = data["dm_on_kickban"] default_days = data["default_days"] default_tempban_duration = data["default_tempban_duration"] msg = "" msg += _("Delete repeats: {num_repeats}\n").format( num_repeats=_("after {num} repeats").format( num=delete_repeats) if delete_repeats != -1 else _("No")) msg += _("Warn mention spam: {num_mentions}\n").format( num_mentions=_("{num} mentions").format( num=warn_mention_spam) if warn_mention_spam else _("No")) msg += _("Kick mention spam: {num_mentions}\n").format( num_mentions=_("{num} mentions").format( num=kick_mention_spam) if kick_mention_spam else _("No")) msg += _("Ban mention spam: {num_mentions}\n").format( num_mentions=_("{num} mentions").format( num=ban_mention_spam) if ban_mention_spam else _("No")) msg += (_( "Mention Spam Strict: All mentions will count including duplicates\n" ) if strict_mention_spam else _("Mention Spam Strict: Only unique mentions will count\n")) msg += _("Respects hierarchy: {yes_or_no}\n").format( yes_or_no=_("Yes") if respect_hierarchy else _("No")) msg += _("Delete delay: {num_seconds}\n").format( num_seconds=_("{num} seconds").format( num=delete_delay) if delete_delay != -1 else _("None")) msg += _("Reinvite on unban: {yes_or_no}\n").format( yes_or_no=_("Yes") if reinvite_on_unban else _("No")) msg += _("Send message to users on kick/ban: {yes_or_no}\n").format( yes_or_no=_("Yes") if dm_on_kickban else _("No")) if default_days: msg += _( "Default message history delete on ban: Previous {num_days} days\n" ).format(num_days=default_days) else: msg += _( "Default message history delete on ban: Don't delete any\n") msg += _("Default tempban duration: {duration}").format( duration=humanize_timedelta(seconds=default_tempban_duration)) await ctx.send(box(msg))
async def make_embed(self, data): vid_data = data["items"][0] video_url = "https://youtube.com/watch?v={}".format(vid_data["id"]) title = vid_data["snippet"]["title"] thumbnail = vid_data["snippet"]["thumbnails"]["medium"]["url"] channel_title = vid_data["snippet"]["channelTitle"] embed = discord.Embed(title=title, url=video_url) is_schedule = False if vid_data["liveStreamingDetails"].get("scheduledStartTime", None) is not None: if "actualStartTime" not in vid_data["liveStreamingDetails"]: start_time = parse_time( vid_data["liveStreamingDetails"]["scheduledStartTime"]) start_in = start_time - datetime.now(timezone.utc) if start_in.total_seconds() > 0: embed.description = _( "This stream will start in {time}").format( time=humanize_timedelta(timedelta=timedelta( minutes=start_in.total_seconds() // 60)) # getting rid of seconds ) else: embed.description = _( "This stream was scheduled for {min} minutes ago" ).format(min=round((start_in.total_seconds() * -1) // 60)) embed.timestamp = start_time is_schedule = True else: # repost message to_remove = [] for message in self._messages_cache: if message.embeds[0].description is discord.Embed.Empty: continue with contextlib.suppress(Exception): autodelete = await self._config.guild(message.guild ).autodelete() if autodelete: await message.delete() to_remove.append(message.id) self._messages_cache = [ x for x in self._messages_cache if x.id not in to_remove ] embed.set_author(name=channel_title) embed.set_image(url=rnd(thumbnail)) embed.colour = 0x9255A5 return embed, is_schedule
async def defaultduration( self, ctx: commands.Context, *, duration: commands.TimedeltaConverter(minimum=timedelta(seconds=1), default_unit="seconds"), ): """Set the default time to be used when a user is tempbanned. Accepts: seconds, minutes, hours, days, weeks `duration` must be greater than zero. Examples: `[p]modset defaultduration 7d12h10m` `[p]modset defaultduration 7 days 12 hours 10 minutes` """ guild = ctx.guild await self.config.guild(guild).default_tempban_duration.set( duration.total_seconds()) await ctx.send( _("The default duration for tempbanning a user is now {duration}." ).format(duration=humanize_timedelta(timedelta=duration)))
async def slowmode( self, ctx, *, interval: commands.TimedeltaConverter( minimum=timedelta(seconds=0), maximum=timedelta(hours=6), default_unit="seconds") = timedelta(seconds=0), ): """Changes channel's slowmode setting. Interval can be anything from 0 seconds to 6 hours. Use without parameters to disable. """ seconds = interval.total_seconds() await ctx.channel.edit(slowmode_delay=seconds) if seconds > 0: await ctx.send( _("Slowmode interval is now {interval}.").format( interval=humanize_timedelta(timedelta=interval))) else: await ctx.send(_("Slowmode has been disabled."))
async def serverinfo(self, ctx, details: bool = False): """ Show server information. `details`: Shows more information when set to `True`. Default to False. """ guild = ctx.guild passed = (ctx.message.created_at - guild.created_at).days created_at = _( "Created on {date}. That's over {num} days ago!").format( date=guild.created_at.strftime("%d %b %Y %H:%M"), num=humanize_number(passed), ) online = humanize_number( len([ m.status for m in guild.members if m.status != discord.Status.offline ])) total_users = humanize_number(guild.member_count) text_channels = humanize_number(len(guild.text_channels)) voice_channels = humanize_number(len(guild.voice_channels)) if not details: data = discord.Embed(description=created_at, colour=await ctx.embed_colour()) data.add_field(name=_("Region"), value=str(guild.region)) data.add_field(name=_("Users online"), value=f"{online}/{total_users}") data.add_field(name=_("Text Channels"), value=text_channels) data.add_field(name=_("Voice Channels"), value=voice_channels) data.add_field(name=_("Roles"), value=humanize_number(len(guild.roles))) data.add_field(name=_("Owner"), value=str(guild.owner)) data.set_footer( text=_("Server ID: ") + str(guild.id) + _(" • Use {command} for more info on the server.").format( command=f"{ctx.clean_prefix}serverinfo 1")) if guild.icon_url: data.set_author(name=guild.name, url=guild.icon_url) data.set_thumbnail(url=guild.icon_url) else: data.set_author(name=guild.name) else: def _size(num: int): for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]: if abs(num) < 1024.0: return "{0:.1f}{1}".format(num, unit) num /= 1024.0 return "{0:.1f}{1}".format(num, "YB") def _bitsize(num: int): for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]: if abs(num) < 1000.0: return "{0:.1f}{1}".format(num, unit) num /= 1000.0 return "{0:.1f}{1}".format(num, "YB") shard_info = (_("\nShard ID: **{shard_id}/{shard_count}**").format( shard_id=humanize_number(guild.shard_id + 1), shard_count=humanize_number(ctx.bot.shard_count), ) if ctx.bot.shard_count > 1 else "") # Logic from: https://github.com/TrustyJAID/Trusty-cogs/blob/master/serverstats/serverstats.py#L159 online_stats = { _("Humans: "): lambda x: not x.bot, _(" • Bots: "): lambda x: x.bot, "\N{LARGE GREEN CIRCLE}": lambda x: x.status is discord.Status.online, "\N{LARGE ORANGE CIRCLE}": lambda x: x.status is discord.Status.idle, "\N{LARGE RED CIRCLE}": lambda x: x.status is discord.Status.do_not_disturb, "\N{MEDIUM WHITE CIRCLE}\N{VARIATION SELECTOR-16}": lambda x: (x.status is discord.Status.offline), "\N{LARGE PURPLE CIRCLE}": lambda x: any(a.type is discord.ActivityType.streaming for a in x.activities), "\N{MOBILE PHONE}": lambda x: x.is_on_mobile(), } member_msg = _( "Users online: **{online}/{total_users}**\n").format( online=online, total_users=total_users) count = 1 for emoji, value in online_stats.items(): try: num = len([m for m in guild.members if value(m)]) except Exception as error: print(error) continue else: member_msg += f"{emoji} {bold(humanize_number(num))} " + ( "\n" if count % 2 == 0 else "") count += 1 vc_regions = { "vip-us-east": _("__VIP__ US East ") + "\U0001F1FA\U0001F1F8", "vip-us-west": _("__VIP__ US West ") + "\U0001F1FA\U0001F1F8", "vip-amsterdam": _("__VIP__ Amsterdam ") + "\U0001F1F3\U0001F1F1", "eu-west": _("EU West ") + "\U0001F1EA\U0001F1FA", "eu-central": _("EU Central ") + "\U0001F1EA\U0001F1FA", "europe": _("Europe ") + "\U0001F1EA\U0001F1FA", "london": _("London ") + "\U0001F1EC\U0001F1E7", "frankfurt": _("Frankfurt ") + "\U0001F1E9\U0001F1EA", "amsterdam": _("Amsterdam ") + "\U0001F1F3\U0001F1F1", "us-west": _("US West ") + "\U0001F1FA\U0001F1F8", "us-east": _("US East ") + "\U0001F1FA\U0001F1F8", "us-south": _("US South ") + "\U0001F1FA\U0001F1F8", "us-central": _("US Central ") + "\U0001F1FA\U0001F1F8", "singapore": _("Singapore ") + "\U0001F1F8\U0001F1EC", "sydney": _("Sydney ") + "\U0001F1E6\U0001F1FA", "brazil": _("Brazil ") + "\U0001F1E7\U0001F1F7", "hongkong": _("Hong Kong ") + "\U0001F1ED\U0001F1F0", "russia": _("Russia ") + "\U0001F1F7\U0001F1FA", "japan": _("Japan ") + "\U0001F1EF\U0001F1F5", "southafrica": _("South Africa ") + "\U0001F1FF\U0001F1E6", "india": _("India ") + "\U0001F1EE\U0001F1F3", "dubai": _("Dubai ") + "\U0001F1E6\U0001F1EA", "south-korea": _("South Korea ") + "\U0001f1f0\U0001f1f7", } verif = { "none": _("0 - None"), "low": _("1 - Low"), "medium": _("2 - Medium"), "high": _("3 - High"), "extreme": _("4 - Extreme"), } features = { "ANIMATED_ICON": _("Animated Icon"), "BANNER": _("Banner Image"), "COMMERCE": _("Commerce"), "COMMUNITY": _("Community"), "DISCOVERABLE": _("Server Discovery"), "FEATURABLE": _("Featurable"), "INVITE_SPLASH": _("Splash Invite"), "MEMBER_LIST_DISABLED": _("Member list disabled"), "MEMBER_VERIFICATION_GATE_ENABLED": _("Membership Screening enabled"), "MORE_EMOJI": _("More Emojis"), "NEWS": _("News Channels"), "PARTNERED": _("Partnered"), "PREVIEW_ENABLED": _("Preview enabled"), "PUBLIC_DISABLED": _("Public disabled"), "VANITY_URL": _("Vanity URL"), "VERIFIED": _("Verified"), "VIP_REGIONS": _("VIP Voice Servers"), "WELCOME_SCREEN_ENABLED": _("Welcome Screen enabled"), } guild_features_list = [ f"\N{WHITE HEAVY CHECK MARK} {name}" for feature, name in features.items() if feature in guild.features ] joined_on = _( "{bot_name} joined this server on {bot_join}. That's over {since_join} days ago!" ).format( bot_name=ctx.bot.user.name, bot_join=guild.me.joined_at.strftime("%d %b %Y %H:%M:%S"), since_join=humanize_number( (ctx.message.created_at - guild.me.joined_at).days), ) data = discord.Embed( description=(f"{guild.description}\n\n" if guild.description else "") + created_at, colour=await ctx.embed_colour(), ) data.set_author( name=guild.name, icon_url= "https://cdn.discordapp.com/emojis/457879292152381443.png" if "VERIFIED" in guild.features else "https://cdn.discordapp.com/emojis/508929941610430464.png" if "PARTNERED" in guild.features else discord.Embed.Empty, ) if guild.icon_url: data.set_thumbnail(url=guild.icon_url) data.add_field(name=_("Members:"), value=member_msg) data.add_field( name=_("Channels:"), value=_("\N{SPEECH BALLOON} Text: {text}\n" "\N{SPEAKER WITH THREE SOUND WAVES} Voice: {voice}"). format(text=bold(text_channels), voice=bold(voice_channels)), ) data.add_field( name=_("Utility:"), value=_( "Owner: {owner}\nVoice region: {region}\nVerif. level: {verif}\nServer ID: {id}{shard_info}" ).format( owner=bold(str(guild.owner)), region= f"**{vc_regions.get(str(guild.region)) or str(guild.region)}**", verif=bold(verif[str(guild.verification_level)]), id=bold(str(guild.id)), shard_info=shard_info, ), inline=False, ) data.add_field( name=_("Misc:"), value= _("AFK channel: {afk_chan}\nAFK timeout: {afk_timeout}\nCustom emojis: {emoji_count}\nRoles: {role_count}" ).format( afk_chan=bold(str(guild.afk_channel)) if guild.afk_channel else bold(_("Not set")), afk_timeout=bold( humanize_timedelta(seconds=guild.afk_timeout)), emoji_count=bold(humanize_number(len(guild.emojis))), role_count=bold(humanize_number(len(guild.roles))), ), inline=False, ) if guild_features_list: data.add_field(name=_("Server features:"), value="\n".join(guild_features_list)) if guild.premium_tier != 0: nitro_boost = _( "Tier {boostlevel} with {nitroboosters} boosts\n" "File size limit: {filelimit}\n" "Emoji limit: {emojis_limit}\n" "VCs max bitrate: {bitrate}").format( boostlevel=bold(str(guild.premium_tier)), nitroboosters=bold( humanize_number(guild.premium_subscription_count)), filelimit=bold(_size(guild.filesize_limit)), emojis_limit=bold(str(guild.emoji_limit)), bitrate=bold(_bitsize(guild.bitrate_limit)), ) data.add_field(name=_("Nitro Boost:"), value=nitro_boost) if guild.splash: data.set_image(url=guild.splash_url_as(format="png")) data.set_footer(text=joined_on) await ctx.send(embed=data)
async def voice_mute( self, ctx: commands.Context, users: commands.Greedy[discord.Member], *, time_and_reason: MuteTime = {}, ): """Mute a user in their current voice channel. `<users...>` is a space separated list of usernames, ID's, or mentions. `[time_and_reason]` is the time to mute for and reason. Time is any valid time length such as `30 minutes` or `2 days`. If nothing is provided the mute will use the set default time or indefinite if not set. Examples: `[p]voicemute @member1 @member2 spam 5 hours` `[p]voicemute @member1 3 days`""" if not users: return await ctx.send_help() if ctx.me in users: return await ctx.send(_("You cannot mute me.")) if ctx.author in users: return await ctx.send(_("You cannot mute yourself.")) async with ctx.typing(): success_list = [] issue_list = [] for user in users: user_voice_state = user.voice can_move, perm_reason = await self._voice_perm_check( ctx, user_voice_state, mute_members=True, manage_permissions=True) if not can_move: issue_list.append((user, perm_reason)) continue duration = time_and_reason.get("duration", None) reason = time_and_reason.get("reason", None) time = "" until = None if duration: until = datetime.now(timezone.utc) + duration time = _(" for {duration}").format( duration=humanize_timedelta(timedelta=duration)) else: default_duration = await self.config.guild( ctx.guild).default_time() if default_duration: until = datetime.now( timezone.utc) + timedelta(seconds=default_duration) time = _(" for {duration}").format( duration=humanize_timedelta(timedelta=timedelta( seconds=default_duration))) guild = ctx.guild author = ctx.author channel = user_voice_state.channel audit_reason = get_audit_reason(author, reason, shorten=True) success = await self.channel_mute_user(guild, channel, author, user, until, audit_reason) if success["success"]: if "reason" in success and success["reason"]: issue_list.append((user, success["reason"])) else: success_list.append(user) await modlog.create_case( self.bot, guild, ctx.message.created_at.replace(tzinfo=timezone.utc), "vmute", user, author, reason, until=until, channel=channel, ) await self._send_dm_notification(user, author, guild, _("Voice mute"), reason, duration) async with self.config.member(user).perms_cache() as cache: cache[channel.id] = success["old_overs"] else: issue_list.append((user, success["reason"])) if success_list: msg = _("{users} has been muted in this channel{time}.") if len(success_list) > 1: msg = _("{users} have been muted in this channel{time}.") await ctx.send( msg.format(users=humanize_list([f"{u}" for u in success_list]), time=time)) if issue_list: msg = _("The following users could not be muted\n") for user, issue in issue_list: msg += f"{user}: {issue}\n" await ctx.send_interactive(pagify(msg))