def index(self, code, state): user = User(**self.serializer.loads(state, max_age=300)) evesso = OAuth2Session(settings.CLIENT_ID) token = evesso.fetch_token(settings.TOKEN_URL, authorization_response=cherrypy.request.base + cherrypy.request.path_info + "?" + cherrypy.request.query_string, state=state, method="POST", client_secret=settings.SECRET_KEY) r = evesso.get(settings.VERIFY_URL) userdata = r.json() if userdata['CharacterName']: server = self.discord_client.servers[0] assert isinstance(server, Server) member = find(lambda m: m.id == user.id, server.members) assert isinstance(member, Member) role = find(lambda r: r.name == 'Capsuleer', server.roles) assert isinstance(role, Role) self.discord_client.add_roles(member, role) self.discord_client.send_message(member, "Welcome %s! You should no be able to switch channels." % userdata[ 'CharacterName']) # self.discord_client.send_message(user, "Found you!") return "Welcome %s! You can now close this window." % userdata['CharacterName'] return "Unknown Error."
async def weeb(self, ctx): """ Weeb is a lifestyle chosen once... Then stuck with you forever... """ weeb = find(lambda r: r.name == "Weeb", ctx.message.server.roles) if weeb in ctx.message.author.roles: return normie = find(lambda r: r.name == "Normies", ctx.message.server.roles) await self.bot.add_roles(ctx.message.author, weeb) await self.bot.remove_roles(ctx.message.author, normie)
async def join(con, *, channel=None): """JOIN A VOICE CHANNEL THAT THE USR IS IN OR MOVE TO A VOICE CHANNEL IF THE BOT IS ALREADY IN A VOICE CHANNEL""" # COMMAND IS IN DM if con.message.channel.is_private == True: await bot.send_message(con.message.channel, "**You must be in a `server text channel` to use this command**") # COMMAND NOT IN DM if con.message.channel.is_private == False: voice_status = bot.is_voice_connected(con.message.server) voice = find(lambda m: m.name == channel, con.message.server.channels) if voice_status == False and channel == None: # VOICE NOT CONNECTED if con.message.author.voice_channel == None: await bot.send_message(con.message.channel, "**You must be in a voice channel or give a voice channel name to join**") if con.message.author.voice_channel != None: await bot.join_voice_channel(con.message.author.voice.voice_channel) if voice_status == False and channel != None: # PICKING A VOICE CHANNEL await bot.join_voice_channel(voice) if voice_status == True: # VOICE ALREADY CONNECTED if voice == None: await bot.send_message(con.message.channel, "**Bot is already connected to a voice channel**") if voice != None: if voice.type == discord.ChannelType.voice: await bot.voice_client_in(con.message.server).move_to(voice)
async def bdo(self, ctx): """ Access to BDO channel """ bdo = find(lambda r: r.name == "BDO", ctx.message.server.roles) if bdo in ctx.message.author.roles: await self.bot.remove_roles(ctx.message.author, bdo) else: await self.bot.add_roles(ctx.message.author, bdo)
async def normie(self, ctx): """ Get access to the server! """ if len(ctx.message.author.roles) == 1: normie = find(lambda r: r.name == "Normies", ctx.message.server.roles) await self.bot.add_roles(ctx.message.author, normie) await self.bot.delete_message(ctx.message) await self.bot.send_message(ctx.message.server.default_channel, "Welcome {0} to the server!".format(ctx.message.author.mention))
def last_game(client, arguments, message): if arguments and len(arguments) == 1: name = arguments[0] member = list(map(lambda server: find(lambda m: m.name == name, server.members), client.servers)) if len(member) > 0 and member[0] is not None: player = member[0] elif len(message.mentions) > 0: player = message.mentions[0] else: client.send_message(message.channel, "Could not find %s" % (name)) else: player = message.author if player.id not in Bot().dota_accounts.keys(): client.send_message(message.channel, "%s not registered" % (player.name)) return account_id = Bot().dota_accounts[player.id].id64() matches = Match.list(account_id) if not isinstance(matches,list): client.send_message(message.channel, matches) return last_match = matches[0] if last_match.match_id not in Bot().match_cache.keys(): client.send_typing(message.channel) result = BotResult.find(last_match.match_id) Bot().match_cache[last_match.match_id] = BotResult.schema().dump(result).data Bot().save_metadata() client.send_message(message.channel, Bot().renderer.render_name("match_result_short", {'result':Bot().match_cache[last_match.match_id]}))
def mentions(self): mentions = [] for player in self.players: for k,v in Bot().dota_accounts.items(): if player.account_id == v.id32(): mentions.append(list(map(lambda server: find(lambda m: m.id == k, server.members), self.discord.servers))[0]) return mentions
def author_has_admin_role(self, msg_author, role: str=None): if role is None: role = self.admin_role #member = find(lambda m: m.id == message.author.id, message.server.members) has_role = find(lambda r: r.name == role, msg_author.roles) return has_role is not None
def is_discord_member(self): if self.account_id != 4294967295: for k,v in Bot().dota_accounts.items(): if self.account_id == v.id32(): member = list(map(lambda server: find(lambda m: m.id == k, server.members), self.discord.servers)) if len(member) > 0: return member[0] return False
async def on_message(message): # check if client is in mentions if not find(lambda m: m.name == client.user.name, message.mentions): return # check if client is not talking to himself if message.author == client.user: return response = random.choice(quotes) await client.send_message(message.channel, response)
async def role_link(ctx, role_name: str, level: int, remove_role: Optional[str] = None): """Associate a role with a level. Removes previous role if given.""" guild = ctx.message.guild role_obj = find(lambda r: r.name == role_name, guild.roles) remove_role_obj = find(lambda r: r.name == remove_role, guild.roles) if role_obj is None: return await ctx.send("**Please make sure the `{}` role exists!**".format(role_name)) if remove_role is not None and remove_role_obj is None: return await ctx.send("**Please make sure the `{}` role exists!**".format(remove_role)) role_info = db.role(role_obj) await role_info.level.set(level) if remove_role_obj is not None: await role_info.remove_role.set(remove_role_obj.id) remove_role_msg = f"Will also remove `{remove_role}` role." if remove_role is not None else "" message = f"**The `{role_name}` role has been linked to level `{level}`. {remove_role_msg}**" await ctx.send(message)
async def contact(self, ctx, *, message: str): """Send a message to my owner""" author = ctx.message.author.name server = ctx.message.server.name owner = utils.find(lambda mem: str(mem.id) == settings.owner, self.bot.get_all_members()) message = "A message from {} on {}:\n\t{}".format( author, server, message) if owner is not None: await self.bot.send_message(owner, message) else: await self.bot.say("Sorry, my owner is offline, try again later?")
def watcher_callback(match): channels = [] for server in set(map(lambda mention: mention.server, match.mentions())): channels.append(find(lambda channel: channel.name == "dotastats",server.channels)) for channel in channels: Bot().client.send_typing(channel) result = BotResult.find(match.match_id) Bot().match_cache[match.match_id] = BotResult.schema().dump(result).data Bot().save_metadata() for channel in channels: Bot().client.send_message(channel, Bot().renderer.render_name("match_result_short", {'result':Bot().match_cache[match.match_id]}))
def who(message): argname = message.content[5:] if len(argname) == 0: client.send_message(message.channel, 'Usage: !who [user]') elif len(argname) < 3: client.send_message(message.channel, 'You need to type more than 3 letters for the user!') else: userfound = False for member in message.channel.server.members: if member.name.lower() == argname.lower(): userfound = True try: gameplaying = find(lambda game: game['id'] == member.game_id, games)['name'] except TypeError: gameplaying = 'None' client.send_message(message.channel, '```Name: ' + member.name + '\nID: ' + member.id + '\nStatus: ' + member.status.capitalize() + '\nGame Playing: ' + gameplaying + '\nAvatar: ' + member.avatar_url() + '\nJoined on: ' + str(member.joined_at.month) + '/' + str(member.joined_at.day) + '/' + str(member.joined_at.year) + '```') break if not userfound: for member in message.channel.server.members: if member.name.lower().startswith(argname.lower()): userfound = True try: gameplaying = find(lambda game: game['id'] == member.game_id, games)['name'] except TypeError: gameplaying = 'None' client.send_message(message.channel, 'Name: ' + member.name + '\nStatus: ' + member.status.capitalize() + '\nGame Playing: ' + gameplaying + '\nJoined on: ' + str( member.joined_at.month) + '/' + str(member.joined_at.day) + '/' + str( member.joined_at.year)) break if not userfound: client.send_message(message.channel, "User not found.")
def leave(self, message, argument): """[id] - Leave a server by id. Uses this server if id is not given.""" if argument is None: server_id = message.channel.server.id else: server_id = argument if server_id not in config['protected_servers']: server = utils.find(lambda s: s.id == server_id, self.servers) if server is not None: self.leave_server(server) else: self.send_message(message.channel, "Can't find server with id " "{}".format(server_id)) else: self.send_message(message.channel, "Refusing to leave protected server")
async def role_unlink(ctx, role_name: str): """Delete a role/level association.""" guild = ctx.message.guild role_obj = find(lambda r: r.name == role_name, guild.roles) if role_obj is None: return await ctx.send(f"**The `{role_name}` role doesn't exist!**") role_info = db.role(role_obj) role_level = await role_info.level() if role_level is not None: await ctx.send(f"**Role/Level association `{role_name}`/`{role_level}` removed.**") await role_info.level.clear() await role_info.remove_role.clear() else: await ctx.send(f"**The `{role_name}` role is not linked to any levels!**")
async def parse_message(self, message, guild_data=None): guild = message.guild content = message.content author = message.author channel = message.channel channel_id = channel and str(channel.id) guild_id = guild and str(guild.id) trello_board = guild and await get_board(guild) prefix, _ = await get_prefix(guild, trello_board) client_match = re.search(f"<@!?{self.client.user.id}>", content) check = (content[:len(prefix)].lower() == prefix.lower() and prefix) or client_match and client_match.group(0) check_verify_channel = False trello_options = {} trello_options_checked = True if check: after = content[len(check):].strip() args = after.split(" ") command_name = args[0] and args[0].lower() del args[0] if command_name: enabled_addons = guild and await get_enabled_addons(guild) or {} for index, command in commands.items(): if index == command_name or command_name in command.aliases: if command.addon: if str(command.addon) not in enabled_addons: return donator_profile = None actually_dm = command.dm_allowed and not guild guild_data = guild_data or (guild and (await self.r.table("guilds").get(guild_id).run() or {"id": guild_id})) or {} fn = command.fn subcommand_attrs = {} subcommand = False if args: # subcommand checking subcommand = command.subcommands.get(args[0]) if subcommand: fn = subcommand subcommand_attrs = getattr(fn, "__subcommandattrs__", None) del args[0] after = args and " ".join(args) or "" CommandArgs = Args( command_name = index, real_command_name = command_name, message = message, guild_data = guild_data, flags = {}, prefix = prefix, has_permission = False, ) if getattr(fn, "__flags__", False): flags, flags_str = command.parse_flags(after) content = content.replace(flags_str, "") message.content = content after = after.replace(flags_str, "") CommandArgs.flags = flags locale = Locale(guild_data and guild_data.get("locale", "en") or "en") response = Response(CommandArgs) if guild and RELEASE == "PRO" and command_name not in ("donate", "transfer", "eval", "status", "prefix"): donator_profile, _ = await get_features(Object(id=guild.owner_id), guild=guild) if not donator_profile.features.get("pro"): await response.error(f"Server not authorized to use Pro. Please use the ``{prefix}donate`` command to see information on " "how to get Bloxlink Pro.") return if guild: ignored_channels = guild_data.get("ignoredChannels", {}) disabled_commands = guild_data.get("disabledCommands", {}) author_perms = author.guild_permissions if guild.owner != author and not (find(lambda r: r.name in MAGIC_ROLES, author.roles) or author_perms.manage_guild or author_perms.administrator): if ignored_channels.get(channel_id): await response.send(f"The server admins have **disabled** all commands in channel {channel.mention}.", dm=True, strict_post=True, no_dm_post=True) try: await message.delete() except Forbidden: pass return if command.name in disabled_commands.get("global", []): await response.send(f"The server admins have **disabled** the command ``{command_name}`` globally.", dm=True, strict_post=True, no_dm_post=True) try: await message.delete() except Forbidden: pass return elif disabled_commands.get("channels", {}).get(channel_id) == command.name: await response.send(f"The server admins have **disabled** the command ``{command_name}`` in channel {channel.mention}.", dm=True, strict_post=True, no_dm_post=True) try: await message.delete() except Forbidden: pass return if not isinstance(author, Member): try: author = await guild.fetch_member(author.id) except NotFound: return blacklisted_discord = await cache_get(f"blacklist:discord_ids:{author.id}", primitives=True) if blacklisted_discord is not None: blacklist_text = blacklisted_discord and f"has an active restriction for: ``{blacklisted_discord}``" or "has an active restriction from Bloxlink." await response.send(f"{author.mention} {blacklist_text}") return if command.cooldown and self.cache: redis_cooldown_key = f"cooldown_cache:{index}:{author.id}" if not donator_profile or (donator_profile and not donator_profile.features.get("premium")): donator_profile, _ = await get_features(author) if not donator_profile.features.get("premium"): on_cooldown = await self.cache.get(redis_cooldown_key) if on_cooldown: cooldown_time = await self.redis.ttl(redis_cooldown_key) embed = Embed(title="Slow down!") embed.description = "This command has a short cooldown since it's relatively expensive for the bot. " \ f"You'll need to wait **{cooldown_time}** more second(s).\n\nDid you know? " \ "**[Bloxlink Premium](https://www.patreon.com/join/bloxlink?)** subscribers NEVER " \ f"see any cooldowns. Find out more information with ``{prefix}donate``." try: m = await channel.send(embed=embed) except (NotFound, Forbidden): pass else: await asyncio.sleep(10) try: await m.delete() await message.delete() except (NotFound, Forbidden): pass return await self.cache.set(redis_cooldown_key, True, expire_time=command.cooldown) if not (command.dm_allowed or guild): try: await channel.send("This command does not support DM; please run it in a server.") except Forbidden: pass finally: return CommandArgs.add(locale=locale, response=response, trello_board=trello_board) try: await command.check_permissions(author, guild, locale, dm=actually_dm, **subcommand_attrs) except PermissionError as e: if subcommand_attrs.get("allow_bypass"): CommandArgs.has_permission = False elif command.permissions.allow_bypass: CommandArgs.has_permission = False else: await response.error(e) return except Message as e: message_type = "send" if e.type == "info" else e.type response_fn = getattr(response, message_type, response.send) if e.args: await response_fn(e) if subcommand_attrs.get("allow_bypass"): CommandArgs.has_permission = False elif command.permissions.allow_bypass: CommandArgs.has_permission = False else: return else: CommandArgs.has_permission = True if subcommand: command_args = subcommand_attrs.get("arguments") else: command_args = command.arguments arguments = Arguments(CommandArgs) try: parsed_args, string_args = await self.more_args(after, CommandArgs, command_args, arguments) CommandArgs.add(parsed_args=parsed_args, string_args=string_args, prompt=arguments.prompt) response.prompt = arguments.prompt # pylint: disable=no-member await fn(CommandArgs) except PermissionError as e: if e.args: await response.error(e) else: await response.error(locale("permissions.genericError")) except Forbidden as e: if e.args: await response.error(e) else: await response.error(locale("permissions.genericError")) except NotFound: await response.error("A channel or message which was vital to this command was deleted before the command could finish.") except RobloxAPIError: await response.error("The Roblox API returned an error; are you supplying the correct ID to this command?") except RobloxDown: await response.error("The Roblox API is currently offline; please wait until Roblox is back online before re-running this command.") except CancelledPrompt as e: arguments.cancelled = True if trello_board: trello_options, _ = await get_options(trello_board) guild_data.update(trello_options) trello_options_checked = True if (e.type == "delete" and not e.dm) and guild_data.get("promptDelete", DEFAULTS.get("promptDelete")): try: await message.delete() except (Forbidden, NotFound): pass else: if e.args: await response.send(f"**{locale('prompt.cancelledPrompt')}:** {e}", dm=e.dm, no_dm_post=True) else: await response.send(f"**{locale('prompt.cancelledPrompt')}.**", dm=e.dm, no_dm_post=True) except Message as e: message_type = "send" if e.type == "send" else e.type response_fn = getattr(response, message_type, response.send) if e.args: await response_fn(e) else: await response_fn("This command closed unexpectedly.") except Error as e: if e.args: await response.error(e) else: await response.error("This command has unexpectedly errored.") except CancelCommand as e: if e.args: await response.send(e) except NotImplementedError: await response.error("The option you specified is currently not implemented, but will be coming soon!") except CancelledError: pass except Exception as e: """ error_id = Bloxlink.error(e, command=command_name, user=(author.id, str(author)), guild=guild and f"id:{guild.id}") if error_id: await response.error("We've experienced an unexpected error. You may report this " f"error with ID ``{error_id}`` in our support server: {SERVER_INVITE}.") else: await response.error("An unexpected error occured.") """ await response.error(locale("errors.commandError")) Bloxlink.error(traceback.format_exc(), title=f"Error source: {command_name}.py") finally: messages = arguments.messages + response.delete_message_queue if arguments.dm_post: if arguments.cancelled: content = f"{author.mention}, **this DM prompt has been cancelled.**" else: content = f"{author.mention}, **this DM prompt has finished.**" try: await arguments.dm_post.edit(content=content) except (NotFound, Forbidden): pass if messages: if not trello_options_checked and trello_board: trello_options, _ = await get_options(trello_board) guild_data.update(trello_options) trello_options_checked = True if not actually_dm and guild_data.get("promptDelete", DEFAULTS.get("promptDelete")): try: await channel.purge(limit=100, check=lambda m: m.id in (*arguments.messages, *response.delete_message_queue)) except (Forbidden, HTTPException): pass break else: check_verify_channel = True else: check_verify_channel = True else: check_verify_channel = True if check_verify_channel and guild: if not isinstance(author, Member): try: author = await guild.fetch_member(author.id) except NotFound: return verify_channel_id = await get_guild_value(guild, "verifyChannel") if verify_channel_id and channel_id == verify_channel_id: if not find(lambda r: r.name in MAGIC_ROLES, author.roles): try: await message.delete() except (Forbidden, NotFound): pass
async def get_role_by_name(ctx, name): role = utils.find(lambda m: m.name == name, ctx.guild.roles) if role: return role else: raise AttributeError(f"Role '{name}' could not be found.")
async def _remove_user_role(self, guild, role_name, user): role = utils.find( lambda r: r.name == role_name, getattr(guild, "roles", []), ) role and await user.remove_roles(role)
async def on_guild_join(self, guild: discord.Guild): await self.wait_until_ready() chan_logger = self.get_channel(692815717078270052) try: general = find(lambda x: x.name == "general", guild.text_channels) if general and general.permissions_for(guild.me).send_messages: embed = discord.Embed( description= "You can support me on <:kofi:693473314433138718>[Kofi](https://ko-fi.com/takitsu) and vote on [top.gg](https://top.gg/bot/682946560417333283/vote) for the bot. <:github:693519776022003742> [Source code](https://github.com/takitsu21/covid-19-tracker)", timestamp=utils.discord_timestamp(), color=utils.COLOR) embed.set_author(name="Coronavirus COVID-19 Tracker", icon_url=guild.me.avatar_url) embed.set_thumbnail(url=self.thumb) embed.add_field( name="Vote", value= "[Click here](https://top.gg/bot/682946560417333283/vote)") embed.add_field( name="Invite Coronavirus COVID-19", value= "[Click here](https://discordapp.com/oauth2/authorize?client_id=682946560417333283&scope=bot&permissions=313408)" ) embed.add_field( name="Discord Support", value="[Click here](https://discordapp.com/invite/wTxbQYb)" ) embed.add_field( name="Source code", value= "[Click here](https://github.com/takitsu21/covid-19-tracker)" ) embed.add_field(name="Help command", value="c!help") embed.add_field(name="Prefix", value="c!") nb_users = 0 channels = 0 for s in self.guilds: nb_users += len(s.members) channels += len(s.channels) embed.add_field( name="<:confirmed:688686089548202004> Confirmed", value=self._data["total"]["confirmed"]) embed.add_field(name="<:recov:688686059567185940> Recovered", value=self._data["total"]["recovered"]) embed.add_field(name="<:_death:688686194917244928> Deaths", value=self._data["total"]["deaths"]) embed.add_field(name="<:servers:693053697453850655> Servers", value=len(self.guilds)) embed.add_field(name="<:users:693053423494365214> Members", value=nb_users) embed.add_field(name="<:hashtag:693056105076621342> Channels", value=channels) embed.add_field( name="<:stack:693054261512110091> Shards", value=f"{ctx.guild.shard_id + 1}/{self.bot.shard_count}") embed.set_footer(text="Made by Taki#0853 (WIP) " + utils.last_update(utils.DATA_PATH), icon_url=guild.me.avatar_url) await general.send(embed=embed) except: pass embed = discord.Embed(title="Bot added to " + guild.name, timestamp=datetime.datetime.utcnow(), color=utils.COLOR) embed.add_field(name="<:users:693053423494365214> Members", value=len(guild.members)) embed.add_field(name="<:hashtag:693056105076621342> Channels", value=len(guild.channels)) embed.set_thumbnail(url=guild.icon_url) embed.set_footer(icon_url=guild.me.avatar_url) await chan_logger.send(embed=embed)
async def _handle_levelup(bot, user, channel): guild = user.guild guild_info = db.guild(guild) user_info = db.user(user) member_info = db.member(user) name = await get_user_name(user) level = await member_info.level() if await db.guild(guild).lvl_msg(): # if lvl msg is enabled lock_channel = await db.guild(guild).lvl_msg_lock() if lock_channel: channel = find(lambda m: m.id == lock_channel, guild.channels) guild_identifier = "" # private message takes precedent, of course if await db.guild(guild).private_lvl_msg(): guild_identifier = f" on {guild.name}" channel = user name = "You" image = await draw_levelup(bot, user) image_buffer = BytesIO() image.save(image_buffer, "png") image_buffer.seek(0) await channel.send( f"**{name} just gained a level{guild_identifier}!**", file=discord.File(filename="levelup.png", fp=image_buffer), ) # add to appropriate role if necessary for role in guild.roles: role_info = db.role(role) if await role_info.level() == level: await user.add_roles(role) remove_role = await role_info.remove_role() if remove_role is not None: remove_role_obj = discord.utils.find( lambda r: r.id == remove_role, guild.roles, ) if remove_role_obj is not None: await user.remove_roles(remove_role_obj) else: await channel.send("Error. Could not find role to remove") # add appropriate badge if necessary try: linked_badges = await guild_info.badge_links() for badge_name, badge_level in linked_badges.items(): if badge_level == level: guild_badges = await guild_info.badges() user_badges = await user_info.badges() badge_id = f"{badge_name}_{guild.id}" user_badges[badge_id] = guild_badges[badge_name] await user_info.badges.set(user_badges) except: await channel.send("Error. Badge was not given!")
async def command_checks(self, command, prefix, response, guild_data, author, channel, locale, CommandArgs, message=None, guild=None, subcommand_attrs=None, slash_command=False): channel_id = str(channel.id) if channel else None donator_profile = None dm = not bool(guild) subcommand_attrs = subcommand_attrs or {} if guild: if command.addon: enabled_addons = guild and await get_enabled_addons(guild ) or {} if str(command.addon) not in enabled_addons: raise CancelCommand if getattr(command.addon, "premium", False): donator_profile, _ = await get_features( Object(id=guild.owner_id), guild=guild) if not donator_profile.features.get("premium"): await response.error( f"This add-on requires premium! You may use `{prefix}donate` for instructions on donating.\n" f"You may also disable this add-on with `{prefix}addon change`.", hidden=True) raise CancelCommand if RELEASE == "PRO" and command.name not in ("donate", "transfer", "eval", "status", "prefix"): donator_profile, _ = await get_features( Object(id=guild.owner_id), guild=guild) if not donator_profile.features.get("pro"): await response.error( f"Server not authorized to use Pro. Please use the `{prefix}donate` command to see information on " "how to get Bloxlink Pro.", hidden=True) raise CancelCommand ignored_channels = guild_data.get("ignoredChannels", {}) disabled_commands = guild_data.get("disabledCommands", {}) if isinstance(author, User): try: author = await guild.fetch_member(author.id) except NotFound: raise CancelCommand author_perms = author.guild_permissions if guild.owner != author and not ( find(lambda r: r.name in MAGIC_ROLES, author.roles) or author_perms.manage_guild or author_perms.administrator): if ignored_channels.get(channel_id): await response.send( f"The server admins have **disabled** all commands in channel {channel.mention}.", dm=True, hidden=True, strict_post=True, no_dm_post=True) if message: try: await message.delete() except (Forbidden, NotFound): pass raise CancelCommand if command.name in disabled_commands.get("global", []): await response.send( f"The server admins have **disabled** the command `{command.name}` globally.", dm=True, hidden=True, strict_post=True, no_dm_post=True) if message: try: await message.delete() except (Forbidden, NotFound): pass raise CancelCommand elif disabled_commands.get("channels", {}).get(channel_id) == command.name: await response.send( f"The server admins have **disabled** the command `{command.name}` in channel {channel.mention}.", dm=True, hidden=True, strict_post=True, no_dm_post=True) if message: try: await message.delete() except (Forbidden, NotFound): pass raise CancelCommand if not isinstance(author, Member): try: author = await guild.fetch_member(author.id) except NotFound: raise CancelCommand restriction = await get_restriction("discord_ids", author.id) if restriction: restrction_text = isinstance( restriction, str ) and f"has an active restriction for: `{restriction}`" or "has an active restriction from Bloxlink." await response.send(f"{author.mention} {restrction_text}", hidden=True) raise CancelCommand if command.cooldown and self.cache: redis_cooldown_key = f"cooldown_cache:{command.name}:{author.id}" if not donator_profile or ( donator_profile and not donator_profile.features.get("premium")): donator_profile, _ = await get_features(author) if not donator_profile.features.get("premium"): on_cooldown = await self.cache.get(redis_cooldown_key) if on_cooldown: cooldown_time = await self.redis.ttl(redis_cooldown_key) embed = Embed(title="Slow down!") embed.description = "This command has a short cooldown since it's relatively expensive for the bot. " \ f"You'll need to wait **{cooldown_time}** more second(s).\n\nDid you know? " \ "**[Bloxlink Premium](https://www.patreon.com/join/bloxlink?)** subscribers NEVER " \ f"see any cooldowns. Find out more information with `{prefix}donate`." m = await response.send(embed=embed, hidden=True) if m: await asyncio.sleep(10) try: await m.delete() if message: await message.delete() except (NotFound, Forbidden): pass raise CancelCommand await self.cache.set(redis_cooldown_key, True, expire_time=command.cooldown) if not (command.dm_allowed or guild): await response.send( "This command does not support DM; please run it in a server.", hidden=True) raise CancelCommand try: await command.check_permissions(author, guild, locale, dm=dm, **subcommand_attrs) except PermissionError as e: if subcommand_attrs.get("allow_bypass"): CommandArgs.has_permission = False elif command.permissions.allow_bypass: CommandArgs.has_permission = False else: await response.error(e, hidden=True) raise CancelCommand except Message as e: message_type = "send" if e.type == "info" else e.type response_fn = getattr(response, message_type, response.send) if e.message: await response_fn(e, hidden=True) if subcommand_attrs.get("allow_bypass"): CommandArgs.has_permission = False elif command.permissions.allow_bypass: CommandArgs.has_permission = False else: raise CancelCommand else: CommandArgs.has_permission = True
def username_and_discriminator_to_userid(cls, username: str, discriminator: str) -> str: return find( lambda m: m.name == username and m.discriminator == discriminator, DiscordBackend.client.get_all_members())
def find_channel(guild, channel='geral'): return utils.find(lambda g: g.name == channel, guild.text_channels)
async def remove_role_from_user(self, channel, user_id, role_name): member = find(lambda m: m.id == user_id, self.get_guild().members) await self.remove_role_from_member(member, role_name)
async def add_role_to_user(self, channel, user_id, role_name): member = find(lambda m: m.id == user_id, self.get_guild().members) await self.add_role_to_member(member, role_name)
async def on_guild_join(guild): general = find(lambda x: x.name == 'bots', guild.text_channels) if general and general.permissions_for(guild.me).send_messages: await general.send( 'Hello {}! Press !help for a full list of commands'.format( guild.name))
async def on_guild_join(guild): general = find(lambda x: x.name == 'general', guild.text_channels) if general and general.permissions_for(guild.me).send_messages: await general.send( 'Hello {}! Glad to be here :grinning: \n\nPlease enter the channel ID with the command $id [channelId] to set the annoucements channel' .format(guild.name))
async def __main__(self, CommandArgs): guild = CommandArgs.guild response = CommandArgs.response guild_data = CommandArgs.guild_data trello_board = CommandArgs.trello_board prefix = CommandArgs.prefix author = CommandArgs.author locale = CommandArgs.locale role_binds_trello, group_ids_trello, trello_binds_list = await get_binds( guild=guild, trello_board=trello_board) bind_count = count_binds(guild_data, role_binds=role_binds_trello, group_ids=group_ids_trello) if bind_count >= FREE_BIND_COUNT: profile, _ = await get_features(Object(id=guild.owner_id), guild=guild) if not profile.features.get("premium"): raise Error( locale("commands.bind.errors.noPremiumBindLimitExceeded", prefix=prefix, free_bind_count=FREE_BIND_COUNT, prem_bind_count=PREM_BIND_COUNT)) if bind_count >= PREM_BIND_COUNT: raise Error( locale("commands.bind.errors.premiumBindLimitExceeded", prefix=prefix, prem_bind_count=PREM_BIND_COUNT)) parsed_args = await CommandArgs.prompt([{ "prompt": f"{locale('commands.bind.prompts.bindTypePrompt.line_1', arrow=ARROW)}\n" f"{locale('commands.bind.prompts.bindTypePrompt.line_2', arrow=ARROW)}\n" f"{locale('commands.bind.prompts.bindTypePrompt.line_3', arrow=ARROW)}\n" f"{locale('commands.bind.prompts.bindTypePrompt.line_4', arrow=ARROW)}\n" f"{locale('commands.bind.prompts.bindTypePrompt.line_5', arrow=ARROW)}", "name": "bind_choice", "type": "choice", "choices": locale("commands.bind.prompts.bindTypePrompt.choices"), "formatting": False }, { "prompt": locale("commands.bind.prompts.nicknamePrompt.line", prefix=prefix, nickname_templates=NICKNAME_TEMPLATES), "name": "nickname", "max": 100, "type": "string", "footer": locale("commands.bind.prompts.nicknamePrompt.footer"), "formatting": False }, { "prompt": "Should any roles be **removed from the user** if they meet the bind conditions? You can specify multiple roles.\n\n" "Note that this is an **advanced option**, so you most likely should `skip` this.", "name": "remove_roles", "multiple": True, "type": "role", "max": 10, "exceptions": ("skip", ), "footer": "Say **skip** to skip this option." }]) bind_choice = parsed_args["bind_choice"].lower() nickname = parsed_args["nickname"] if "display-name" in nickname: display_name_confirm = (await CommandArgs.prompt([{ "prompt": "**Warning!** You chose Display Names for your Nickname Template.\n" "Display Names **aren't unique** and can **lead to impersonation.** Are you sure you want to use this? yes/no", "type": "choice", "choices": ("yes", "no"), "name": "confirm", "embed_title": "Display Names Confirmation", "embed_color": BROWN_COLOR, "formatting": False }]))["confirm"] if display_name_confirm == "no": raise CancelledPrompt remove_roles = [str(r.id) for r in parsed_args["remove_roles"] ] if parsed_args["remove_roles"] != "skip" else [] remove_roles_trello = [ str(r) for r in parsed_args["remove_roles"] ] if parsed_args["remove_roles"] != "skip" else [] if trello_board: trello_binds_list = await trello_board.get_list( lambda l: l.name.lower() == "bloxlink binds") if not trello_binds_list: try: trello_binds_list = await trello_board.create_list( name="Bloxlink Binds") except TrelloUnauthorized: await response.error( locale("commands.bind.errors.trelloError")) except (TrelloNotFound, TrelloBadRequest): pass trello_card_binds, _ = await parse_trello_binds( trello_board=trello_board, trello_binds_list=trello_binds_list) else: trello_binds_list = None trello_group_bind = None trello_card_binds = { "groups": { "entire group": {}, "binds": {} }, "assets": {}, "badges": {}, "gamePasses": {} } if nickname.lower() in (locale("prompt.skip"), locale("prompt.done"), locale("prompt.next")): nickname = None nickname_lower = None else: nickname_lower = nickname.lower() if bind_choice == locale("commands.bind.group"): parsed_args_group = await CommandArgs.prompt([{ "prompt": locale("commands.bind.prompts.groupPrompt.line"), "name": "group", "validation": self.validate_group }, { "prompt": f"{locale('commands.bind.prompts.groupBindMode.line_1', arrow=ARROW)}\n" f"{locale('commands.bind.prompts.groupBindMode.line_2', arrow=ARROW)}\n" f"{locale('commands.bind.prompts.groupBindMode.line_3', arrow=ARROW)}", "name": "type", "type": "choice", "choices": locale("commands.bind.prompts.groupBindMode.choices") }]) group = parsed_args_group["group"] group_id = group.group_id group_ids = guild_data.get("groupIDs", {}) found_group = trello_card_binds["groups"]["entire group"].get( group_id) or group_ids.get(group_id) trello_group_bind = trello_card_binds["groups"][ "entire group"].get(group_id) if parsed_args_group["type"] == locale( "commands.bind.entireGroup"): if found_group: if (nickname and found_group["nickname"] != nickname) or ( sorted(remove_roles) != sorted( found_group.get("removeRoles", []))): group_ids[group_id] = { "nickname": nickname, "groupName": group.name, "removeRoles": remove_roles } guild_data["groupIDs"] = group_ids await self.r.table("guilds").insert( guild_data, conflict="update").run() trello_group_bind = trello_card_binds["groups"][ "entire group"].get(group_id) make_trello_card = True if trello_group_bind and trello_group_bind["nickname"]: for card_data in trello_group_bind["trello"].get( "cards", []): card = card_data["card"] try: await card.edit( desc=card.description.replace( trello_group_bind["nickname"], nickname or 'None')) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass make_trello_card = False if make_trello_card: card_bind_data = [ f"Group: {group_id}", f"Nickname: {nickname}" ] if remove_roles: card_bind_data.append( f"Remove roles: {', '.join(remove_roles_trello)}" ) try: await trello_binds_list.create_card( name="Bloxlink Group Bind", desc="\n".join(card_bind_data)) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass if trello_binds_list: trello_binds_list.parsed_bind_data = None ending_s = group.name.endswith("s") and "'" or "'s" await post_event( guild, guild_data, "bind", f"{author.mention} ({author.id}) has **changed** `{group.name}`{ending_s} nickname template.", BLURPLE_COLOR) await clear_guild_data(guild) raise Message( "Since your group is already linked, the nickname was updated.", type="success") else: raise Message("This group is already linked!", type="silly") for _, roleset_data in group.rolesets.items(): discord_role = find(lambda r: r.name == roleset_data[0], guild.roles) if not discord_role: try: discord_role = await guild.create_role( name=roleset_data[0]) except Forbidden: raise PermissionError( "I was unable to create the Discord role. Please ensure my role has the `Manage Roles` permission." ) # add group to guild_data.groupIDs group_ids[group_id] = { "nickname": nickname not in ("skip", "next") and nickname, "groupName": group.name, "removeRoles": remove_roles } guild_data["groupIDs"] = group_ids await self.r.table("guilds").insert(guild_data, conflict="update").run() if trello_binds_list: card_bind_data = [ f"Group: {group_id}", f"Nickname: {nickname}" ] if remove_roles: card_bind_data.append( f"Remove roles: {', '.join(remove_roles_trello)}") try: await trello_binds_list.create_card( name="Bloxlink Group Bind", desc="\n".join(card_bind_data)) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass await post_event( guild, guild_data, "bind", f"{author.mention} ({author.id}) has **linked** group `{group.name}`.", BLURPLE_COLOR) await clear_guild_data(guild) raise Message("Success! Your group was successfully linked.", type="success") else: # select ranks from their group # ask if they want to auto-create the binds or select a specific role # shows confirmation embed with arrows from rank to discord role discord_role = await CommandArgs.prompt([{ "prompt": "Please provide **Discord role name(s)** for this bind, separated by commas.", "name": "role", "type": "role", "multiple": True, "max": 10 }]) discord_roles = discord_role["role"] new_ranks = {"binds": [], "ranges": []} role_binds = guild_data.get("roleBinds") or {} if isinstance(role_binds, list): role_binds = role_binds[0] role_binds["groups"] = role_binds.get("groups") or { } # {"groups": {"ranges": {}, "binds": {}}} role_binds["groups"][group_id] = role_binds["groups"].get( group_id) or {} role_binds["groups"][group_id]["binds"] = role_binds["groups"][ group_id].get("binds") or {} role_binds["groups"][group_id]["ranges"] = role_binds[ "groups"][group_id].get("ranges") or {} role_binds["groups"][group_id]["groupName"] = group.name role_binds["groups"][group_id]["removeRoles"] = remove_roles rolesets_embed = Embed(title=f"{group.name} Rolesets", description="\n".join( f"**{x[0]}** {ARROW} {x[1]}" for x in group.rolesets.values())) rolesets_embed = await CommandArgs.response.send( embed=rolesets_embed) response.delete(rolesets_embed) failures = 0 while True: if failures == 5: raise Error( "Too many failed attempts. Please run this command again." ) selected_ranks = await CommandArgs.prompt([{ "prompt": f"Please select the rolesets that should receive the role(s) **{', '.join([r.name for r in discord_roles])}**. " "You may specify the roleset name or ID. You may provide them in a list, " "or as a range. You may also say `everyone` to capture everyone in the group; " "and you can negate the number to catch everyone with the rank _and above._\n" "You can also say `guest` to include **all non-group members**.\n\n" "Example 1: `1,4,-6,VIP, 10, 50-100, Staff Members, 255`.\nExample 2: `" "-100` means everyone with rank 100 _and above._\nExample 3: `everyone` " "means everyone in the group.\n\n" "For your convenience, your Rolesets' names and IDs were sent above.", "name": "ranks", "formatting": False }], last=True) for rank in selected_ranks["ranks"].split(","): rank = rank.strip() if rank.isdigit() and rank != "0": if 1 <= int(rank) <= 255: new_ranks["binds"].append(str(rank)) else: response.delete(await response.error( "Ranks must be an integer between [1-255]" )) failures += 1 break elif rank in ("all", "everyone"): new_ranks["binds"].append("all") elif rank in ("0", "guest"): new_ranks["binds"].append("0") elif rank[:1] == "-": try: int(rank) except ValueError: pass else: new_ranks["binds"].append(rank) else: range_search = bind_num_range.search(rank) if range_search: num1, num2 = range_search.group( 1), range_search.group(2) if (1 <= int(num1) <= 255) and (1 <= int(num2) <= 255): new_ranks["ranges"].append([num1, num2]) else: response.delete(await response.error( "Ranges must be between [1-255].")) failures += 1 break else: # they specified a roleset name as a string roleset_find = group.rolesets.get(rank.lower()) if roleset_find: new_ranks["binds"].append( str(roleset_find[1])) else: response.delete(await response.error( "Could not find a matching Roleset name. Please try again." )) failures += 1 break else: break if new_ranks["binds"]: for x in new_ranks["binds"]: rank = role_binds["groups"][group_id].get("binds", {}).get( x, {}) if not isinstance(rank, dict): rank = { "nickname": nickname_lower, "roles": [str(rank)], "removeRoles": remove_roles } for discord_role in discord_roles: role_id = str(discord_role.id) if role_id not in rank["roles"]: rank["roles"].append(role_id) else: for discord_role in discord_roles: role_id = str(discord_role.id) if role_id not in rank.get("roles", []): rank["roles"] = rank.get("roles") or [] rank["roles"].append(role_id) if nickname_lower: rank["nickname"] = nickname else: if not rank.get("nickname"): rank["nickname"] = None rank["removeRoles"] = remove_roles role_binds["groups"][group_id]["binds"][x] = rank # trello binds: # rank is in list of ranks # update nickname # append role # else: make new card if trello_binds_list: make_binds_card = True if trello_card_binds: trello_bind_group = trello_card_binds[ "groups"]["binds"].get(group_id, {}).get("binds") if trello_bind_group: card_data_ = trello_bind_group.get(x) if card_data_: for card in card_data_.get( "trello", {}).get("cards", []): trello_card = card["card"] trello_ranks = card.get( "ranks") or [] if (x in trello_ranks or x == "all" ) and len(trello_ranks) == 1: trello_bind_roles = card.get( "roles", set()) card_bind_data = [ f"Group: {group_id}", f"Nickname: {(nickname != 'skip' and nickname) or rank.get('nickname') or card_data_.get('nickname') or 'None'}", ] if remove_roles: card_bind_data.append( f"Remove roles: {', '.join(remove_roles_trello)}" ) for discord_role in discord_roles: trello_bind_roles.add( discord_role.name) card_bind_data.append( f"Roles: {', '.join(trello_bind_roles)}" ) card_bind_data.append( f"Ranks: {card['trello_str']['ranks']}" ) trello_card_desc = "\n".join( card_bind_data) if trello_card_desc != trello_card.description: trello_card.description = trello_card_desc try: await trello_card.edit( desc=trello_card_desc ) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass trello_binds_list.parsed_bind_data = None make_binds_card = False break if make_binds_card: card_bind_data = [ f"Group: {group_id}", f"Nickname: {nickname != 'skip' and nickname or 'None'}", f"Roles: {', '.join([r.name for r in discord_roles])}", ] if remove_roles: card_bind_data.append( f"Remove roles: {', '.join(remove_roles_trello)}" ) if x != "all": card_bind_data.append(f"Ranks: {x}") trello_card_desc = "\n".join(card_bind_data) try: card = await trello_binds_list.create_card( name="Bloxlink Bind", desc=trello_card_desc) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass trello_binds_list.parsed_bind_data = None if new_ranks["ranges"]: role_binds["groups"][group_id]["ranges"] = role_binds[ "groups"][group_id].get("ranges") or [] for x in new_ranks[ "ranges"]: # list of dictionaries: [{"high": 10, "low": 1, "nickname": ""},...] range_, num = self.find_range( x, role_binds["groups"][group_id]["ranges"]) found = bool(range_) for discord_role in discord_roles: role_id = str(discord_role.id) if not role_id in range_.get("roles", []): range_["roles"] = range_.get("roles") or [] range_["roles"].append(role_id) if nickname_lower: range_["nickname"] = nickname else: if not range_.get("nickname"): range_["nickname"] = None range_["removeRoles"] = remove_roles if found: role_binds["groups"][group_id]["ranges"][ num] = range_ else: range_["low"] = int(x[0]) range_["high"] = int(x[1]) role_binds["groups"][group_id]["ranges"].append( range_) if trello_binds_list: make_binds_card = True if trello_card_binds: trello_range_group = trello_card_binds[ "groups"]["binds"].get(group_id, {}).get("ranges") if trello_range_group: for trello_range in trello_range_group: trello_data = trello_range["trello"] for card in trello_data.get( "cards", []): trello_card = card["card"] trello_ranks = card.get( "ranks", []) if trello_range["low"] == range_[ "low"] and trello_range[ "high"] == range_[ "high"] and len( trello_ranks ) == 1: trello_data = trello_range[ "trello"] trello_bind_roles = trello_range.get( "roles", set()) card_bind_data = [ f"Group: {group_id}", f"Nickname: {(nickname != 'skip' and nickname) or trello_range.get('nickname') or 'None'}", ] if remove_roles: card_bind_data.append( f"Remove roles: {', '.join(remove_roles_trello)}" ) for discord_role in discord_roles: trello_bind_roles.add( discord_role.name) card_bind_data.append( f"Roles: {', '.join(trello_bind_roles)}" ) card_bind_data.append( f"Ranks: {card['trello_str']['ranks']}" ) trello_card_desc = "\n".join( card_bind_data) if trello_card_desc != trello_card.description: trello_card.description = trello_card_desc try: await trello_card.edit( desc=trello_card_desc ) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass trello_binds_list.parsed_bind_data = None make_binds_card = False break if make_binds_card: card_bind_data = [ f"Group: {group_id}", f"Nickname: {nickname != 'skip' and nickname or 'None'}", f"Roles: {', '.join([r.name for r in discord_roles])}", f"Ranks: {range_['low']}-{range_['high']}" ] if remove_roles: card_bind_data.append( f"Remove roles: {', '.join(remove_roles_trello)}" ) trello_card_desc = "\n".join(card_bind_data) try: card = await trello_binds_list.create_card( name="Bloxlink Range Bind", desc=trello_card_desc) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass trello_binds_list.parsed_bind_data = None await self.r.table("guilds").insert( { "id": str(guild.id), "roleBinds": role_binds }, conflict="update").run() text = ["Successfully **bound** rank ID(s): `"] if new_ranks["binds"]: text.append(", ".join(new_ranks["binds"])) if new_ranks["ranges"]: text2 = "" if new_ranks["binds"]: text2 = "; " text.append( f"{text2}ranges: {', '.join([r[0] + ' - ' + r[1] for r in new_ranks['ranges']])}" ) text.append( f"` with Discord role(s) **{', '.join([r.name for r in discord_roles])}**." ) text = "".join(text) await post_event( guild, guild_data, "bind", f"{author.mention} ({author.id}) has **bound** group `{group.name}`.", BLURPLE_COLOR) await clear_guild_data(guild) await response.success(text) elif bind_choice in ("asset", "badge", "gamepass"): if bind_choice == "gamepass": bind_choice_title = "GamePass" bind_choice_plural = "gamePasses" else: bind_choice_title = bind_choice.title() bind_choice_plural = f"{bind_choice}s" vg_parsed_args = await CommandArgs.prompt([ { "prompt": f"Please provide the **{bind_choice_title} ID** to use for this bind.", "name": "bind_id", "type": "number", "formatting": False }, { "prompt": "Please provide **Discord role name(s)** for this bind, separated by commas.", "name": "role", "type": "role", "multiple": True, "max": 10 }, ], last=True) discord_roles = vg_parsed_args["role"] bind_id = str(vg_parsed_args["bind_id"]) if bind_choice == "asset": try: text, response_ = await fetch( f"{API_URL}/marketplace/productinfo?assetId={bind_id}") except RobloxNotFound: raise Error( f"An Asset with ID `{bind_id}` does not exist.") json_data = await response_.json() display_name = json_data.get("Name") elif bind_choice == "badge": try: text, response_ = await fetch( f"https://badges.roblox.com/v1/badges/{bind_id}") except RobloxNotFound: raise Error(f"A Badge with ID `{bind_id}` does not exist.") json_data = await response_.json() display_name = json_data.get("displayName") elif bind_choice == "gamepass": bind_choice_title = "GamePass" bind_choice_plural = "gamePasses" try: text, response_ = await fetch( f"http://api.roblox.com/marketplace/game-pass-product-info?gamePassId={bind_id}" ) except (RobloxNotFound, RobloxAPIError): raise Error( f"A GamePass with ID `{bind_id}` does not exist.") json_data = await response_.json() if json_data.get("ProductType") != "Game Pass": raise Error( f"A GamePass with ID `{bind_id}` does not exist.") display_name = json_data.get("Name") role_binds = guild_data.get("roleBinds") or {} if isinstance(role_binds, list): role_binds = role_binds[0] role_binds[bind_choice_plural] = role_binds.get( bind_choice_plural) or {} role_binds[bind_choice_plural][ bind_id] = role_binds[bind_choice_plural].get(bind_id) or {} role_binds[bind_choice_plural][bind_id]["nickname"] = nickname role_binds[bind_choice_plural][bind_id][ "displayName"] = display_name role_binds[bind_choice_plural][bind_id][ "removeRoles"] = remove_roles role_binds[bind_choice_plural][bind_id]["roles"] = role_binds[ bind_choice_plural][bind_id].get("roles", []) roles = role_binds[bind_choice_plural][bind_id]["roles"] for discord_role in discord_roles: role_id = str(discord_role.id) if not role_id in roles: roles.append(role_id) role_binds[bind_choice_plural][bind_id]["roles"] = roles if trello_binds_list: make_binds_card = True if trello_card_binds: trello_bind_vg = trello_card_binds.get( bind_choice_plural, {}).get(bind_id) if trello_bind_vg: trello_bind_roles = set( trello_bind_vg.get("roles", set())) for card in trello_bind_vg.get("trello", {})["cards"]: trello_card = card["card"] card_bind_data = [ f"{bind_choice_title} ID: {bind_id}", f"Display Name: {display_name}", f"Nickname: {(nickname != 'skip' and nickname) or trello_bind_vg.get('nickname') or 'None'}", ] for discord_role in discord_roles: trello_bind_roles.add(discord_role.name) card_bind_data.append( f"Roles: {', '.join(trello_bind_roles)}") trello_card_desc = "\n".join(card_bind_data) if trello_card_desc != trello_card.description: trello_card.description = trello_card_desc try: await trello_card.edit( desc=trello_card_desc) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass trello_binds_list.parsed_bind_data = None make_binds_card = False break if make_binds_card: card_bind_data = [ f"{bind_choice_title} ID: {bind_id}", f"Display Name: {display_name}", f"Nickname: {nickname != 'skip' and nickname or 'None'}", f"Roles: {', '.join([d.name for d in discord_roles])}", ] if remove_roles: card_bind_data.append( f"Remove roles: {', '.join(remove_roles_trello)}") trello_card_desc = "\n".join(card_bind_data) try: card = await trello_binds_list.create_card( name=f"Bloxlink {bind_choice_title} Bind", desc=trello_card_desc) except TrelloUnauthorized: await response.error( "In order for me to edit your Trello binds, please add `@bloxlink` to your " "Trello board.") except (TrelloNotFound, TrelloBadRequest): pass trello_binds_list.parsed_bind_data = None await self.r.table("guilds").insert( { "id": str(guild.id), "roleBinds": role_binds }, conflict="update").run() await post_event( guild, guild_data, "bind", f"{author.mention} ({author.id}) has **bound** {bind_choice_title} `{display_name}`.", BLURPLE_COLOR) await clear_guild_data(guild) await response.success( f"Successfully **bound** {bind_choice_title} `{display_name}` ({bind_id}) with Discord role(s) **{', '.join([r.name for r in discord_roles])}!**" )
async def __main__(self, CommandArgs): author = CommandArgs.author response = CommandArgs.response prefix = CommandArgs.prefix if not SELF_HOST: author_data = await self.r.db("bloxlink").table("users").get( str(author.id)).run() or { "id": str(author.id) } try: primary_account, accounts = await get_user("username", author=author, everything=False, basic_details=True) if accounts: parsed_accounts = await parse_accounts(accounts) parsed_accounts_str = ", ".join(parsed_accounts.keys()) parsed_args = await CommandArgs.prompt([{ "prompt": "This command will allow you to switch into an account you verified as in the past.\n" f"If you would like to link __a new account__, then please use `{prefix}verify add`.\n\n" "**__WARNING:__** This will remove __all of your roles__ in the server and give you " "new roles depending on the server configuration.", "footer": "Say **next** to continue.", "type": "choice", "choices": ["next"], "name": "_", "formatting": False }, { "prompt": "Are you trying to change your account for _this_ server? If so, simply say `next`.\nIf not, please provide " "the __Server ID__ of the server to switch as. Please see this article to find the Server ID: " "[click here](https://support.discordapp.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID->).", "name": "guild", "validation": self.validate_server, }, { "prompt": "We'll switch your account for the server **{guild.name}**.\n" "Please select an account to switch into:```" + parsed_accounts_str + "```", "name": "account", "type": "choice", "choices": list(parsed_accounts.keys()) }, { "prompt": "Would you like to make this your __primary__ account? Please say **yes** or **no**.", "name": "primary", "type": "choice", "choices": ("yes", "no") }], last=True) guild = parsed_args["guild"] username = parsed_args["account"] roblox_id = (parsed_accounts.get(username)).id guild_data = await self.r.table("guilds").get(str( guild.id)).run() or { "id": str(guild.id) } trello_board = await get_board(guild_data=guild_data, guild=guild) if trello_board: options_trello, _ = await get_options(trello_board) guild_data.update(options_trello) allow_reverify = guild_data.get( "allowReVerify", DEFAULTS.get("allowReVerify")) roblox_accounts = author_data.get("robloxAccounts", {}) if guild and not allow_reverify: guild_accounts = roblox_accounts.get("guilds", {}) chosen_account = guild_accounts.get(str(guild.id)) if chosen_account and chosen_account != roblox_id: raise Error( "You already selected your account for this server. `allowReVerify` must be " "enabled for you to change it.") try: member = await guild.fetch_member(author.id) except (Forbidden, NotFound): await verify_member( author, roblox_id, guild=guild, author_data=author_data, allow_reverify=allow_reverify, primary_account=parsed_args["primary"] == "yes") raise Message( "You're not a member of the provided server, so I was only able to update your account internally.", type="success") try: username = await verify_as( member, guild, response=response, primary=parsed_args["primary"] == "yes", roblox_id=roblox_id, trello_board=trello_board, update_user=False) except Message as e: if e.type == "error": await response.error(e) else: await response.send(e) except Error as e: await response.error(e) else: role_binds, group_ids, _ = await get_binds( guild_data=guild_data, trello_board=trello_board) if count_binds( guild_data, role_binds=role_binds, group_ids=group_ids) and not find( lambda r: r.name == "Bloxlink Bypass", member.roles): for role in list(member.roles): if role != guild.default_role and role.name != "Muted": try: await member.remove_roles( role, reason="Switched User") except Forbidden: pass try: added, removed, nickname, errors, warnings, roblox_user = await update_member( member, guild=guild, roles=True, nickname=True, response=response, cache=False) except BloxlinkBypass: await response.info( "Since you have the `Bloxlink Bypass` role, I was unable to update your roles/nickname; however, your account was still changed." ) return except Blacklisted as b: if isinstance(b.message, str): raise Error( f"{author.mention} has an active restriction for: `{b}`." ) else: raise Error( f"{author.mention} has an active restriction from Bloxlink." ) else: welcome_message = guild_data.get( "welcomeMessage") or DEFAULTS.get( "welcomeMessage") welcome_message = await get_nickname( author, welcome_message, guild_data=guild_data, roblox_user=roblox_user, is_nickname=False) await post_event( guild, guild_data, "verification", f"{author.mention} ({author.id}) has **switched their user** to `{username}`.", GREEN_COLOR) await CommandArgs.response.send(welcome_message) else: raise Message( f"You only have one account linked! Please use `{prefix}verify add` to add another.", type="info") except UserNotVerified: raise Error( f"You're not linked to Bloxlink. Please use `{prefix}verify add`." ) else: raise Message(f"{author.mention}, to verify with Bloxlink, please visit our website at " \ f"<{VERIFY_URL}>. It won't take long!\nStuck? See this video: <https://www.youtube.com/watch?v=hq496NmQ9GU>")
async def launch_santa(context): """ Quick note about Discord user mentions before you read this function: Discord users all have a unique ID that can be used to mention them as if you were to @ their name. I'll call this the user mention. It looks something like this: <@162606971705491458> or <@!179067358369939456> Your user mention may or may not have an '!' as it's third character. This is dynamic as far as I know. Because of this, user-rsn pairs are saved by the bot based on your ID number, not the extraneous symbols. When creating SENDER_LIST, the bot looks up users based on their mention. There is a check in there that removes the extra '!' if the user does not have one in their mention """ user_roles = context.message.author.roles #gets user role list for role in user_roles: #loops through user roles if '🗝️ FiH Leader' == role.name: #checks if user has role to use command santa_file = open('secret_santa.txt', 'r') #opens secret santa roster participants = santa_file.read() #reads in participant list (set of RSNs) santa_file.close() #closes secret santa roster participant_list = participants.split('\n') #splits participants into list participant_users = [] #creates user array for p in participant_list: #loops through participant list user = get_user(p) #gets the user associated with given RSN if user is not None: #checks if RSN has been claimed by a user participant_users.append(user) #adds user to participant list JAYCOLE = find(lambda m: m.mention == get_user("Jaycole"), context.message.channel.server.members) #stores info for me for testing purposes if JAYCOLE is None: #check if it used the wrong mention j_user = get_user("Jaycole") #gets my user mention again j_user = re.sub("!", "", j_user) #removes ! from mention JAYCOLE = find(lambda m: m.mention == j_user, context.message.channel.server.members) #re-saves me SENDER_LIST = [] #initialize sender list, which will be an array of Members # Member is a subclass of User, member is a Member # participant_users is an array of mentions for p in participant_users: #loop through participants member = find(lambda m: m.mention == p, context.message.channel.server.members) #find the person's User based on their mention if member is None: #checks if it used the wrong mention p = re.sub("!", "", p) #removes ! from mention member = find(lambda m: m.mention == p, context.message.channel.server.members) #re checks for User based on new mention SENDER_LIST.append(member) #adds user to sender list receivers = participant_list #stores receivers as a pointer to participant list so I don't have to read in twice. f = open("santa_log.txt", "w+") #opens log file for user in SENDER_LIST: s = random.uniform(0, receivers.__len__()) #gets random value within list bounds s = round(s) #rounds random number to a usable index receiver = receivers[s - 1] #gets receiver at that index while receiver == get_rsn(user.mention) and receiver is not None: #redraws if user gets themself or an error s = random.uniform(0, receivers.__len__()) s = round(s) receiver = receivers[s - 1] receivers.pop(s - 1) #removes receiver from list try: #tries to send target to user await client.send_message(user, "Hey " + get_rsn(user.mention) + ", Your secret santa target is " + receiver + "!") except: #catches if user private messages are set to private, sends target to me await client.send_message(JAYCOLE, "Hey " + get_rsn(user.mention) + ", your secret santa target is " + receiver + "!") #await client.send_message(JAYCOLE, "Hey " + get_rsn(user.mention) + ", your secret santa target is " + receiver + "!") - test line to send all targets to me to test function f.write((user.name + " got " + receiver + '\n')) #writes matches to log time.sleep(1) #waits one second to avoid overrunning action limits f.close() #closes santa log await client.say("Secret Santa targets have been sent out! Check your inbox for your person!") #announces that santa targets have been sent.
async def on_guild_join(guild): starboard = find(lambda x: x.name == 'starboard', guild.text_channels) if not starboard: await guild.create_text_channel('starboard')
def get_channel(i): p_i = C.channels[i] if i in C.channels else i return (C.client.get_channel(p_i) or C.client.get_channel( p_i.translate(C.punct2space).replace(' ', '')) or find(C.client.get_all_channels(), name=i) or find(C.client.get_all_channels(), name=i.replace('#', '')))
async def __main__(self, CommandArgs): prefix = CommandArgs.prefix guild = CommandArgs.message.guild response = CommandArgs.response my_permissions = guild.me.guild_permissions if not (my_permissions.manage_channels and my_permissions.manage_roles): raise Error( "I need both the ``Manage Channels`` and ``Manage Roles`` permissions." ) setup_args = await CommandArgs.prompt([{ "prompt": "**Thank you for choosing Bloxlink!** In a few simple prompts, **we'll configure this add-on " "for your server.**\n\n**The Court Add-on**\nThis add-on allows you to assign judges which have " "the power to create cases within your Discord server. Created cases reside in Discord channels where " "the messages are all saved and can be exported later.", "name": "_", "footer": "Say **next** to continue.", "type": "choice", "choices": ["next"], "embed_title": "Setup Prompt" }, { "prompt": "Which **role(s)** are considered the ``Judge`` roles? Members with these roles will be able to " "create new cases and use certain judicial administrative commands.", "name": "judge_roles", "type": "role", "multiple": True, "embed_title": "Setup Prompt" }, { "prompt": "Which ``channel`` would you like to use for logging case events?", "name": "log_channel", "footer": "Say **skip** to skip this step.", "exceptions": ("skip", ), "type": "channel", }, { "prompt": "Which ``category`` would you like to use for archiving closed cases? If you skip this, then old cases " "will simply be deleted.", "name": "archive_category", "footer": "Say **skip** to skip this step.", "exceptions": ("skip", ), "type": "category", }, { "prompt": "Please specify the **groups** to use with your set-up.\n\nA group holds members for each trial. For example, typical groups " "for a USA style court room include the ``prosecution``, ``defence``, ``jurors``, and ``witnesses``. Please **give a list separated by " "commas** of your group names.\n\nFor example, you may write: ``prosecution, defense, jurors``\n\nJudges will be able to add people into these groups to fit their trial.\n\n__It's fine if you include groups " "which aren't used__, groups __can be__ blank. ", "name": "groups", "type": "list", }], last=True) judge_roles = setup_args["judge_roles"] log_channel = setup_args["log_channel"] groups = setup_args["groups"] archive_category = setup_args["archive_category"] addon_data = await self.r.table("addonData").get(str(guild.id) ).run() or {} court_data = addon_data.get("court") or {} category = None create_category = False if archive_category != "skip": overwrites = { guild.default_role: PermissionOverwrite(read_messages=False), guild.me: PermissionOverwrite(read_messages=True), } overwrites.update({ k: PermissionOverwrite(read_messages=True) for k in judge_roles }) try: await archive_category.edit(overwrites=overwrites) except Forbidden: raise Error( "I need both the ``Manage Channels`` and ``Manage Roles`` permissions." ) if court_data.get("category"): category = find(lambda c: c.id == int(court_data["category"]), guild.categories) if not category: create_category = True else: create_category = True if create_category: overwrites = { guild.default_role: PermissionOverwrite(read_messages=False), guild.me: PermissionOverwrite(read_messages=True), } overwrites.update({ k: PermissionOverwrite(read_messages=True) for k in judge_roles }) try: category = find(lambda c: c.name == "Cases", guild.categories) or \ await guild.create_category("Cases", overwrites=overwrites) except Forbidden: raise Error( "I need both the ``Manage Channels`` and ``Manage Roles`` permissions." ) addon_data["court"] = { "judgeRoles": [str(x.id) for x in judge_roles], "logChannel": str(log_channel.id) if log_channel != "skip" else None, "archiveCategory": str(archive_category.id) if archive_category != "skip" else None, "category": str(category.id) if category else None, "groups": groups } await self.r.table("addonData").insert( { "id": str(guild.id), **addon_data }, conflict="update").run() embed = Embed( title="Additional Information", description= f"- Use ``{prefix}case create`` to make a new case chat.\n" "- Need to change your groups? You will need to run this command again.\n" f"- It's recommended to give your cases IDs! You'll be able to run ``{prefix}case lookup`` to find its information.\n" f"- You will need to add case members with ``{prefix}case add`` and assign them to a group. Remove them with ``{prefix}case remove``.\n" f"- Run ``{prefix}case end`` inside your case chat to archive the case.\n" f"- If you manually delete case channels, then you will need to run ``{prefix}case cleanup`` to free them from the database; otherwise, they will count against your case limit.\n" f"- Case members can be easily muted/unmuted with ``{prefix}case mute`` or ``{prefix}case unmute``." ) await response.send(embed=embed) await response.success( f"Successfully saved your **Court add-on!** Now, judges (people with the {', '.join([r.mention for r in judge_roles])} role(s)) will be " f"able to run ``{prefix}case create`` to create a new case chat.", allowed_mentions=AllowedMentions(roles=False))
def on_member_remove(member): channel = find(lambda chan: chan.name == 'public', member.server.channels) client.send_message(channel, '{name} has left the server.'.format(name=member))
async def parse_message(self, message, guild_data=None): guild = message.guild content = message.content author = message.author channel = message.channel if guild: guild_restriction = await get_restriction("guilds", guild.id) if guild_restriction: await guild.leave() raise CancelCommand guild_permissions = guild and guild.me.guild_permissions channel_id = channel and str(channel.id) guild_id = guild and str(guild.id) trello_board = guild and await get_board(guild) prefix, _ = await get_prefix(guild, trello_board) client_match = re.search(f"<@!?{self.client.user.id}>", content) check = (content[:len(prefix)].lower() == prefix.lower() and prefix) or client_match and client_match.group(0) check_verify_channel = False if check: after = content[len(check):].strip() args = after.split(" ") command_name = args[0] and args[0].lower() del args[0] if command_name: for index, command in commands.items(): if index == command_name or command_name in command.aliases: guild_data = guild_data or ( guild and (await self.r.table("guilds").get(guild_id).run() or { "id": guild_id })) or {} fn = command.fn subcommand_attrs = {} subcommand = False if args: # subcommand checking subcommand = command.subcommands.get(args[0]) if subcommand: fn = subcommand subcommand_attrs = getattr( fn, "__subcommandattrs__", None) del args[0] after = args and " ".join(args) or "" CommandArgs = Args(command_name=index, real_command_name=command_name, message=message, channel=message.channel, author=message.author, guild=message.guild, guild_data=guild_data, flags={}, prefix=prefix, has_permission=False, command=command) if getattr(fn, "__flags__", False): flags, flags_str = command.parse_flags(after) content = content.replace(flags_str, "") message.content = content after = after.replace(flags_str, "") CommandArgs.flags = flags locale = Locale( guild_data and guild_data.get("locale", "en") or "en") response = Response(CommandArgs, author, channel, guild, message, slash_command=False) CommandArgs.add(locale=locale, response=response, trello_board=trello_board) await self.command_checks(command, prefix, response, guild_data, author, channel, locale, CommandArgs, message, guild, subcommand_attrs, slash_command=False) arguments = Arguments(CommandArgs, author, channel, command, guild, message, subcommand=(subcommand, subcommand_attrs) if subcommand else None, slash_command=False) await self.execute_command(command, fn, response, CommandArgs, author, channel, arguments, locale, guild_data, guild, message, trello_board, after, False) break else: check_verify_channel = True else: check_verify_channel = True else: check_verify_channel = True if guild and guild_permissions.manage_messages: if not isinstance(author, Member): try: author = await guild.fetch_member(author.id) except NotFound: return if check_verify_channel: verify_channel_id = await get_guild_value( guild, "verifyChannel") if verify_channel_id and channel_id == verify_channel_id: if not find(lambda r: r.name in MAGIC_ROLES, author.roles): try: await message.delete() except (Forbidden, NotFound): pass
def finder(predicate, seq): data = find(predicate, seq) return data
"Set the universal nickname template. Note that `{prefix}bind` nicknames will override this." ), "unverifiedRoleName": (None, "string", 100, False, "Set the 'Unverified' role name -- the role that Unverified users get."), "shorterNicknames": (None, "boolean", None, False, "Brackets in group rank names will be captured instead of the full rank name, resulting in a shorter nickname." ), "ageLimit": (None, "number", None, True, "Set the minimum Roblox age in days a user must be to enter your server. People who are less than this value will be kicked." ), "inactiveRole": (lambda g, gd: gd.get("inactiveRole") and find(lambda r: r.id == int(gd["inactiveRole"]), g.roles), "role", None, True, "Set the role given to people who declared themselves as \"inactive\" from `{prefix}profile`." ), "banRelatedAccounts": (None, "boolean", None, True, "If this is enabled: when members are banned, their known alts are also banned from the server." ), "unbanRelatedAccounts": (None, "boolean", None, True, "If this is enabled: when members are unbanned, their known alts are also unbanned from the server." ), "disallowAlts": (None, "boolean", None, True, "If this is enabled: when someone joins the server and already has a linked account in the server, kick the old alt out." ),
async def elections_timed(Demobot): dev = False # Making the election day not wednesday for dev purposes while True: currt = datetime.now(tz=pytz.utc) nextelection = currt + timedelta((2 - currt.weekday()) % 7 + (0 if dev else 1)) nextelection = nextelection.replace(hour=2, minute=0, second=0, microsecond=0) await asyncio.sleep((nextelection - currt).total_seconds() if not dev else 1) for a in server_data: chann = nested_get(a, "channels", "announcements") citizen_m = nested_get(a, "roles", "citizen").mention tim = nextelection.astimezone( pytz.timezone('US/Pacific')).strftime('%H:%M') if chann: await Demobot.send_message( chann, citizen_m + "! Elections have now started. They end in two days at " + tim + ".") next = nested_get(a, 'channels', 'elections') if next: await Demobot.send_message( next, '```\n```\n\n**Elections Start Here**\n\n' + 'Leader: Candidate with the largest difference between up and down wins.\n' + 'Representative: Candidates with at least a third of the generic win.\n\n' + 'Click the reactions to toggle a vote. You can vote more than once.\n' + '**Remember to vote the generic!**') nested_set({}, a, 'elections', 'msg') le = nested_get(a, 'elections', 'leader') for b in le: c = await Demobot.send_message( next, '.\n\n**Leader Candidate**\n' + nested_get(a, 'elections', 'leader', b).desc + '\n\nVotes: **0 - 0**') await Demobot.add_reaction(c, '👍') await Demobot.add_reaction(c, '👎') nested_set( nested_get(a, 'elections', 'leader', b).ii, a, 'elections', 'msg', c.id) er = nested_get(a, 'elections', 'representative') out = '.\n\n**Representative Candidates**\nYou must vote the generic vote!\n\n' key = 127462 count = ('\n\nVotes: **0 | ' + '0 - ' * len(er))[:-3] + '**' for b in er: out += chr(key) + ' ' + nested_get( a, 'elections', 'representative', b).desc + '\n' nested_set( nested_get(a, 'elections', 'representative', b).ii, a, 'elections', 'msg', key) key += 1 c = await Demobot.send_message(next, out + count) await Demobot.add_reaction(c, '🗳') for d in range(127462, key): await Demobot.add_reaction(c, chr(d)) nested_set('rep', a, 'elections', 'msg', c.id) await asyncio.sleep(172800 if not dev else 1) for a in server_data: chann = nested_get(a, 'channels', 'announcements') citizen_m = nested_get(a, "roles", "citizen").mention for l in nested_get(a, 'members', 'leader'): await Demobot.remove_roles(l, nested_get(a, 'roles', 'leader')) le = nested_get(a, 'elections', 'leader') winner = 1000 user = None for b in le: c = nested_get(a, 'elections', 'leader', b) if winner == 1000 or len(c.up) - len(c.down) > winner: winner = len(c.up) - len(c.down) user = find(lambda m: m.id == c.ii, Demobot.get_server(a).members) for l in nested_get(a, 'members', 'representative'): await Demobot.remove_roles( l, nested_get(a, 'roles', 'representative')) generic = len(nested_get(a, 'elections', 'generic')) er = nested_get(a, 'elections', 'representative') users = [] nested_pop(a, 'elections', 'representatives') for b in er: c = nested_get(a, 'elections', 'representative', b) nested_set(Backup(time(), len(c.up) / generic), a, 'elections', 'backup', c.ii) if len(c.up) / generic >= 1 / 3 and not c.ii == user.id: users.append( find(lambda m: m.id == c.ii, Demobot.get_server(a).members)) secondary = [] forbid = [user.id] for b in range(max(0, 3 - len(users))): thing = next_backup(a, forbid) secondary.append( find(lambda m: m.id == thing, Demobot.get_server(a).members)) forbid.append(thing) await Demobot.remove_roles( user, nested_get(a, 'roles', 'representative')) await Demobot.add_roles(user, nested_get(a, 'roles', 'leader')) out = '' for u in users: await Demobot.add_roles( u, nested_get(a, 'roles', 'representative')) out += u.mention + ', ' out = 'No one was elected representative.\n' \ if out == '' else out[:-2] + " have been elected representative!\n" for u in secondary: await Demobot.add_roles( u, nested_get(a, 'roles', 'representative')) out += u.mention + ', ' if chann: await Demobot.send_message( chann, citizen_m + "! Elections have now ended.") await Demobot.send_message( chann, user.mention + " has been elected leader!") await Demobot.send_message( chann, out[:-2] + " have been made reps from the backup list.") if not dev: nested_set({}, a, 'elections') nested_set(set([]), a, 'elections', 'generic') await asyncio.sleep(100000)
async def on_message(self, message, **kwargs): # Things assert isinstance(message, Message) client = self.client # Prefixes prefix = kwargs.get("prefix") # Custom commands registered for the server server_commands = self.handler.get_custom_commands( message.channel.server) # Checks for server specific commands for command in server_commands: # UPDATE 2.1.4: not .startswith anymore! if str(message.content) == command: # Maybe same replacement logic in the future update? # /todo implement advanced replacement logic await client.send_message(message.channel, server_commands.get(command)) self.stats.add(MESSAGE) return if not is_valid_command(message.content, valid_commands, prefix=prefix): return else: self.stats.add(MESSAGE) # A shortcut def startswith(*msg): for b in msg: if message.content.startswith(b): return True return False # COMMANDS # !hello if startswith(prefix + "hello"): if len(message.mentions) >= 1: await client.send_message(message.channel, "Hi " + message.mentions[0].mention) elif len(message.mentions) == 0: await client.send_message(message.channel, "Hi " + message.author.mention) # !uptime elif startswith(prefix + "uptime"): d = datetime( 1, 1, 1) + timedelta(seconds=time.time() - self.nano.boot_time) uptime = "I have been tirelessly answering people for\n" \ "**{} days, {} hours, {} minutes and {} seconds!**".format(d.day - 1, d.hour, d.minute, d.second) await client.send_message(message.channel, uptime) # !nano, nano.info elif startswith((prefix + "nano", "nano.info")): await client.send_message( message.channel, nano_info.replace("<version>", self.nano.version)) # !github elif startswith(prefix + "github"): await client.send_message(message.channel, nano_github) # !roll elif startswith(prefix + "roll"): if startswith(prefix + "roll"): num = message.content[len(prefix + "roll "):] else: num = message.content[len(prefix + "rng "):] if not str(num).isnumeric(): await client.send_message(message.channel, "Not a number.") return rn = randint(0, int(num)) result = "**{}**. {}".format(rn, "**GG**" if rn == int(num) else "") await client.send_message( message.channel, "{}, you rolled {}".format(message.author.mention, result)) # !dice elif startswith(prefix + "dice"): rn = randint(1, 6) await client.send_message( message.channel, "{}, the dice shows... **{}**".format(message.author.mention, rn)) # !ping elif startswith(prefix + "ping"): base_time = datetime.now() - message.timestamp base_taken = int(divmod(base_time.total_seconds(), 60)[1] * 100) a = await client.send_message(message.channel, PING_MSG) self.pings[a.id] = [ time.monotonic(), message.channel.id, base_taken ] await client.add_reaction(a, "\U0001F44D") self.stats.add(PING) # !decide elif startswith(prefix + "decide"): cut = str(message.content)[len(prefix + "decide "):] if len(cut.split("|")) == 1: await client.send_message( message.channel, "Guess what? It's " + str(cut) + ". **ba dum tss.**") else: split = cut.split("|") rn = randint(0, len(split) - 1) await client.send_message( message.channel, "**drum roll**... I have decided: {}".format(split[rn])) # !8ball elif startswith(prefix + "8ball"): answer = eight_ball[randint(0, len(eight_ball) - 1)] await client.send_message( message.channel, "The magic 8ball says: *{}*.".format(answer)) # !quote elif startswith(prefix + "quote"): chosen = str(quotes[randint(0, len(quotes) - 1)]) # Find the part where the author is mentioned place = chosen.rfind("–") await client.send_message( message.channel, "{}\n- __{}__".format(chosen[:place], chosen[place + 1:])) # !invite elif startswith(prefix + "invite", "nano.invite"): application = await client.application_info() # Most of the permissions that Nano uses perms = "1543765079" url = "<https://discordapp.com/oauth2/" \ "authorize?client_id={}&scope=bot&permissions={}>".format(application.id, perms) await client.send_message(message.channel, invite.replace("<link>", url)) # !avatar elif startswith(prefix + "avatar"): # Selects the proper user if len(message.mentions) == 0: name = str(str(message.content)[len(prefix + "avatar "):]) member = utils.find(lambda m: m.name == name, message.channel.server.members) else: member = message.mentions[0] if not member: member = message.author url = member.avatar_url if url: await client.send_message( message.channel, "**{}**'s avatar: {}".format(member.name, url)) else: await client.send_message( message.channel, "**{}** does not have an avatar. {}".format( member.name, StandardEmoji.EXPRESSIONLESS)) # !say elif startswith(prefix + "say"): if not self.handler.is_mod(message.author, message.server): await client.send_message(message.channel, StandardEmoji.WARNING + not_mod) return "return" content = str(message.content[len(prefix + "say "):]).strip(" ") if len(message.channel_mentions) != 0: channel = message.channel_mentions[0] content = content.replace(channel.mention, "").strip(" ") else: channel = message.channel content = self.at_everyone_filter(content, message.author, message.server) await client.send_message(channel, content) await self.log_say_command(message, content, prefix) # !selfrole [role name] elif startswith(prefix + "selfrole"): role = str(message.content[len(prefix + "selfrole"):]).strip(" ") s_role = self.handler.get_selfrole(message.server.id) if is_disabled(s_role): await client.send_message( message.channel, StandardEmoji.WARNING + " This feature is not enabled on this server.") elif (role != s_role) and len(message.role_mentions) == 0: await client.send_message( message.channel, StandardEmoji.CROSS + " Wrong role name.") else: if len(message.role_mentions) != 0: role = message.role_mentions[0] else: role = utils.find(lambda r: r.name == s_role, message.server.roles) if not role: return # If user already has the role, remove it if role in message.author.roles: await client.remove_roles(message.author, role) await client.send_message( message.channel, StandardEmoji.PERFECT + " Removed **{}** from your list of roles.".format( s_role)) else: await client.add_roles(message.author, role) await client.send_message(message.channel, StandardEmoji.PERFECT)
"Linked Groups": (None, None, None, False, "Bind groups to your server so group members get specific roles."), "allowOldRoles": (None, "boolean", None, False, "Bloxlink will NOT remove roles if this is enabled."), "autoRoles": (None, "boolean", None, False, "Bloxlink will give all matching/corresponding roles to people who join the server. Set eligible roles with ``{prefix}bind``. Note that this being enabled will override 'autoVerification'."), "autoVerification": (None, "boolean", None, False, "Bloxlink will give the Verified role to people who join the server and are linked to Bloxlink.\nNote that 'autoRoles' being enabled overrides this setting."), #"dmVerifications": (None, "boolean", None, False, "Set whether verifications default to DMs."), "dynamicRoles": (None, "boolean", None, False, "Bloxlink will make missing group roles from your Linked Groups as people need them."), "welcomeMessage": (None, "string", 1500, False, "The welcome message is used on ``{prefix}verify`` responses. Note that you can use these templates: ```{templates}```"), "joinDM": (lambda g, gd: bool(gd.get("verifiedDM", True)) or bool(gd.get("unverifiedDM")), None, None, False, "Customize the join DM messages of people who join the server."), "persistRoles": (None, "boolean", None, True, "Update members' roles/nickname as they type."), "allowReVerify": (None, "boolean", None, True, "If this is enabled: members can change their Roblox account as many times as they want in your server; otherwise, only allow 1 account change."), "trelloID": (None, None, None, False, "Link a Trello board that can change Bloxlink settings!"), "nicknameTemplate": (None, "string", 100, False, "Set the universal nickname template. Note that ``{prefix}bind`` nicknames will override this."), "unverifiedRoleName": (None, "string", 100, False, "Set the 'Unverified' role name -- the role that Unverified users get."), "shorterNicknames": (None, "boolean", None,False, "Brackets in group rank names will be captured instead of the full rank name, resulting in a shorter nickname."), "ageLimit": (None, "number", None, True, "Set the minimum Roblox age in days a user must be to enter your server. People who are less than this value will be kicked."), "inactiveRole": (lambda g, gd: gd.get("inactiveRole") and find(lambda r: r.id == int(gd["inactiveRole"]), g.roles), "role", None, True, "Set the role given to people who declared themselves as \"inactive\" from ``{prefix}profile``."), "banRelatedAccounts": (None, "boolean", None, True, "If this is enabled: when members are banned, their known alts are also banned from the server."), "unbanRelatedAccounts": (None, "boolean", None, True, "If this is enabled: when members are unbanned, their known alts are also unbanned from the server."), "disallowAlts": (None, "boolean", None, True, "If this is enabled: when someone joins the server and already has a linked account in the server, kick the old alt out."), "disallowBanEvaders": (None, "choice", ("ban", "kick"), True, "If this is enabled: when members join, and they have a banned account in the server, their new account will also be actioned."), #"groupShoutChannel": (lambda g, gd: g.get_channel(int(gd.get("groupShoutChannel", "0"))), None, None, True, "Group shouts will be sent to your Discord channel."), "whiteLabel": (lambda g, gd: bool(gd.get("customBot")), None, None, True, "Modify the username and profile picture of __most__ Bloxlink responses."), "promptDelete": (None, "boolean", None, False, "Toggle the deleting of prompt messages after it finishes."), "deleteCommands": (None, "number", 25, False, "Set X higher than 0 to delete every command after X seconds."), "trelloBindMode": (None, "choice", ("merge", "replace"), False, "Choose 'replace' if trello binds should replace the server binds, or 'merge' if trello binds should be merged with the server binds. Default = merge."), } PROMPT = { "PROMPT_TIMEOUT": 300, "PROMPT_ERROR_COUNT": 5 }
def on_member_join(member): channel = find(lambda chan: chan.name == 'public', member.server.channels) client.send_message(channel, 'Please welcome {name} to the server!'.format(name=member.mention()))
async def on_guild_join(guild): await client.change_presence(activity=discord.Game(name=f"P!help | Serving pizza in {len(client.guilds)} servers"), status=discord.Status.online) general = find(lambda x: x.name == 'general', guild.text_channels) if general and general.permissions_for(guild.me).send_messages: await general.send(f"Hello {guild.name}! Do P!help and I'll DM you with info about how to make an order!")
async def __main__(self, CommandArgs): response = CommandArgs.response guild_data = CommandArgs.guild_data prefix = CommandArgs.prefix guild = CommandArgs.guild async with response.loading(): try: category = find(lambda c: c.name == "Verification", guild.categories) or \ await guild.create_category("Verification") verify_info = find(lambda t: t.name == "verify-instructions", category.channels) or \ await guild.create_text_channel("verify-instructions", category=category) verify_channel = find(lambda t: t.name == "verify", category.channels) or \ await guild.create_text_channel("verify", category=category) sample_channel = await guild.create_text_channel("sample-channel") except Forbidden: raise PermissionError("I was unable to create the necessary channels. Please ensure I have the " "`Manage Channels` permission.") except HTTPException: raise Error("You have too many channels or categories! Please delete some before continuing.") try: await verify_info.send("This server uses Bloxlink to manage Roblox verification. In " "order to unlock all the features of this server, you'll need " "to verify your Roblox account with your Discord account!\n\nTo " f"do this, run `{prefix}getrole` in {verify_channel.mention} and follow the instructions.") await sample_channel.send("This is a sample channel that only Verified users " \ "can read. This channel is not important, you may freely delete it.\n" \ "To create another sample channel, right click this channel and click 'Clone " \ "Text Channel', or just run this command again.") except (Forbidden, NotFound): raise PermissionError("I was unable to send messages to the created channels. Please give me the " "proper permissions.") try: await verify_info.set_permissions(guild.me, send_messages=True, read_messages=True) verified_role_name = guild_data.get("verifiedRoleName", DEFAULTS.get("verifiedRoleName")) for role in guild.roles: if role.name != guild.me.name: await verify_info.set_permissions(role, send_messages=False, read_messages=True) await verify_channel.set_permissions(role, send_messages=True, read_messages=True) if role.name == verified_role_name: for target, overwrite in sample_channel.overwrites.items(): await sample_channel.set_permissions(target, overwrite=None) await sample_channel.set_permissions(guild.default_role, send_messages=False, read_messages=False) await sample_channel.set_permissions(role, send_messages=True, read_messages=True) except Forbidden: raise PermissionError("Unable to set permissions to the channels. Please ensure I have the " "`Manage Channels` and `Manage Roles` permission.") except NotFound: raise Error("Please do not delete the created channels while I'm setting them up...") await self.r.table("guilds").insert({ "id": str(guild.id), "verifyChannel": str(verify_channel.id) }, conflict="update").run() await response.success(f"All done! Your new verification channel is {verify_channel.mention} and " \ "is now managed by Bloxlink.")
async def on_member_join(member): if member.server.id == '393603672778604544': await client.add_roles( member, find(lambda r: r.id == '393637330700861441', member.server.roles))
async def on_guild_join(guild): general = find(lambda x: x.name == 'general', guild.text_channels) if general and general.permissions_for(guild.me).send_messages: await general.send('Hey it\'s me, AraonJR {} sure looks cozy!'.format(guild.name))
async def check_permissions(self, author, guild, locale, dm=False, permissions=None, **kwargs): permissions = permissions or self.permissions if author.id == OWNER: return True if permissions.developer_only or self.developer_only: if author.id != OWNER: raise PermissionError("This command is reserved for the Bloxlink Developer.") if (kwargs.get("premium", self.premium) or permissions.premium) and not kwargs.get("free_to_use", self.free_to_use): prem, _ = await get_features(Object(id=guild.owner_id), guild=guild) if not prem.features.get("premium"): prem, _ = await get_features(author) if not prem.attributes["PREMIUM_ANYWHERE"]: raise Message("This command is reserved for Bloxlink Premium subscribers!\n" "The server owner must have premium for this to work. If you " "would like the server owner to have premium instead, please use the ``!transfer`` " "command.\nYou may subscribe to Bloxlink Premium on Patreon: https://patreon.com/bloxlink", type="silly") try: if not dm: author_perms = author.guild_permissions for role_exception in permissions.exceptions["roles"]: if find(lambda r: r.name == role_exception, author.roles): return True if permissions.bloxlink_role: role_name = permissions.bloxlink_role if find(lambda r: r.name == "Bloxlink Admin", author.roles): return True else: if role_name == "Bloxlink Manager": if author_perms.manage_guild or author_perms.administrator: pass else: raise PermissionError("You need the ``Manage Server`` permission to run this command.") elif role_name == "Bloxlink Moderator": if author_perms.kick_members or author_perms.ban_members or author_perms.administrator: pass else: raise PermissionError("You need the ``Kick`` or ``Ban`` permission to run this command.") elif role_name == "Bloxlink Updater": if author_perms.manage_guild or author_perms.administrator or author_perms.manage_roles or find(lambda r: r.name == "Bloxlink Updater", author.roles): pass else: raise PermissionError("You either need: a role called ``Bloxlink Updater``, the ``Manage Roles`` " "role permission, or the ``Manage Server`` role permission.") elif role_name == "Bloxlink Admin": if author_perms.administrator: pass else: raise PermissionError("You need the ``Administrator`` role permission to run this command.") if permissions.allowed.get("discord_perms"): for perm in permissions.allowed["discord_perms"]: if perm == "Manage Server": if author_perms.manage_guild or author_perms.administrator: pass else: raise PermissionError("You need the ``Manage Server`` permission to run this command.") else: if not getattr(author_perms, perm, False) and not perm.administrator: raise PermissionError(f"You need the ``{perm}`` permission to run this command.") for role in permissions.allowed["roles"]: if not find(lambda r: r.name == role, author.roles): raise PermissionError(f"Missing role: ``{role}``") if permissions.allowed.get("functions"): for function in permissions.allowed["functions"]: if iscoroutinefunction(function): data = [await function(author)] else: data = [function(author)] if not data[0]: raise PermissionError if isinstance(data[0], tuple): if not data[0][0]: raise PermissionError(data[0][1]) except PermissionError as e: if e.args: raise PermissionError(e) raise PermissionError("You do not meet the required permissions for this command.")
async def buy_ticket(self, ctx: SlashContext, name: str): # ticket buying logic await ensure_registered(ctx.author.id) can_control_bot = find(lambda _: _.name in ROLES_CAN_CONTROL_BOT, ctx.author.roles) async with in_transaction( ): # prevent race conditions via select_for_update + in_transaction # select user 2nd time to lock it's row user = await User.filter(id=ctx.author.id ).select_for_update().get(id=ctx.author.id ) # validate that lottery exists lottery = await Lottery.get_or_none(name=name) if not lottery: return await ctx.send( f"{ctx.author.mention}, error, sweepstake `{name}` doesn't exist", delete_after=DELETE_AFTER, ) # validate that we allow selling tickets if lottery.status == LotteryStatus.STOP_SALES: return await ctx.send( f"{ctx.author.mention}, tickets can't be bought for `{name}` because there are no tickets left or it's close to strike date", # noqa: E501 delete_after=DELETE_AFTER, ) elif lottery.status == LotteryStatus.STRIKED: return await ctx.send( f"{ctx.author.mention}, tickets can't be bought for `{name}` because winning tickets were already selected", # noqa: E501 delete_after=DELETE_AFTER, ) elif lottery.status == LotteryStatus.ENDED: return await ctx.send( f"{ctx.author.mention}, tickets can't be bought for `{name}` because it has ended", delete_after=DELETE_AFTER, ) elif lottery.is_whitelisted and not can_control_bot: return await ctx.send( f"{ctx.author.mention}, tickets can't be bought for `{name}` because it is of `whitelisted` type", delete_after=DELETE_AFTER, ) # validate user balance if user.balance < lottery.ticket_price: return await ctx.send( f"{ctx.author.mention}, not enough points, you only have `{pp_points(user.balance)}`{POINTS_EMOJI} in your sweepstake wallet and ticket price is `{int(lottery.ticket_price)}`{POINTS_EMOJI}. To add points to your sweepstake wallet, `!send @{ctx.bot.user.display_name}#{ctx.bot.user.discriminator} [number of points]`", # noqa: E501 delete_after=DELETE_AFTER, ) # handle whitelisted lotteries is_whitelisted_ticket = lottery.is_whitelisted and can_control_bot if is_whitelisted_ticket: try: await ctx.send( f"Hello, {ctx.author.mention}, this sweepstake is of whitelisted type, please mention user for whom you want to buy a ticket", # noqa: E501 delete_after=DELETE_AFTER, ) message = await self.bot.wait_for( "message", check=lambda m: m.guild is not None and m.author == ctx .author, timeout=300, ) if len(message.raw_mentions) != 1: return await ctx.send( f"{ctx.author.mention}, you need to mention only one person", delete_after=DELETE_AFTER) # noqa: E501 owner_id = message.raw_mentions[0] await ensure_registered(owner_id) owner = await User.get(id=owner_id) except asyncio.TimeoutError: return else: owner = user # to generate random ticket number that doesn't have collisions we will need to grab all ticket numbers # from database and then check in python which numbers are available ticket_numbers = await Ticket.filter(lottery=lottery ).values_list("ticket_number", flat=True) # create ticket for user try: ticket = await Ticket.create( user=owner, lottery=lottery, ticket_number=cryptogen.choice([ _ # make range to behave as inclusive range, this way ticket with max_number could be won for _ in range(lottery.ticket_min_number, lottery.ticket_max_number + 1) if _ not in ticket_numbers ]), ) user.balance = user.balance - lottery.ticket_price await user.save(update_fields=["balance", "modified_at"]) if is_whitelisted_ticket: await ctx.send( f":tickets: Congratulations <@!{owner.id}>, you just had {lottery.name} purchased for you by {ctx.author.mention}. Your ticket number is: {ticket.ticket_number}:tickets:" # noqa: E501 ) else: await ctx.send( f"{ctx.author.mention}, you bought {lottery.name} ticket with number: `{ticket.ticket_number}`, your balance is: `{pp_points(user.balance)}`{POINTS_EMOJI}" # noqa: E501 ) except IndexError: # it means that all tickets were sold, stop ticket sales for lottery lottery.status = LotteryStatus.STOP_SALES await lottery.save(update_fields=["status", "modified_at"]) await ctx.send( f"{ctx.author.mention}, ouch, the last ticket was sold a moment ago", delete_after=DELETE_AFTER, )
async def blue(ctx, member: discord.Member = None): '''changes role colour''' if member is None: member = ctx.message.author await eight.replace_roles( member, find(lambda r: r.name == 'Blue', ctx.message.server.roles))