async def update_guild_prefix(self, ctx, prefix): """Updates the command prefix for the Discord server. .. Note:: Requires `administrator` privilege. :param ctx: The invocation context. :param prefix: The command prefix to update to. """ user = DiscordUser(ctx.author) if len(prefix) > 3: embed = quickembed.error( desc='Prefix can not be longer than 3 characters', user=user) else: user.update_guild_info(ctx.guild, prefix) stored_prefix = user.guild_info(ctx.guild.id)['prefix'] if prefix == stored_prefix: embed = quickembed.success( desc='Prefix updated to **{}**'.format(stored_prefix), user=user, ) else: embed = quickembed.error(desc='Failed to update prefix', user=user) await ctx.send(embed=embed)
async def open_matches(self, ctx): """Lists the available `Match`es to bet on. .. Note: If the number of available `Match`es exceeds 5, they will be displayed with their `short view`. If it does not exceed 5, their full details will be displayed as individual messages. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) rows = user.search_match_by_open_bets() if len(rows) > 5: embed = quickembed.info( desc='Short View - Use `!match [id]` for full view') embed.set_author(name='Open Bet Matches') for row in rows: match = Match(row.id) embed.add_field( name='[Match {}]'.format(match.id), value='{}'.format(match.info_text_short()), inline=True, ) await ctx.send(embed=embed) elif len(rows) > 0: for row in rows: await ctx.send(embed=Match(row.id).info_embed()) else: await ctx.send(embed=quickembed.error( desc='No open bet matches available', user=user))
async def recent_match_info(self, ctx): """Displays details for the last completed `Match`. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) rows = user.search_match_by_recent_completed() if rows: embed = Match(rows[0].id).info_embed() else: embed = quickembed.error(desc='No match found', user=user) await ctx.send(embed=embed)
async def misc_commands(self, ctx): """Sends a link to the list of available *dumb commands*. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) embed = quickembed.info( desc= 'FJBot Command:\nhttps://idleuser.com/projects/fjbot/command-list', user=DiscordUser(ctx.author), ) await ctx.send(embed=embed)
async def superstar_birthdays(self, ctx): """Display a list of upcoming `Superstar` birthdays. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) bdays = user.superstar_birthday_upcoming() embed = quickembed.info(desc='Upcoming Birthdays', user=user) embed.add_field( name='\u200b', value='{}'.format('\n'.join( ['[{}] - {}'.format(b['dob'], b['name']) for b in bdays])), ) await ctx.send(embed=embed)
async def user_join_royalrumble(self, ctx): """TODO: Enters the user into the current Royal Rumble event by providing them an entry number. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) response = user.join_royalrumble() if response['success']: embed = quickembed.success(desc='Entry Number: `{}`'.format( response['message']), user=user) else: embed = quickembed.error(desc=response['message'], user=user) await ctx.send(embed=embed)
async def rate_match(self, ctx, *args): """Adds a 0-5 star rating to a `Match`. .. Note: If no `match_id` is provided, the rating will be added to the most recently closed `Match`. :param ctx: The invocation context. :param args: Must be either `[rating]` or `[match_id] [rating]`. Rating must be between 0-5. :return: """ user = DiscordUser(ctx.author) try: if len(args) == 1: match_id = None rating = float(args[0]) else: match_id = int(args[0]) rating = float(args[1]) except Exception: msg = ('Invalid `!rate` command\n' '`!rate [rating]` (rates last match)\n' '`!rate [match_id] [rating]`') embed = quickembed.error(desc=msg, user=user) await ctx.send(embed=embed) return if not match_id: rows = user.search_match_by_recent_completed() if not rows: msg = 'No current match set to rate' embed = quickembed.error(desc=msg, user=user) await ctx.send(embed=embed) return match_id = rows[0].id response = user.rate_match(match_id, rating) if response['success']: match = Match(match_id) stars = '' for i in range(1, 6): if rating >= i: stars += '★' else: stars += '☆' msg = 'Rated `Match {}` {} ({})\n{}'.format( match_id, stars, rating, match.info_text_short()) embed = quickembed.success(desc=msg, user=user) else: msg = response['message'] embed = quickembed.error(desc=msg, user=user) await ctx.send(embed=embed)
async def user_reset_password_link(self, ctx): """Sends a reset password link for the website to the user through DM. .. note:: This bypasses the login credentials by using a temporary password. The temporary password is only valid for resetting the account's password. It expires once the password has changed or 5 minutes has passed. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) link = user.request_reset_password_link() msg = '<{}>\n(link expires in 5 minutes)'.format(link) await ctx.author.send(embed=quickembed.general(desc=msg, user=user)) embed = quickembed.success(user=user, desc='Link DMed') await ctx.send(embed=embed)
async def check_registered_users(self): await self.bot.wait_until_ready() guild = self.bot.get_guild(config.base['guild_id']) role = guild.get_role(753640365612990546) members = guild.members for member in guild.members: user = DiscordUser(member) is_registered = user.is_registered() has_role = role in member.roles if is_registered and not has_role: await member.add_roles(role) logger.info('Added @registered to: {}'.format(user.name)) elif not is_registered and has_role: await member.remove_roles(role) logger.info('Removed @registered from: {}'.format(user.name))
async def upcoming_events(self, ctx): """Displays a list of upcoming PPV events in order. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) ppvs = user.future_events(ppv_check=1) embed = quickembed.info(desc='Upcoming Events (PT)', user=user) embed.add_field( name='\u200b', value='\n'.join([ '{} - **{}**'.format(e['date_time'], e['name']) for e in ppvs ]), ) await ctx.send(embed=embed)
async def delete_spam_messages(self, ctx): """Deletes duplicate messages in the channel. .. Note:: Messages are checked per author. The original message will remain. :param ctx: The invocation context. """ msgs = [] spam = [] async for msg in ctx.channel.history(limit=50): c = str(msg.author) + msg.content if c in msgs: spam.append(msg) else: msgs.append(c) spam.append(ctx.message) await ctx.channel.delete_messages(spam) if len(spam) > 1: embed = quickembed.info( '```Deleted {} spam messages```'.format(len(spam)), DiscordUser(ctx.author), ) self.bot.log(embed=embed)
async def unmute_member(self, ctx, member: discord.Member): """Unmutes a member by removing their `Muted` role. .. Note:: Requires `Manage Roles` privilege. .. Note:: A `Muted` role must exist with the proper permissions. It's a simple role that can only read the channels and not send messages. :param ctx: The invocation context. :param member: """ user = DiscordUser(ctx.author) role = discord.utils.find(lambda r: r.name == 'Muted', ctx.guild.roles) if not role: embed = quickembed.error(desc='`Muted` role does not exist', user=user) elif role in member.roles: await member.remove_roles(role) embed = quickembed.success(desc='Unmuted {}'.format(member), user=user) else: embed = quickembed.error( desc='{} is already unmuted'.format(member), user=user) await ctx.send(embed=embed)
async def add_discord_command(self, ctx, command, *, response): """Inserts a quick chatroom command. :param ctx: The invocation context. :param command: The command name to add. :param response: The response for the command. """ user = DiscordUser(ctx.author) command = '!{}'.format(command.strip('!')) res = user.add_chatroom_command(command, response) if res['success']: embed = quickembed.success( desc='Command `{}` updated'.format(command), user=user) else: embed = quickembed.error(desc='Failed', user=user) await ctx.send(embed=embed)
async def mock_member(self, ctx, member: discord.Member = None): """Spongebob mocking memes a Discord users last message. .. note:: The user being mocked must have a message within the last 50 messages in the channel that is not a command. Otherwise, nothing will happen. You cannot mock non-Discord user or a bot. :param ctx: The invocation context. :param member: The Discord user to mock. """ user = DiscordUser(ctx.author) if member and not member.bot: async for m in ctx.channel.history(limit=50): if m.author == member and not m.content.startswith('!'): mock_msg_list = [] alpha_cnt = 0 for letter in m.content: if not letter.isalpha(): mock_msg_list.append(letter) continue alpha_cnt += 1 if alpha_cnt % 2: mock_msg_list.append(letter.upper()) else: mock_msg_list.append(letter.lower()) mock_msg = ''.join(mock_msg_list) embed = quickembed.info('```"{}"\n - {}```'.format( mock_msg, member), user=user) await ctx.send(embed=embed) break
async def tickle_member(self, ctx, member: discord.Member = None, *, reason='no reason provided'): """Tickle another Discord user. :param ctx: The invocation context. :param member: The Discord user to tickle. :param reason: The reason for the tickle. """ user = DiscordUser(ctx.author) if not member: embed = quickembed.info( '{} tried to tickle someone, but everyone is ran away.'.format( user.mention), user=user, ) elif member.bot: embed = quickembed.info( "{} spread {}'s cheeks and tickled the inside for trying to touch a bot" .format(member.mention, user.mention), user=user, ) elif member == ctx.author: embed = quickembed.info('{} tickled themself. Pathetic..'.format( user.mention), user=user) else: embed = quickembed.info( '{} tickled {}\nReason: {}'.format(user.mention, member.mention, reason), user=user, ) await ctx.send(embed=embed)
async def user_login_link(self, ctx): """Sends a quick login link for the website to the user through DM. .. note:: This bypasses the website login by using a temporary token. The token expires once the link is used or 5 minutes has passed. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) link = user.request_login_link() msg = 'Quick login link for you! (link expires in 5 minutes)\n<{}>'.format( link) await ctx.author.send(embed=quickembed.general(desc=msg, user=user)) embed = quickembed.success(user=user, desc='Login link DMed') await ctx.send(embed=embed)
async def hug_member(self, ctx, member: discord.Member = None, *, reason='no reason provided'): """Hug another Discord user. :param ctx: The invocation context. :param member: The Discord user to hug. :param reason: The reason for the hug. """ user = DiscordUser(ctx.author) if not member: embed = quickembed.info( '{} tried to hug someone, but no one was there.'.format( user.mention), user=user, ) elif member.bot: embed = quickembed.info( "{} tried to hug a {}, but is rejected. Even bots doesn't like you." .format(user.mention, member.mention), user=user, ) elif member == ctx.author: embed = quickembed.info('{} hugged themself. Pathetic..'.format( user.mention), user=user) else: embed = quickembed.info( '{} hugged {}\nReason: {}'.format(user.mention, member.mention, reason), user=user, ) await ctx.send(embed=embed)
async def fjbucks_balance(self, ctx): """ .. Important:: Work in progress. :param ctx: The invocation context. """ await ctx.send(embed=DiscordUser(ctx.author).fjbucks_wallet_embed())
async def member_roles(self, ctx): """Displays the roles the requesting user currently has in the server. :param ctx: The invocation context. """ roles = '{}'.format([role.name for role in ctx.author.roles]) embed = quickembed.info(desc='Roles: {}'.format(roles), user=DiscordUser(ctx.author)) await ctx.send(embed=embed)
async def royalrumble_info(self, ctx): """Provides a quick login link to the Matches website's Royal Rumble page through DM. .. Note: The hyperlink can only be used once and within a short time frame before it expires. :param ctx: The invocation context. """ # response = user.royalrumble_info() # TODO: check if available to enter user = DiscordUser(ctx.author) link = user.request_login_link() link = link.replace('projects/matches?', 'projects/matches/royalrumble?') msg = 'Join the rumble here! (link expires in 5 minutes)\n<{}>'.format( link) await ctx.author.send(embed=quickembed.general(desc=msg, user=user)) embed = quickembed.success(user=user, desc='Rumble link DMed ;)') await ctx.send(embed=embed)
async def flip_coin(self, ctx): """Performs a basic coin flip and displays the result. :param ctx: The invocation context. """ result = 'Heads' if random.getrandbits(1) else 'Tails' embed = quickembed.info(desc='Coin flip', user=DiscordUser(ctx.author)) embed.add_field(name=result, value='\u200b', inline=False) await ctx.send(embed=embed)
async def roll_dice(self, ctx): """Performs a basic dice roll and returns the result. :param ctx: The invocation context. """ result = '[{}] [{}]'.format(random.randint(1, 6), random.randint(1, 6)) embed = quickembed.info(desc='Dice roll', user=DiscordUser(ctx.author)) embed.add_field(name=result, value='\u200b', inline=False) await ctx.send(embed=embed)
async def update_discord_command(self, ctx, command, *, response): """Updates a quick chatroom command. .. Note:: Only the bot owner can use this. :param ctx: The invocation context. :param command: The command name to update. :param response: The updated response for the command. """ user = DiscordUser(ctx.author) command = '!{}'.format(command.strip('!')) res = user.update_chatroom_command(command, response) if res['success']: embed = quickembed.success( desc='Command `{}` updated'.format(command), user=user) else: embed = quickembed.error(desc='Failed', user=user) await ctx.send(embed=embed)
async def uptime(self, ctx): """Display the amount of time the bot has been alive. :param ctx: The invocation context. """ embed = quickembed.info( desc='Uptime: {}'.format(datetime.now() - self.bot.start_dt), user=DiscordUser(ctx.author), ) await ctx.send(embed=embed)
async def pause_audio(self, ctx): """Pauses the audio player. :param ctx: The invocation context. """ if ctx.voice_client and ctx.voice_client.is_playing(): ctx.voice_client.pause() await ctx.send( embed=quickembed.info(desc=':mute: Paused the party :mute:', user=DiscordUser(ctx.author)))
async def stop_audio(self, ctx): """Stops the audio and leaves the voice channel. :param ctx: The invocation context. """ if ctx.voice_client: await ctx.voice_client.disconnect() await ctx.send( embed=quickembed.info(desc=':mute: Stopped the party :mute:', user=DiscordUser(ctx.author)))
async def invite(self, ctx): """Sends the Discord server invite link defined in :mod:`config`. :param ctx: The invocation context. """ embed = quickembed.info( desc='Invite Link:\n{}\n\nInvite Bot:\n{}'.format( config.base['invite']['guild'], config.base['invite']['bot']), user=DiscordUser(ctx.author), ) await ctx.send(embed=embed)
async def resume_audio(self, ctx): """Resumes the audio player. :param ctx: The invocation context. """ if ctx.voice_client and ctx.voice_client.is_paused(): ctx.voice_client.resume() await ctx.send(embed=quickembed.info( desc=':musical_note: Resumed the party :musical_note:', user=DiscordUser(ctx.author), ))
async def match_info(self, ctx, match_id=None): """Display info the `Match`. :param ctx: The invocation context. :param match_id: The `Match` id. """ user = DiscordUser(ctx.author) try: match_id = int(match_id) except Exception as e: match_id = None logger.debug('match_info: {}'.format(e)) msg = 'Invalid `!match` command\n`!match [match_id]`' await ctx.send(embed=quickembed.error(desc=msg, user=user)) if match_id: rows = user.search_match_by_id(match_id) if rows: await ctx.send(embed=Match(rows[0].id).info_embed()) else: await ctx.send(embed=quickembed.error( desc='Match `{}` not found'.format(match_id), user=user))
async def leaderboard_season3(self, ctx): """Displays the leaderboard for Season 3. :param ctx: The invocation context. """ user = DiscordUser(ctx.author) lb = user.leaderboard(season=3) embed = discord.Embed(description='Season 3', color=0x0080FF) embed.set_author( name='Leaderboard', url='https://idleuser.com/projects/matches/leaderboard?season_id=3', icon_url=self.bot.user.avatar_url, ) lb = [ '{}. {} ({:,})'.format(i + 1, l['username'], l['total_points']) for i, l in enumerate(lb[:10]) ] embed.add_field(name='\u200b', value='\n'.join(lb) if lb else 'Nothing found', inline=True) await ctx.send(embed=embed)