async def play(self, ctx, *, url:str): """Enqueues a song to be played""" await ctx.channel.trigger_typing() if ctx.voice_client is None: if ctx.author.voice: try: await ctx.author.voice.channel.connect() except discord.errors.Forbidden: await ctx.send(Language.get("music.no_connect_perms", ctx).format(ctx.author.voice.channel)) return else: await ctx.send(Language.get("music.no_voice_channel", ctx)) return queue = self.get_queue(ctx) url = url.strip("<>") try: song = self.download_video(ctx, url) except youtube_dl.utils.DownloadError as error: await ctx.send(Language.get("music.failed_download", ctx).format(str(error.exc_info[1]).strip("[youtube] "))) return except: await ctx.send(traceback.format_exc()) return await queue.songs.put(song) queue.song_list.append(str(song)) await ctx.send(Language.get("music.enqueued", ctx).format(song))
async def e621(self, ctx, *, tags: str): """Searches e621.net for the specified tagged images""" await ctx.channel.trigger_typing() tags = strip_global_mentions(tags, ctx) try: data = requests.get( "https://e621.net/post/index.json?limit={}&tags={}".format( limit, tags), headers=header).json() except json.JSONDecodeError: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): images.append(data[random.randint(0, count)]["file_url"]) await ctx.send( Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def skip(self, ctx): """Skips a song""" queue = self.get_queue(ctx) if not ctx.voice_client: await ctx.send("I'm not in a voice channel.") return if ctx.author.id in config.dev_ids or ctx.author.id == config.owner_id: queue.voice_client.stop() await ctx.send(Language.get("music.bot_dev_skip", ctx)) elif ctx.author == queue.current.requester: queue.voice_client.stop() await ctx.send(Language.get("music.song_requester_skip", ctx)) else: needed = config.skip_votes_needed channel_members = len([member for member in queue.voice_client.channel.members if not member.bot]) if channel_members <= needed: needed = channel_members - 1 if ctx.author.id not in queue.skip_votes: queue.skip_votes.append(ctx.author.id) else: await ctx.send(Language.get("music.already_skip_voted", ctx)) return if len(queue.skip_votes) >= needed: queue.voice_client.stop() await ctx.send(Language.get("music.skip", ctx)) else: await ctx.send(Language.get("music.skip_vote_added", ctx).format(len(queue.skip_votes), needed))
async def changestatus(ctx, status: str, *, name: str = None): """Changes the bot's status with the specified status type and name""" if lock_status: if not ctx.author.id == config.owner_id and not ctx.author.id in config.dev_ids: await ctx.send(Language.get("bot.status_locked", ctx)) return activity = None if status == "invisible" or status == "offline": await ctx.send( Language.get("bot.forbidden_status_type", ctx).format(status)) return try: statustype = discord.Status(status) except ValueError: await ctx.send(Language.get("bot.valid_status_types", ctx)) return if name != "": activity = discord.Activity(name=name, type=discord.ActivityType.playing) await bot.change_presence(activity=activity, status=statustype) if name is not None: await ctx.send( Language.get("bot.status_change_with_name", ctx).format(name, status)) await channel_logger.log_to_channel( ":information_source: `{}`/`{}` has changed the game name to `{}` with a(n) `{}` status type" .format(ctx.author.id, ctx.author, name, status)) else: await ctx.send(Language.get("bot.status_change", ctx).format(status)) await channel_logger.log_to_channel( ":information_source: `{}`/`{}` has changed the status type to `{}`" .format(ctx.author.id, ctx.author, name))
async def yandere(self, ctx, *, tags: str): """Searches yande.re for the specified tagged images""" await ctx.channel.trigger_typing() try: data = json.loads( requests.get( "https://yande.re/post/index.json?limit={}&tags={}".format( limit, tags)).text) except json.JSONDecodeError: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): images.append(data[random.randint(0, count)]["file_url"]) await ctx.send( Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def showjoinleaveconfig(self, ctx): """Shows the on user join and leave config""" await ctx.channel.trigger_typing() join_message = read_data_entry(ctx.guild.id, "join-message") if join_message is not None: join_message = join_message.replace("%user%", "@{}".format(ctx.author.name)).replace("%server%", ctx.guild.name) leave_message = read_data_entry(ctx.guild.id, "leave-message") if leave_message is not None: leave_message = leave_message.replace("%user%", "@{}".format(ctx.author.name)).replace("%server%", ctx.guild.name) join_leave_channel_id = read_data_entry(ctx.guild.id, "join-leave-channel") if join_leave_channel_id is not None: join_leave_channel = discord.utils.get(ctx.guild.channels, id=join_leave_channel_id).mention if join_leave_channel is None: update_data_entry(ctx.guild.id, "join-leave-channel", None) else: join_leave_channel = None join_role_id = read_data_entry(ctx.guild.id, "join-role") if join_role_id is not None: join_role = discord.utils.get(ctx.guild.roles, id=join_role_id).name if join_role is None: update_data_entry(ctx.guild.id, "join-role", None) else: join_role = None fields = {Language.get("configuration.join_message", ctx):join_message, Language.get("configuration.leave_message", ctx):leave_message, Language.get("configuration.channel", ctx):join_leave_channel, Language.get("configuration.join_role", ctx):join_role} embed = make_list_embed(fields) embed.title = Language.get("configuration.showjoinleaveconfig_title", ctx) embed.color = 0xFF0000 await ctx.send(embed=embed)
async def rule34(self, ctx, *, tags: str): await ctx.channel.trigger_typing() try: data = json.loads( requests.get( "http://rule34.xxx/index.php?page=dapi&s=post&q=index&json=1&limit={}&tags={}" .format(limit, tags)).text) except json.JSONDecodeError: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): image = data[random.randint(0, count)] images.append("http://img.rule34.xxx/images/{}/{}".format( image["directory"], image["image"])) await ctx.send( Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def rule34(self, ctx, *, tags: str): """Searches rule34.xxx for the specified tagged images""" await ctx.channel.trigger_typing() tags = strip_global_mentions(tags, ctx) try: data = requests.get( "http://rule34.xxx/index.php?page=dapi&s=post&q=index&json=1&limit={}&tags={}" .format(limit, tags), headers=header).json() except json.JSONDecodeError: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(strip_global_mentions(tags, ctx))) return count = len(data) if count == 0: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): image = data[random.randint(0, count)] images.append("http://img.rule34.xxx/images/{}/{}".format( image["directory"], image["image"])) await ctx.send( Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def banlist(self, ctx): """Displays the server's banlist""" try: banlist = await ctx.guild.bans() except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_ban_perms", ctx)) return bancount = len(banlist) display_bans = [] bans = None if bancount == 0: bans = Language.get("moderation.no_bans", ctx) else: for ban in banlist: if len(", ".join(display_bans)) < 1800: display_bans.append(str(ban.user)) else: bans = ", ".join(display_bans) + Language.get( "moderation.banlist_and_more", ctx).format(len(banlist) - len(display_bans)) break if not bans: bans = ", ".join(display_bans) await ctx.send( Language.get("moderation.banlist", ctx).format(bancount, bans))
async def createrole(self, ctx, *, name:str): """Creates a role with the specified name""" try: await ctx.guild.create_role(name=name, reason=Language.get("createrole_reason", ctx).format(ctx.author), permissions=ctx.guild.default_role.permissions) await ctx.send(Language.get("createrole_success", ctx).format(name)) except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_manage_role_perms", ctx))
async def danbooru(self, ctx, *, tags: str): """Searches danbooru.donmai.us for the specified tagged images""" await ctx.channel.trigger_typing() try: data = requests.get( "https://danbooru.donmai.us/post/index.json?limit={}&tags={}". format(limit, tags), headers=header).json() except json.JSONDecodeError: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): try: images.append(data[random.randint(0, count)]["file_url"]) except KeyError: await ctx.send(data["message"]) return await ctx.send( Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def xbooru(self, ctx, *, tags: str): """Searches xbooru.com for the specified tagged images""" await ctx.channel.trigger_typing() try: data = json.loads( requests.get( "https://xbooru.com/index.php?page=dapi&s=post&q=index&json=1&limit={}&tags={}" .format(limit, tags)).text) except json.JSONDecodeError: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): try: post = data[random.randint(0, count)] images.append("http://img3.xbooru.com/images/{}/{}".format( post["directory"], post["image"])) except KeyError: await ctx.send(data["message"]) return await ctx.send( Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def rule34(ctx, *, tags: str): """A wonderfun NSFW command""" await ctx.channel.trigger_typing() try: data = requests.get( "http://rule34.xxx/index.php?page=dapi&s=post&q=index&json=1&limit={}&tags={}" .format(tags), headers=header).json() except json.JSONDecodeError as f: logger.error(f) await ctx.send(Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send(Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 8 if count < 8: image_count = count images = [] for i in range(image_count): image = data[random.randint(0, count)] images.append("http://img.rule34.xxx/images/{}/{}".format( image["directory"], image["image"])) await ctx.send(("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def gelbooru(self, ctx, *, tags: str): """Searches gelbooru.com for the specified tagged images""" await ctx.channel.trigger_typing() tags = strip_global_mentions(tags, ctx) try: data = requests.get( "https://gelbooru.com/index.php?page=dapi&s=post&q=index&json=1&limit={}&tags={}" .format(limit, tags), headers=header).json() except json.JSONDecodeError: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send( Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): try: images.append("{}".format(data[random.randint( 0, count)]["file_url"])) except KeyError: await ctx.send(data["message"]) return await ctx.send( Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def rate(self, ctx, user:discord.User=None): """Have the bot rate yourself or another user (rigged af)""" if user is None or user.id == ctx.author.id: await ctx.send(Language.get("fun.rate_author", ctx)) elif user == self.bot.user: await ctx.send(Language.get("fun.rate_self", ctx)) else: await ctx.send(Language.get("fun.rate_user", ctx).format(user.name, random.randint(0, 10)))
async def emoteinfo(self, ctx, *, emote:discord.Emoji): """Gets information on a custom emote (Only works for servers the bot is on)""" fields = {Language.get("information.name", ctx):emote.name, Language.get("information.id", ctx):emote.id, Language.get("information.server_origin", ctx):emote.guild.name, Language.get("information.created_on", ctx):format_time(emote.created_at), Language.get("information.colons_required", ctx):emote.require_colons, Language.get("information.managed_by_twitch", ctx):emote.managed} embed = make_list_embed(fields) embed.title = ":{}:".format(emote.name) embed.color = 0xFF0000 embed.set_thumbnail(url=emote.url) await ctx.send(embed=embed)
async def config(self, ctx, type:str, *, value:str): """Modifies the server's local config""" await ctx.channel.trigger_typing() if type == "mod-role" or type == "mute-role": update_data_entry(ctx.guild.id, type, value) await ctx.send(Language.get("configuration.set_success", ctx).format(type, value)) else: await ctx.send(Language.get("configuration.invalid_set_type", ctx).format(type))
async def stream(ctx, *, name:str): """Sets the streaming status with the specified name""" if lock_status: if not ctx.author.id == config.owner_id and not ctx.author.id in config.dev_ids: await ctx.send(Language.get("bot.status_locked", ctx)) return await bot.change_presence(activity=discord.Activity(name=name, type=discord.ActivityType.streaming, url="https://www.twitch.tv/ZeroEpoch1969")) await ctx.send(Language.get("bot.now_streaming", ctx).format(name)) await channel_logger.log_to_channel(":information_source: `{}`/`{}` has changed the streaming status to `{}`".format(ctx.author.id, ctx.author, name))
async def inviteme(self, ctx): await ctx.send( Language.get("bot.joinserver", ctx).format( "https://discord.com/oauth2/authorize?client_id=657372691749273612&scope=bot&permissions=2134375927" )) await ctx.author.send( Language.get("bot.joinserver", ctx).format( "https://discord.com/oauth2/authorize?client_id=657372691749273612&scope=bot&permissions=2134375927" ))
async def id(self, ctx, user: discord.User = None): """Gets your ID or the specified user's ID""" if user is None: await ctx.send( Language.get("information.author_id", ctx).format(ctx.author.id)) else: await ctx.send( Language.get("information.user_id", ctx).format(user.mention, user.id))
async def id(self, ctx, user: discord.User = None): """Gets your ID or if you @mention a user it gets their id""" if user is None: await ctx.send( Language.get("information.author_id", ctx).format(ctx.author.id)) else: await ctx.send( Language.get("information.user_id", ctx).format(user.mention, user.id))
async def showconfig(self, ctx): """Shows the server's configuration""" await ctx.channel.trigger_typing() mod_role_name = read_data_entry(ctx.guild.id, "mod-role") mute_role_name = read_data_entry(ctx.guild.id, "mute-role") fields = {Language.get("configuration.mod_role", ctx):mod_role_name, Language.get("configuration.mute_role", ctx):mute_role_name} embed = make_list_embed(fields) embed.title = Language.get("configuration.server_configuration", ctx) embed.color = 0xFF0000 await ctx.send(embed=embed)
async def joinleave(self, ctx, type:str, *, value:str): """Configures on user join and leave settings""" await ctx.channel.trigger_typing() if type == "join-message": update_data_entry(ctx.guild.id, type, value) await ctx.send(Language.get("configuration.join_message_set_success", ctx).format(value.replace("%user%", "@{}".format(ctx.author.name)).replace("%server%", ctx.guild.name))) elif type == "leave-message": update_data_entry(ctx.guild.id, type, value) await ctx.send(Language.get("configuration.leave_message_set_success", ctx).format(value.replace("%user%", "@{}".format(ctx.author.name)).replace("%server%", ctx.guild.name))) elif type == "channel": if value == "remove": update_data_entry(ctx.guild.id, "join-leave-channel", None) await ctx.send(Language.get("configuration.join-leave_disabled", ctx)) return channel = discord.utils.get(ctx.guild.channels, name=value) if channel is None: await ctx.send(Language.get("configuration.channel_not_found", ctx).format(value)) return update_data_entry(ctx.guild.id, "join-leave-channel", channel.id) await ctx.send(Language.get("configuration.join-leave_channel_set_success", ctx).format(channel.mention)) elif type == "join-role": if value == "remove": update_data_entry(ctx.guild.id, type, None) await ctx.send(Language.get("configuration.join-leave_role_disabled", ctx)) return role = discord.utils.get(ctx.guild.roles, name=value) if role is None: await ctx.send(Language.get("configuration.role_not_found", ctx).format(value)) return update_data_entry(ctx.guild.id, type, role.id) await ctx.send(Language.get("configuration.join-role_set_success", ctx).format(role.name)) else: await ctx.send(Language.get("configuration.join_settings_invalid_type", ctx).format(type))
async def anime(self, ctx, *, name: str): """Searches MyAnimeList for the specified anime""" await ctx.channel.trigger_typing() r = requests.get( "https://myanimelist.net/api/anime/search.xml?q={}".format(name), auth=requests.auth.HTTPBasicAuth(config._malUsername, config._malPassword)) if r.status_code == 401: log.critical( "The MyAnimeList credinals are incorrect, please check your MyAnimeList login information in the config." ) await ctx.send(Language.get("myanimelist.incorrect_creds", ctx)) return try: xmldoc = minidom.parseString(r.text) except XmlParserErrors.ExpatError: await ctx.send( Language.get("myanimelist.no_anime_found", ctx).format(name)) return # pls no flame anime = xmldoc.getElementsByTagName("entry")[0] id = anime.getElementsByTagName("id")[0].firstChild.nodeValue title = anime.getElementsByTagName("title")[0].firstChild.nodeValue try: english = anime.getElementsByTagName( "english")[0].firstChild.nodeValue except: english = title episodes = anime.getElementsByTagName( "episodes")[0].firstChild.nodeValue score = anime.getElementsByTagName("score")[0].firstChild.nodeValue type = anime.getElementsByTagName("type")[0].firstChild.nodeValue status = anime.getElementsByTagName("status")[0].firstChild.nodeValue start_date = anime.getElementsByTagName( "start_date")[0].firstChild.nodeValue end_date = anime.getElementsByTagName( "end_date")[0].firstChild.nodeValue image = anime.getElementsByTagName("image")[0].firstChild.nodeValue synopsis = saxutils.unescape( anime.getElementsByTagName("synopsis")[0].firstChild.nodeValue) synopsis = remove_html(synopsis) if len(synopsis) > 300: synopsis = synopsis[:300] + "..." url = "https://myanimelist.net/anime/{}".format(id) fields = { Language.get("myanimelist.english_title", ctx): english, Language.get("myanimelist.episodes", ctx): episodes, Language.get("myanimelist.mal_line", ctx): score, Language.get("myanimelist.type", ctx): type, Language.get("myanimelist.status", ctx): status, Language.get("myanimelist.start_date", ctx): start_date, Language.get("myanimelist.end_date", ctx): end_date } embed = make_list_embed(fields) embed.title = title embed.description = synopsis embed.url = url embed.color = 0xFF0000 embed.set_thumbnail(url=image) await ctx.send(embed=embed)
async def pin(self, ctx, id:int): """Pins the message with the specified ID to the channel""" try: message = await ctx.channel.fetch_message(id) except discord.errors.NotFound: await ctx.send(Language.get("bot.no_message_found", ctx).format(id)) return try: await message.pin() except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_manage_messages_perms", ctx))
async def unpin(self, ctx, id:int): """Unpins the message with the specified ID from the channel""" pinned_messages = await ctx.channel.pins() message = discord.utils.get(pinned_messages, id=id) if message is None: await ctx.send(Language.get("moderation.no_pinned_message_found", ctx).format(id)) return try: await message.unpin() await ctx.send(Language.get("moderation.unpin_success", ctx)) except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_manage_messages_perms", ctx))
async def kick(self, ctx, user:discord.Member): """Kicks the specified user from the server""" try: await ctx.guild.kick(user) except discord.errors.Forbidden: if user.top_role.position == ctx.me.top_role.position: await ctx.send(Language.get("moderation.no_kick_highest_role", ctx)) elif user.top_role.position > ctx.me.top_role.position: await ctx.send(Language.get("moderation.no_kick_higher_role", ctx)) else: await ctx.send(Language.get("moderation.no_kick_perms", ctx)) await ctx.send(Language.get("moderation.kick_success", ctx).format(user))
async def config(self, ctx, type: str, *, value: str): """Modifies the server's local config""" await ctx.channel.trigger_typing() if type == "mod-role" or type == "mute-role": update_data_entry(ctx.guild.id, type, value) await ctx.send( Language.get("configuration.set_success", ctx).format(type, value)) else: await ctx.send( Language.get("configuration.invalid_set_type", ctx).format(type))
async def removereactions(self, ctx, id:int): """Clear reactions from a message""" try: message = await ctx.channel.fetch_message(id) except discord.errors.NotFound: await ctx.send(Language.get("bot.no_message_found", ctx).format(id)) return try: await message.clear_reactions() await ctx.send(Language.get("moderation.removereactions_success", ctx)) except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_manage_messages_perms", ctx))
async def isitdown(self, ctx, *, url:str): """Checks to see if a website is online or not""" await ctx.channel.trigger_typing() url = url.strip("<>") if not url.startswith("http://") and not url.startswith("https://"): url = "http://{}".format(url) try: starttime = time.time() requests.get(url, timeout=3) ping = Language.get("information.ping_time", ctx) % (time.time() - starttime) await ctx.send(Language.get("information.online_ping", ctx).format(url, ping)) except: await ctx.send(Language.get("information.offline_ping", ctx).format(url))
async def showconfig(self, ctx): """Shows the server's configuration""" await ctx.channel.trigger_typing() mod_role_name = read_data_entry(ctx.guild.id, "mod-role") mute_role_name = read_data_entry(ctx.guild.id, "mute-role") fields = { Language.get("configuration.mod_role", ctx): mod_role_name, Language.get("configuration.mute_role", ctx): mute_role_name } embed = make_list_embed(fields) embed.title = Language.get("configuration.server_configuration", ctx) embed.color = 0xFF0000 await ctx.send(embed=embed)
async def pin(self, ctx, messageid:int): try: await ctx.message.delete() message = await ctx.channel.fetch_message(messageid) except discord.errors.NotFound: await ctx.send(Language.get("bot.no_message_found", ctx).format(messageid)) return try: await message.pin() await ctx.send(f"Successfully pinned message with id {messageid}") except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_manage_messages_perms", ctx))
async def serverinfo(self, ctx): """Gets information on the current server""" guild = ctx.guild human_count = len([member for member in guild.members if not member.bot]) bot_count = len(([member for member in guild.members if member.bot])) timeout_times = {60:Language.get("information.timeout_times.60", ctx), 300:Language.get("information.timeout_times.300", ctx), 900:Language.get("information.timeout_times.900", ctx), 1800:Language.get("information.timeout_times.1800", ctx), 3600:Language.get("information.timeout_times.3600", ctx)} fields = {Language.get("information.id", ctx):guild.id, Language.get("information.created_on", ctx):format_time(guild.created_at), Language.get("information.region", ctx):guild.region, Language.get("information.member_count_title", ctx).format(len(guild.members)):Language.get("information.member_count", ctx).format(human_count, bot_count), Language.get("information.channel_count_title", ctx).format(len(guild.channels)):Language.get("information.channel_count", ctx).format(len(guild.text_channels), len(guild.voice_channels)), Language.get("information.role_count", ctx):len(guild.roles), Language.get("information.owner", ctx):guild.owner, Language.get("information.owner_id", ctx):guild.owner_id, Language.get("information.afk_channel", ctx):guild.afk_channel, Language.get("information.afk_timeout", ctx):timeout_times[guild.afk_timeout], Language.get("information.verification_level", ctx):str(ctx.guild.verification_level).capitalize().replace("High", tableflip).replace("Extreme", doubleflip), Language.get("information.2fa_enabled", ctx):convert_to_bool(guild.mfa_level)} embed = make_list_embed(fields) embed.title = guild.name embed.color = 0xFF0000 if guild.icon_url: embed.set_thumbnail(url=guild.icon_url) await ctx.send(embed=embed)
async def joinleave(self, ctx, type: str, *, value: str): """Configures on user join and leave settings""" await ctx.channel.trigger_typing() if type == "join-message": update_data_entry(ctx.guild.id, type, value) await ctx.send( Language.get("configuration.join_message_set_success", ctx).format( value.replace("%user%", "@{}".format( ctx.author.name)).replace( "%server%", ctx.guild.name))) elif type == "leave-message": update_data_entry(ctx.guild.id, type, value) await ctx.send( Language.get("configuration.leave_message_set_success", ctx).format( value.replace("%user%", "@{}".format( ctx.author.name)).replace( "%server%", ctx.guild.name))) elif type == "channel": if value == "remove": update_data_entry(ctx.guild.id, "join-leave-channel", None) await ctx.send( Language.get("configuration.join-leave_disabled", ctx)) return channel = discord.utils.get(ctx.guild.channels, name=value) if channel is None: await ctx.send( Language.get("configuration.channel_not_found", ctx).format(value)) return update_data_entry(ctx.guild.id, "join-leave-channel", channel.id) await ctx.send( Language.get("configuration.join-leave_channel_set_success", ctx).format(channel.mention)) elif type == "join-role": if value == "remove": update_data_entry(ctx.guild.id, type, None) await ctx.send( Language.get("configuration.join-leave_role_disabled", ctx)) return role = discord.utils.get(ctx.guild.roles, name=value) if role is None: await ctx.send( Language.get("configuration.role_not_found", ctx).format(value)) return update_data_entry(ctx.guild.id, type, role.id) await ctx.send( Language.get("configuration.join-role_set_success", ctx).format(role.name)) else: await ctx.send( Language.get("configuration.join_settings_invalid_type", ctx).format(type))
async def getuserbyid(self, ctx, id:int): """Gets a user by id""" user = discord.utils.get(list(self.bot.get_all_members()), id=id) if not user: await ctx.send(Language.get("information.no_mutual_servers", ctx).format(id)) return if user.game: game = user.game.name fields = {Language.get("information.name", ctx):user.name, Language.get("information.discriminator", ctx):user.discriminator, Language.get("information.id", ctx):user.id, Language.get("information.statud", ctx):str(user.status).replace("dnd", "do not disturb"), Language.get("information.game", ctx):game, Language.get("information.boot", ctx):user.bot} embed = make_list_embed(fields) embed.title = str(user) embed.color = 0xFF0000 embed.set_thumbnail(url=get_avatar(user)) await ctx.send(embed=embed)
async def stats(ctx): """Gets the bot's stats""" voice_clients = [] for guild in bot.guilds: if guild.me.voice: voice_clients.append(guild.me.voice.channel) fields = { Language.get("bot.stats.users", ctx): len(list(bot.get_all_members())), Language.get("bot.stats.servers", ctx): len(bot.guilds), Language.get("bot.stats.channels", ctx): len(list(bot.get_all_channels())), Language.get("bot.stats.voice_clients", ctx): len(voice_clients), Language.get("bot.stats.discordpy_version", ctx): discord.__version__, Language.get("bot.stats.bot_version", ctx): BUILD_VERSION, Language.get("bot.stats.built_by", ctx): BUILD_AUTHORS, Language.get("bot.stats.translators", ctx): ", ".join(TRANSLATORS.keys()) } embed = make_list_embed(fields) embed.title = str(bot.user) embed.color = 0xFF0000 embed.set_thumbnail(url=bot.user.avatar_url) bot_owner = discord.utils.get(list(bot.get_all_members()), id=config.owner_id) if bot_owner is not None: embed.set_footer(text=bot_owner, icon_url=get_avatar(bot_owner)) await ctx.send(embed=embed)
async def osu(self, ctx, *, username:str): """Gets an osu! profile stats with the specified name""" if not config.enableOsu: await ctx.send(Language.get("information.osu_command_disabled", ctx)) return try: import osuapi except ImportError: log.critical("The osu api is enabled, but the osuapi module was not found! Please run \"pip install osuapi\"") await ctx.send(Language.get("osu_import_fail", ctx)) return await ctx.channel.trigger_typing() api = osuapi.OsuApi(config._osuKey, connector=osuapi.AHConnector()) try: user = await api.get_user(username) except osuapi.HTTPError as e: if e.code == 401: log.critical("An invalid osu! api key was set, please check the config for instructions on how to get a proper api key!") await ctx.send(Language.get("information.osu_invalid_key", ctx)) return else: log.critical("An unknown error occured while trying to get an osu! profile.") await ctx.send(Language.get("information.osu_unknown_error", ctx)) return try: user = user[0] except IndexError: await ctx.send(Language.get("information.no_osu_profile_found", ctx).format(username)) return fields = {Language.get("information.id", ctx):user.user_id, Language.get("information.country", ctx):user.country, Language.get("information.level", ctx):int(user.level), Language.get("information.hits", ctx):user.total_hits, Language.get("information.score", ctx):user.total_score, Language.get("information.accuracy", ctx):"{0:.2f}%".format(user.accuracy), Language.get("information.play_count", ctx):user.playcount, Language.get("information.ranked_score", ctx):user.ranked_score, Language.get("information.a_rank", ctx):user.count_rank_a, Language.get("information.s_rank", ctx):user.count_rank_s, Language.get("information.ss_rank", ctx):user.count_rank_ss} embed = make_list_embed(fields) embed.title = Language.get("information.osu_stats_title", ctx).format(user.username) embed.color = 0xFF00FF embed.set_thumbnail(url="http://s.ppy.sh/a/{}".format(user.user_id)) await ctx.send(embed=embed)
async def massban(self, ctx, *, ids:str): """Mass bans users by ids (separate ids with spaces)""" await ctx.channel.trigger_typing() ids = ids.split(" ") failed_ids = [] success = 0 for id in ids: try: await self.bot.http.ban(int(id), ctx.guild.id, delete_message_days=0) success += 1 except: failed_ids.append("`{}`".format(id)) if len(failed_ids) != 0: await ctx.send(Language.get("moderation.massban_failed_ids", ctx).format(", ".join(ids))) await ctx.send(Language.get("moderation.massban_success", ctx).format(success, len(ids)))
async def prune(self, ctx, amount:int): """Prunes the specified amount of messages (you can also prune messages from a specific user too)""" try: await ctx.message.delete() except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_manage_messages_perms", ctx)) return deleted = await ctx.channel.purge(limit=amount) deleted_message = await ctx.send(Language.get("moderation.pruned", ctx).format(ctx.author.mention, len(deleted))) await asyncio.sleep(10) # The try and except pass is so in the event a user prunes again or deletes the prune notification before the bot automatically does it, it will not raise an error try: await deleted_message.delete() except: pass
async def unban(self, ctx, *, username:str): """Unbans the user with the specifed name from the server""" try: banlist = await ctx.guild.bans() except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_ban_perms", ctx)) return user = None for ban in banlist: if ban.user.name == username: user = ban.user if user is None: await ctx.send(Language.get("moderation.user_not_banned", ctx).format(username)) return await ctx.guild.unban(user) await ctx.send(Language.get("moderation.unban_success", ctx).format(user))
async def uptime(ctx): """Displays how long the bot has been online for""" second = time.time() - start_time minute, second = divmod(second, 60) hour, minute = divmod(minute, 60) day, hour = divmod(hour, 24) week, day = divmod(day, 7) await ctx.send(Language.get("bot.uptime", ctx) % (week, day, hour, minute, second))
async def stats(ctx): """Gets the bot's stats""" voice_clients = [] for guild in bot.guilds: if guild.me.voice: voice_clients.append(guild.me.voice.channel) fields = {Language.get("bot.stats.users", ctx):len(list(bot.get_all_members())), Language.get("bot.stats.servers", ctx):len(bot.guilds), Language.get("bot.stats.channels", ctx):len(list( bot.get_all_channels())), Language.get("bot.stats.voice_clients", ctx):len(voice_clients), Language.get("bot.stats.discordpy_version", ctx):discord.__version__, Language.get("bot.stats.bot_version", ctx): BUILD_VERSION, Language.get("bot.stats.built_by", ctx):BUILD_AUTHORS, Language.get("bot.stats.translators", ctx):", ".join(TRANSLATORS.keys())} embed = make_list_embed(fields) embed.title = str(bot.user) embed.color = 0xFF0000 embed.set_thumbnail(url=bot.user.avatar_url) bot_owner = discord.utils.get(list(bot.get_all_members()), id=config.owner_id) if bot_owner is not None: embed.set_footer(text=bot_owner, icon_url=get_avatar(bot_owner)) await ctx.send(embed=embed)
async def ping(ctx): """Pings the bot""" pingms = await ctx.send(Language.get("bot.pinging", ctx)) start = time.time() async with aiosession.get("https://discordapp.com"): duration = time.time() - start duration = round(duration * 1000) await pingms.edit(content="{0} // **{1}ms**".format(pingms.content, duration))
async def getemotes(self, ctx): """Gets a list of the server's emotes""" emotes = ctx.guild.emojis if len(emotes) == 0: await ctx.send(Language.get("information.no_server_emotes", ctx)) return emotes = ["`:{}:` = {}".format(emote.name, emote) for emote in emotes] await ctx.send("\n".join(emotes))
async def banid(self, ctx, id:int, *, reason:str=None): """Bans the user with the specified id from the server (Useful if the user isn't on the server yet)""" if reason is None: reason = Language.get("moderation.no_reason", ctx) reason += Language.get("moderation.banned_by", ctx).format(ctx.author) try: await self.bot.http.ban(id, ctx.guild.id, delete_message_days=0, reason=reason) except discord.errors.HTTPException or discord.errors.NotFound: await ctx.send(Language.get("moderation.invalid_user_id", ctx).format(id)) return except discord.errors.Forbidden: await ctx.send(Language.get("moderation.no_ban_perms", ctx)) return banlist = await ctx.guild.bans() for ban in banlist: if ban.user.id == id: user = ban.user await ctx.send(Language.get("moderation.ban_success", ctx).format(user))
async def yandere(self, ctx, *, tags:str): """Searches yande.re for the specified tagged images""" await ctx.channel.trigger_typing() try: data = requests.get("https://yande.re/post/index.json?limit={}&tags={}".format(limit, tags), headers=header).json() except json.JSONDecodeError: await ctx.send(Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send(Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): images.append(data[random.randint(0, count)]["file_url"]) await ctx.send(Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def emoteurl(self, ctx, *, emote:str): """Gets the url for a CUSTOM emote (meaning no unicode emotes)""" emote_id = extract_emote_id(emote) if emote_id is None: await ctx.send(Language.get("information.non-custom_emote", ctx)) return extension = "png" if emote.startswith("<a"): extension = "gif" await ctx.send("https://discordapp.com/api/emojis/{}.{}".format(emote_id, extension))
async def manga(self, ctx, *, name:str): """Searches MyAnimeList for the specified manga""" await ctx.channel.trigger_typing() r = requests.get("https://myanimelist.net/api/manga/search.xml?q={}".format(name), auth=requests.auth.HTTPBasicAuth(config._malUsername, config._malPassword)) if r.status_code == 401: log.critical("The MyAnimeList credinals are incorrect, please check your MyAnimeList login information in the config.") await ctx.send(Language.get("myanimelist.incorrect_creds", ctx)) return try: xmldoc = minidom.parseString(r.text) except XmlParserErrors.ExpatError: await ctx.send(Language.get("myanimelist.no_manga_found", ctx).format(name)) return # pls no flame manga = xmldoc.getElementsByTagName("entry")[0] id = manga.getElementsByTagName("id")[0].firstChild.nodeValue title = manga.getElementsByTagName("title")[0].firstChild.nodeValue try: english = manga.getElementsByTagName("english")[0].firstChild.nodeValue except: english = title chapters = manga.getElementsByTagName("chapters")[0].firstChild.nodeValue volumes = manga.getElementsByTagName("volumes")[0].firstChild.nodeValue score = manga.getElementsByTagName("score")[0].firstChild.nodeValue type = manga.getElementsByTagName("type")[0].firstChild.nodeValue status = manga.getElementsByTagName("status")[0].firstChild.nodeValue start_date = manga.getElementsByTagName("start_date")[0].firstChild.nodeValue end_date = manga.getElementsByTagName("end_date")[0].firstChild.nodeValue image = manga.getElementsByTagName("image")[0].firstChild.nodeValue synopsis = saxutils.unescape(manga.getElementsByTagName("synopsis")[0].firstChild.nodeValue) synopsis = remove_html(synopsis) if len(synopsis) > 300: synopsis = synopsis[:300] + "..." url = "https://myanimelist.net/manga/{}".format(id) fields = {Language.get("myanimelist.english_title", ctx):english, Language.get("myanimelist.chapaters", ctx):chapters, Language.get("myanimelist.volumes", ctx):volumes, Language.get("myanimelist.mal_history", ctx):score, Language.get("myanimelist.type", ctx):type, Language.get("myanimelist.status", ctx):status, Language.get("myanimelist.start_date", ctx):start_date, Language.get("myanimelist.end_date", ctx):end_date} embed = make_list_embed(fields) embed.title = title embed.description = synopsis embed.url = url embed.color = 0xFF0000 embed.set_thumbnail(url=image) await ctx.send(embed=embed)
async def rule34(self, ctx, *, tags:str): await ctx.channel.trigger_typing() try: data = requests.get("http://rule34.xxx/index.php?page=dapi&s=post&q=index&json=1&limit={}&tags={}".format(limit, tags), headers=header).json() except json.JSONDecodeError: await ctx.send(Language.get("nsfw.no_results_found", ctx).format(tags)) return count = len(data) if count == 0: await ctx.send(Language.get("nsfw.no_results_found", ctx).format(tags)) return image_count = 4 if count < 4: image_count = count images = [] for i in range(image_count): image = data[random.randint(0, count)] images.append("http://img.rule34.xxx/images/{}/{}".format(image["directory"], image["image"])) await ctx.send(Language.get("nsfw.results", ctx).format(image_count, count, tags, "\n".join(images)))
async def color(self, ctx, *, hexcode:str): """Displays the given hex color""" await ctx.channel.trigger_typing() if not hexcode.startswith("#"): hexcode = "#{}".format(hexcode) try: Image.new("RGBA", (50, 50), hexcode).save("data/color.png") except ValueError: await ctx.send(Language.get("bot.invalid_color", ctx).format(hexcode)) return await ctx.send(file=discord.File("data/color.png", "{}.png".format(hexcode.strip("#"))))
async def discrim(self, ctx, *, discriminator:str): """Gets a username#discriminator list of all users that the bot can see with the specified discriminator""" members = [] for member in list(self.bot.get_all_members()): if member.discriminator == discriminator and str(member) not in members: members.append(str(member)) if len(members) == 0: members = Language.get("information.no_discrims_found", ctx).format(discriminator) else: members = "```{}```".format(", ".join(members)) await ctx.send(members)