def infraction_duration(self, event, infraction, duration): try: inf = Infraction.get(id=infraction) except Infraction.DoesNotExist: raise CommandFail('invalid infraction (try `!infractions recent`)') if inf.actor_id != event.author.id and event.user_level < CommandLevels.ADMIN: raise CommandFail('only administrators can modify the duration of infractions created by other moderators') if not inf.active: raise CommandFail('that infraction is not active and cannot be updated') expires_dt = parse_duration(duration, inf.created_at) converted = False if inf.type_ in [Infraction.Types.MUTE.index, Infraction.Types.BAN.index]: inf.type_ = Infraction.Types.TEMPMUTE if inf.type_ == Infraction.Types.MUTE.index else Infraction.Types.TEMPBAN converted = True elif inf.type_ not in [Infraction.Types.TEMPMUTE.index, Infraction.Types.TEMPBAN.index, Infraction.Types.TEMPROLE.index]: raise CommandFail('cannot set the duration for that type of infraction') inf.expires_at = expires_dt inf.save() self.queue_infractions() if converted: raise CommandSuccess('ok, I\'ve made that infraction temporary, it will now expire on {}'.format( inf.expires_at.isoformat() )) else: raise CommandSuccess('ok, I\'ve updated that infractions duration, it will now expire on {}'.format( inf.expires_at.isoformat() ))
def manager_info(self, event, user, mode, item): user = self.state.users.get(user) if mode == 'add': special_list = rdb.hget('ServerManagers', '{}'.format(user.id)) temp_list = [] temp_list.append(item) final_list = str(temp_list).strip('[]') new = str('{}, {}'.format(special_list, final_list)) rdb.hset('ServerManagers', '{}'.format(user.id), new) raise CommandSuccess('{} has been added to the list of server managers'.format(user)) if mode == 'remove': special_list = rdb.hget('ServerManagers', '{}'.format(user.id)) if special_list == None: raise CommandFail('User is not a manager on any Airplane protected servers.') temp_list = special_list.split(', ') found = False for x in temp_list: if x == item: found = True temp_list.remove(item) if found == False: raise CommandFail('something went wrong, please try again later') else: new = str(temp_list).strip('[]') rdb.hset('ServerManagers', '{}'.format(user.id), new) raise CommandSuccess('The server has been removed from the list of servers the user manages.')
def random_number(self, event, end=10, start=0): """ Returns a random number """ # Because someone will be an idiot if end > 9223372036854775807: raise CommandSuccess('Ending number too big!') if end <= start: raise CommandSuccess( 'Ending number must be larger than starting number!') raise CommandSuccess(str(random.randint(start, end)))
def search(self, event, query: str): queries = [] if query.isdigit(): queries.append((User.user_id == query)) q = USER_MENTION_RE.findall(query) if len(q) and q[0].isdigit(): queries.append((User.user_id == q[0])) else: queries.append( (User.username**'%{}%'.format(query.replace('%', '')))) if '#' in query: username, discrim = query.rsplit('#', 1) if discrim is not None: queries.append(((User.username == username) & (User.discriminator == discrim))) users = User.select().where(reduce(operator.or_, queries)).limit(10) if len(users) == 0: raise CommandFail('No users found for query `{}`'.format( S(query, escape_codeblocks=True))) if len(users) == 1: if users[0].user_id in self.state.users: return self.info(event, self.state.users.get(users[0].user_id)) raise CommandSuccess( 'Found the following users for your query: ```{}```'.format( '\n'.join([ '{} ({})'.format(str(i), i.user_id) for i in users[:25] ])))
def lock_stars(self, event): if event.guild.id in self.locks: raise CommandFail('Starboard is already locked') return self.locks[event.guild.id] = True raise CommandSuccess('Starboard has been locked')
def cmd_remind(self, event, duration, content=None): if Reminder.count_for_user(event.author.id) > 15: raise CommandFail('You can only have 15 reminders going at once!') remind_at = parse_duration(duration) if remind_at > (datetime.utcnow() + timedelta(seconds=5 * YEAR_IN_SEC)): raise CommandFail('That\'s too far in the future... I\'ll forget!') if event.msg.message_reference.message_id: referenced_msg: MessageReference = event.channel.get_message( event.msg.message_reference.message_id) content = 'https://discord.com/channels/{}/{}/{}'.format( self.state.channels.get(referenced_msg.channel_id).guild_id, referenced_msg.channel_id, referenced_msg.id) elif not content: raise CommandFail( 'You need to provide content for the reminder, or reply to a message!' ) r = Reminder.create(message_id=event.msg.id, remind_at=remind_at, content=content) self.reminder_task.set_next_schedule(r.remind_at) raise CommandSuccess( 'I\'ll remind you at <t:{0}:f> (<t:{0}:R>)'.format( int(r.remind_at.replace(tzinfo=pytz.UTC).timestamp())))
def force_update_stars(self, event): # First, iterate over stars and repull their reaction count stars = StarboardEntry.select( StarboardEntry, Message).join(Message).where( (Message.guild_id == event.guild.id) & (~(StarboardEntry.star_message_id >> None))).order_by( Message.timestamp.desc()).limit(100) info_msg = event.msg.reply('Updating starboard...') for star in stars: msg = self.client.api.channels_messages_get( star.message.channel_id, star.message_id) users = [i.id for i in msg.get_reactors(STAR_EMOJI)] if set(users) != set(star.stars): self.log.warning( 'star %s had outdated reactors list (%s vs %s)', star.message_id, len(users), len(star.stars)) StarboardEntry.update( stars=users, dirty=True, ).where( (StarboardEntry.message_id == star.message_id)).execute() self.queue_update(event.guild.id, event.config) info_msg.delete() raise CommandSuccess('Starboard Updated!')
def command_sql(self, event): conn = database.obj.connection() try: tbl = MessageTable(codeblock=False) with conn.cursor() as cur: start = time.time() cur.execute(event.codeblock.format(e=event)) dur = time.time() - start if not cur.description: raise CommandSuccess('execution complete (had no return)') else: tbl.set_header(*[desc[0] for desc in cur.description]) for row in cur.fetchall(): tbl.add(*row) result = tbl.compile() if len(result) > 1900: return event.msg.reply( '_took {}ms_'.format(int(dur * 1000)), attachments=[('result.txt', result)]) event.msg.reply('```' + result + '```\n_took {}ms_\n'.format(int(dur * 1000))) except psycopg2.Error as e: event.msg.reply('```{}```'.format(e.pgerror))
def help(self, event, user=None): if not user: user = event.msg.author cmds = '' othercmds = '' for plugin in self.bot.plugins.values(): plugin_cmds = [] ungrouped_plugin_cmds = [] event.level = self.get_level(event.guild, user) for command in self.bot.commands: if command.level and (command.level != -1) and ( command.level <= event.level) and command.plugin is plugin: if command.group: plugin_cmds.append('{} {}'.format( command.group, command.name)) else: ungrouped_plugin_cmds.append(command.name) plugin_cmds = sorted(plugin_cmds) if not plugin_cmds: continue # No commands? lets go. cmds += "**{}**: {}\n".format(plugin.name.capitalize(), ', '.join(plugin_cmds)) othercmds += "{}".format(', '.join(ungrouped_plugin_cmds)) raise CommandSuccess('You can use:\n {}'.format(cmds + othercmds))
def on_play(self, event, url): g = Guild.select(Guild).where((Guild.guild_id == event.guild.id)).get() if g.premium == False: raise CommandFail('This guild does not have premium enabled, please contact an Airplane global administrator.') # item = YoutubeDLInput(url, command='ffmpeg').pipe(BufferedOpusEncoderPlayable) # self.get_player(event.guild.id).queue.append(item) item = YoutubeDLInput(url) song = item.info if song['extractor'] is 'youtube': if song['is_live']: raise CommandFail('Sorry, live streams are not supported.') if song['duration'] > 7200: raise CommandFail('Sorry you are not allowed to play songs over 2 hours.') if song['duration'] > event.config.max_song_length: raise CommandFail('Sorry, you may not go over the server time limit.') item2 = item.pipe(BufferedOpusEncoderPlayable) self.get_player(event.guild.id).queue.append(item2) song = item.info if song['extractor'] is 'youtube': if song['artist']: return event.msg.reply('Now playing **{songname}** by **{author}**. Song length is `{duration}`'.format(songname=song['alt_title'], author=song['artist'], duration=timedelta(seconds=song['duration']))) else: return event.msg.reply('Now playing **{songname}** uploaded by **{author}**. Song length is `{duration}`'.format(songname=song['title'], author=song['uploader'], duration=timedelta(seconds=song['duration']))) else: return CommandSuccess('You\'re playing a song :D')
def cmd_remind(self, event, duration, content): if Reminder.count_for_user(event.author.id) > 15: raise CommandFail('You can only have 15 reminders going at once!') remind_at = parse_duration(duration) if remind_at > (datetime.utcnow() + timedelta(seconds=5 * YEAR_IN_SEC)): raise CommandSuccess('Thats too far in the future, I\'ll forget!') r = Reminder.create(message_id=event.msg.id, remind_at=remind_at, content=content) self.reminder_task.set_next_schedule(r.remind_at) raise CommandSuccess('I\'ll remind you at {} ({})'.format( r.remind_at.isoformat(), humanize.naturaldelta(r.remind_at - datetime.utcnow()), ))
def command_markov(self, event, entity): if isinstance(entity, DiscoUser): q = Message.select().where(Message.author_id == entity.id).limit(500000) else: q = Message.select().where(Message.channel_id == entity.id).limit(500000) text = [msg.content for msg in q] self.models[entity.id] = markovify.NewlineText('\n'.join(text)) raise CommandSuccess('Created markov model for {} using {} messages'.format(entity, len(text)))
def mkick(self, event, args): members = [] failed_ids = [] for user_id in args.users: member = event.guild.get_member(user_id) if not member: #TODO: this sucks, batch these # raise CommandFail('failed to kick {}, user not found'.format(user_id)) failed_ids.append(member) continue if not self.can_act_on(event, member, throw=False): # raise CommandFail('failed to kick {}, invalid permissions'.format(user_id)) failed_ids.append(member) continue members.append(member) msg = event.msg.reply('Ok, kick {} users for `{}`?'.format( len(members), args.reason or 'no reason')) msg.chain(False).\ add_reaction(GREEN_TICK_EMOJI).\ add_reaction(RED_TICK_EMOJI) try: mra_event = self.wait_for_event( 'MessageReactionAdd', message_id=msg.id, conditional=lambda e: (e.emoji.id in (GREEN_TICK_EMOJI_ID, RED_TICK_EMOJI_ID) and e. user_id == event.author.id)).get(timeout=10) except gevent.Timeout: return finally: msg.delete() if mra_event.emoji.id != GREEN_TICK_EMOJI_ID: return for member in members: if event.config.notify_action_on: if event.config.notify_action_on.kicks: try: member.user.open_dm().send_message( 'You have been **Kicked** from the guild **{}** for `{}`' .format(event.guild.name, reason or 'no reason')) except: pass else: pass else: pass Infraction.kick(self, event, member, args.reason) raise CommandSuccess( 'kicked {} users. Was unable to remove {} users.'.format( len(members), len(failed_ids)))
def unlock_role(self, event, role_id): if role_id not in event.config.locked_roles: raise CommandFail('role %s is not locked' % role_id) if role_id in self.unlocked_roles and self.unlocked_roles[role_id] > time.time(): raise CommandFail('role %s is already unlocked' % role_id) self.unlocked_roles[role_id] = time.time() + 300 raise CommandSuccess('role is unlocked for 5 minutes')
def mban(self, event, args): members = [] failed_ids = [] for user_id in args.users: if not self.can_act_on(event, user_id, throw=False): # raise CommandFail('failed to kick {}, invalid permissions'.format(user_id)) failed_ids.append(user_id) continue members.append(user_id) msg = event.msg.reply('Ok, ban {} users for `{}`?'.format( len(members), args.reason or 'no reason')) msg.chain(False).\ add_reaction(GREEN_TICK_EMOJI).\ add_reaction(RED_TICK_EMOJI) try: mra_event = self.wait_for_event( 'MessageReactionAdd', message_id=msg.id, conditional=lambda e: (e.emoji.id in (GREEN_TICK_EMOJI_ID, RED_TICK_EMOJI_ID) and e. user_id == event.author.id)).get(timeout=10) except gevent.Timeout: return finally: msg.delete() if mra_event.emoji.id != GREEN_TICK_EMOJI_ID: return for user_id in members: if event.config.notify_action_on: if event.config.notify_action_on.bans: try: event.guild.get_member(user.id).user.open_dm( ).send_message( 'You have been **Permanently Banned** from the guild **{}** for `{}`.' .format(event.guild.name, reason or 'no reason specified.')) except: pass else: pass else: pass Infraction.ban(self, event, user_id, args.reason, guild=event.guild) raise CommandSuccess( 'banned {} users and failed to ban {} users.'.format( len(members), len(failed_ids)))
def seen(self, event, user: User): try: msg = Message.select(Message.timestamp).where( Message.author_id == user.id).order_by( Message.timestamp.desc()).limit(1).get() except Message.DoesNotExist: raise CommandFail("I've never seen {}".format(user)) raise CommandSuccess('I last saw {} {}'.format( user, int(msg.timestamp.timestamp())))
def leave_role(self, event, name): role_id = event.config.group_roles.get(name.lower()) if not role_id or role_id not in event.guild.roles: raise CommandFail('invalid or unknown group') member = event.guild.get_member(event.author) if role_id not in member.roles: raise CommandFail('you are not a member of that group') member.remove_role(role_id) raise CommandSuccess(u'you have left the {} group'.format(name))
def stars_hide(self, event, mid): count = StarboardEntry.update( blocked=True, dirty=True, ).where((StarboardEntry.message_id == mid)).execute() if not count: raise CommandFail('No starred message with that ID') self.queue_update(event.guild.id, event.config) raise CommandSuccess( 'Message {} has been hidden from the starboard'.format(mid, ))
def xp(self, event, user=None): member = user if user else event.author try: gml = GuildMemberLevel.select().where( (GuildMemberLevel.user_id == member.id) & (GuildMemberLevel.guild_id == event.guild.id)).get() except GuildMemberLevel.DoesNotExist: raise CommandFail( 'That user does not have any XP (Have they sent a message?)') raise CommandSuccess('{} is level {} ({} XP)'.format( member, self.level_from_xp(gml.xp), gml.xp))
def unban(self, event, user, reason=None): try: GuildBan.get(user_id=user, guild_id=event.guild.id) event.guild.delete_ban(user) except GuildBan.DoesNotExist: raise CommandFail('user with id `{}` is not banned'.format(user)) Infraction.create(guild_id=event.guild.id, user_id=user, actor_id=event.author.id, type_=Infraction.Types.UNBAN, reason=reason) raise CommandSuccess('unbanned user with id `{}`'.format(user))
def seen(self, event, user): try: msg = Message.select(Message.timestamp).where( Message.author_id == user.id).order_by( Message.timestamp.desc()).limit(1).get() except Message.DoesNotExist: raise CommandFail("I've never seen {}".format(user)) raise CommandSuccess( 'I last saw {} {} (at {})'. format( #TODO: Prettify this timestamp response like in inf latest user, humanize.naturaltime(datetime.utcnow() - msg.timestamp), msg.timestamp))
def nickname(self, event, user, newname=None): member = event.guild.get_member(user) if member: self.can_act_on(event, member.id) user_id = member.user.id kwargs = {} if newname == None: kwargs['nick'] = '' member.modify(**kwargs) try: raise CommandSuccess('reset {}\'s nickname.'.format( member.username)) return except: raise CommandSuccess('reset <@!{}>\'s nickname.'.format( member.user.id)) return elif (len(newname) > 32): raise CommandFail( 'invalid nickname. Nicknames must be <= 32 chars') return else: kwargs['nick'] = newname member.modify(**kwargs) try: raise CommandSuccess( 'updated {}\'s nickname to (`{}`)'.format( member.username, newname)) return except: raise CommandSuccess( 'updated <@!{}>\'s nickname to (`{}`)'.format( member.user.id, newname)) return else: raise CommandFail('invalid user')
def xp_edit(self, event, user, amount=None, action=None): member = event.guild.get_member(user) if not member: raise CommandFail('Invalid member') if not isinstance(amount, int): raise CommandFail('Invalid amount') self.can_act_on(event, member.id) if action == 'give': user = GuildMemberLevel.get().where( (GuildMemberLevel.user_id == member.id) & (GuildMemberLevel.guild_id == member.guild_id)).execute() user.add_xp(amount) raise CommandSuccess('{} was given {} XP. (New Total: `{}`)'.format( member.alias, amount, 'in dev' #Get Current Amount (do above and just pull as var w/ this amt+ added) )) elif action == 'take': user = GuildMemberLevel.get().where( (GuildMemberLevel.user_id == member.id) & (GuildMemberLevel.guild_id == member.guild_id)).execute() user.rmv_xp(amount) raise CommandSuccess('Took {} XP from {}. (New Total: `{}`)'.format( amount, member.alias, 'in dev' #Get Current Amount (do above and just pull as var w/ this amt+ added) )) else: raise CommandSuccess('not done')
def nickname(self, event, user, newname=None): member = event.guild.get_member(user) if member: victim_level = self.bot.plugins.get('CorePlugin').get_level( event.guild, user.id) if (event.user_level <= victim_level) & (user.id != event.author.id): raise CommandFail('invalid permissions') kwargs = {} if newname == None: kwargs['nick'] = '' member.modify(**kwargs) raise CommandSuccess(u'reset `{}`\'s nickname.'.format( unicode(member.user))) # try: # raise CommandSuccess(u'reset `{}`\'s nickname.'.format(member.username)) # except: # raise CommandSuccess(u'reset <@!{}>\'s nickname.'.format(member.user.id)) elif (len(newname) > 32): raise CommandFail( 'invalid nickname. Nicknames must be <= 32 chars') else: kwargs['nick'] = unicode(newname) member.modify(**kwargs) raise CommandSuccess( u'updated `{}`\'s nickname to (`{}`)'.format( unicode(member.user), unicode(newname))) # try: # raise CommandSuccess(u'updated `{}`\'s nickname to (`{}`)'.format(member.username, unicode(newname).encode('utf-8'))) # except: # raise CommandSuccess(u'updated <@!{}>\'s nickname to (`{}`)'.format(member.user.id, unicode(newname).encode('utf-8'))) else: raise CommandFail('invalid user')
def xp_unblock(self, event, user): member = event.guild.get_member(user) if member: self.can_act_on(event, member.id) success = XPBlock.delete().where( (XPBlock.guild_id == event.guild.id) & (XPBlock.user_id == user.id)).execute() if not success: raise CommandFail('{} was not blocked from gaining XP'.format( user, )) else: raise CommandFail('Invalid user') raise CommandSuccess('Unblocked {} from gaining XP.'.format(member))
def stars_unblock(self, event, entity): count = StarboardBlock.delete().where( (StarboardBlock.guild_id == event.guild.id) & (StarboardBlock.entity_id == entity.id)).execute() if not count: raise CommandFail('{} is already allowed on the starboard'.format( entity, )) # Reenable posts and stars for this user StarboardEntry.unblock(entity.id) # Finally, queue an update for the guild self.queue_update(event.guild.id, event.config) raise CommandSuccess('Allowed {} on the starboard'.format(entity, ))
def stars_unblock(self, event, user): count = StarboardBlock.delete().where( (StarboardBlock.guild_id == event.guild.id) & (StarboardBlock.user_id == user.id)).execute() if not count: raise CommandFail('{} was not blocked from the starboard'.format( user, )) # Renable posts and stars for this user StarboardEntry.unblock_user(user.id) # Finally, queue an update for the guild self.queue_update(event.guild.id, event.config) raise CommandSuccess('Unblocked {} from the starboard'.format(user, ))
def archive_extend(self, event, archive_id, duration): try: archive = MessageArchive.get(archive_id=archive_id) except MessageArchive.DoesNotExist: raise CommandFail('invalid message archive id') archive.expires_at = parse_duration(duration) MessageArchive.update(expires_at=parse_duration(duration)).where( (MessageArchive.archive_id == archive_id)).execute() raise CommandSuccess( 'duration of archive {} has been extended (<{}>)'.format( archive_id, archive.url, ))
def leave_role(self, event, name): if not event.config.group_roles: return role_id = event.config.group_roles.get(name.lower()) if not role_id or role_id not in event.guild.roles: raise CommandFail('invalid or unknown group') member = event.guild.get_member(event.author) if role_id not in member.roles: raise CommandFail('you are not a member of that group') member.remove_role(role_id) if event.config.group_confirm_reactions: event.msg.add_reaction(GREEN_TICK_EMOJI) return raise CommandSuccess(u'you have left the {} group'.format(name))
def on_tags_remove(self, event, name): try: tag = Tag.select(Tag, User).join( User, on=(User.user_id == Tag.author_id )).where((Tag.guild_id == event.guild.id) & (Tag.name == S(name))).get() except Tag.DoesNotExist: raise CommandFail('no tag by that name exists') if tag.author_id != event.author.id: if event.user_level <= event.config.min_level_remove_others: raise CommandFail( 'you do not have the required permissions to remove other users tags' ) tag.delete_instance() raise CommandSuccess(u'ok, deleted tag `{}`'.format(tag.name))