def func_ban_member(self, args, extra={}): if len(args) == 0: return "Invalid User", None member = self.get_member(args[0][3:][:-1]) author = extra["author"] if not member: return "Member not found", None with DBManager.create_session_scope() as db_session: author_user = User._create_or_get_by_discord_id( db_session, str(author.id), user_name=str(author)) member_user = User._create_or_get_by_discord_id( db_session, str(member.id), user_name=str(member)) if author.id == member.id: return "You cannot ban yourself :)", None if author_user.level == member_user.level: return "You cannot ban someone who has the same level as you :)", None elif author_user.level < member_user.level: return "You cannot ban someone who is a higher level than you :)", None timeout_in_seconds = int( args[1] if len(args) > 2 and args[1] != "" else 0) delete_message_days = int( args[2] if len(args) > 3 and args[2] != "" else 0) reason = args[3] if len(args) == 4 else "" message = f"Member {member.mention} has been banned!" self.ban( user=member, timeout_in_seconds=timeout_in_seconds, delete_message_days=delete_message_days, reason=f"{reason}\nBanned by {author}", ) return message, None
def wait_discord_load(self): self.socket_manager = SocketManager(self.bot_name, self.execute_now) self.module_manager = ModuleManager(self.socket_manager, bot=self).load() self.commands = CommandManager( socket_manager=self.socket_manager, module_manager=self.module_manager, bot=self, ).load() HandlerManager.trigger("manager_loaded") # promote the admin to level 2000 owner = self.config["main"].get("owner_id", None) if owner is None: log.warning( "No admin user specified. See the [main] section in the example config for its usage." ) else: with DBManager.create_session_scope() as db_session: owner = User._create_or_get_by_discord_id( db_session, str(owner)) if owner is None: log.warning( "The login name you entered for the admin user does not exist on twitch. " "No admin user has been created.") else: owner.level = 2000
async def func_level(self, args, extra={}): if len(args) != 2: return "Invalid Comand Args", None member = self.filters.get_member([args[0]], None, {})[0] if not member: return f"Invalid Member {args[0]}", None if member == extra["author"]: return "You cannot edit your own level :)", None level = args[1] try: level = int(level) except ValueError: return f"Invalid level (1-2000) {args[1]}", None if level >= extra["user_level"]: return "You cannot set a level higher then your own!", None with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(member.id), str(member)) if user.level >= extra["user_level"]: return ( "You cannot set a level of a user with a higher then your own!", None, ) user.level = level return f"Level, {level}, set for {member.mention}!", None
async def run_action(self, bot, author, channel, message, args): cur_time = greenbot.utils.now().timestamp() with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(author.id), str(author)) with user.spend_currency_context( self.cost if args["user_level"] < Command.BYPASS_DELAY_LEVEL else 0): ret = await self.action.run(bot, author, channel, message, args) if not ret: raise FailedCommand("return currency") # Only spend points, and increment num_uses if the action succeded if self.data is not None: self.data.num_uses += 1 self.data.last_date_used = greenbot.utils.now() # TODO: Will this be an issue? self.last_run = cur_time self.last_run_by_user[str(author.id)] = cur_time if ret == "return currency": db_session.commit() raise FailedCommand("return currency")
async def on_message(self, message): member = self.bot.guild.get_member(message.author.id) if isinstance(message.author, discord.Member) and ( message.guild != self.bot.guild ): return with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id( db_session, message.author.id, user_name=str(member) if member else str(message.author), ) Message._create( db_session, message.id, message.author.id, message.channel.id if isinstance(message.author, discord.Member) else None, message.content, ) db_session.commit() HandlerManager.trigger( "discord_message", message_raw=message, message=message.content, author=message.author, user_level=user.level if user else 50, channel=message.channel if isinstance(message.author, discord.Member) else None, whisper=not isinstance(message.author, discord.Member), )
def process_messages(self): with DBManager.create_session_scope() as db_session: regular_role = self.bot.get_role(self.settings["regular_role_id"]) sub_role = self.bot.get_role(self.settings["sub_role_id"]) for member in regular_role.members: count = Message._get_week_count_user(db_session, str(member.id)) if (count < self.settings["min_msgs_per_week"] or sub_role not in member.roles): self.bot.remove_role(member, regular_role) db_session.commit() messages = Message._get_last_hour(db_session) channels_to_listen_in = self.settings[ "channels_to_listen_in"].split(" ") if len( self.settings["channels_to_listen_in"]) != 0 else [] for message in messages: if message.channel_id not in channels_to_listen_in and len( channels_to_listen_in) != 0: continue count = Message._get_day_count_user(db_session, message.user_id) if message.user_id != str(self.bot.bot_id): if count < self.settings["daily_max_msgs"] - 1: message.user.points += self.settings["hourly_credit"] elif count == self.settings["daily_max_msgs"] - 1: message.user.points += self.settings["daily_limit"] message.credited = True db_session.commit() for user in User._get_users_with_points( db_session, self.settings["min_regular_points"]): member = self.bot.get_member(user.discord_id) if (not member or sub_role not in member.roles or regular_role in member.roles): continue self.bot.add_role(member, regular_role)
def get(id): with DBManager.create_session_scope() as db_session: user = User.find_by_id(db_session, id) if user is None: return {"error": "Not found"}, 404 # the aliases like above are not needed here since this API endpoint is new since version 1.38 return user.jsonify()
async def on_message(self, message): member = self.bot.discord_bot.get_member(message.author.id) not_whisper = isinstance(message.author, discord.Member) if not_whisper and (message.guild != self.bot.discord_bot.guild): return if not member: return with DBManager.create_session_scope() as db_session: User._create_or_get_by_discord_id(db_session, str(member.id), str(member)) db_session.commit() if self.new_message(db_session, message) is None: log.error("Discord api running slow?") return db_session.commit() current_timeout = Timeout._is_timedout(db_session, str(member.id)) if current_timeout and not_whisper: await message.delete() await self.bot.timeout_manager.apply_timeout( member, current_timeout) return user_level = self.bot.psudo_level_member(db_session, member) if message.author.id == self.bot.discord_bot.client.user.id: return if user_level < 500: matched_phrase = self.bot.banphrase_manager.check_message( message.content) if matched_phrase: await self.bot.banphrase_manager.punish(member, matched_phrase) await message.delete() return await HandlerManager.trigger( "parse_command_from_message", message=message, content=message.content, user_level=user_level, author=message.author, not_whisper=not_whisper, channel=message.channel, )
def get_user(self, key, extra={}): user = (self.get_member(extra["argument"][3:][:-1]) if extra["argument"] else None) if not user: user = extra["author"] with DBManager.create_session_scope() as db_session: db_user = User._create_or_get_by_discord_id(db_session, user.id) return getattr(db_user, key) if db_user else None
def func_kick_member(self, args, extra={}): author = extra["author"] if len(args) == 0: return "Invalid User", None member = self.get_member(args[0][3:][:-1]) if not member: return "Member not found", None with DBManager.create_session_scope() as db_session: author_user = User._create_or_get_by_discord_id( db_session, str(author.id), user_name=str(author)) member_user = User._create_or_get_by_discord_id( db_session, str(member.id), user_name=str(member)) if author_user.level <= member_user.level: return "You cannot kick someone who has the same level as you :)", None reason = args[1] if len(args) > 1 else "" message = f"Member {member} has been kicked!" self.kick(member, f"{reason}\nKicked by {author}") return message, None
def discord_auth(): discord.callback() user = discord.fetch_user() with DBManager.create_session_scope(expire_on_commit=False) as db_session: session["user"] = User._create_or_get_by_discord_id( db_session, str(user.id), str(user) ).jsonify() session["user_displayname"] = str(user) next_url = session.get("state", "/") return redirect(next_url)
def psudo_level_member(self, db_session, member): user_level = 100 user = User._create_or_get_by_discord_id(db_session, str(member.id), str(member)) for role_id in self.roles: role = self.filters.get_role([role_id], None, {})[0] if not role: continue if role in member.roles: user_level = max(int(user_level), int(self.roles[role_id])) return max(user_level, user.level)
def run(self, bot, author, channel, message, args): if self.action is None: log.warning("This command is not available.") return False if args["user_level"] < self.level: # User does not have a high enough power level to run this command return False if args["whisper"] and self.can_execute_with_whisper is False: # This user cannot execute the command through a whisper return False cd_modifier = 0.2 if args["user_level"] >= 500 else 1.0 cur_time = greenbot.utils.now().timestamp() time_since_last_run = (cur_time - self.last_run) / cd_modifier if (time_since_last_run < self.delay_all and args["user_level"] < Command.BYPASS_DELAY_LEVEL): log.debug( f"Command was run {time_since_last_run:.2f} seconds ago, waiting..." ) return False time_since_last_run_user = (cur_time - self.last_run_by_user.get( str(author.id), 0)) / cd_modifier if (time_since_last_run_user < self.delay_user and args["user_level"] < Command.BYPASS_DELAY_LEVEL): log.debug( f"{author.name}#{author.discriminator} ran command {time_since_last_run_user:.2f} seconds ago, waiting..." ) return False with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(author.id), str(author)) if self.cost > 0 and not user.can_afford(self.cost): # User does not have enough points to use the command return False args.update(self.extra_args) if self.run_in_thread: log.debug(f"Running {self} in a thread") ScheduleManager.execute_now( self.run_action, args=[bot, author, channel, message, args]) else: self.run_action(bot, author, channel, message, args) return True
def get(login): # add ?user_input=true to query user more fuzzily query_by_user_input = request.args.get("user_input") == "true" with DBManager.create_session_scope() as db_session: if query_by_user_input: user = User.find_by_user_input(db_session, login) else: user = User.find_by_login(db_session, login) if user is None: return {"error": "Not found"}, 404 # these are provided for legacy purposes - so we don't break the API interface. json = user.jsonify() json["username_raw"] = json["name"] json["username"] = json["login"] json["nl_rank"] = json["num_lines_rank"] json["minutes_in_chat_online"] = int(json["time_in_chat_online"] / 60) json["minutes_in_chat_offline"] = int( json["time_in_chat_offline"] / 60) return json
def func_set_balance(self, args, extra={}): if len(args) == 0: return "Invalid User", None user_id = args[0][3:][:-1] try: amount = int(args[1]) except: return f"Invalid points amount", None with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(user_id)) user.points = amount currency = self._get_currency().get("name").capitalize() return f"{currency} balance for <@!{user_id}> set to {amount}", None
def func_adj_balance(self, args, extra={}): if len(args) == 0: return "Invalid User", None user_id = args[0][3:][:-1] try: amount = int(args[1]) except: return f"Invalid points amount", None with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(user_id)) user.points += amount action = "added to" if amount > 0 else "removed from" currency = self._get_currency().get("name") return f"{amount} {currency} {action} <@!{user_id}> ", None
async def process_messages(self): with DBManager.create_session_scope() as db_session: regular_role = self.bot.filters.get_role( [self.settings["regular_role_id"]], None, {})[0] sub_role = self.bot.filters.get_role( [self.settings["sub_role_id"]], None, {})[0] counts_by_week = Message._get_week_count_by_user(db_session) for member in regular_role.members: count = counts_by_week.get(str(member.id), 0) if (count < self.settings["min_msgs_per_week"] or sub_role not in member.roles): await self.bot.remove_role( member, regular_role, "They failed to meet the requirements to keep the role" ) channels_to_listen_in = ( self.settings["channels_to_listen_in"].split(" ") if len(self.settings["channels_to_listen_in"]) != 0 else None) messages = Message._get_last_hour(db_session, channels_to_listen_in) counts_by_day = Message._get_day_count_by_user(db_session) for message in messages: count = counts_by_day.get(message.user_id, 0) if message.user_id != str(self.bot.bot_id): if count < self.settings["daily_max_msgs"] - 1: message.user.points += self.settings["hourly_credit"] elif count == self.settings["daily_max_msgs"] - 1: message.user.points += self.settings["daily_limit"] message.credited = True counts_by_day[message.user_id] = count + 1 for user in User._get_users_with_points( db_session, self.settings["min_regular_points"]): member = self.bot.filters.get_member([user.discord_id], None, {})[0] if not member: continue count = counts_by_week.get(str(member.id), 0) if (sub_role not in member.roles or (regular_role in member.roles or count < self.settings["min_msgs_per_week"])): continue await self.bot.add_role( member, regular_role, "They met the requirements to get the role")
def func_level(self, args, extra={}): if len(args) == 0: return "Invalid User", None member_id = args[0][3:][:-1] level = args[1] if len(args) >= 2 else None try: level = int(level) except: return "Invalid level (1-2000)", None if level >= extra["user_level"]: return "You cannot set a level higher then your own!", None with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(member_id)) if user.level >= extra["user_level"]: return "You cannot set a level of a user with a higher then your own!", None user.level = level return f"Level, {level}, set for <@!{member_id}>", None
async def func_set_balance(self, args, extra={}): if len(args) != 2: return "Invalid Comand Args", None member = self.filters.get_member([args[0]], None, {})[0] if not member: return f"Invalid Member {args[0]}", None try: amount = int(args[1]) except ValueError: return ( f"Invalid points amount, please enter a valid positive integer not {args[0]}", None, ) with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(member.id), str(member)) user.points = amount currency = self.bot.get_currency().get("name").capitalize() return f"{currency} balance for {member.mention} set to {amount}", None
async def func_adj_balance(self, args, extra={}): if len(args) != 2: return "Invalid Comand Args", None member = self.filters.get_member([args[0]], None, {})[0] if not member: return f"Invalid Member {args[0]}", None try: amount = int(args[1]) except ValueError: return ( f"Invalid points amount, please enter a valid positive integer not {args[0]}", None, ) with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(member.id), str(member)) user.points += amount action = "added to" if amount > 0 else "removed from" currency = self.bot.get_currency().get("name") return f"{amount} {currency} {action} {member.mention} ", None
def get_user(self, args, key, extra): member = self.get_member([args[0]], None, extra)[0] with DBManager.create_session_scope() as db_session: db_user = User._create_or_get_by_discord_id( db_session, member.id, str(member)) return getattr(db_user, key) if key and db_user else db_user, None
async def run(self, bot, author, channel, message, args): if self.action is None: log.warning("This command is not available.") return False if args["user_level"] < self.level: # User does not have a high enough power level to run this command return False if args["whisper"] and self.can_execute_with_whisper is False: # This user cannot execute the command through a whisper return False cd_modifier = 0.2 if args["user_level"] >= 500 else 1.0 load_channels = json.loads(self.channels) if channel and str( channel.id) not in load_channels and len(load_channels) > 0: return False cur_time = greenbot.utils.now().timestamp() time_since_last_run = (cur_time - self.last_run) / cd_modifier if (time_since_last_run < self.delay_all and args["user_level"] < Command.BYPASS_DELAY_LEVEL): await bot.private_message( user=author, message= f"The command **{self.command}** was executed too recently please try again in {greenbot.utils.seconds_to_resp(int(self.delay_all-time_since_last_run))}", ignore_escape=True) return False time_since_last_run_user = (cur_time - self.last_run_by_user.get( str(author.id), 0)) / cd_modifier if (time_since_last_run_user < self.delay_user and args["user_level"] < Command.BYPASS_DELAY_LEVEL): await bot.private_message( user=author, message= f"You executed the command **{self.command}** too recently please try again in {greenbot.utils.seconds_to_resp(int(self.delay_user-time_since_last_run_user))}", ignore_escape=True) return False with DBManager.create_session_scope() as db_session: user = User._create_or_get_by_discord_id(db_session, str(author.id), str(author)) if self.cost > 0 and not user.can_afford( self.cost ) and args["user_level"] < Command.BYPASS_DELAY_LEVEL: # User does not have enough points to use the command await bot.private_message( user=author, message= f"You need {self.cost} points to execute that command", ignore_escape=True) return False args.update(self.extra_args) if self.run_in_thread: log.debug(f"Running {self} in a thread") await ScheduleManager.execute_now( self.run_action, args=[bot, author, channel, message, args]) else: await self.run_action(bot, author, channel, message, args) return True