Esempio n. 1
0
    def on_banphrase_update(self, data):
        try:
            banphrase_id = int(data["id"])
        except (KeyError, ValueError):
            log.warning("No banphrase ID found in on_banphrase_update")
            return False

        updated_banphrase = find(
            lambda banphrase: banphrase.id == banphrase_id, self.banphrases)
        if updated_banphrase:
            with DBManager.create_session_scope(
                    expire_on_commit=False) as db_session:
                db_session.add(updated_banphrase)
                db_session.refresh(updated_banphrase)
                db_session.expunge(updated_banphrase)
        else:
            with DBManager.create_session_scope(
                    expire_on_commit=False) as db_session:
                updated_banphrase = (db_session.query(Banphrase).filter_by(
                    id=banphrase_id).one_or_none())
                db_session.expunge_all()
                if updated_banphrase is not None:
                    self.db_session.add(updated_banphrase.data)

        if updated_banphrase:
            if updated_banphrase not in self.banphrases:
                self.banphrases.append(updated_banphrase)
            if (updated_banphrase.enabled is True
                    and updated_banphrase not in self.enabled_banphrases):
                self.enabled_banphrases.append(updated_banphrase)

        for banphrase in self.enabled_banphrases:
            if banphrase.enabled is False:
                self.enabled_banphrases.remove(banphrase)
Esempio n. 2
0
    def __init__(self, config, args):
        self.config = config
        self.args = args
        self.private_loop = asyncio.get_event_loop()
        self.private_loop.set_exception_handler(custom_exception_handler)

        self.discord_token = self.config["main"]["discord_token"]

        ScheduleManager.init(self.private_loop)

        DBManager.init(self.config["main"]["db"])

        ActionParser.bot = self

        # redis
        redis_options = {}
        if "redis" in config:
            redis_options = dict(config.items("redis"))
        RedisManager.init(**redis_options)
        utils.wait_for_redis_data_loaded(RedisManager.get())

        # SQL migrations
        try:
            with DBManager.create_dbapi_connection_scope() as sql_conn:
                sql_migratable = DatabaseMigratable(sql_conn)
                sql_migration = Migration(sql_migratable,
                                          greenbot.migration_revisions.db,
                                          self)
                sql_migration.run()
        except ValueError as error:
            log.error(error)

        HandlerManager.init_handlers()

        self.movienight_api = MovieNightAPI(self, self.config["wsc"],
                                            self.config["wowza_cdn"])

        HandlerManager.add_handler("parse_command_from_message",
                                   self.parse_command_from_message)
        self.bot_name = self.config["main"]["bot_name"]
        self.command_prefix = self.config["discord"]["command_prefix"]
        self.settings = {
            "discord_token": self.discord_token,
            "bot_name": self.bot_name,
            "command_prefix": self.command_prefix,
            "discord_guild_id": self.config["discord"]["discord_guild_id"],
        }

        HandlerManager.add_handler("discord_ready", self.wait_discord_load)

        self.discord_bot = DiscordBotManager(
            bot=self,
            settings=self.settings,
            redis=RedisManager.get(),
            private_loop=self.private_loop,
        )
        self.twitter_manager = TwitterManager(self)
        self.filters = Filters(self, self.discord_bot)
        self.functions = Functions(self, self.filters)
Esempio n. 3
0
 def edit_command(self, command_to_edit, **options):
     if "group" in options:
         self.remove_command_aliases(command_to_edit)
     command_to_edit.set(**options)
     command_to_edit.data.set(**options)
     DBManager.session_add_expunge(command_to_edit)
     if "group" in options:
         self.add_db_command_aliases(command_to_edit)
     self.commit()
     self.rebuild()
