async def unmute(self, ctx, *, member=None): """Allows a muted member to send messages in chat (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return if member == None: msg = 'Usage: `{}unmute [member]`'.format(ctx.prefix) return await ctx.send(msg) if type(member) is str: memberName = member member = DisplayName.memberForName(memberName, ctx.guild) if not member: msg = 'I couldn\'t find *{}*...'.format(memberName) return await ctx.send(Utils.suppressed(ctx, msg)) mess = await ctx.send("Unmuting...") await self._unmute(member, ctx.guild) # pm = "You have been **Unmuted** by *{}*.\n\nYou can send messages on *{}* again.".format(DisplayName.name(ctx.author), Utils.suppressed(ctx, ctx.guild.name)) msg = '*{}* has been **Unmuted**.'.format(DisplayName.name(member)) await mess.edit(content=msg) '''try:
async def muterole(self, ctx): """Lists the target role to apply when muting (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return role = self.settings.getServerStat(ctx.guild, "MuteRole") if not role: return await ctx.send( "There is no mute role setup. You can set one with `{}setmuterole [role]` - or have me create one with `{}createmuterole [role_name]`" .format(ctx.prefix, ctx.prefix)) try: mute_role = ctx.guild.get_role(int(role)) except: mute_role = None if not mute_role: return await ctx.send( "The prior mute role (ID: `{}`) no longer exists. You can set one with `{}setmuterole [role]` - or have me create one with `{}createmuterole [role_name]`" .format(role, ctx.prefix, ctx.prefix)) await ctx.send("Muted users will be given **{}**.".format( Utils.suppressed(ctx, mute_role.name)))
async def setkillrole(self, ctx, *, role: discord.Role = None): """Sets the required role to kill/resurrect the bot (admin only).""" if not await Utils.is_admin_reply(ctx): return if role == None: self.settings.setServerStat(ctx.guild, "RequiredKillRole", "") msg = 'Kill/resurrect now *admin-only*.' return await ctx.send(msg) if type(role) is str: try: role = discord.utils.get(ctx.server.roles, name=role) except: print("That role does not exist") return # If we made it this far - then we can add it self.settings.setServerStat(ctx.guild, "RequiredKillRole", role.id) msg = 'Role required for kill/resurrect set to **{}**.'.format( role.name) await ctx.send(Utils.suppressed(ctx, msg))
async def listmuted(self, ctx): """Lists the names of those that are muted.""" muteList = self.settings.getServerStat(ctx.guild, "MuteList") activeMutes = [] for entry in muteList: member = DisplayName.memberForID(entry['ID'], ctx.guild) if member: # Found one! activeMutes.append(DisplayName.name(member)) if not len(activeMutes): await ctx.send("No one is currently muted.") return # We have at least one member muted msg = 'Currently muted:\n\n' msg += ', '.join(activeMutes) await ctx.send(Utils.suppressed(ctx, msg))
async def listmuted(self, ctx): """Menampilkan list nama member yang di mute.""" muteList = self.settings.getServerStat(ctx.guild, "MuteList") activeMutes = [] for entry in muteList: member = DisplayName.memberForID(entry['ID'], ctx.guild) if member: # Found one! activeMutes.append(DisplayName.name(member)) if not len(activeMutes): await ctx.send( "┐( ̄ヘ ̄;)┌\nTidak ada satupun member yang dalam status mute.") return # We have at least one member muted msg = 'Member saat ini yang di mute:\n\n' msg += ', '.join(activeMutes) await ctx.send(Utils.suppressed(ctx, msg))
async def onjoin(self, member, server): # Welcome try: welcomeChannel = server.get_channel( int(self.settings.getServerStat(server, "WelcomeChannel"))) except: welcomeChannel = None if welcomeChannel: await self._welcome(member, server, welcomeChannel) else: await self._welcome(member, server) if not self.settings.getServerStat(server, "JoinPM", False): return # We need to attempt to dm the rules rules = self.settings.getServerStat(server, "Rules") if rules: try: await member.send( Utils.suppressed( server, "***{}*** **Rules:**:\n{}".format(server.name, rules))) except: pass
async def pcpp(self, ctx, url = None, style = None, escape = None): """Convert a pcpartpicker.com link into markdown parts. Available styles: normal, md, mdblock, bold, and bolditalic.""" usage = "Usage: `{}pcpp [url] [style=normal, md, mdblock, bold, bolditalic] [escape=yes/no (optional)]`".format(ctx.prefix) if not style: style = 'normal' if not url: return await ctx.send(usage) if escape == None: escape = 'no' escape = escape.lower() in ["yes","true","on","enable","enabled"] output = await PCPP.getMarkdown(url, style, escape) if not output: msg = 'Something went wrong! Make sure you use a valid pcpartpicker link.' return await ctx.send(msg) if len(output) > 2000: msg = "That's an *impressive* list of parts - but the max length allowed for messages in Discord is 2000 characters, and you're at *{}*.".format(len(output)) msg += '\nMaybe see if you can prune up that list a bit and try again?' return await ctx.send(msg) await ctx.send(Utils.suppressed(ctx,output))
async def removemotd(self, ctx, *, chan=None): """Removes the message of the day from the selected channel.""" channel = ctx.message.channel author = ctx.message.author server = ctx.message.guild usage = 'Usage: `{}broadcast [message]`'.format(ctx.prefix) # Check if we're suppressing @here and @everyone mentions if self.settings.getServerStat(ctx.message.guild, "SuppressMentions"): suppress = True else: suppress = False if not await Utils.is_admin_reply(ctx): return if chan == None: chan = channel if type(chan) is str: try: chan = discord.utils.get(server.channels, name=chan) except: print("That channel does not exist") return # At this point - we should have the necessary stuff motdArray = self.settings.getServerStat(server, "ChannelMOTD") for a in motdArray: # Get the channel that corresponds to the id if str(a['ID']) == str(chan.id): # We found it - throw an error message and return motdArray.remove(a) self.settings.setServerStat(server, "ChannelMOTD", motdArray) msg = 'MOTD for *{}* removed.'.format(channel.name) await channel.send(msg) await channel.edit(topic=None) await self.updateMOTD() return msg = 'MOTD for *{}* not found.'.format(chan.name) msg = Utils.suppressed(ctx, msg) await channel.send(msg)
async def _send_greeting(self, member, server, channel=None, stat_name="Welcome"): # Helper to send the welcome/goodbye message message = self.settings.getServerStat(server, stat_name) if message in (None, ""): return # Let's regex and replace [[user]] [[atuser]] and [[server]] message = re.sub(self.regexUserName, "{}".format(DisplayName.name(member)), message) message = re.sub(self.regexUserPing, "{}".format(member.mention), message) message = re.sub(self.regexServer, "{}".format(Utils.suppressed(server, server.name)), message) message = re.sub(self.regexCount, "{:,}".format(len(server.members)), message) # Get place info place_str = str(len(server.members)) end_str = "th" if place_str.endswith("1") and not place_str.endswith("11"): end_str = "st" elif place_str.endswith("2") and not place_str.endswith("12"): end_str = "nd" elif place_str.endswith("3") and not place_str.endswith("13"): end_str = "rd" message = re.sub(self.regexPlace, "{:,}{}".format(len(server.members), end_str), message) # Get online users online_count = len([ x for x in server.members if not x.status == discord.Status.offline ]) message = re.sub(self.regexOnline, "{:,}".format(online_count), message) if channel: return await channel.send(message) try: await self._getDefault(server).send(message) except: pass
async def listadmin(self, ctx): """Melihat list admin dan id.""" promoArray = self.settings.getServerStat(ctx.message.guild, "AdminArray") promoSorted = sorted(promoArray, key=itemgetter('Name')) if not len(promoSorted): em = discord.Embed( color=0XFF8C00, description= "> Saat ini tidak ada role admin yang terdaftar.\n> \n" "> **Panduan menambahkan admin role**\n" "> `{}addadmin [role]`".format(ctx.prefix)) em.set_author( name="List Admin", url="https://acinonyxesports.com", icon_url= "https://cdn.discordapp.com/attachments/518118753226063887/725569194304733435/photo.jpg" ) em.set_footer(text="Request by : {}".format(ctx.author.name), icon_url="{}".format(ctx.author.avatar_url)) roleText = em await ctx.send(embed=roleText) return roleText = "__**Current Admin Roles:**__\n\n" for arole in promoSorted: found = False for role in ctx.message.guild.roles: if str(role.id) == str(arole["ID"]): # Found the role ID found = True roleText = '{}**{}** (ID : `{}`)\n'.format( roleText, role.name, arole['ID']) if not found: roleText = '{}**{}** (Dihapus dari server)\n'.format( roleText, arole['Name']) await ctx.send(Utils.suppressed(ctx, roleText))
async def rolecall(self, ctx, *, role = None): """Lists the number of users in a current role.""" if role == None: msg = 'Usage: `{}rolecall [role]`'.format(ctx.prefix) return await ctx.send(msg) if type(role) is str: roleName = role role = DisplayName.roleForName(roleName, ctx.guild) if not role: msg = 'I couldn\'t find *{}*...'.format(roleName) return await ctx.send(Utils.suppressed(ctx,msg)) # Create blank embed role_embed = discord.Embed(color=role.color) role_embed.set_author(name='{}'.format(role.name)) # We have a role members = [x for x in ctx.guild.members if role in x.roles] memberCount = len(members) memberOnline = len([x for x in members if x.status != discord.Status.offline]) role_embed.add_field(name="Members", value='{:,} of {:,} online.'.format(memberOnline, memberCount), inline=True) await ctx.send(embed=role_embed)
async def profileinfo(self, ctx, *, member=None, name=None): """Displays info about a profile from the passed user's profile list.""" if not member: msg = 'Usage: `{}profileinfo [member] [profile name]`'.format( ctx.prefix) return await ctx.send(msg) item = self._get_profile(ctx, member) if item == None: return await ctx.send("Sorry, I couldn't find that user/profile.") member, item = item # We have a profile current_time = int(time.time()) msg = '**{}:**\n'.format(item['Name']) msg += "Created: {} ago\n".format( ReadableTime.getReadableTimeBetween(item.get( "Created", None), current_time, True)) if item.get( "Created", None) else "Created: `UNKNOWN`\n" if item.get("Updated", None): msg += "Updated: {} ago\n".format( ReadableTime.getReadableTimeBetween(item["Updated"], current_time, True)) return await ctx.send(Utils.suppressed(ctx, msg))
async def rawgoodbye(self, ctx, *, member=None): """Prints the current goodbye message's markdown (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return if member == None: member = ctx.message.author if type(member) is str: memberName = member member = DisplayName.memberForName(memberName, ctx.guild) if not member: msg = 'I couldn\'t find *{}*...'.format(memberName) return await ctx.send(Utils.suppressed(ctx, msg)) # Here we have found a member, and stuff. # Let's make sure we have a message message = self.settings.getServerStat(ctx.guild, "Goodbye") if message in (None, ""): return await ctx.send( 'Goodbye message not setup. You can do so with the `{}setgoodbye [message]` command.' .format(ctx.prefix)) # Escape the markdown message = discord.utils.escape_markdown(message) await ctx.send(message) # Print the goodbye channel try: welcomeChannel = ctx.guild.get_channel( int(self.settings.getServerStat(ctx.guild, "WelcomeChannel"))) except: welcomeChannel = None if welcomeChannel: msg = 'The current goodbye channel is **{}**.'.format( welcomeChannel.mention) else: if self._getDefault(ctx.guild): msg = 'The current goodbye channel is the default channel (**{}**).'.format( self._getDefault(ctx.guild).mention) else: msg = 'There is *no channel* set for goodbye messages.' await ctx.send(msg)
async def muterole(self, ctx): """Melihat role mute yang telah di setting dalam server (bot-admin/admin only).""" if not await Utils.is_bot_admin_reply(ctx): return role = self.settings.getServerStat(ctx.guild,"MuteRole") if not role: em = discord.Embed(color = 0XFF8C00, description = "> Tidak ada mute role yang telah disetup.\n" "> Kamu dapat membuat memilih role dengan cara mengetik `{}setmuterole [role]`.\n" "> Atau kamu juga dapat membuatnya yang baru dengan cara mengetik `{}createmuterole [role_name]`" .format(ctx.prefix, ctx.prefix)) em.set_footer(text = f"{ctx.author}", icon_url = f"{ctx.author.avatar_url}") return await ctx.send(embed = em) try: mute_role = ctx.guild.get_role(int(role)) except: mute_role = None em = discord.Embed(color = 0XFF8C00, description = "> Mute role sebelumnya dengan ID `{}` tidak ditemukan dalam server mu.\n" "> Kamu dapat membuat memilih role lain cara mengetik `{}setmuterole [role]`.\n" "> Atau kamu juga dapat membuatnya yang baru dengan cara mengetik `{}createmuterole [role_name]`") em.set_footer(text = f"{ctx.author}", icon_url = f"{ctx.author.avatar_url}") if not mute_role: return await ctx.send(embed = em) msg = "User yang di mute akan diberi role **{}**.".format(Utils.suppressed(ctx,mute_role.name)) em = discord.Embed(color = 0XFF8C00, description = msg) em.set_footer(text = "{}".format(ctx.author), icon_url = "{}".format(ctx.author.avatar_url)) await ctx.send(embed = em)
async def listadmin(self, ctx): """Lists admin roles and id's.""" promoArray = self.settings.getServerStat(ctx.message.guild, "AdminArray") promoSorted = sorted(promoArray, key=itemgetter('Name')) if not len(promoSorted): roleText = "There are no admin roles set yet. Use `{}addadmin [role]` to add some.".format(ctx.prefix) await ctx.send(roleText) return roleText = "__**Current Admin Roles:**__\n\n" for arole in promoSorted: found = False for role in ctx.message.guild.roles: if str(role.id) == str(arole["ID"]): # Found the role ID found = True roleText = '{}**{}** (ID : `{}`)\n'.format(roleText, role.name, arole['ID']) if not found: roleText = '{}**{}** (removed from server)\n'.format(roleText, arole['Name']) await ctx.send(Utils.suppressed(ctx,roleText))
async def listen(self, ctx, *, member = None): """Removes a member from the bot's "ignore" list (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return if member == None: return await ctx.send('Usage: `{}listen [member]`'.format(ctx.prefix)) if type(member) is str: memberName = member member = DisplayName.memberForName(memberName, ctx.guild) if not member: msg = 'I couldn\'t find *{}*...'.format(memberName) return await ctx.send(Utils.suppressed(ctx,msg)) ignoreList = self.settings.getServerStat(ctx.guild, "IgnoredUsers") for user in ignoreList: if str(member.id) == str(user["ID"]): # Found our user - already ignored ignoreList.remove(user) self.settings.setServerStat(ctx.guild, "IgnoredUsers", ignoreList) return await ctx.send("*{}* is no longer being ignored.".format(DisplayName.name(member))) await ctx.send('*{}* wasn\'t being ignored...'.format(DisplayName.name(member)))
async def clean(self, ctx, messages=None, *, chan: discord.TextChannel = None): """Menghapus jumlah pesan yang diminta dalam channel yang di tentukan (admin only). __Update fitur 16 januari 2020__ Menghapus pesan dalam jumlaj yang diminta lalu membuat file backup dan mengirimkan file.txt dalam pesan DM. *file.txt berisi nama user dan isi pesan. **File tidak akan dikirimkan jika kamu mematikan fitur direct message dalam server mu.""" if not await Utils.is_bot_admin_reply(ctx): return if not chan: chan = ctx.channel if chan in self.cleanChannels: # Don't clean messages from a channel that's being cleaned return # Try to get the number of messages to clean so you don't "accidentally" clean # any... try: messages = int(messages) except: return await ctx.send( "Aku membutuhkan jumlah pesan yang akan dihapus!") # Make sure we're actually trying to clean something if messages < 1: return await ctx.send( "Aku tidak dapat menghapus pesan kurang dari 1 pesan!") # Add channel to list self.cleanChannels.append(chan) # Remove original message await ctx.message.delete() if messages > 1000: messages = 1000 # Use history instead of purge counter = 0 # I tried bulk deleting - but it doesn't work on messages over 14 days # old - so we're doing them individually I guess. # Setup deleted message logging # Log the user who called for the clean msg = '' totalMess = messages while totalMess > 0: gotMessage = False if totalMess > 100: tempNum = 100 else: tempNum = totalMess try: async for message in chan.history(limit=tempNum): # Save to a text file new_msg = '{}#{}:\n {}\n'.format( message.author.name, message.author.discriminator, message.content) if len(message.attachments): new_msg += "\n --- Attachments ---\n\n" for a in message.attachments: new_msg += " " + a.url + "\n" new_msg += "\n" msg = new_msg + msg await message.delete() gotMessage = True counter += 1 totalMess -= 1 except Exception: pass if not gotMessage: # No more messages - exit break # Remove channel from list self.cleanChannels.remove(chan) msg = 'Messages cleaned by {}#{} in {} - #{}\n\n'.format( ctx.message.author.name, ctx.message.author.discriminator, Utils.suppressed(ctx, ctx.guild.name), ctx.channel.name) + msg # Timestamp and save to file timeStamp = datetime.today().strftime("%Y-%m-%d %H.%M") filename = "cleaned-{}.txt".format(timeStamp) msg = msg.encode('utf-8') with open(filename, "wb") as myfile: myfile.write(msg) # Send the cleaner a pm letting them know we're done try: await ctx.author.send( '*{}* message{} telah dihapus dari *#{}* di server *{}!*'. format(counter, "" if counter == 1 else "s", chan.name, Utils.suppressed(ctx, ctx.guild.name))) # PM the file await ctx.author.send(file=discord.File(filename)) except: # Assume the author doesn't accept pms - just silently fail pass if self.shouldLog('message.delete', ctx.guild): # We're logging logmess = '{}#{} menggunakan clean di server #{}'.format( ctx.author.name, ctx.author.discriminator, chan.name) pfpurl = ctx.author.avatar_url if len( ctx.author.avatar_url) else ctx.author.default_avatar_url await self._logEvent(ctx.guild, "{:,} message{} dihapus.".format( counter, "" if counter == 1 else "s"), title=logmess, filename=filename, thumbnail=pfpurl) # Delete the remaining file os.remove(filename)
async def ismuted(self, ctx, *, member=None): """Says whether a member is muted in chat.""" if member == None: msg = 'Usage: `{}ismuted [member]`'.format(ctx.prefix) return await ctx.send(msg) memberName = member member = DisplayName.memberForName(memberName, ctx.guild) if not member: msg = 'I couldn\'t find *{}*...'.format(memberName) return await ctx.send(Utils.suppressed(ctx, msg)) # Check if we have a muted role try: mute_role = ctx.guild.get_role( int(self.settings.getServerStat(ctx.guild, "MuteRole"))) except: mute_role = None item = next( (x for x in self.settings.getServerStat(ctx.guild, "MuteList", []) if str(x["ID"]) == str(member.id)), None) if mute_role and mute_role in member.roles: # We're muted using the role - let's get the cooldown if any if not item or item["Cooldown"] == None: # No cooldown - let's just give the bad news... return await ctx.send("*{}* is **muted**.".format( DisplayName.name(member))) # We're still muted - but have a cooldown return await ctx.send("*{}* is **muted**.\n*{}* remain.".format( DisplayName.name(member), ReadableTime.getReadableTimeBetween(int(time.time()), item["Cooldown"]))) muted_channels = 0 # Walk the channels we may be muted in for channel in ctx.guild.channels: if not isinstance(channel, (discord.TextChannel, discord.VoiceChannel)): continue if hasattr(channel, "permissions_synced" ): # Implemented in 1.3.0 of discord.py if channel.permissions_synced: channel = channel.category # Get the category if we're synced overs = channel.overwrites_for( member) # Get any overrides for the user # Check if we match any of the mute overrides - and if we have any others if any(x[0] in self.mute_perms and x[1] != None for x in overs): muted_channels += 1 # Tell the user if the target is muted if muted_channels: if not item or item["Cooldown"] == None: # No cooldown - let's just give the bad news... return await ctx.send( "*{}* is **muted** in {} channel{}.".format( DisplayName.name(member), muted_channels, "" if muted_channels == 1 else "s")) # We're still muted - but have a cooldown return await ctx.send( "*{}* is **muted** in {} channel{},\n*{}* remain.".format( DisplayName.name(member), muted_channels, "" if muted_channels == 1 else "s", ReadableTime.getReadableTimeBetween( int(time.time()), item["Cooldown"]))) # Not muted - let em know await ctx.send("*{}* is **unmuted**.".format(DisplayName.name(member)))
async def testgoodbye(self, ctx, *, member=None): """Test goodbye message diserver mu (admin only).""" if not await Utils.is_bot_admin_reply(ctx): msg = '┐( ̄ヘ ̄;)┌\nKamu tidak memiliki hak untuk menggunakan command ini' em = discord.Embed(color=0XFF8C00, description=msg) em.set_footer(text="{}".format(ctx.author), icon_url="{}".format(ctx.author.avatar_url)) return await ctx.send(embed=em) if member == None: member = ctx.message.author if type(member) is str: memberName = member member = DisplayName.memberForName(memberName, ctx.guild) if not member: msg = '┐( ̄ヘ ̄;)┌\nAku tidak dapat menemukan *{}*...'.format( memberName) return await ctx.send(Utils.suppressed(ctx, msg)) # Here we have found a member, and stuff. # Let's make sure we have a message message = self.settings.getServerStat(ctx.guild, "Goodbye") if message in (None, ""): em = discord.Embed( color=0XFF8C00, description= "> Kamu belum melakukan setup untuk welcome message untuk server ***{}***.\n" "> Kamu dapat melakukannya dengan menggunakan command:\n" "> *`{}setgoodbye [message]`*\n> \n" "> atau ketik *`{}help setgoodbye`* untuk informasi lebih lanjut." .format(ctx.guild.name, ctx.prefix, ctx.prefix)) em.set_author( name="Test goodbye message gagal!", icon_url= "https://cdn.discordapp.com/attachments/518118753226063887/725569194304733435/photo.jpg" ) em.set_footer( text="Saat mengetik command, tanda [] tidak usah digunakan\n{}" .format(ctx.author), icon_url="{}".format(ctx.author.avatar_url)) return await ctx.send(embed=em) await self._goodbye(member, ctx.guild, ctx.channel) # Print the goodbye channel try: welcomeChannel = ctx.guild.get_channel( int(self.settings.getServerStat(ctx.guild, "WelcomeChannel"))) except: welcomeChannel = None if welcomeChannel: msg = 'Goodbye message akan dikirim ke channel: **{}**.'.format( welcomeChannel.mention) text = "{}".format(ctx.author) else: if self._getDefault(ctx.guild): msg = 'Goodbye message saat ini akan dikirim dalam channel default (**{}**)\nKamu dapat mengatur channel welcome message dengan command `{}setwelcomechannel [channel]`.'.format( self._getDefault(ctx.guild).mention, ctx.prefix) text = "Saat mengetik command, tanda [] tidak usah digunakan\n{}".format( ctx.author) else: msg = '┐( ̄ヘ ̄;)┌\n*Tidak ada channel* yang telah di setting untuk mengirimkan goodbye message.\nKamu dapat mengatur channel welcome message dengan command `{}setwelcomechannel [channel]`.' text = "Saat mengetik command, tanda [] tidak usah digunakan\n{}".format( ctx.author) em = discord.Embed(color=0XFF8C00, description=msg) em.set_footer(text=text, icon_url="{}".format(ctx.author.avatar_url)) await ctx.send(embed=em)
async def rules(self, ctx): """Menampilkan server rule.""" rules = self.settings.getServerStat(ctx.guild, "Rules") msg = "***{}*** **Rule:**\n{}".format(ctx.guild.name, rules) await ctx.send(Utils.suppressed(ctx, msg))
async def choose(self, ctx, *choices: str): """Chooses between multiple choices.""" await ctx.send(Utils.suppressed(ctx, random.choice(choices)))
async def promoteto(self, ctx, *, member=None, role=None): """Auto-adds the required xp to promote the passed user to the passed role (admin only).""" if not await self._can_run(ctx): return usage = 'Usage: `{}promoteto [member] [role]`'.format(ctx.prefix) if member == None: return await ctx.send(usage) if role == None: # Either a role wasn't set - or it's the last section if type(member) is str: # It' a string - the hope continues # Let's search for a name at the beginning - and a role at the end parts = member.split() memFromName = None for j in range(len(parts)): # Reverse search direction i = len(parts) - 1 - j # Name = 0 up to i joined by space nameStr = ' '.join(parts[0:i + 1]) # Role = end of name -> end of parts joined by space roleStr = ' '.join(parts[i + 1:]) memFromName = DisplayName.memberForName(nameStr, ctx.guild) if memFromName: # We got a member - let's check for a role roleFromName = DisplayName.roleForName( roleStr, ctx.guild) if not roleFromName == None: # We got a member and a role - break role = roleFromName break if memFromName == None: # Never found a member at all msg = 'I couldn\'t find *{}* on the server.'.format(member) return await ctx.send(Utils.suppressed(ctx, msg)) if roleFromName == None: # We couldn't find one or the other return await ctx.send(usage) member = memFromName # Get user's xp xp = int(self.settings.getUserStat(member, ctx.guild, "XP")) # Get the role list promoArray = self.getSortedRoles(ctx.guild) nextRole = self.getIndexForRole(role, ctx.guild) currentRole = self.getCurrentRoleIndex(member, ctx.guild) vowels = 'aeiou' if nextRole == None: msg = '**{}** doesn\'t appear to be in the xp role list - consider adding it with the `{}addxprole [role] [xp amount]` command.'.format( role.name, ctx.prefix) return await ctx.send(Utils.suppressed(ctx, msg)) if currentRole == nextRole: # We are already the target role if role.name[:1].lower() in vowels: msg = '*{}* is already an **{}**.'.format( DisplayName.name(member), role.name) else: msg = '*{}* is already a **{}**.'.format( DisplayName.name(member), role.name) return await ctx.send(Utils.suppressed(ctx, msg)) elif currentRole > nextRole: # We are a higher role than the target msg = '*{}* already has **{}** in their collection of roles.'.format( DisplayName.name(member), role.name) return await ctx.send(Utils.suppressed(ctx, msg)) if nextRole >= len(promoArray): msg = 'There are no higher roles to promote *{}* into.'.format( DisplayName.name(member)) else: newRole = DisplayName.roleForID(promoArray[nextRole]['ID'], ctx.guild) neededXp = int(promoArray[nextRole]['XP']) - xp self.settings.incrementStat(member, ctx.guild, "XP", neededXp) # Start at the bottom role and add all roles up to newRole addRoles = [] for i in range(0, nextRole + 1): addRole = DisplayName.roleForID(promoArray[i]['ID'], ctx.guild) if addRole: if not addRole in member.roles: addRoles.append(addRole) # await member.add_roles(*addRoles) # Use role manager instead self.settings.role.add_roles(member, addRoles) if not newRole: # Promotion role doesn't exist msg = 'It looks like **{}** is no longer on this server. *{}* was still given *{:,} xp* - but I am unable to promote them to a non-existent role. Consider revising your xp roles.'.format( promoArray[nextRole]['Name'], DisplayName.name(member), neededXp) else: msg = '*{}* was given *{:,} xp* and promoted to **{}**!'.format( DisplayName.name(member), neededXp, newRole.name) self.bot.dispatch("xp", member, ctx.author, neededXp) return await ctx.send(Utils.suppressed(ctx, msg))
async def demote(self, ctx, *, member=None): """Auto-removes the required xp to demote the passed user to the previous role (admin only).""" if not await self._can_run(ctx): return usage = 'Usage: `{}demote [member]`'.format(ctx.prefix) if member == None: return await ctx.send(usage) if type(member) is str: memberName = member member = DisplayName.memberForName(memberName, ctx.message.guild) if not member: msg = 'I couldn\'t find *{}*...'.format(memberName) # Check for suppress return await ctx.send(Utils.suppressed(ctx, msg)) # Get user's xp xp = int(self.settings.getUserStat(member, ctx.guild, "XP")) # Get the role list promoArray = self.getSortedRoles(ctx.guild) currentRole = self.getCurrentRoleIndex(member, ctx.guild) nextRole = currentRole - 1 if nextRole == -1: # We're removing the user from all roles neededXp = int(promoArray[0]['XP']) - xp - 1 self.settings.incrementStat(member, ctx.guild, "XP", neededXp) remRoles = [] for i in range(0, len(promoArray)): remRole = DisplayName.roleForID(promoArray[i]['ID'], ctx.guild) if remRole: if remRole in member.roles: remRoles.append(remRole) # await member.remove_roles(*remRoles) # Use role manager instead self.settings.role.rem_roles(member, remRoles) msg = '*{} xp* was taken from *{}* and they were demoted out of the xp system!'.format( neededXp * -1, DisplayName.name(member)) self.bot.dispatch("xp", member, ctx.author, neededXp) elif nextRole < -1: msg = 'There are no lower roles to demote *{}* into.'.format( DisplayName.name(member)) else: newRole = DisplayName.roleForID(promoArray[nextRole]['ID'], ctx.guild) neededXp = int(promoArray[nextRole]['XP']) - xp self.settings.incrementStat(member, ctx.guild, "XP", neededXp) # Start at the currentRole and remove that and all roles above remRoles = [] for i in range(currentRole, len(promoArray)): remRole = DisplayName.roleForID(promoArray[i]['ID'], ctx.guild) if remRole: if remRole in member.roles: remRoles.append(remRole) # await member.remove_roles(*remRoles) # Use role manager instead self.settings.role.rem_roles(member, remRoles) if not newRole: # Promotion role doesn't exist msg = 'It looks like **{}** is no longer on this server. *{:,} xp* was still taken from *{}* - but I am unable to demote them to a non-existent role. Consider revising your xp roles.'.format( promoArray[nextRole]['Name'], neededXp * -1, DisplayName.name(member)) else: msg = '*{:,} xp* was taken from *{}* and they were demoted to **{}**!'.format( neededXp * -1, DisplayName.name(member), newRole.name) self.bot.dispatch("xp", member, ctx.author, neededXp) return await ctx.send(Utils.suppressed(ctx, msg))
async def temp(self, ctx, member=None, role=None, *, cooldown=None): """Gives the passed member the temporary role for the passed amount of time - needs quotes around member and role (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return if member == None or role == None: msg = 'Usage: `{}temp "[member]" "[role]" [cooldown]`'.format( ctx.prefix) return await ctx.send(msg) # Get member and role member_from_name = DisplayName.memberForName(member, ctx.guild) role_from_name = DisplayName.roleForName(role, ctx.guild) if not member_from_name and not role_from_name: msg = "I couldn't find either the role or member..." return await ctx.send(msg) if not member_from_name: msg = 'I couldn\'t find *{}*...'.format(member) return await ctx.send(Utils.suppressed(ctx, msg)) # Don't allow us to temp admins or bot admins if Utils.is_bot_admin(ctx, member_from_name): return await ctx.send( "You can't apply temp roles to other admins or bot-admins.") if not role_from_name: msg = 'I couldn\'t find *{}*...'.format(role) return await ctx.send(Utils.suppressed(ctx, msg)) # Make sure our role is in the list promoArray = self.settings.getServerStat(ctx.guild, "TempRoleList") if not role_from_name.id in [int(x["ID"]) for x in promoArray]: # No dice return await ctx.send("That role is not in the temp role list!") if cooldown == None: return await ctx.send( "You must specify a time greater than 0 seconds.") if not cooldown == None: # Get the end time end_time = None try: # Get current time - and end time currentTime = int(time.time()) cal = parsedatetime.Calendar() time_struct, parse_status = cal.parse(cooldown) start = datetime(*time_struct[:6]) end = time.mktime(start.timetuple()) # Get the time from now to end time end_time = end - currentTime except: pass if end_time == None: # We didn't get a time return await ctx.send("That time value is invalid.") # Set the cooldown cooldown = end_time if cooldown < 1: return await ctx.send( "You must specify a time greater than 0 seconds.") message = await ctx.send("Applying...") # Here we have a member, role, and end time - apply them! user_roles = self.settings.getUserStat(member_from_name, ctx.guild, "TempRoles") # Check and see if we're overriding a current time found = False temp_role = {} for r in user_roles: if int(r["ID"]) == role_from_name.id: # Already have it - update the cooldown r["Cooldown"] = cooldown + int( time.time()) if cooldown != None else cooldown r["AddedBy"] = ctx.author.id temp_role = r found = True break if not found: # Add it anew temp_role["ID"] = role_from_name.id temp_role["Cooldown"] = cooldown + int( time.time()) if cooldown != None else cooldown temp_role["AddedBy"] = ctx.author.id user_roles.append(temp_role) self.settings.setUserStat(member_from_name, ctx.guild, "TempRoles", user_roles) if not role_from_name in member_from_name.roles: self.settings.role.add_roles(member_from_name, [role_from_name]) if not cooldown == None: # We have a cooldown msg = "*{}* has been given **{}** for *{}*.".format( DisplayName.name(member_from_name), role_from_name.name, ReadableTime.getReadableTimeBetween(0, cooldown)) pm = "You have been given **{}** in *{}* for *{}*".format( role_from_name.name, ctx.guild.name, ReadableTime.getReadableTimeBetween(0, cooldown)) self.bot.loop.create_task( self.check_temp_roles(member_from_name, temp_role)) else: msg = "*{}* has been given **{}** *until further notice*.".format( DisplayName.name(member_from_name), role_from_name.name) pm = "You have been given **{}** in *{} until further notice*.".format( role_from_name.name, ctx.guild.name) # Announce it await message.edit(content=Utils.suppressed(ctx, msg)) # Check if we pm if self.settings.getServerStat(ctx.guild, "TempRolePM"): try: await member_from_name.send(pm) except: pass
async def on_member_join(self, member): guild = member.guild pfpurl = member.avatar_url if len(member.avatar_url) else member.default_avatar_url # Try and determine which invite was used invite = None invite_list = self.invite_list.get(str(guild.id),[]) try: new_invites = await guild.invites() except: new_invites = [] changed = [x for x in new_invites for y in invite_list if x.code == y.code and x.uses != y.uses] if len(changed) == 1: # We have only one changed invite - this is the one! invite = changed[0] self.invite_list[str(guild.id)] = new_invites if not self.shouldLog('user.join', guild): return # A new member joined msg = '👐 {}#{} ({}) joined {}.'.format(member.name, member.discriminator, member.id, Utils.suppressed(guild, guild.name)) log_msg = "Account Created: {}".format("Unknown" if member.created_at == None else member.created_at.strftime("%b %d %Y - %I:%M %p") + " UTC") if invite: log_msg += "\n"+self.format_invite(invite) await self._logEvent(guild, log_msg, title=msg, color=discord.Color.teal(), thumbnail=pfpurl)
async def on_member_unban(self, guild, member): if not self.shouldLog('user.unban', guild): return # A member was unbanned pfpurl = member.avatar_url if len(member.avatar_url) else member.default_avatar_url msg = '🔵 {}#{} ({}) was unbanned from {}.'.format(member.name, member.discriminator, member.id, Utils.suppressed(guild, guild.name)) await self._logEvent(guild, "", title=msg, color=discord.Color.green(),thumbnail=pfpurl)
async def _get_item(self, ctx, name, l_role="RequiredLinkRole", l_list="Links", l_name="Link", l_key="URL", raw=False): # Helper function to pull items from lists if not name: em = discord.Embed(color=0XFF8C00, description='**Panduan**\n' '`{}{}[[name]] "[[[name]] name]"`'.format( ctx.prefix, "raw" if raw else "").replace( "[[name]]", l_name.lower())) em.set_footer(text="{}#{}".format(ctx.author.name, ctx.author.discriminator), icon_url="{}".format(ctx.author.avatar_url)) return await ctx.send(embed=em) itemList = self.settings.getServerStat(ctx.guild, l_list) # Check other lists other_commands = [] other_names = [] for i in self.alt_lists: if i["list"] == l_list: # Our list - skip continue check_list = self.settings.getServerStat(ctx.guild, i["list"]) if any(x["Name"].lower() == name.lower() for x in check_list): # Add the list other_commands.append(i) other_names.append( Utils.suppressed( ctx, "{}{} {}".format(ctx.prefix, i["command"], name))) if not itemList or itemList == []: no_items = 'No [[name]]s in list! You can add some with the `{}add[[name]] "[[[name]] name]" [[[key]]]` command!'.format( ctx.prefix).replace("[[name]]", l_name.lower()).replace( "[[key]]", l_key.lower()) if raw or not len(other_commands): # No other matches return await ctx.send(no_items) msg = no_items + "\n\nMaybe you meant:" index, message = await PickList.Picker(title=msg, list=other_names, ctx=ctx).pick() # Check if we errored/cancelled if index < 0: return await message.edit(content=no_items) # Got something await message.edit(content="`{}`".format(other_names[index])) # Invoke return await ctx.invoke(self.bot.all_commands.get( other_commands[index]["command"]), name=name) for item in itemList: if item['Name'].lower() == name.lower(): msg = '**{}:**\n{}'.format( item['Name'], discord.utils.escape_markdown(item[l_key]) if raw else item[l_key]) return await ctx.send(Utils.suppressed(ctx, msg)) not_found = Utils.suppressed( ctx, '`{}` not found in {} list!'.format( name.replace("`", "").replace("\\", ""), l_name.lower())) # No matches - let's fuzzy search potentialList = FuzzySearch.search(name, itemList, 'Name') if len(potentialList): # Setup and display the picker msg = not_found + '\n\nSelect one of the following close matches:' p_list = [x["Item"]["Name"] for x in potentialList] p_list.extend(other_names) index, message = await PickList.Picker(title=msg, list=p_list, ctx=ctx).pick() # Check if we errored/cancelled if index < 0: return await message.edit(content=not_found) # Check if we have another command if index >= len(potentialList): # We're into our other list await message.edit( content="`{}`".format(other_names[index - len(potentialList)])) # Invoke return await ctx.invoke(self.bot.all_commands.get( other_commands[index - len(potentialList)]["command"]), name=name) # Display the item for item in itemList: if item["Name"] == potentialList[index]["Item"]["Name"]: msg = '**{}:**\n{}'.format( item['Name'], discord.utils.escape_markdown(item[l_key]) if raw else item[l_key]) return await message.edit( content=Utils.suppressed(ctx, msg)) return await message.edit( content="{} `{}` no longer exists!".format( l_name, potentialList[index]["Item"]["Name"].replace( "`", "").replace("\\", ""))) # Here we have no potentials return await ctx.send(not_found)
async def rules(self, ctx): """Display the server's rules.""" rules = self.settings.getServerStat(ctx.guild, "Rules") msg = "***{}*** **Rules:**\n{}".format(ctx.guild.name, rules) await ctx.send(Utils.suppressed(ctx, msg))
async def listen(self, ctx, *, member=None): """Menghapus member dari list ignore dalam server mu (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return if member == None: em = discord.Embed( color=0XFF8C00, description= "> Menghapus member dari list ignore, dan dapat menggunakan bot ini dalam server mu\n> \n" "> **Panduan Penggunaan**\n" "> `{}listen [member]`".format(ctx.prefix)) em.set_author( name="Command listen", url="https://acinonyxesports.com", icon_url= "https://cdn.discordapp.com/attachments/518118753226063887/725569194304733435/photo.jpg" ) em.set_footer( text= "Saat mengetik command, tanda [] tidak usah digunakan\nRequest by : {}" .format(ctx.author.name), icon_url="{}".format(ctx.author.avatar_url)) return await ctx.send(embed=em) if type(member) is str: memberName = member member = DisplayName.memberForName(memberName, ctx.guild) if not member: msg = '┐( ̄ヘ ̄;)┌\nAku tidak dapat menemukan *{}* dalam list ignore...'.format( memberName) return await ctx.send(Utils.suppressed(ctx, msg)) ignoreList = self.settings.getServerStat(ctx.guild, "IgnoredUsers") for user in ignoreList: if str(member.id) == str(user["ID"]): # Found our user - already ignored ignoreList.remove(user) self.settings.setServerStat(ctx.guild, "IgnoredUsers", ignoreList) em = discord.Embed( color=0XFF8C00, description="> User <@{}>\n" "> Telah dihapus dari ignore list, dan dapat menggunakan bot ini dalam server mu\n> \n" "> **Panduan penambahan member**\n" "> `{}ignore [member]`\n".format(member.id, ctx.prefix)) em.set_author( name="Command ignore", url="https://acinonyxesports.com", icon_url= "https://cdn.discordapp.com/attachments/518118753226063887/725569194304733435/photo.jpg" ) em.set_footer( text= "Saat mengetik command, tanda [] tidak usah digunakan\nRequest by : {}" .format(ctx.author.name), icon_url="{}".format(ctx.author.avatar_url)) return await ctx.send(embed=em) await ctx.send('*{}* tidak terdaftar dalam list ignore...'.format( DisplayName.name(member)))
async def _ring(self, caller, receiver, hidden, dial_hide): # This should be called when he have a valid caller, receiver, and no one is busy receiver_chan = self._gettelechannel(receiver) caller_chan = self._gettelechannel(caller) if receiver_chan == None or caller_chan == None: # No dice return # Add both to the call list self.switchboard.append({ "Members": [caller, receiver], "Hidden": hidden, "Connected": False }) our_call = self.switchboard[len(self.switchboard) - 1] # Let the caller know we're dialing msg = ":telephone: Dialing... " teleNum = self.settings.getServerStat(receiver, "TeleNumber") msg_add = [] if hidden: msg_add.append("*67 ") if dial_hide: msg_add.append("###-") msg_add.append("####") else: msg_add.append(teleNum[:3] + "-") msg_add.append(teleNum[3:]) # Send dialing message = await caller_chan.send(msg) # Dialing edits for i in msg_add: msg += i await message.edit(content=msg) await asyncio.sleep(0.5) # Here - we should have "dialed" # Send a message to the other channel that there's a call incoming # Save last call self.settings.setServerStat( receiver, "LastCall", self.settings.getServerStat(caller, "TeleNumber")) if hidden: caller_number = "UNKNOWN CALLER" self.settings.setServerStat(receiver, "LastCallHidden", True) else: self.settings.setServerStat(receiver, "LastCallHidden", False) caller_number = self.settings.getServerStat(caller, "TeleNumber") caller_number = caller_number[:3] + "-" + caller_number[3:] await receiver_chan.send( ":telephone: Incoming call from: *{}*\nType *pickup* to answer.". format(caller_number)) # Ring for 30 seconds - then report no answer # Setup the check def check(ctx, msg): # This now catches the message and the context # print(ctx) if msg.author.bot: return False m_cont = msg.content.lower() if msg.channel == receiver_chan and m_cont == "pickup": return True if msg.channel == caller_chan and m_cont == "hangup": return True return False # Wait for a response try: talk = await self.bot.wait_for('message_context', check=check, timeout=30) except Exception: talk = None if talk: talk = talk[1] if talk == None: # No answer - hangup self._hangup(caller) await caller_chan.send(":telephone: No answer...") await receiver_chan.send(":telephone: Ringing stops.") return elif talk.content.lower() == "hangup": # You hung up the call self._hangup(caller) await caller_chan.send(":telephone: You have hung up.") await receiver_chan.send(":telephone: Ringing stops.") return # Connect the call: our_call["Connected"] = True # They answered! await caller_chan.send( ":telephone_receiver: Connected.\nType *hangup* to end the call.") await receiver_chan.send( ":telephone_receiver: Connected.\nType *hangup* to end the call.") # Wait on the call while True: # Setup the check def check_in_call(msg): if msg.author.bot: return False if msg.channel == receiver_chan or msg.channel == caller_chan: return True return False try: # 1 minute timeout talk = await self.bot.wait_for('message', check=check_in_call, timeout=60) except Exception: talk = None if talk == None: # Timed out self._hangup(caller) self._hangup(receiver) await caller_chan.send(":telephone: Disconnected.") await receiver_chan.send(":telephone: Disconnected.") return elif talk.content.lower() == "hangup": # One side hung up self._hangup(caller) self._hangup(receiver) if talk.channel == caller_chan: # The caller disconnected await receiver_chan.send( ":telephone: The other phone was hung up.") await caller_chan.send(":telephone: You have hung up.") else: # The receiver disconnected await caller_chan.send( ":telephone: The other phone was hung up.") await receiver_chan.send(":telephone: You have hung up.") return else: talk_msg = talk.content # Let's make sure we strip links out - and nullify discord.gg links to patch a spam loophole # Create a set of all matches (to avoid duplicates in case of spam) if self.settings.getServerStat( receiver if talk.channel == caller_chan else caller, "TeleBlockLinks", True): # Remove links only if the target channel chooses to matches = [ x.group(0) for x in re.finditer(self.regex, talk_msg) ] dmatches = [ x.group(0) for x in re.finditer(self.dregex, talk_msg) ] matches.extend(dmatches) matches = OrderedDict.fromkeys( matches) # Use an OrderedDict to avoid duplicates # Now we iterate that list and replace all links with `link removed` for x in matches: talk_msg = talk_msg.replace(x, "`link removed`") # Clean out mentions from the message talk_msg = Utils.suppressed(talk.guild, talk_msg, force=True) # Must be conversation if talk.channel == caller_chan: # Coming from the talking channel if hidden: await receiver_chan.send(":telephone_receiver: " + talk_msg) else: user = DisplayName.name(talk.author).replace( "`", "" ).replace( "\\", "" ) # Remove @here and @everyone mentions in username await receiver_chan.send( ":telephone_receiver: `{}`: {}".format( user, talk_msg)) else: user = DisplayName.name(talk.author).replace( "`", "").replace( "\\", "" ) # Remove @here and @everyone mentions in username await caller_chan.send( ":telephone_receiver: `{}`: {}".format(user, talk_msg))