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 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 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 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 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 scheduler_task(self, payload): """Handles a single weekly scheduled message by creating the message and sleeping until the appropriate time defined in the message. .. important:: The channel the message is sent to is defined in :mod:`config`. Modify where appropriate for your own Discord server. :param payload: The event details to deliver. See :func:`utils.fjclasses.DbHelper.chatroom_scheduler_list`. """ try: role_name = '' embed = quickembed.info(desc='Event') embed.add_field(name=payload['message'], value='\u200b', inline=False) if payload['name'] in ['RAW', 'SmackDown', 'NXT']: channel = self.bot.get_channel(config.base['channel']['wwe']) role_name = 'WWE-{}-Squad'.format(payload['name']) elif 'AEW' in payload['name']: channel = self.bot.get_channel(config.base['channel']['aew']) role_name = 'AEW-Squad' elif 'Dev-Test' in payload['name']: channel = self.bot.get_channel( config.base['channel']['bot-test']) role_name = 'Admin' else: channel = self.bot.get_channel( config.base['channel']['general']) logger.info( 'Task scheduled - channel:`{}` name:`{}` sleep_until:`{}`'. format( channel.name, payload['name'], self.scheduled_payloads[payload['name']]['task_datetime'], )) await asyncio.sleep( self.scheduled_payloads[payload['name']]['task_wait_time']) # final check before sending message if (channel and payload['name'] in self.scheduled_payloads and payload.items() == self.scheduled_payloads[ payload['name']]['data'].items()): msg = '' if role_name: role = discord.utils.get(channel.guild.roles, name=role_name) msg = '{}'.format(role.mention) await channel.send(msg, embed=embed) if payload['tweet']: await self.bot.tweet(payload['tweet']) else: logger.info( 'Task message not sent. Payload does not match. - `{}`'. format(payload['name'])) except asyncio.CancelledError: logger.info('Task Cancelled - `{}`'.format(payload['name'])) finally: del self.scheduled_payloads[payload['name']] logger.info('Task End - `{}`'.format(payload['name']))
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 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 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 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 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 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 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 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 joined(self, ctx, member: discord.Member = None): """Displays the date the user joined the Discord server. :param ctx: The invocation context. :param member: The Discord user to display. """ member = member if member else ctx.author embed = quickembed.info( desc='{0.name} joined on `{0.joined_at}`'.format(member), user=DiscordUser(ctx.author), ) await ctx.send(embed=embed)
async def countdown(self, ctx, *, start_num=5): """Starts a basic countdown message. .. note:: The original message is updated to avoid spamming the chat. :param ctx: The invocation context. :param start_num: The number to start countdown at. Must be 10 or below. Default is 5. """ start_num = 5 if start_num > 10 else start_num user = DiscordUser(ctx.author) embed = quickembed.info(desc='Countdown', user=user) embed.add_field(name=start_num, value='\u200b', inline=False) msg = await ctx.send(embed=embed) await asyncio.sleep(1) for i in range(start_num - 1, 0, -1): embed = quickembed.info(desc='countdown', user=user) embed.add_field(name=i, value='\u200b', inline=False) await msg.edit(embed=embed) await asyncio.sleep(1) embed = quickembed.info(desc='countdown', user=user) embed.add_field(name='GO!', value='\u200b', inline=False) await msg.edit(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 punch_member(self, ctx, member: discord.Member = None, *, reason='no reason provided'): """Punch another Discord user. :param ctx: The invocation context. :param member: The Discord user to punch. :param reason: The reason for the punch. """ user = DiscordUser(ctx.author) if not member: embed = quickembed.info( '{} tried to punch someone, but no one was there.'.format( user.mention), user=user, ) elif member.bot: embed = quickembed.info( "{} tried to punch a {}, but hurt their hand instead.".format( user.mention, member.mention), user=user, ) elif member == ctx.author: embed = quickembed.info( '{} accidentally punched themself like an idiot.'.format( user.mention), user=user, ) else: embed = quickembed.info( '{} punched {}\nReason: {}'.format(user.mention, member.mention, reason), user=user, ) await ctx.send(embed=embed)
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 slap_member(self, ctx, member: discord.Member = None, *, reason='no reason provided'): """Slap another Discord user. .. note:: DO NOT ATTEMPT TO SLAP THE BOT. :param ctx: The invocation context. :param member: The Discord user to slap. :param reason: The reason for the slap. """ user = DiscordUser(ctx.author) if not member: embed = quickembed.info( "{} slapped the air. They're a different kind of special.". format(user.mention), user=user, ) elif member.bot: embed = quickembed.info( "{} slapped {}'s cheeks for trying to abuse a bot".format( member.mention, user.mention), user=user, ) elif member == ctx.author: embed = quickembed.info('You god damn m*******t', user=user) else: embed = quickembed.info( '{} slapped {}\nReason: {}'.format(user.mention, member.mention, reason), user=user, ) await ctx.send(embed=embed)
async def showtime_schedule_task(self): """Retrieves the closest event from the database and creates a scheduled message to post to a channel. .. important:: The channel the message is sent to is defined in :mod:`config`. Modify where appropriate for your own Discord server. """ await self.bot.wait_until_ready() while not self.bot.is_closed(): event_list = DbHelper().future_events() if not event_list: await asyncio.sleep(60) continue event = event_list[0] dt = datetime.datetime.now() event_start_timer = (event['date_time'] - dt).total_seconds() embed = quickembed.info(desc='Event') embed.add_field(name='{} has begun!'.format(event['name']), value='\u200b', inline=False) event_length_timer = 14400 if event['ppv']: channel = self.bot.get_channel(config.base['channel']['ppv']) else: await asyncio.sleep(60) continue logger.info( 'showtime_schedule_task: channel:`{}` events:`{}` sleep until:`{}`' .format( channel.name, event['name'], dt + datetime.timedelta(seconds=event_start_timer), )) await asyncio.sleep(event_start_timer) if channel: role = discord.utils.get(channel.guild.roles, name='PPV-Squad') await channel.send(role.mention, embed=embed) activity = discord.Activity(type=discord.ActivityType.watching, name=event['name']) tweet_msg = '{} has begun! discuss the live event with us in our WatchWrestling Discord. #WatchWrestling #discord\n\nhttps://discord.gg/U5wDzWP8yD'.format( event['name']) await self.bot.tweet(tweet_msg) await self.bot.change_presence(activity=activity) await asyncio.sleep(event_length_timer) await self.bot.change_presence(activity=None) logger.info('END showtime_schedule_task')
async def change_volume(self, ctx, volume: int): """Updates the current audio player's volume. .. Note:: The volume received is divided by 100 because the player's volume value must be a float between 0 and 1. Think of the input as a percentage. :param ctx: The invocation context. :param volume: The percentage of the audio. Should be 0-100. """ user = DiscordUser(ctx.author) if ctx.voice_client is None: await ctx.send(embed=quickembed.error( desc='Not connected to a voice channel', user=user)) ctx.voice_client.source.volume = volume / 100 await ctx.send(embed=quickembed.info( desc='Changed volume to {}%'.format(volume), user=user))
async def play_local(self, ctx, *, query): """Plays audio from a local file. .. Note:: Only the bot owner can use this. :param ctx: The invocation context. :param query: The local source file to get the audio from. """ source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(query)) ctx.voice_client.play( source, after=lambda e: logger.error('Player error: %s' % e) if e else None) await ctx.send('Now playing: {}'.format(query)) await ctx.send(embed=quickembed.info( desc='Now playing: {}'.format(query), user=DiscordUser(ctx.author)) )
async def stream_yt(self, ctx, *, url): """Plays audio directly from a YouTube stream. :param ctx: The invocation context. :param url: """ async with ctx.typing(): player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=True) ctx.voice_client.play( player, after=lambda e: logger.error('Player error: %s' % e) if e else None, ) await ctx.send(embed=quickembed.info( desc='Now playing: {}'.format(player.title), user=DiscordUser(ctx.author), ))
async def play_yt(self, ctx, *, url): """Plays audio from a YouTube stream after downloading it. .. Note:: Only the bot owner can use this. :param ctx: The invocation context. :param url: The YouTube URL to the video to stream from. """ async with ctx.typing(): player = await YTDLSource.from_url(url, loop=self.bot.loop) ctx.voice_client.play( player, after=lambda e: logger.error('Player error: %s' % e) if e else None, ) await ctx.send(embed=quickembed.info( desc='Now playing: {}'.format(player.title), user=DiscordUser(ctx.author), ))
async def scheduler_pending(self, ctx): """Displays a list of pending alert messages. .. note:: Only the bot owner can use this. :param ctx: The invocation context. """ if self.scheduled_payloads.items(): user = DiscordUser(ctx.author) embed = quickembed.info(desc="Today's Scheduled Alerts (PT)", user=user) embed.add_field( name='\u200b', value='\n'.join([ '{1} - **{0}**'.format(k, v['task_datetime']) for k, v in self.scheduled_payloads.items() ]), ) else: embed = quickembed.error(desc='Nothing scheduled for today') await ctx.send(embed=embed)