Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
    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")
Beispiel #5
0
 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),
         )
Beispiel #6
0
 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)
Beispiel #7
0
    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()
Beispiel #8
0
    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,
        )
Beispiel #9
0
 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
Beispiel #10
0
 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
Beispiel #11
0
 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)
Beispiel #12
0
 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)
Beispiel #13
0
    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
Beispiel #14
0
    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
Beispiel #15
0
 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
Beispiel #16
0
 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
Beispiel #17
0
    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")
Beispiel #18
0
 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
Beispiel #19
0
    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
Beispiel #20
0
    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
Beispiel #21
0
 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
Beispiel #22
0
    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