Esempio n. 4
0
    async def giveaway_start(self, bot, author, channel, message, args):
        with DBManager.create_session_scope() as db_session:
            current_giveaway = Giveaway._get_current_giveaway(db_session)
            if current_giveaway:
                await self.bot.say(
                    channel=channel,
                    message=
                    "There is already a giveaway running. Please use !wipegiveaway before you start a new one. (Don't forget to chose a winner before you end!)",
                    ignore_escape=True)
                return False

            desc_array = re.findall(r'"([^"]*)"', message)
            if not len(desc_array) == 2:
                await self.bot.say(
                    channel=channel,
                    message=
                    'Please set 2 arguments between quotation marks. `!startgiveaway "<item>" "<deadline>"`\nExample: `!startgiveaway "a new GTX2900" "10 days"`',
                    ignore_escape=True)
                return False

            if Giveaway._create(db_session, str(author.id), desc_array[0],
                                desc_array[1]):
                await self.bot.say(
                    channel=channel,
                    message=
                    "New giveaway was started! Use !giveawaywinner to chose a winner when the time has passed.",
                    ignore_escape=True)
                return True

            await self.bot.say(
                channel=channel,
                message=
                "An unknown error has occurred, please contact a moderator",
                ignore_escape=True)
            return False
Esempio n. 5
0
    def post(self, row_id, **options):
        args = self.post_parser.parse_args()

        try:
            new_state = int(args["new_state"])
        except (ValueError, KeyError):
            return {"error": "Invalid `new_state` parameter."}, 400

        with DBManager.create_session_scope() as db_session:
            row = db_session.query(Module).filter_by(id=row_id).one_or_none()

            if not row:
                return {"error": "Module with this ID not found"}, 404

            if validate_module(row_id) is False:
                return {"error": "cannot modify module"}, 400

            row.enabled = True if new_state == 1 else False
            db_session.commit()
            payload = {"id": row.id, "new_state": row.enabled}
            AdminLogManager.post(
                "Module toggled",
                options["user"].discord_id,
                "Enabled" if row.enabled else "Disabled",
                row.id,
            )
            SocketClientManager.send("module.update", payload)
            return {"success": "successful toggle", "new_state": new_state}
Esempio n. 6
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),
         )
Esempio n. 7
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
Esempio n. 8
0
    async def untimeout_user(self, bot, author, channel, message, args):
        command_args = message.split(" ") if message else []
        if len(command_args) == 0:
            await self.bot.say(
                channel=channel,
                message=f"!untimeout (here) <User mention> (reason...)")
            return False

        member = self.bot.filters.get_member([command_args[0]], None, {})[0]
        if not member:
            await self.bot.say(channel=channel,
                               message=f"Cant find member, {command_args[0]}")
            return False

        unban_reason = " ".join(command_args[1:])

        with DBManager.create_session_scope() as db_session:
            success, resp = await self.bot.timeout_manager.untimeout_user(
                db_session, member, author, unban_reason)
            if success:
                await self.bot.say(
                    channel=channel,
                    message=f"Member {member.mention} has been untimedout")
                return True

            self.bot.say(channel=channel, message=resp)
            return False
Esempio n. 9
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
Esempio n. 10
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")
Esempio n. 11
0
    def load(self, do_reload=True):
        """ Load module classes """

        from greenbot.modules import available_modules

        self.all_modules = [module(self.bot) for module in available_modules]

        with DBManager.create_session_scope() as db_session:
            # Make sure there's a row in the DB for each module that's available
            db_modules = db_session.query(Module).all()
            for module in self.all_modules:
                mod = find(
                    lambda db_module, registered_module=module: db_module.id ==
                    registered_module.ID,
                    db_modules,
                )
                if mod is None:
                    log.info(f"Creating row in DB for module {module.ID}")
                    mod = Module(module.ID, enabled=module.ENABLED_DEFAULT)
                    db_session.add(mod)

        if do_reload is True:
            self.reload()

        return self
