async def unlockdown(self, ctx, target_channel=None): """Iterate through the channels in the lockdown list and clear the send_message, add_reaction, and speak permissions for the everyone role (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return if target_channel: c = DisplayName.channelForName(target_channel, ctx.guild) if not c: return await ctx.send( "The passed value is not a valid channel or category!") orphaned, channels = self._verify_lockdown(ctx, c.id) lockdown = channels else: lockdown, channels = self._get_lockdown(ctx) if not await self._check_lockdown(lockdown, ctx): return message = await Message.EmbedText( title="Unlockdown", description="🟢 Unlocking {:,} entr{}...".format( len(lockdown), "y" if len(lockdown) == 1 else "ies"), color=ctx.author).send(ctx) cats, chans = await self._perform_lockdown(ctx, channels, unlock=True) if cats == chans == 0: return await Message.EmbedText( title="Unlockdown", description="**UNLOCKDOWN FAILED!**").edit(ctx, message) await Message.EmbedText( title="Unlockdown", description="🟢 Unlocked {}{}.".format( "{:,} categor{}".format(cats, "y" if cats == 1 else "ies") if cats else "", "" if not chans else "{}{:,} channel{}.".format( ", " if cats else "", chans, "" if chans == 1 else "s"))).edit(ctx, message)
async def remlock(self, ctx, *, channel_list=None): """Removes the passed space-delimited list of channels and categories from the lockdown list (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return lockdown, channels = self._get_lockdown(ctx) if not await self._check_lockdown(lockdown, ctx): return if not channel_list: return await ctx.send("Usage: `{}remlock [channel list]`".format( ctx.prefix)) resolved = [] resolved_id = [] for channel in channel_list.split(): c = DisplayName.channelForName(channel, ctx.guild) if c and c.id in lockdown: resolved.append(c) resolved_id.append(c.id) # Also consider child channels as needed if isinstance(c, discord.CategoryChannel): for c_child in c.channels: if c_child and c_child.id in lockdown: resolved.append(c_child) resolved_id.append(c_child.id) if not len(resolved): return await ctx.send( "No valid channels passed!\nUsage: `{}remlock [channel list]`". format(ctx.prefix)) lockdown = [x for x in lockdown if not x in resolved_id] self.settings.setServerStat(ctx.guild, "LockdownList", lockdown) desc = "\n".join([self._get_mention(x) for x in resolved]) await Message.EmbedText( title="{:,} Entr{} Removed from Lockdown List".format( len(resolved), "y" if len(resolved) == 1 else "ies"), description=desc, color=ctx.author, footer=self.key).send(ctx)
async def antiraidping(self, ctx, user_or_role=None, channel=None): """Sets up what user or role to ping and in what channel when anti-raid is activated (bot-admin only).""" if not await Utils.is_bot_admin_reply(ctx): return if user_or_role == None: # print the settings user_role = self.settings.getServerStat(ctx.guild, "AntiRaidPing", None) if user_role: u = DisplayName.memberForName(user_role, ctx.guild) if not u: u = DisplayName.roleForName(user_role, ctx.guild) user_role = u chan = self.settings.getServerStat(ctx.guild, "AntiRaidChannel", None) if chan: chan = DisplayName.channelForName(chan, ctx.guild) if not user_role or not chan: return await ctx.send("Anti-raid ping is not setup.") return await ctx.send( "Anti-raid activity will mention {} and be announced in {}!". format( Nullify.escape_all(user_role.display_name) if isinstance( user_role, discord.Member) else Nullify.escape_all( user_role.name), chan.mention)) if channel == None: return await ctx.send( "Usage: `{}antiraidping user_or_role channel`".format( ctx.prefix)) # We're setting it up - let's check the user first, then role, then channel ur = DisplayName.memberForName(user_or_role, ctx.guild) if not ur: ur = DisplayName.roleForName(user_or_role, ctx.guild) if not ur: return await ctx.send("I couldn't find that user or role.") ch = DisplayName.channelForName(channel, ctx.guild) if not ch: return await ctx.send("I couldn't find that channel.") # Got them! - Save and report self.settings.setServerStat(ctx.guild, "AntiRaidPing", ur.id) self.settings.setServerStat(ctx.guild, "AntiRaidChannel", ch.id) return await ctx.send( "Anti-raid activity will mention {} and be announced in {}!". format( Nullify.escape_all(ur.display_name) if isinstance( ur, discord.Member) else Nullify.escape_all(ur.name), ch.mention))
async def tr(self, ctx, *, translate=None): """Translate some stuff! Takes a phrase, the from language identifier (optional), and the to language identifier. To see a number of potential language identifiers, use the langlist command. Example Translation: $tr Hello there, how are you? en es Would translate from English to Spanish resulting in: ¿Hola como estás? If you do not specify the from language, Google translate will attempt to automatically determine it.""" usage = "Usage: `&tr [input] [from code (optional)] [to code]`".format( ctx.prefix) if translate == None: return await ctx.send(usage) word_list = translate.split(" ") if len(word_list) < 2: return await ctx.send(usage) to_lang = word_list[len(word_list) - 1] from_lang = word_list[len(word_list) - 2] if len(word_list) >= 3 else "" # Get the from language name from the passed code from_lang_name = googletrans.LANGUAGES.get(from_lang.lower(), None) # Get the to language name from the passed code to_lang_name = googletrans.LANGUAGES.get(to_lang.lower(), None) if not to_lang_name: # No dice on the language :( return await Message.EmbedText( title="Error", description="Specified language can't be found", color=ctx.author).send(ctx) # Get all but our language codes joined with spaces trans = " ".join(word_list[:-2] if from_lang_name else word_list[:-1]) # If our from_lang_name is None, we need to auto-detect it if not from_lang_name: from_output = await self.bot.loop.run_in_executor( None, self.translator.detect, trans) from_lang = from_output.lang from_lang_name = googletrans.LANGUAGES.get(from_lang, "Unknown") # Let's actually translate now result_output = await self.bot.loop.run_in_executor( None, functools.partial(self.translator.translate, trans, dest=to_lang, src=from_lang)) result = result_output.text # Explore the results! if not result: await Message.EmbedText(title="Error", description="Unable to translate input", color=ctx.author).send(ctx) return if result == trans: # We got back what we put in... await Message.EmbedText( title="Error", description= "The text returned from Google was the same as the text input. Either the translation failed - or you were translating from/to the same language (en -> en)", color=ctx.author).send(ctx) return await Message.EmbedText( title="{}, your translation is:".format( DisplayName.name(ctx.author)), force_pm=True, color=ctx.author, description=result, footer="{} --> {} - Powered by Google Translate".format( string.capwords(from_lang_name), string.capwords(to_lang_name))).send(ctx)
async def checkroles(user, channel, settings, bot, suppress: bool = False, **kwargs): # This method checks whether we need to promote, demote, or whatever # then performs the said action, and outputs. if user.bot: return # Don't apply roles to bots DisplayName = bot.get_cog("DisplayName") Utils = bot.get_cog("Utils") if not DisplayName or not Utils: return # We are missing dependencies if type(channel) is discord.Guild: server = channel channel = None else: server = channel.guild # Get our preliminary vars msg = None xpPromote = kwargs.get("xp_promote", settings.getServerStat(server, "XPPromote")) xpDemote = kwargs.get("xp_demote", settings.getServerStat(server, "XPDemote")) userXP = int(settings.getUserStat(user, server, "XP")) suppProm = kwargs.get("suppress_promotions", settings.getServerStat(server, "SuppressPromotions")) suppDem = kwargs.get("suppress_demotions", settings.getServerStat(server, "SuppressDemotions")) onlyOne = kwargs.get("only_one_role", settings.getServerStat(server, "OnlyOneRole")) # Check if we're suppressing @here and @everyone mentions if settings.getServerStat(server, "SuppressMentions"): suppressed = True else: suppressed = False changed = False promoArray = settings.getServerStat(server, "PromotionArray") promoArray = sorted(promoArray, key=lambda x: int(x['XP'])) addRoles = [] remRoles = [] # Final checks for singular role-holding. Will find a better system at # some point - probably... if onlyOne: # Only one role allowed, make sure we don't have the rest # Get the role we're supposed to be at current_role = None is_higher = False target_role = None for role in promoArray: test_role = DisplayName.roleForID(role['ID'], server) # Check if it's a real role if not test_role: continue if int(role["XP"]) > userXP: # We don't have xp for this role # Set it if we already have it though if test_role in user.roles: current_role = test_role is_higher = True else: # We've got the resources for it target_role = test_role # Set it if we already have it though if test_role in user.roles: current_role = test_role # Remove all roles except current if current_role == target_role: for role in promoArray: test_role = DisplayName.roleForID(role['ID'], server) if test_role != target_role and test_role in user.roles: changed = True remRoles.append(test_role) else: # Demote if needed if is_higher: if xpDemote: # We can remove roles above - but keep the last one msg = '*{}* was demoted from **{}**!'.format( DisplayName.name(user), current_role.name) for role in promoArray: test_role = DisplayName.roleForID(role['ID'], server) if test_role != target_role and test_role in user.roles: remRoles.append(test_role) addRoles.append(target_role) changed = True else: # We're not demoting - but let's add only the current role to the list for role in promoArray: test_role = DisplayName.roleForID(role['ID'], server) if test_role != current_role and test_role in user.roles: remRoles.append(test_role) changed = True # Promote if needed else: if xpPromote: # Remove all roles below msg = '*{}* was promoted to **{}**!'.format( DisplayName.name(user), target_role.name) for role in promoArray: test_role = DisplayName.roleForID(role['ID'], server) if test_role != target_role and test_role in user.roles: remRoles.append(test_role) addRoles.append(target_role) changed = True else: # We're not promoting - but let's add only the current role to the list for role in promoArray: test_role = DisplayName.roleForID(role['ID'], server) if test_role != current_role and test_role in user.roles: remRoles.append(test_role) changed = True else: # Check promotions first if xpPromote: # This is, by far, the more functional way for role in promoArray: # Iterate through the roles, and add which we have xp for if int(role['XP']) <= userXP: # We *can* have this role, let's add it to a list addRole = DisplayName.roleForID(role['ID'], server) if addRole: if not addRole in user.roles: addRoles.append(addRole) if not suppProm: msg = '*{}* was promoted to **{}**!'.format( DisplayName.name(user), addRole.name) changed = True # Allow independent promotion/demotion if xpDemote: for role in promoArray: # Iterate through the roles, and add which we have xp for if int(role['XP']) > userXP: # We *can* have this role, let's add it to a list remRole = DisplayName.roleForID(role['ID'], server) if remRole: if remRole in user.roles: remRoles.append(remRole) if not suppDem: msg = '*{}* was demoted from **{}**!'.format( DisplayName.name(user), remRole.name) changed = True # Add and remove roles as needed if len(addRoles) or len(remRoles): settings.role.change_roles(user, add_roles=addRoles, rem_roles=remRoles) # Check if we have a message to display - and display it if msg and channel and (not suppress): msg = Utils.suppressed(server, msg) await channel.send(msg) return changed
async def on_member_join(self, member): if not self.settings.getServerStat(member.guild, "AntiRaidEnabled", False): return # Not enabled, ignore if self.settings.getServerStat(member.guild, "AntiRaidActive", False): # Currently in anti-raid mode, find out what to do with the new join ar_cooldown = self.settings.getServerStat(member.guild, "AntiRaidCooldown", 600) # 10 minute default ar_lastjoin = self.settings.getServerStat(member.guild, "AntiRaidLastJoin", 0) if time.time( ) - ar_lastjoin >= ar_cooldown: # No longer watching - disable anti-raid self.settings.setServerStat(member.guild, "AntiRaidActive", False) else: # Gather our response to the new user and put it into effect await self._anti_raid_respond(member) # Save the last join timestamp in the anti-raid list self.settings.setServerStat(member.guild, "AntiRaidLastJoin", time.time()) # Gather the settings and go from there ar_joins = self.settings.getServerStat(member.guild, "AntiRaidJoins", []) ar_maxj = self.settings.getServerStat(member.guild, "AntiRaidMax", 10) ar_time = self.settings.getServerStat(member.guild, "AntiRaidTime", 10) ar_joins.insert( 0, (member.id, time.time())) # Add (mem_id,timestamp) to the front of the list ar_joins = ar_joins[: ar_maxj] # Ensure the list is only as long as the max joins allowed self.settings.setServerStat(member.guild, "AntiRaidJoins", ar_joins) # Save the updated list if len(ar_joins) < ar_maxj: return # List isn't long enough to consider - bail # Compare the first and last join times to the threshold if ar_joins[0][1] - ar_joins[-1][1] <= ar_time: # Enable anti-raid! if not self.settings.getServerStat(member.guild, "AntiRaidActive", False): self.settings.setServerStat(member.guild, "AntiRaidActive", True) mention = self.settings.getServerStat(member.guild, "AntiRaidPing", None) if mention: m = DisplayName.memberForName(mention, member.guild) if not m: m = DisplayName.roleForName(mention, member.guild) if m: # Got a member or role - let's get the channel channel = self.settings.getServerStat( member.guild, "AntiRaidChannel", None) if channel: c = DisplayName.channelForName( channel, member.guild) if c: # Got a member/role and a channel - try to post the ping try: await c.send( "{} - Anti-raid has been enabled!". format(m.mention)) except: pass self.settings.setServerStat(member.guild, "AntiRaidLastJoin", time.time()) for m_id, t in ar_joins: # Resolve the ids and react accordingly m = member.guild.get_member(m_id) if m: await self._anti_raid_respond(m)