def on_message(self, message): yield from super().on_message(message) if not message.content.startswith(PREFIX): return command = Command(None, for_message=message) command.client = self.client cmd = message.content[len(PREFIX):] try: reddit_cmd = RedditCommand.objects.get(command=cmd) reddit_cmd.times_used = F('times_used') + 1 reddit_cmd.save() except RedditCommand.DoesNotExist: return allow_nsfw = self.get_nsfw_allowed(command) if reddit_cmd.nsfw and not allow_nsfw: yield from command.reply('No NSFW commands allowed here') return yield from command.send_typing() subreddit = self.reddit_bot.get_subreddit(reddit_cmd.subreddit) logger.debug('Fetched subreddit %s', reddit_cmd.subreddit) submissions = [s for s in subreddit.get_hot(limit=50)] submission = random.choice(submissions) logger.debug('Picked a submission') yield from command.reply(submission.url) logger.debug('Sent message')
def seen(self, command): if command.message.mentions: if len(command.message.mentions) > 1: yield from command.reply('Supply one user at a time') return d_member = command.message.mentions[0] member = Member.objects.filter(discord_id=d_member.id).first() username = d_member.name else: username = command.args.name member = Member.objects.filter(name__iexact=username).first() all_members = command.message.channel.server.members d_member = next( (m for m in all_members if m.name.lower() == username.lower()), None) if d_member and d_member.status == Status.online: yield from command.reply('{} is currently online'.format( d_member.name)) if member: member.last_seen = now() member.save() return if not member or not member.last_seen: yield from command.reply('Haven\'t seen {} (yet)'.format(username)) return if member: last_message = member.messages_authored.latest('timestamp') reply1 = "{name} was last seen: {last_seen} ago".format( name=username, last_seen=timesince(member.last_seen)) reply2 = "The last message was: ```{message}```".format( message=last_message.content) yield from command.reply("{}\n{}".format(reply1, reply2))
def add_status(self, command): """ Adds a new status to the database """ status, created = GameStatus.objects.get_or_create(status=command.args.status.strip()) if created: yield from command.reply('Status `{status}` added to the database.'.format(status=status)) else: yield from command.reply('Status already existed, pk: {}'.format(status.pk))
def mark_nsfw(self, command): sr = command.args.subreddit rc = RedditCommand.objects.filter(subreddit=sr, nsfw=False) if not rc.exists(): yield from command.reply('No command configured for {sr}'.format(sr=sr)) return updated = rc.update(nsfw=True) yield from command.reply('Marked **{sr}** as NSFW (affected {n} command(s))'.format(sr=sr, n=updated))
def delete_status(self, command): """ Deletes the specified status (supply the ID from !list status) """ id_ = command.args.id deleted, _ = GameStatus.objects.filter(id=id_).delete() if not deleted: yield from command.reply('Status {id} did not exist'.format(id=id_)) else: yield from command.reply('Status deleted')
def remindme(self, command): yield from command.send_typing() try: timestamp = self.parse_time(command.args.time) except ValueError: yield from command.reply("Could not parse the time \"{}\"".format(command.args.time)) return member = Member.objects.from_message(command.message) Message.objects.create(member=member, text=command.args.message, deliver_at=timestamp) yield from command.reply("I'll do so in {}".format(timeuntil(timestamp)))
def git_checkout(self, command): repo = Repo(settings.PROJECT_ROOT) branch = command.args.branch try: head = getattr(repo.heads, branch) except AttributeError: yield from command.reply('Branch `%s` does not exist' % branch) else: head.checkout() yield from command.reply('Checked out `%s`' % branch) return
def delete_status(self, command): """ Deletes the specified status (supply the ID from !list status) """ id_ = command.args.id deleted, _ = GameStatus.objects.filter(id=id_).delete() if not deleted: yield from command.reply( 'Status {id} did not exist'.format(id=id_)) else: yield from command.reply('Status deleted')
def mark_nsfw(self, command): sr = command.args.subreddit rc = RedditCommand.objects.filter(subreddit=sr, nsfw=False) if not rc.exists(): yield from command.reply( 'No command configured for {sr}'.format(sr=sr)) return updated = rc.update(nsfw=True) yield from command.reply( 'Marked **{sr}** as NSFW (affected {n} command(s))'.format( sr=sr, n=updated))
def add_status(self, command): """ Adds a new status to the database """ status, created = GameStatus.objects.get_or_create( status=command.args.status.strip()) if created: yield from command.reply( 'Status `{status}` added to the database.'.format( status=status)) else: yield from command.reply('Status already existed, pk: {}'.format( status.pk))
def allow_nsfw(self, command): discord_channel = command.message.channel if discord_channel.is_private: return channel, _ = Channel.objects.get_or_create( discord_id=discord_channel.id, defaults={'name': discord_channel.name}) if channel.allow_nsfw: yield from command.reply('Channel already allowed NSFW') return channel.allow_nsfw = True channel.save() yield from command.reply('NSFW is now allowed')
def add_subreddit(self, command): cmd, subreddit = command.args.cmd, command.args.subreddit try: sr = self.reddit_bot.get_subreddit(subreddit) nsfw = sr.over18 except praw.errors.InvalidSubreddit: yield from command.reply('Subreddit `{}` does not exist'.format(subreddit)) return reddit_cmd, created = RedditCommand.objects.get_or_create( command=cmd, defaults={'subreddit': subreddit, 'nsfw': nsfw} ) tpl = 'Added %r' if created else 'Command already exists: %r' yield from command.reply(tpl % reddit_cmd)
def stat_messages(self, command): yield from command.send_typing() queryset = Member.objects.exclude(is_bot=True).annotate(num_messages=Count('messages_authored')) top_10 = queryset.order_by('-num_messages')[:10] data = [(member.name or str(member), member.num_messages) for member in top_10] output = tabulate(data, headers=('User', 'Messages')) yield from command.reply("```\n{}\n```".format(output))
def unsubscribe_all(self, command): """ Removes all notifications subscriptions """ user = command.message.author.id deleted, _ = GameNotification.objects.filter(user=user).delete() yield from command.reply('Unsubscribed you from {num} games'.format(num=deleted))
def list_status(self, command): """ Lists all available statuses """ statuses = GameStatus.objects.values('id', 'status').order_by('id') msg = '\n'.join(['{id} - {status}'.format(**status) for status in statuses]) yield from command.reply(msg)
def sysinfo(self, command): """ Shows system/bot information """ process = psutil.Process(os.getpid()) mem_usage = process.memory_info().rss created = datetime.datetime.fromtimestamp(int(process.create_time())) repo = Repo(settings.PROJECT_ROOT) msg = ( "Uptime: `{uptime}`\n" "Memory usage: `{mem}`\n" "OS: `{system}, {release}`\n" "Current branch: `{branch}`, `{commit}`, \n`{message}`\n" ).format( mem=filesizeformat(mem_usage), uptime=timesince(created), system=platform.system(), release=platform.release(), branch=repo.active_branch.name, commit=repo.active_branch.commit.hexsha, message=repo.active_branch.commit.message, ) yield from command.reply(msg)
def sysinfo(self, command): """ Shows system/bot information """ process = psutil.Process(os.getpid()) mem_usage = process.memory_info().rss created = datetime.datetime.fromtimestamp(int(process.create_time())) repo = Repo(settings.PROJECT_ROOT) msg = ( "Uptime: `{uptime}`\n" "Memory usage: `{mem}`\n" "OS: `{system}, {release}`\n" "Current branch: `{branch}`, `{commit}`, \n`{message}`\n" "{website}, \n{github}\n" ).format( mem=filesizeformat(mem_usage), uptime=timesince(created), system=platform.system(), release=platform.release(), branch=repo.active_branch.name, commit=repo.active_branch.commit.hexsha, message=repo.active_branch.commit.message, website=settings.SITE_URL, github=settings.GITHUB_URL ) yield from command.reply(msg)
def list_status(self, command): """ Lists all available statuses """ statuses = GameStatus.objects.values('id', 'status').order_by('id') msg = '\n'.join( ['{id} - {status}'.format(**status) for status in statuses]) yield from command.reply(msg)
def migrate(self, command): """ Migrates the database forward """ out = StringIO() call_command('migrate', interactive=False, no_color=True, stdout=out) out.seek(0) yield from command.reply(out.read())
def export_stat_games(self, command): yield from command.reply('Generating file...') file_format = EXPORT_FORMATS[command.args.format or 'csv']() resource = GamesPlayedResource() dataset = resource.export(GameSession.objects.get_game_durations()) export_data = file_format.export_data(dataset) if file_format.is_binary(): _file = BytesIO(export_data) else: _file = StringIO(export_data) download = Download.objects.create(title='Games playtime') filename = '{}.{}'.format(command.command.name, file_format.get_extension()) download.file.save(filename, File(_file)) yield from command.reply('Download the file at {}'.format( download.file.url))
def unmute(self, command): user = command.message.author.id game = command.args.game updated = GameNotification.objects.filter(user=user, game_name__iexact=game).update(muted=False) if updated: msg = 'Unmuted {game} notifications' else: msg = '{game} notifications were not muted' yield from command.reply(msg.format(game=game))
def subscribe(self, command): """ Sets up notifications for <game> """ user = command.message.author.id game = command.args.game notification, created = GameNotification.objects.get_or_create(game_name=game.lower(), user=user) msg = 'Subscribed you to {game}' if created else 'You were already subscribed to {game}' yield from command.reply(msg.format(game=game))
def update_self(self, command): """ Shortcut to update current branch """ yield from command.reply('Starting full self update...') yield from self.git_pull(command) yield from self.migrate(command) yield from self.sysinfo(command) yield from self.restart(command)
def list_plugins(self, command): all_plugins = set(settings.PLUGINS) enabled = set(self.plugins) disabled = all_plugins ^ enabled msg = 'Enabled plugins: `{enabled}`\nDisabled plugins: `{disabled}`'.format( enabled='`, `'.join(enabled), disabled='`, `'.join(disabled) ) yield from command.reply(msg)
def unsubscribe(self, command): """ Removes notification subscription for <game> """ user = command.message.author.id game = command.args.game deleted, _ = GameNotification.objects.filter(user=user, game_name__iexact=game).delete() if deleted: yield from command.reply('Unsubscribed you from {game}'.format(game=game))
def add_subreddit(self, command): cmd, subreddit = command.args.cmd, command.args.subreddit try: sr = self.reddit_bot.get_subreddit(subreddit) nsfw = sr.over18 except praw.errors.InvalidSubreddit: yield from command.reply( 'Subreddit `{}` does not exist'.format(subreddit)) return reddit_cmd, created = RedditCommand.objects.get_or_create( command=cmd, defaults={ 'subreddit': subreddit, 'nsfw': nsfw }) tpl = 'Added %r' if created else 'Command already exists: %r' yield from command.reply(tpl % reddit_cmd)
def til(self, command): """ Shows a random submission from r/todayilearned """ yield from command.send_typing() subreddit = self.reddit_bot.get_subreddit(self.options['subreddit']) logger.debug('Fetched subreddit') submissions = [s for s in subreddit.get_hot(limit=50) if s.url] submission = random.choice(submissions) logger.debug('Picked a submission') yield from command.reply('{title}\n{url}'.format(url=submission.url, title=submission.title))
def daisy(self, command): """ Shows a random submission from r/DaisyRidley """ yield from command.send_typing() subreddit = self.reddit_bot.get_subreddit(self.options['subreddit']) logger.debug('Fetched subreddit') submissions = [s for s in subreddit.get_hot(limit=50) if 'imgur' in s.url] submission = random.choice(submissions) logger.debug('Picked a submission') yield from command.reply(submission.url) logger.debug('Sent message')
def change_status(self, command): """ Randomly picks a new status """ status = command.args.status if not status: status = GameStatus.objects.order_by('?').values_list('status', flat=True).first() if status is None: yield from command.reply('I have no known statuses...') return game = Game(name=status) yield from self.client.change_status(game=game, idle=False)
def change_status(self, command): """ Randomly picks a new status """ status = command.args.status if not status: status = GameStatus.objects.order_by('?').values_list( 'status', flat=True).first() if status is None: yield from command.reply('I have no known statuses...') return game = Game(name=status) yield from self.client.change_status(game=game, idle=False)
def list_subreddits(self, command): i = 0 buffer_ = [] commands = RedditCommand.objects.all() allow_nsfw = self.get_nsfw_allowed(command) if not allow_nsfw: commands = commands.filter(nsfw=False) for reddit_cmd in commands: i += 1 line = '{i}. {cmd} ({used}x used)'.format( i=i, cmd=reddit_cmd, used=reddit_cmd.times_used) if reddit_cmd.nsfw: line = '{} **NSFW**'.format(line) buffer_.append(line) if len(buffer_) % 10 == 0: yield from command.reply("\n".join(buffer_)) buffer_ = [] if len(buffer_): yield from command.reply("\n".join(buffer_))
def daisy(self, command): """ Shows a random submission from r/DaisyRidley """ yield from command.send_typing() subreddit = self.reddit_bot.get_subreddit(self.options['subreddit']) logger.debug('Fetched subreddit') submissions = [ s for s in subreddit.get_hot(limit=50) if 'imgur' in s.url ] submission = random.choice(submissions) logger.debug('Picked a submission') yield from command.reply(submission.url) logger.debug('Sent message')
def list(self, command): """ Lists the current notification subscriptions """ user = command.message.author.id games = GameNotification.objects.filter(user=user).values('game_name', 'muted') _games = [] for game in games: _games.append( '{name}{muted}'.format(name=game['game_name'], muted=' (muted)' if game['muted'] else '') ) msg = 'You\'re subscribed to: {games}'.format(games=', '.join(_games)) yield from command.reply(msg)
def list(self, command): """ Lists the current notification subscriptions """ user = command.message.author.id games = GameNotification.objects.filter(user=user).values('game_name', 'muted') _games = [] for game in games: _games.append( '{name}{muted}'.format(name=game['game_name'], muted=' (muted)' if game['muted'] else '') ) msg = 'You\'re susbcribed to: {games}'.format(games=', '.join(_games)) yield from command.reply(msg)
def restart(self, command): """ Restarts the bot. Check that the person sending the command has permission to restart the bot. We rely on ``supervisord`` here - if the process dies, supervisord will bring it back up. FIXME: https://docs.python.org/3/library/asyncio-dev.html#pending-task-destroyed """ author_id = command.message.author.id logger.info('Restart issued by %s, with ID %s', command.message.author.name, author_id) yield from command.send_typing() yield from command.reply('Restarting...') raise KeyboardInterrupt
def list_subreddits(self, command): i = 0 buffer_ = [] commands = RedditCommand.objects.all() allow_nsfw = self.get_nsfw_allowed(command) if not allow_nsfw: commands = commands.filter(nsfw=False) for reddit_cmd in commands: i += 1 line = '{i}. {cmd} ({used}x used)'.format( i=i, cmd=reddit_cmd, used=reddit_cmd.times_used ) if reddit_cmd.nsfw: line = '{} **NSFW**'.format(line) buffer_.append(line) if len(buffer_) % 10 == 0: yield from command.reply("\n".join(buffer_)) buffer_ = [] if len(buffer_): yield from command.reply("\n".join(buffer_))
def help(self, command): help_messages = [] for module, plugin in self.client._method_pool.plugin_modules.items(): if plugin is self: # TODO: FIXME continue msgs = [cmd.as_help() for cmd in get_commands(plugin)] if not msgs: continue help_messages += [ '**{plugin}**'.format(plugin=module_to_plugin_name(module)) ] + msgs + [''] msg = '\n'.join(help_messages) yield from command.reply(msg)
def stat_games(self, command): yield from command.send_typing() games = GameSession.objects.get_game_durations()[:15] def format_delta(delta): hours, seconds = divmod(delta.seconds, 3600) minutes, seconds = divmod(seconds, 60) min_minutes = not hours and not delta.days return "{days} days, {hours} hours, {minutes} minutes".format( days=delta.days, hours=hours, minutes=max(1, minutes) if min_minutes else minutes) data = [(game['game__name'], format_delta(game['time'])) for game in games] yield from command.reply("```\n{}\n```".format( tabulate(data, headers=('Game', 'Time'))))
def stat_games(self, command): yield from command.send_typing() games = GameSession.objects.filter(duration__isnull=False).values('game__name').annotate( time=Sum('duration'), num_players=Count('member', distinct=True) ).filter(num_players__gt=1).order_by('-time')[:15] def format_delta(delta): hours, seconds = divmod(delta.seconds, 3600) minutes, seconds = divmod(seconds, 60) min_minutes = not hours and not delta.days return "{days} days, {hours} hours, {minutes} minutes".format( days=delta.days, hours=hours, minutes=max(1, minutes) if min_minutes else minutes) data = [ (game['game__name'], format_delta(game['time'])) for game in games ] yield from command.reply("```\n{}\n```".format(tabulate(data, headers=('Game', 'Time'))))
def discord_id(self, command): member = command.message.author yield from command.reply('{0.mention}: {0.id}'.format(member))
def list(self, command): user = command.message.author.id games = GameNotification.objects.filter(user=user).values_list('game_name', flat=True) msg = 'You\'re susbcribed to: {games}'.format(games=', '.join(games)) yield from command.reply(msg)
def git_pull(self, command): repo = Repo(settings.PROJECT_ROOT) repo.remotes.origin.pull() yield from command.reply('Pulled the latest commits')
def penis(self, command): length = random.choice(range(3, 15)) yield from command.reply('8{length}3'.format(length='='*length))
def whoinvented(self, command): guspetti = find(lambda m: m.id == '104532370899611648', command.message.server.members) yield from command.reply( "According to {guspetti}, {word} was invented by the Romans in Rome" .format(guspetti=guspetti.mention, word=command.args.subject))
def penis(self, command): """ Draws an ASCII penis """ length = random.choice(range(3, 15)) yield from command.reply('8{length}D'.format(length='='*length))