Esempio n. 12
0
    async def initial_unbans(self):
        try:
            data = json.loads(self.redis.get(f"{self.bot.bot_name}:timeouts-discord"))
            for user in data:
                unban_date = utils.parse_date(data[user]["unban_date"])
                time_now = utils.now()
                resp_timeout = data.get("resp_timeout", "")
                resp_timeout += " after " if resp_timeout else ""
                if unban_date < time_now:
                    ScheduleManager.execute_now(
                        method=self.unban,
                        args=[
                            data[user]["discord_id"],
                            f"Unbanned by timer{resp_timeout}",
                        ],
                    )
                    continue
                ScheduleManager.execute_delayed(
                    delay=(unban_date - time_now).seconds,
                    method=self.unban,
                    args=[data[user]["discord_id"], f"Unbanned by timer{resp_timeout}"],
                )
        except Exception as e:
            log.exception(e)
            self.redis.set(f"{self.bot.bot_name}:timeouts-discord", json.dumps({}))

        with DBManager.create_session_scope() as db_session:
            unnamed_users = db_session.query(User).filter_by(user_name="").all()
            for user in unnamed_users:
                member = self.get_member(int(user.discord_id))
                if not member:
                    db_session.delete(user)
                    continue

                user.user_name = str(member)
Esempio n. 13
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
Esempio n. 14
0
    async def func_kick_member(self,
                               args,
                               extra={}
                               ):  # !kick <member_mention> <reason....>
        if len(args) != 2:
            return "Invalid Comand Args", None

        author = extra["author"]
        member = self.filters.get_member([args[0]], None, {})[0]
        if not member:
            return "Member not found", None

        with DBManager.create_session_scope() as db_session:
            if extra["user_level"] < self.bot.psudo_level_member(
                    db_session, member):
                return (
                    "You cannot kick someone who has the same or a higher level than you :)",
                    None,
                )

        reason = args[1]
        resp = await self.bot.kick(member, f"{reason}\nKicked by {author}")
        if not resp:
            return f"Failed to kick member {member}!", None

        return f"Member {member.mention} has been kicked by {author.mention}!", None
Esempio n. 15
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)
Esempio n. 16
0
 def is_enabled(cls):
     with DBManager.create_session_scope() as db_session:
         db_module = db_session.query(Module).filter_by(
             id=cls.ID).one_or_none()
         if db_module is None:
             return cls.ENABLED_DEFAULT
         else:
             return db_module.enabled
Esempio n. 17
0
 def commands_edit(command_id, **options):
     with DBManager.create_session_scope() as db_session:
         command = (db_session.query(Command).options(
             joinedload(Command.data).joinedload(
                 CommandData.user)).filter_by(id=command_id).one_or_none())
         with DBManager.create_session_scope() as db_session:
             user = (db_session.query(User).filter_by(
                 discord_id=session["user"]["discord_id"]).one_or_none())
             if command.action.functions and user.level < 1500:
                 abort(403)
         if command is None:
             return render_template("admin/command_404.html"), 404
         return render_template(
             "admin/edit_command.html",
             command=command,
             user=options.get("user", None),
         )
Esempio n. 18
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
Esempio n. 19
0
 def banphrases(**options):
     with DBManager.create_session_scope() as db_session:
         banphrases = (db_session.query(Banphrase).options(
             joinedload(Banphrase.data).joinedload(BanphraseData.user),
             joinedload(Banphrase.data).joinedload(BanphraseData.user2),
         ).order_by(Banphrase.id).all())
         return render_template("admin/banphrases.html",
                                banphrases=banphrases)
Esempio n. 20
0
    def timers_edit(timer_id, **options):
        with DBManager.create_session_scope() as db_session:
            timer = db_session.query(Timer).filter_by(id=timer_id).one_or_none()

            if timer is None:
                return render_template("admin/timer_404.html"), 404

            return render_template("admin/create_timer.html", timer=timer)
Esempio n. 21
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()
Esempio n. 22
0
 def timers(**options):
     with DBManager.create_session_scope() as db_session:
         return render_template(
             "admin/timers.html",
             timers=db_session.query(Timer).all(),
             created=session.pop("timer_created_id", None),
             edited=session.pop("timer_edited_id", None),
         )
