async def _send_update_pm(self, server: discord.Server, subid: str): sub = self.submissions[server.id]["submissions"][subid] user = server.get_member(sub["submitter"]) if sub["status"] == "rejected": await self.bot.send_message( user, "Your emoji submission `{}` in {} has been rejected by {}.\n" "Here is the reason they gave:{}" "As a reminder, here is what your rejected emoji looks like:". format(sub["name"], server.name, server.get_member(sub["rejector"]).mention, cf.box(sub["reject_reason"]))) await self.bot.send_file(user, sub["image"]) await self.bot.send_message( user, "You may fix the problems with your emoji and resubmit it," " or contact the rejector with any questions.") elif sub["status"] == "approved": await self.bot.send_message( user, "Your emoji submission `{}` in {} has been approved by {}.". format(sub["name"], server.name, server.get_member(sub["approver"]).mention))
def from_dict(cls, time_callback: Callable[[], float], server: discord.Server, data: Dict): self = SprintData(time_callback) self.founder = server.get_member(data['founder']) member_uids = [] for u_id in data['members']: member = server.get_member(u_id) if member is not None: self.members.append(member) member_uids.append(member.id) else: logger.warning( "Can't restore member: ID {} not found on server".format( u_id)) self.start = { u_id: value for u_id, value in data['start'].items() if u_id in member_uids } self.end = { u_id: value for u_id, value in data['end'].items() if u_id in member_uids } self.finalized = set(data['finalized']) self.start_time = self._loop_time(data['start_time']) self.end_time = self._loop_time(data['end_time']) self.warn_times = deque(self._loop_time(t) for t in data['warn_times']) self.finalize_time = self._loop_time(data['finalize_time']) return self
def query_user(server: discord.Server, id_: str): """ Find a user given an ID string passed by command, or create it if it does not exist. id_ can be passed to a command as a discord mention ``<@123456789012345678>`` or ``<@!123456789012345678>``, or as a Discord ID ``123456789012345678`` (various malformed inputs may also be accepted, e.g., ``@123456789012345678``). For Discord Mention or Discord ID, if the user is not found but exists on Discord, a new entry is created. In other cases, a :cls:`~.UserNotFound` error is raised. :raises UserNotFound: User was not found. Either the Discord user exists neither on Discord nor in the database, or a database ID was passed and could not be found. :raises discord.HTTPException: Discord API error occurred :raises db.exc.MultipleResultsFound: Should never happen - database is buggered. """ # Parse the passed ID try: discord_id = extract_user_id(id_) except discord.InvalidArgument: raise ValueError('Invalid Discord user ID format') logger.debug('query_user: passed Discord ID: {}'.format(discord_id)) # Check if user exists try: db_user = session.query(User).filter_by(discord_id=discord_id).one() except db.orm_exc.MultipleResultsFound: logger.exception("Er, mate, I think we've got a problem here. " "The database is buggered.") raise except db.orm_exc.NoResultFound: logger.debug('query_user: user not found, creating user') try: member = server.get_member(discord_id) # type: discord.Member except discord.NotFound as e: raise UserNotFound('Discord user not found') from e db_user = create_user(member) logger.debug('query_user: created user: {!r}'.format(db_user)) else: logger.debug('query_user: found user: {!r}'.format(db_user)) try: member = server.get_member(discord_id) # type: discord.Member except discord.NotFound: logger.warning("Can't find user {!r} on Discord, skipping update nicknames" .format(db_user)) else: update_nicknames(db_user, member) return db_user
def get_birthday_count(self, server: discord.Server): count = 0 for user_bd in self.user_birthdays: if user_bd.server_id == server.id and server.get_member( user_bd.user_id) is not None: count += 1 return count
def team_members(team: RWTeam, color=None, server: discord.Server = None, server_members: dict = None): if color is None: color = random_discord_color() em = discord.Embed(title=team.name, description='#{}'.format(team.tag), color=color) tag2id = {v: k for k, v in server_members.items()} o = [] for m in team.members: user_id = tag2id.get(m.tag) user = None if user_id is not None: user = server.get_member(user_id) o.append("{name} #{tag}, {role}, {trophies} {d_name}".format( name=remove_color_tags(m.name), tag=m.tag, role=m.role, trophies=m.stars, d_name=user if user else "----")) count = 10 pagified = grouper(o, count) for index, page in enumerate(pagified): v = [line for line in page if line is not None] em.add_field(name="Members {}-{}".format(index * 10 + 1, index * 10 + len(v)), value='\n'.join(v)) return em
def speak_permissions(self, server: discord.Server, channel: discord.Channel = None): if not channel: channel = self.get_welcome_channel(server) return server.get_member( self.bot.user.id).permissions_in(channel).send_messages
def get_user_color(user: discord.User, server: discord.Server) -> discord.Colour: """Gets the user's color based on the highest role with a color""" # If it's a PM, server will be none if server is None: return discord.Colour.default() member = server.get_member(user.id) # type: discord.Member if member is not None: return member.colour return discord.Colour.default()
async def update_user_roles(bot: discord.Client, server: discord.Server, users: Sequence[m.User]): # noinspection PyTypeChecker role_ids = [o.role_id for o in q.query_genres() + q.query_project_types()] project_roles = set(get_role(server, role_id) for role_id in role_ids if role_id is not None) for u in users: member = server.get_member(u.discord_id) desired_roles = set() for taxon in {u.genre, u.type} - {None}: if taxon.role_id is not None: desired_roles.add(get_role(server, taxon.role_id)) new_roles = (set(member.roles) - project_roles) | desired_roles await bot.replace_roles(member, *new_roles)
def get_member(bot: discord.Client, user_id, server: discord.Server = None, server_list=None) -> discord.Member: """Returns a member matching the id If no server_id is specified, the first member matching the id will be returned, meaning that the server he belongs to will be unknown, so member-only functions may be inaccurate. User functions remain the same, regardless of server""" if server_list is not None and len(server_list) > 0: members = [m for ml in [s.members for s in server_list] for m in ml] return discord.utils.find(lambda m: m.id == str(user_id), members) if server is not None: return server.get_member(str(user_id)) else: return discord.utils.get(bot.get_all_members(), id=str(user_id))
def find_member(server: discord.Server, name, steps=3, mention=True): """ Find any member by their name or a formatted mention. Steps define the depth at which to search. More steps equal less accurate checks. +--------+------------------+ | step | function | +--------+------------------+ | 0 | perform no check | | 1 | name is equal | | 2 | name starts with | | 3 | name is in | +--------+------------------+ :param server: discord.Server to look through for members. :param name: display_name as a string or mention to find. :param steps: int from 0-3 to specify search depth. :param mention: bool, check for mentions. :return: discord.Member """ member = None # Return a member from mention found_mention = member_mention_pattern.search(name) if found_mention and mention: member = server.get_member(found_mention.group("id")) return member name = name.lower() # Steps to check, higher values equal more fuzzy checks checks = [ lambda m: m.name.lower() == name or m.display_name.lower() == name, lambda m: m.name.lower().startswith(name) or m.display_name.lower( ).startswith(name), lambda m: name in m.display_name.lower() or name in m.name.lower() ] for i in range(steps if steps <= len(checks) else len(checks)): member = discord.utils.find(checks[i], server.members) if member: break # Return the found member or None return member
async def show_list(self, server: discord.Server): alive = [] fallen = [] for user in self.list: name = server.get_member(user) if not name: continue name = name.display_name if self.list[user]: alive.append(name) else: fallen.append(name) await self.bot.say( 'Those who still live:\n' + ', '.join(alive) + '\n\nThose who sacrificed everything for a better universe:\n' + ', '.join(fallen))
def find_member(server: discord.Server, name, steps=3, mention=True): """ Find any member by their name or a formatted mention. Steps define the depth at which to search. More steps equal less accurate checks. +--------+------------------+ | step | function | +--------+------------------+ | 0 | perform no check | | 1 | name is equal | | 2 | name starts with | | 3 | name is in | +--------+------------------+ :param server: discord.Server to look through for members. :param name: display_name as a string or mention to find. :param steps: int from 0-3 to specify search depth. :param mention: check for mentions. """ member = None # Return a member from mention found_mention = member_mention_regex.search(name) if found_mention and mention: member = server.get_member(found_mention.group("id")) name = name.lower() if not member: # Steps to check, higher values equal more fuzzy checks checks = [lambda m: m.display_name.lower() == name, lambda m: m.display_name.lower().startswith(name), lambda m: name in m.display_name.lower()] for i in range(steps if steps <= len(checks) else len(checks)): member = discord.utils.find(checks[i], server.members) if member: break # Return the found member or None return member
def check_claim_eligibility(self, author: discord.User, server: discord.Server, uuid: str) -> str: """Loop through `data/claimed.csv` to make sure a user isn't claiming a second or duplicate account. Args: author (discord.User): The user we're checking. server (discord.Server): The server the claim originated from. uuid (str): The UUID of the Minecraft account. Returns: str: Message describing any or lack of conflicts. """ with open(self.claimfile, 'r', newline='') as claimed_file: reader = csv.DictReader(claimed_file) for row in reader: # Respond whether we get a UUID match, Discord ID match, # or no match if (row['DISCORD_ID'] == author.id): msg = 'You already registered account {} [`{}`].' return msg.format(row['USERNAME'], row['UUID']) elif (row['UUID'] == uuid): if server.get_member(row['DISCORD_ID']): tag = row['DISCORD_MENTION'] else: tag = row['DISCORD_NICK'] msg = '{} already claimed account {} [`{}`].' return msg.format(tag, row['USERNAME'], row['UUID']) # The for loop doesn't execute if there are no rows in the file. # Thus, this part is outside to catch both 'not found' and # 'fresh file' cases. msg = 'OK for you to register this nick with this account.' return msg
def get_economy_ranks(self, server: discord.Server, time_id: str, top_max=5): """Return economy ranks by time id as a list.""" out = [] out.append("__Richest members__") economy = self.bot.get_cog("Economy") if economy is not None: bank = economy.bank if bank is not None: if server.id in bank.accounts: accounts = bank.accounts[server.id] accounts = dict( sorted(accounts.items(), key=lambda x: -x[1]["balance"])) for i, (k, v) in enumerate(accounts.items()): if i < top_max: member = server.get_member(k) if member: out.append("`{:>2}.` {} ({} credits)".format( str(i + 1), member.display_name, str(v["balance"]))) return out
async def run_racfaudit(self, server: discord.Server, clan_filters=None) -> AuditResult: """Run audit and return results.""" audit_results = { "elder_promotion_req": [], "coleader_promotion_req": [], "leader_promotion_req": [], "no_discord": [], "no_clan_role": [], "no_member_role": [], "not_in_our_clans": [], } error = False out = [] try: member_models = await self.family_member_models() except ClashRoyaleAPIError as e: # await self.bot.say(e.status_message) error = True else: out.append("**100T Family Audit**") # associate Discord user to member for member_model in member_models: tag = clean_tag(member_model.get('tag')) try: discord_id = self.players[tag]["user_id"] except KeyError: pass else: member_model['discord_member'] = server.get_member(discord_id) # find member_models mismatch discord_members = [] for member_model in member_models: has_discord = member_model.get('discord_member') if has_discord is None: audit_results["no_discord"].append(member_model) if has_discord: discord_member = member_model.get('discord_member') discord_members.append(discord_member) # promotions is_elder = False is_coleader = False is_leader = False for r in discord_member.roles: if r.name.lower() == 'elder': is_elder = True if r.name.lower() == 'coleader': is_coleader = True if r.name.lower() == 'leader': is_leader = True if is_elder: if member_model.get('role').lower() != 'elder': audit_results["elder_promotion_req"].append(member_model) if is_coleader: if member_model.get('role').lower() != 'coleader': audit_results["coleader_promotion_req"].append(member_model) if is_leader: if member_model.get('role').lower() != 'leader': audit_results["leader_promotion_req"].append(member_model) # no clan role clan_name = member_model['clan']['name'] clan_role_name = self.clan_roles[clan_name] if clan_role_name not in [r.name for r in discord_member.roles]: audit_results["no_clan_role"].append({ "discord_member": discord_member, "member_model": member_model }) # no member role discord_role_names = [r.name for r in discord_member.roles] if 'Member' not in discord_role_names: audit_results["no_member_role"].append(discord_member) # find discord member with roles for user in server.members: user_roles = [r.name for r in user.roles] if 'Member' in user_roles: if user not in discord_members: audit_results['not_in_our_clans'].append(user) # show results def list_member(member_model): """member row""" clan = member_model.get('clan') clan_name = None if clan is not None: clan_name = clan.get('name') row = "**{name}** #{tag}, {clan_name}, {role}, {trophies}".format( name=member_model.get('name'), tag=member_model.get('tag'), clan_name=clan_name, role=get_role_name(member_model.get('role')), trophies=member_model.get('trophies') ) return row for clan in self.config['clans']: # await self.bot.type() await asyncio.sleep(0) display_output = False if clan_filters: for c in clan_filters: if c.lower() in clan['name'].lower(): display_output = True else: display_output = True if not display_output: continue if clan['type'] == 'Member': out.append("-" * 40) out.append(inline(clan.get('name'))) # no discord out.append(underline("Members without discord")) for member_model in audit_results["no_discord"]: try: if member_model['clan']['name'] == clan.get('name'): out.append(list_member(member_model)) except KeyError: pass # elders out.append(underline("Elders need promotion")) for member_model in audit_results["elder_promotion_req"]: try: if member_model['clan']['name'] == clan.get('name'): out.append(list_member(member_model)) except KeyError: pass # coleaders out.append(underline("Co-Leaders need promotion")) for member_model in audit_results["coleader_promotion_req"]: try: if member_model['clan']['name'] == clan.get('name'): out.append(list_member(member_model)) except KeyError: pass # clan role out.append(underline("No clan role")) for result in audit_results["no_clan_role"]: try: if result["member_model"]['clan']['name'] == clan.get('name'): out.append(result['discord_member'].mention) except KeyError: pass # not in our clans out.append("-" * 40) out.append(underline("Discord users not in our clans but with member roles")) for result in audit_results['not_in_our_clans']: out.append('`{}` {}'.format(result, result.id)) return AuditResult( audit_results=audit_results, output=out, error=error )
async def run(self, server: discord.Server = None, exec=False, status_channel=None): """Run audit against server.""" results = dict() # Fetch club info teams = await self.cog._get_teams(server.id) for r, team_tag, in zip(teams.results, teams.team_tags): if isinstance(r, Exception): raise RushWarsAuditException() results[team_tag] = r tag2id = self.cog.tag_to_id(server_id=server.id) member_ids = [] # for each member, find discord user id for team_tag, team in results.items(): for member in team.members: member_tag = member.get('tag') if member_tag is not None: user_id = tag2id.get(member_tag) member_ids.append(user_id) member["discord_user_id"] = user_id # non members non_member_ids = [ m.id for m in server.members if m.id not in member_ids ] cfg = await self.cog._get_server_config(server_id=server.id) team_tag_to_team_roles = {} team_role_names = [] for team in cfg.get('teams', []): team_tag_to_team_roles[team.get('tag')] = [ discord.utils.get(server.roles, name=name) for name in team.get('roles', []) ] team_role_names += team.get('roles') all_team_roles = [ discord.utils.get(server.roles, name=name) for name in team_role_names ] rw_member_role = discord.utils.get(server.roles, name="RW-Member") rw_members_roles = [rw_member_role] + all_team_roles if status_channel: for member_id in non_member_ids: user = server.get_member(member_id) if user is not None: if rw_member_role in user.roles: await self.cog.bot.send_message( status_channel, "{} is not in our teams".format(user)) if exec: await self.exec_remove_roles( user, rw_members_roles, channel=status_channel) for member_id in member_ids: user = server.get_member(member_id) if user is not None: if rw_member_role not in user.roles: await self.cog.bot.send_message( status_channel, "{} is in our teams".format(user)) if exec: await self.exec_add_roles(user, [rw_member_role], channel=status_channel) # teams for team_tag, team in results.items(): team_member_ids = [] for member in team.members: user_id = member.get('discord_user_id') if user_id is not None: team_member_ids.append(user_id) non_team_member_ids = [ m.id for m in server.members if m.id not in team_member_ids ] team_roles = team_tag_to_team_roles[team_tag] team_role = team_roles[0] # members for user_id in team_member_ids: user = server.get_member(user_id) if user is not None: if team_role not in user.roles: await self.cog.bot.send_message( status_channel, "{} is in {}".format(user, team.name)) if exec: await self.exec_add_roles(user, [team_role], channel=status_channel) for user_id in non_team_member_ids: user = server.get_member(user_id) if user is not None: if team_role in user.roles: await self.cog.bot.send_message( status_channel, "{} is not in {}".format(user, team.name)) if exec: await self.exec_remove_roles( user, [team_role], channel=status_channel) # print_json(results) await self.cog.bot.send_message(status_channel, "Audit finished")
def _get_permabanned_members_db(server: discord.Server) -> List[Tuple[User, discord.Member]]: records = controller.query_unexpired_records(types=RecordType.perma) members_raw = ((r.user, server.get_member(r.user.discord_id)) for r in records) return [m for m in members_raw if m[1] is not None]
def as_member_of(self, server: discord.Server) -> discord.Member: return server.get_member(self.user.id)
async def run(self, server: discord.Server = None, exec=False, status_channel=None): """Run audit against server.""" results = dict() # Fetch club info clubs = await self.cog._get_clubs(server.id) for r, club_tag, in zip(clubs.results, clubs.club_tags): if isinstance(r, Exception): raise BrawlStarsAuditException() results[club_tag] = r tag2id = self.cog.tag_to_id(server_id=server.id) member_ids = [] # for each member, find discord user id for club_tag, club in results.items(): for member in club.get('members', []): member_tag = member.get('tag') if member_tag is not None: user_id = tag2id.get(member_tag) member_ids.append(user_id) member["discord_user_id"] = user_id # non members non_member_ids = [ m.id for m in server.members if m.id not in member_ids ] cfg = await self.cog._get_server_config(server_id=server.id) club_tag_to_club_roles = {} club_role_names = [] for club in cfg.get('clubs', []): club_tag_to_club_roles[club.get('tag')] = [ discord.utils.get(server.roles, name=name) for name in club.get('roles', []) ] club_role_names += club.get('roles') all_club_roles = [ discord.utils.get(server.roles, name=name) for name in club_role_names ] bs_member_role = discord.utils.get(server.roles, name="BS-Member") bs_member_roles = [bs_member_role] + all_club_roles if status_channel: for member_id in non_member_ids: user = server.get_member(member_id) if user is not None: if bs_member_role in user.roles: await self.cog.bot.send_message( status_channel, "{} is not in our clubs".format(user)) if exec: await self.exec_remove_roles( user, bs_member_roles, channel=status_channel) for member_id in member_ids: user = server.get_member(member_id) if user is not None: if bs_member_role not in user.roles: await self.cog.bot.send_message( status_channel, "{} is in our clubs".format(user)) if exec: await self.exec_add_roles(user, [bs_member_role], channel=status_channel) # clubs for club_tag, club in results.items(): club_member_ids = [] for member in club.get('members', []): user_id = member.get('discord_user_id') if user_id is not None: club_member_ids.append(user_id) non_club_member_ids = [ m.id for m in server.members if m.id not in club_member_ids ] club_roles = club_tag_to_club_roles[club_tag] club_role = club_roles[0] # members for user_id in club_member_ids: user = server.get_member(user_id) if user is not None: if club_role not in user.roles: await self.cog.bot.send_message( status_channel, "{} is in {}".format(user, club.get('name'))) if exec: await self.exec_add_roles(user, [club_role], channel=status_channel) for user_id in non_club_member_ids: user = server.get_member(user_id) if user is not None: if club_role in user.roles: await self.cog.bot.send_message( status_channel, "{} is not in {}".format(user, club.get('name'))) if exec: await self.exec_remove_roles( user, [club_role], channel=status_channel) # add visitor for those who don’t have normal roles # if exec: # visitor_role = discord.utils.get(server.roles, name='Visitor') # membership_role_names = ['Member', 'BS-Member', 'BOT', 'Guest', 'Visitor'] # for user in server.members: # try: # user_role_names = [r.name for r in user.roles] # if len(set(user_role_names) & set(membership_role_names)) == 0: # await self.exec_add_roles(user, [visitor_role], channel=status_channel) # except Exception as e: # await self.cog.bot.send_emssage(status_channel, "Error auditing {}".format(user)) # print_json(results) await self.cog.bot.send_message(status_channel, "Audit finished")
def speak_permissions(self, server: discord.Server, channel: discord.Channel=None): return server.get_member( self.bot.user.id).permissions_in(channel).send_messages
def _get_tempbanned_members_db( server: discord.Server) -> List[model.Record]: records = c.query_unexpired_records(types=RecordType.temp) members_raw = (server.get_member(record.user.discord_id) for record in records) return [m for m in members_raw if m is not None]
def get_admin_count(self, server: discord.Server): count = 0 for admin in self.user_admins: if admin.server_id == server.id and server.get_member(admin.user_id) is not None: count += 1 return count
async def log_server_channel(self, ctx, server: discord.Server, channel: discord.Channel, count=1000, before=None, after=None, reverse=False): """Save channel messages.""" channel_messages = [] await self.bot.say("Logging messages after message ID: {}".format( after.id)) async for message in self.bot.logs_from(channel, limit=count, before=before, after=after, reverse=reverse): msg = { 'author_id': message.author.id, 'content': message.content, 'timestamp': message.timestamp.isoformat(), 'id': message.id, 'reactions': [], 'attachments': [] } for reaction in message.reactions: r = { 'custom_emoji': reaction.custom_emoji, 'count': reaction.count } if reaction.custom_emoji: # <:emoji_name:emoji_id> r['emoji'] = '<:{}:{}>'.format(reaction.emoji.name, reaction.emoji.id) else: r['emoji'] = reaction.emoji msg['reactions'].append(r) for attach in message.attachments: msg['attachments'].append(attach['url']) channel_messages.append(msg) channel_messages = sorted(channel_messages, key=lambda x: x['timestamp']) self.settings[server.id][channel.id] = channel_messages dataIO.save_json(JSON, self.settings) # write out for message in channel_messages: author_id = message['author_id'] author = server.get_member(author_id) author_mention = author_id if author is not None: author_mention = author.mention content = message['content'] timestamp = message['timestamp'] message_id = message['id'] description = '{}: {}'.format(author_mention, content) em = discord.Embed(title=channel.name, description=description) for reaction in message['reactions']: em.add_field(name=reaction['emoji'], value=reaction['count']) for attach in message['attachments']: em.set_image(url=attach) em.set_footer(text='{} - ID: {}'.format(timestamp, message_id)) await self.bot.say(embed=em)