Esempio n. 23
0
    def on_timer_update(self, data):
        try:
            timer_id = int(data["id"])
        except (KeyError, ValueError):
            log.warning("No timer ID found in on_timer_update")
            return False

        updated_timer = find(lambda timer: timer.id == timer_id, self.timers)
        if updated_timer:
            with DBManager.create_session_scope(
                    expire_on_commit=False) as db_session:
                db_session.add(updated_timer)
                db_session.refresh(updated_timer)
                updated_timer.refresh_action()
                db_session.expunge(updated_timer)
        else:
            with DBManager.create_session_scope(
                    expire_on_commit=False) as db_session:
                updated_timer = (db_session.query(Timer).filter_by(
                    id=timer_id).one_or_none())

        # Add the updated timer to the timer lists if required
        if updated_timer:
            if updated_timer not in self.timers:
                self.timers.append(updated_timer)

            if updated_timer not in self.online_timers:
                if updated_timer.interval_online > 0:
                    self.online_timers.append(updated_timer)
                    updated_timer.refresh_tts()

            if updated_timer not in self.offline_timers:
                if updated_timer.interval_offline > 0:
                    self.offline_timers.append(updated_timer)
                    updated_timer.refresh_tts()

        for timer in self.online_timers:
            if timer.enabled is False or timer.interval_online <= 0:
                self.online_timers.remove(timer)

        for timer in self.offline_timers:
            if timer.enabled is False or timer.interval_offline <= 0:
                self.offline_timers.remove(timer)

        return True
Esempio n. 24
0
    def remove_command(self, command):
        self.remove_command_aliases(command)

        with DBManager.create_session_scope() as db_session:
            self.db_session.expunge(command.data)
            db_session.delete(command.data)
            db_session.delete(command)

        self.rebuild()
Esempio n. 25
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)
Esempio n. 26
0
    def banphrases_edit(banphrase_id, **options):
        with DBManager.create_session_scope() as db_session:
            banphrase = (db_session.query(Banphrase).filter_by(
                id=banphrase_id).one_or_none())

            if banphrase is None:
                return render_template("admin/banphrase_404.html"), 404

            return render_template("admin/create_banphrase.html",
                                   banphrase=banphrase)
Esempio n. 27
0
 def add_entry(entry_type, source, message, data={}):
     with DBManager.create_session_scope() as db_session:
         entry_object = AdminLogEntry(
             type=entry_type,
             user_id=source,
             message=message,
             created_at=utils.now(),
             data=data,
         )
         db_session.add(entry_object)
Esempio n. 28
0
 def get(self, timer_id, **options):
     with DBManager.create_session_scope() as db_session:
         timer = db_session.query(Timer).filter_by(
             id=timer_id).one_or_none()
         if timer is None:
             return {"error": "Invalid timer ID"}, 404
         AdminLogManager.post("Timer removed", options["user"].discord_id,
                              timer.name)
         db_session.delete(timer)
         SocketClientManager.send("timer.remove", {"id": timer.id})
         return {"success": "good job"}
Esempio n. 29
0
    def __init__(self, bot):
        self.bot = bot
        self.banphrases = []
        self.enabled_banphrases = []
        self.db_session = DBManager.create_session(expire_on_commit=False)

        if self.bot:
            self.bot.socket_manager.add_handler("banphrase.update",
                                                self.on_banphrase_update)
            self.bot.socket_manager.add_handler("banphrase.remove",
                                                self.on_banphrase_remove)
Esempio n. 30
0
    def db_settings(cls):
        settings = {}
        with DBManager.create_session_scope() as session:
            module = session.query(Module).filter(Module.id == cls.ID).one()
            if module.settings is not None:
                try:
                    settings = json.loads(module.settings)
                except ValueError:
                    pass

        return settings