Ejemplo n.º 1
0
    def twitter_follow(**options):
        json_data = request.get_json()
        if not json_data:
            return {"error": "No input data provided"}, 400

        try:
            data: UserRequest = UserRequestSchema().load(json_data)
        except ValidationError as err:
            return {
                "error": f"Did not match schema: {json.dumps(err.messages)}"
            }, 400

        username = data.username.strip()

        if not username:
            return {
                "message": "username must contain at least 1 character"
            }, 400

        with DBManager.create_session_scope() as db_session:
            twitter_user = db_session.query(TwitterUser).filter_by(
                username=username).one_or_none()
            if twitter_user is not None:
                return {"message": f"We are already following {username}"}, 409

            twitter_user = TwitterUser(username)

            db_session.add(twitter_user)
            db_session.flush()
            db_session.commit()

            SocketClientManager.send("twitter.follow", {"username": username})

            return {"message": f"Successfully followed {username}"}, 200
Ejemplo n.º 2
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"],
                                 "Enabled" if row.enabled else "Disabled",
                                 row.id)
            SocketClientManager.send("module.update", payload)
            return {"success": "successful toggle", "new_state": new_state}
Ejemplo n.º 3
0
    def modules_edit(module_id, **options):
        module_manager = ModuleManager(None).load(do_reload=False)
        current_module = find(lambda m: m.ID == module_id, module_manager.all_modules)

        if current_module is None:
            return render_template('admin/module_404.html'), 404

        sub_modules = []
        for module in module_manager.all_modules:
            module.db_module = None

        with DBManager.create_session_scope() as db_session:
            for db_module in db_session.query(Module):
                module = find(lambda m: m.ID == db_module.id, module_manager.all_modules)
                if module:
                    module.db_module = db_module
                    if module.PARENT_MODULE == current_module.__class__:
                        sub_modules.append(module)

            if current_module.db_module is None:
                return render_template('admin/module_404.html'), 404

            if request.method == 'POST':
                form_values = {key: value for key, value in request.form.items()}
                res = current_module.parse_settings(**form_values)
                if res is False:
                    return render_template('admin/module_404.html'), 404

                current_module.db_module.settings = json.dumps(res)
                db_session.commit()

                settings = None
                try:
                    settings = json.loads(current_module.db_module.settings)
                except (TypeError, ValueError):
                    pass
                current_module.load(settings=settings)

                payload = {
                        'id': current_module.db_module.id,
                        }

                SocketClientManager.send('module.update', payload)

                AdminLogManager.post('Module edited', options['user'], current_module.NAME)

                return render_template('admin/configure_module.html',
                        module=current_module,
                        sub_modules=sub_modules)
            else:
                settings = None
                try:
                    settings = json.loads(current_module.db_module.settings)
                except (TypeError, ValueError):
                    pass
                current_module.load(settings=settings)

                return render_template('admin/configure_module.html',
                        module=current_module,
                        sub_modules=sub_modules)
Ejemplo n.º 4
0
    def timer_toggle(timer_id: int, **options) -> ResponseReturnValue:
        try:
            json_data = request.get_json()
            if not json_data:
                return {"error": "Missing json body"}, 400
            data: ToggleState = ToggleStateSchema().load(json_data)
        except ValidationError as err:
            return {
                "error": f"Did not match schema: {json.dumps(err.messages)}"
            }, 400

        with DBManager.create_session_scope() as db_session:
            row = db_session.query(Timer).filter_by(id=timer_id).one_or_none()

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

            row.enabled = data.new_state
            db_session.commit()
            payload = {"id": row.id, "new_state": data.new_state}
            AdminLogManager.post("Timer toggled", options["user"],
                                 "Enabled" if data.new_state else "Disabled",
                                 row.name)
            SocketClientManager.send("timer.update", payload)
            return {
                "success": "successful toggle",
                "new_state": data.new_state
            }
Ejemplo n.º 5
0
    def module_toggle(row_id: str, **options) -> ResponseReturnValue:
        try:
            json_data = request.get_json()
            if not json_data:
                return {"error": "Missing json body"}, 400
            data: ToggleState = ToggleStateSchema().load(json_data)
        except ValidationError as err:
            return {
                "error": f"Did not match schema: {json.dumps(err.messages)}"
            }, 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 = data.new_state
            db_session.commit()
            payload = {"id": row.id, "new_state": data.new_state}
            AdminLogManager.post("Module toggled", options["user"],
                                 "Enabled" if row.enabled else "Disabled",
                                 row.id)
            SocketClientManager.send("module.update", payload)
            log.info(f"new state: {data} - {data.new_state}")
            return {
                "success": "successful toggle",
                "new_state": data.new_state
            }
Ejemplo n.º 6
0
def generic_toggle(route_key, row_id, **options):
    valid_routes = {
            'timer': Timer,
            'banphrase': Banphrase,
            'module': Module,
            }

    if route_key not in valid_routes:
        return make_response(jsonify({'error': 'Invalid route.'}), 400)
    if 'new_state' not in request.form:
        return make_response(jsonify({'error': 'Missing `new_state` parameter.'}), 400)
    try:
        new_state = int(request.form['new_state'])
    except (ValueError, KeyError):
        return make_response(jsonify({'error': 'Invalid `new_state` parameter.'}), 400)

    route_value = valid_routes[route_key]

    with DBManager.create_session_scope() as db_session:
        row = db_session.query(route_value).filter_by(id=row_id).one_or_none()
        if row:
            row.enabled = True if new_state == 1 else False
            db_session.commit()
            SocketClientManager.send('{}.update'.format(route_key), {'{}_id'.format(route_key): row.id})
            return make_response(jsonify({'success': 'successful toggle', 'new_state': new_state}))
        else:
            return make_response(jsonify({'error': 'invalid {} id'.format(route_key)}))
Ejemplo n.º 7
0
def generic_toggle(route_key, row_id, **options):
    valid_routes = {
            'timer': Timer,
            'banphrase': Banphrase,
            'module': Module,
            }

    if route_key not in valid_routes:
        return make_response(jsonify({'error': 'Invalid route.'}), 400)
    if 'new_state' not in request.form:
        return make_response(jsonify({'error': 'Missing `new_state` parameter.'}), 400)
    try:
        new_state = int(request.form['new_state'])
    except (ValueError, KeyError):
        return make_response(jsonify({'error': 'Invalid `new_state` parameter.'}), 400)

    route_value = valid_routes[route_key]

    with DBManager.create_session_scope() as db_session:
        row = db_session.query(route_value).filter_by(id=row_id).one_or_none()
        if row:
            row.enabled = True if new_state == 1 else False
            db_session.commit()
            SocketClientManager.send('{}.update'.format(route_key), {'{}_id'.format(route_key): row.id})
            return make_response(jsonify({'success': 'successful toggle', 'new_state': new_state}))
        else:
            return make_response(jsonify({'error': 'invalid {} id'.format(route_key)}))
Ejemplo n.º 8
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'],
                    'Enabled' if row.enabled else 'Disabled',
                    row.id)
            SocketClientManager.send('module.update', payload)
            return {'success': 'successful toggle', 'new_state': new_state}
Ejemplo n.º 9
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(Banphrase).filter_by(id=row_id).one_or_none()

            if not row:
                return {
                        'error': 'Banphrase with this ID not found'
                        }, 404

            row.enabled = True if new_state == 1 else False
            db_session.commit()
            payload = {
                    'id': row.id,
                    'new_state': row.enabled,
                    }
            AdminLogManager.post('Banphrase toggled',
                    options['user'],
                    'Enabled' if row.enabled else 'Disabled',
                    row.phrase)
            SocketClientManager.send('banphrase.update', payload)
            return {'success': 'successful toggle', 'new_state': new_state}
Ejemplo n.º 10
0
def generic_toggle(route_key, row_id, **options):
    valid_routes = {
            'timer': Timer,
            'banphrase': Banphrase,
            'module': Module,
            }

    route_name = {
            'timer': lambda x: x.name,
            'banphrase': lambda x: x.phrase,
            'module': lambda x: x.id,
            }

    route_title = {
            'timer': 'Timer',
            'banphrase': 'Banphrase',
            'module': 'Module',
            }

    route_validator = {
            'module': lambda x: validate_module(x.id)
            }

    if route_key not in valid_routes:
        return make_response(jsonify({'error': 'Invalid route.'}), 400)
    if 'new_state' not in request.form:
        return make_response(jsonify({'error': 'Missing `new_state` parameter.'}), 400)
    try:
        new_state = int(request.form['new_state'])
    except (ValueError, KeyError):
        return make_response(jsonify({'error': 'Invalid `new_state` parameter.'}), 400)

    route_value = valid_routes[route_key]

    with DBManager.create_session_scope() as db_session:
        row = db_session.query(route_value).filter_by(id=row_id).one_or_none()
        if row:
            validator = route_validator.get(route_key, None)

            if validator is not None:
                res = validator(row)
                if not res:
                    return make_response(jsonify({'error': 'cannot modify {}'.format(route_key)}), 400)

            row.enabled = True if new_state == 1 else False
            db_session.commit()
            payload = {
                    '{}_id'.format(route_key): row.id,  # remove this
                    'id': row.id,
                    'new_state': row.enabled,
                    }
            AdminLogManager.post('{title} toggled'.format(title=route_title[route_key]),
                    options['user'],
                    'Enabled' if row.enabled else 'Disabled',
                    route_name[route_key](row))
            SocketClientManager.send('{}.update'.format(route_key), payload)
            return make_response(jsonify({'success': 'successful toggle', 'new_state': new_state}))
        else:
            return make_response(jsonify({'error': 'invalid {} id'.format(route_key)}))
Ejemplo n.º 11
0
def timer_remove(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 make_response(jsonify({"error": "Invalid timer ID"}))
        db_session.delete(timer)
        SocketClientManager.send("timer.remove", {"timer_id": timer.id})
        return make_response(jsonify({"success": "good job"}))
Ejemplo n.º 12
0
def timer_remove(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 make_response(jsonify({'error': 'Invalid timer ID'}))
        db_session.delete(timer)
        SocketClientManager.send('timer.remove', {'timer_id': timer.id})
        return make_response(jsonify({'success': 'good job'}))
Ejemplo n.º 13
0
def timer_remove(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 make_response(jsonify({'error': 'Invalid timer ID'}))
        db_session.delete(timer)
        SocketClientManager.send('timer.remove', {'timer_id': timer.id})
        return make_response(jsonify({'success': 'good job'}))
Ejemplo n.º 14
0
def modules_edit(module_id, **options):
    module_manager = ModuleManager(None).load(do_reload=False)
    current_module = find(lambda m: m.ID == module_id,
                          module_manager.all_modules)

    if current_module is None:
        return render_template('admin/module_404.html'), 404

    sub_modules = []
    for module in module_manager.all_modules:
        module.db_module = None

    with DBManager.create_session_scope() as db_session:
        for db_module in db_session.query(Module):
            module = find(lambda m: m.ID == db_module.id,
                          module_manager.all_modules)
            if module:
                module.db_module = db_module
                if module.PARENT_MODULE == current_module.__class__:
                    sub_modules.append(module)

        if current_module.db_module is None:
            return render_template('admin/module_404.html'), 404

        if request.method == 'POST':
            form_values = {key: value for key, value in request.form.items()}
            res = current_module.parse_settings(**form_values)
            if res is False:
                return render_template('admin/module_404.html'), 404

            current_module.db_module.settings = json.dumps(res)
            db_session.commit()

            settings = None
            try:
                settings = json.loads(current_module.db_module.settings)
            except (TypeError, ValueError):
                pass
            current_module.load(settings=settings)

            SocketClientManager.send(
                'module.update', {'module_id': current_module.db_module.id})

            return render_template('admin/configure_module.html',
                                   module=current_module,
                                   sub_modules=sub_modules)
        else:
            settings = None
            try:
                settings = json.loads(current_module.db_module.settings)
            except (TypeError, ValueError):
                pass
            current_module.load(settings=settings)

            return render_template('admin/configure_module.html',
                                   module=current_module,
                                   sub_modules=sub_modules)
Ejemplo n.º 15
0
def timers_create(**options):
    session.pop('timer_created_id', None)
    session.pop('timer_edited_id', None)
    if request.method == 'POST':
        id = None
        try:
            if 'id' in request.form:
                id = int(request.form['id'])
            name = request.form['name'].strip()
            interval_online = int(request.form['interval_online'])
            interval_offline = int(request.form['interval_offline'])
            message_type = request.form['message_type']
            message = request.form['message'].strip()
        except (KeyError, ValueError):
            abort(403)

        if interval_online < 0 or interval_offline < 0:
            abort(403)

        if message_type not in ['say', 'me']:
            abort(403)

        if len(message) == 0:
            abort(403)

        options = {
                'name': name,
                'interval_online': interval_online,
                'interval_offline': interval_offline,
                }

        action = {
                'type': message_type,
                'message': message
                }
        options['action'] = action

        if id is None:
            timer = Timer(**options)

        with DBManager.create_session_scope(expire_on_commit=False) as db_session:
            if id is not None:
                timer = db_session.query(Timer).filter_by(id=id).one_or_none()
                if timer is None:
                    return redirect('/admin/timers/', 303)
                timer.set(**options)
            else:
                db_session.add(timer)

        SocketClientManager.send('timer.update', {'timer_id': timer.id})
        if id is None:
            session['timer_created_id'] = timer.id
        else:
            session['timer_edited_id'] = timer.id
        return redirect('/admin/timers/', 303)
    else:
        return render_template('admin/create_timer.html')
Ejemplo n.º 16
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'], timer.name)
         db_session.delete(timer)
         SocketClientManager.send('timer.remove', {'id': timer.id})
         return {'success': 'good job'}
Ejemplo n.º 17
0
def banphrase_remove(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 make_response(jsonify({"error": "Invalid banphrase ID"}))
        db_session.delete(banphrase)
        db_session.delete(banphrase.data)
        SocketClientManager.send("banphrase.remove", {"banphrase_id": banphrase.id})
        return make_response(jsonify({"success": "good job"}))
Ejemplo n.º 18
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"], timer.name)
         db_session.delete(timer)
         SocketClientManager.send("timer.remove", {"id": timer.id})
         return {"success": "good job"}
Ejemplo n.º 19
0
    def timers_create(**options):
        session.pop('timer_created_id', None)
        session.pop('timer_edited_id', None)
        if request.method == 'POST':
            id = None
            try:
                if 'id' in request.form:
                    id = int(request.form['id'])
                name = request.form['name'].strip()
                interval_online = int(request.form['interval_online'])
                interval_offline = int(request.form['interval_offline'])
                message_type = request.form['message_type']
                message = request.form['message'].strip()
            except (KeyError, ValueError):
                abort(403)

            if interval_online < 0 or interval_offline < 0:
                abort(403)

            if message_type not in ['say', 'me']:
                abort(403)

            if len(message) == 0:
                abort(403)

            options = {
                    'name': name,
                    'interval_online': interval_online,
                    'interval_offline': interval_offline,
                    }

            action = {
                    'type': message_type,
                    'message': message
                    }
            options['action'] = action

            if id is None:
                timer = Timer(**options)

            with DBManager.create_session_scope(expire_on_commit=False) as db_session:
                if id is not None:
                    timer = db_session.query(Timer).filter_by(id=id).one_or_none()
                    if timer is None:
                        return redirect('/admin/timers/', 303)
                    timer.set(**options)
                else:
                    db_session.add(timer)

            SocketClientManager.send('timer.update', {'timer_id': timer.id})
            if id is None:
                session['timer_created_id'] = timer.id
            else:
                session['timer_edited_id'] = timer.id
            return redirect('/admin/timers/', 303)
        else:
            return render_template('admin/create_timer.html')
Ejemplo n.º 20
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'], timer.name)
         db_session.delete(timer)
         SocketClientManager.send('timer.remove', {'id': timer.id})
         return {'success': 'good job'}
Ejemplo n.º 21
0
def banphrase_remove(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 make_response(jsonify({'error': 'Invalid banphrase ID'}))
        db_session.delete(banphrase)
        db_session.delete(banphrase.data)
        SocketClientManager.send('banphrase.remove', {'banphrase_id': banphrase.id})
        return make_response(jsonify({'success': 'good job'}))
Ejemplo n.º 22
0
def banphrase_remove(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 make_response(jsonify({'error': 'Invalid banphrase ID'}))
        db_session.delete(banphrase)
        db_session.delete(banphrase.data)
        SocketClientManager.send('banphrase.remove', {'banphrase_id': banphrase.id})
        return make_response(jsonify({'success': 'good job'}))
Ejemplo n.º 23
0
def modules_edit(module_id, **options):
    module_manager = ModuleManager(None).load(do_reload=False)
    current_module = find(lambda m: m.ID == module_id,
                          module_manager.all_modules)

    if current_module is None:
        return render_template('admin/module_404.html'), 404

    if request.method == 'POST':
        form_values = {key: value for key, value in request.form.items()}
        res = current_module.parse_settings(**form_values)
        if res is False:
            return render_template('admin/module_404.html'), 404

        with DBManager.create_session_scope() as db_session:
            db_module = db_session.query(Module).filter_by(
                id=module_id).one_or_none()
            if db_module is None:
                return render_template('admin/module_404.html'), 404

            db_module.settings = json.dumps(res)
            db_session.commit()

            current_module.db_module = db_module

            settings = None
            try:
                settings = json.loads(db_module.settings)
            except (TypeError, ValueError):
                pass
            current_module.load(settings=settings)

            SocketClientManager.send('module.update',
                                     {'module_id': db_module.id})

            return render_template('admin/configure_module.html',
                                   module=current_module)
        pass
    else:
        with DBManager.create_session_scope() as db_session:
            db_module = db_session.query(Module).filter_by(
                id=module_id).one_or_none()
            if db_module is None:
                return render_template('admin/module_404.html'), 404

            current_module.db_module = db_module

            settings = None
            try:
                settings = json.loads(db_module.settings)
            except (TypeError, ValueError):
                pass
            current_module.load(settings=settings)

            return render_template('admin/configure_module.html',
                                   module=current_module)
Ejemplo n.º 24
0
 def get(self, 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 {'error': 'Invalid banphrase ID'}, 404
         AdminLogManager.post('Banphrase removed', options['user'], banphrase.phrase)
         db_session.delete(banphrase)
         db_session.delete(banphrase.data)
         SocketClientManager.send('banphrase.remove', {'id': banphrase.id})
         return {'success': 'good job'}, 200
Ejemplo n.º 25
0
 def banphrases_remove(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 {"error": "Invalid banphrase ID"}, 404
         AdminLogManager.post("Banphrase removed", options["user"], banphrase.id, banphrase.phrase)
         db_session.delete(banphrase)
         db_session.delete(banphrase.data)
         SocketClientManager.send("banphrase.remove", {"id": banphrase.id})
         return {"success": "good job"}, 200
Ejemplo n.º 26
0
 def get(self, 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 {'error': 'Invalid banphrase ID'}, 404
         AdminLogManager.post('Banphrase removed', options['user'], banphrase.phrase)
         db_session.delete(banphrase)
         db_session.delete(banphrase.data)
         SocketClientManager.send('banphrase.remove', {'id': banphrase.id})
         return {'success': 'good job'}, 200
Ejemplo n.º 27
0
    def post(self, playsound_name, **options):
        with DBManager.create_session_scope() as db_session:
            count = db_session.query(Playsound).filter(Playsound.name == playsound_name).count()

            if count <= 0:
                return "Playsound does not exist", 404
            # explicitly don't check for disabled

        SocketClientManager.send("playsound.play", {"name": playsound_name})

        return "OK", 200
Ejemplo n.º 28
0
def modules_edit(module_id, **options):
    module_manager = ModuleManager(None).load(do_reload=False)
    current_module = find(lambda m: m.ID == module_id, module_manager.all_modules)

    if current_module is None:
        return render_template('admin/module_404.html'), 404

    if request.method == 'POST':
        form_values = {key: value for key, value in request.form.items()}
        res = current_module.parse_settings(**form_values)
        if res is False:
            return render_template('admin/module_404.html'), 404

        with DBManager.create_session_scope() as db_session:
            db_module = db_session.query(Module).filter_by(id=module_id).one_or_none()
            if db_module is None:
                return render_template('admin/module_404.html'), 404

            db_module.settings = json.dumps(res)
            db_session.commit()

            current_module.db_module = db_module

            settings = None
            try:
                settings = json.loads(db_module.settings)
            except (TypeError, ValueError):
                pass
            current_module.load(settings=settings)

            SocketClientManager.send('module.update', {'module_id': db_module.id})

            return render_template('admin/configure_module.html',
                    module=current_module)
        pass
    else:
        with DBManager.create_session_scope() as db_session:
            db_module = db_session.query(Module).filter_by(id=module_id).one_or_none()
            if db_module is None:
                return render_template('admin/module_404.html'), 404

            current_module.db_module = db_module

            settings = None
            try:
                settings = json.loads(db_module.settings)
            except (TypeError, ValueError):
                pass
            current_module.load(settings=settings)

            return render_template('admin/configure_module.html',
                    module=current_module)
Ejemplo n.º 29
0
    def post(self, **options):
        args = self.post_parser.parse_args()
        with DBManager.create_session_scope() as db_session:
            twitter_user = db_session.query(TwitterUser).filter_by(username=args["username"]).one_or_none()
            if twitter_user is None:
                return {"message": "We are not following a twitter user by that name."}, 404

            db_session.delete(twitter_user)
            db_session.flush()
            db_session.commit()

            SocketClientManager.send("twitter.unfollow", {"username": args["username"]})

            return {"message": "Successfully unfollowed {}".format(args["username"])}, 200
Ejemplo n.º 30
0
    def post(self, playsound_name, **options):
        with DBManager.create_session_scope() as db_session:
            count = db_session.query(Playsound).filter(
                Playsound.name == playsound_name).count()

            if count <= 0:
                return "Playsound does not exist", 404
            # explicitly don't check for disabled

        if options["user"].username_raw == "dank__doge":
            return "Feels Very Weird Man", 403

        SocketClientManager.send("playsound.play", {"name": playsound_name})

        return "OK", 200
Ejemplo n.º 31
0
    def post(self, **options):
        args = self.post_parser.parse_args()
        with DBManager.create_session_scope() as db_session:
            twitter_user = db_session.query(TwitterUser).filter_by(username=args["username"]).one_or_none()
            if twitter_user is not None:
                return {"message": "We are already following {}".format(args["username"])}, 409

            twitter_user = TwitterUser(args["username"].lower())

            db_session.add(twitter_user)
            db_session.flush()
            db_session.commit()

            SocketClientManager.send("twitter.follow", {"username": args["username"]})

            return {"message": "Successfully followed {}".format(args["username"])}, 200
Ejemplo n.º 32
0
    def post(self, **options):
        args = self.post_parser.parse_args()
        with DBManager.create_session_scope() as db_session:
            twitter_user = db_session.query(TwitterUser).filter_by(username=args['username']).one_or_none()
            if twitter_user is None:
                return {
                        'message': 'We are not following a twitter user by that name.',
                        }, 404

            db_session.delete(twitter_user)
            db_session.flush()
            db_session.commit()

            SocketClientManager.send('twitter.unfollow', {'username': args['username']})

            return {
                    'message': 'Successfully unfollowed {}'.format(args['username']),
                    }, 200
Ejemplo n.º 33
0
    def post(self, **options):
        args = self.post_parser.parse_args()
        with DBManager.create_session_scope() as db_session:
            twitter_user = db_session.query(TwitterUser).filter_by(username=args['username']).one_or_none()
            if twitter_user is not None:
                return {
                        'message': 'We are already following {}'.format(args['username']),
                        }, 409

            twitter_user = TwitterUser(args['username'].lower())

            db_session.add(twitter_user)
            db_session.flush()
            db_session.commit()

            SocketClientManager.send('twitter.follow', {'username': args['username']})

            return {
                    'message': 'Successfully followed {}'.format(args['username']),
                    }, 200
Ejemplo n.º 34
0
def generic_toggle(route_key, row_id, **options):
    valid_routes = {"timer": Timer, "banphrase": Banphrase, "module": Module}

    if route_key not in valid_routes:
        return make_response(jsonify({"error": "Invalid route."}), 400)
    if "new_state" not in request.form:
        return make_response(jsonify({"error": "Missing `new_state` parameter."}), 400)
    try:
        new_state = int(request.form["new_state"])
    except (ValueError, KeyError):
        return make_response(jsonify({"error": "Invalid `new_state` parameter."}), 400)

    route_value = valid_routes[route_key]

    with DBManager.create_session_scope() as db_session:
        row = db_session.query(route_value).filter_by(id=row_id).one_or_none()
        if row:
            row.enabled = True if new_state == 1 else False
            db_session.commit()
            SocketClientManager.send("{}.update".format(route_key), {"{}_id".format(route_key): row.id})
            return make_response(jsonify({"success": "successful toggle", "new_state": new_state}))
        else:
            return make_response(jsonify({"error": "invalid {} id".format(route_key)}))
Ejemplo n.º 35
0
    def banphrases_toggle(row_id, **options):
        json_data = request.get_json()
        if not json_data:
            return {"error": "No input data provided"}, 400

        try:
            data: ToggleState = ToggleStateSchema().load(json_data)
        except ValidationError as err:
            return {"error": f"Did not match schema: {json.dumps(err.messages)}"}, 400

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

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

            row.enabled = data.new_state
            db_session.commit()
            payload = {"id": row.id, "new_state": data.new_state}
            AdminLogManager.post(
                "Banphrase toggled", options["user"], "Enabled" if data.new_state else "Disabled", row.id, row.phrase
            )
            SocketClientManager.send("banphrase.update", payload)
            return {"success": "successful toggle", "new_state": data.new_state}
Ejemplo n.º 36
0
    def get(self, command_id, **options):
        with DBManager.create_session_scope() as db_session:
            command = db_session.query(Command).filter_by(id=command_id).one_or_none()
            if command is None:
                return {'error': 'Invalid command ID'}, 404
            if command.level > options['user'].level:
                return {'error': 'Unauthorized'}, 403
            log_msg = 'The !{} command has been removed'.format(command.command.split('|')[0])
            AdminLogManager.add_entry('Command removed',
                    options['user'],
                    log_msg)
            db_session.delete(command.data)
            db_session.delete(command)

        if SocketClientManager.send('command.remove', {'command_id': command_id}) is True:
            return {'success': 'good job'}, 200
        else:
            return {'error': 'could not push update'}, 500
Ejemplo n.º 37
0
    def post(self, command_id, **options):
        with DBManager.create_session_scope() as db_session:
            command = db_session.query(Command).filter_by(
                id=command_id).one_or_none()
            if command is None:
                return {"error": "Invalid command ID"}, 404
            if command.level > options["user"].level:
                return {"error": "Unauthorized"}, 403
            log_msg = f"The !{command.command.split('|')[0]} command has been removed"
            AdminLogManager.add_entry("Command removed", options["user"],
                                      log_msg)
            db_session.delete(command.data)
            db_session.delete(command)

        if SocketClientManager.send("command.remove",
                                    {"command_id": command_id}) is True:
            return {"success": "good job"}, 200
        else:
            return {"error": "could not push update"}, 500
Ejemplo n.º 38
0
    def toggle_banphrases(self):
        with DBManager.create_session_scope() as db_session:
            row = db_session.query(Banphrase).filter_by(id=108).one_or_none()
            row2 = db_session.query(Banphrase).filter_by(id=113).one_or_none()

            row.enabled = True if not row.enabled else False
            row2.enabled = True if not row2.enabled else False

            db_session.commit()
            payload1 = {"id": row.id, "new_state": row.enabled}
            payload2 = {"id": row2.id, "new_state": row2.enabled}

            SocketClientManager.init("/tmp/.bullbot.sock")
            SocketClientManager.send("banphrase.update", payload1)
            SocketClientManager.send("banphrase.update", payload2)
Ejemplo n.º 39
0
def banphrases_create(**options):
    session.pop('banphrase_created_id', None)
    session.pop('banphrase_edited_id', None)
    if request.method == 'POST':
        id = None
        try:
            if 'id' in request.form:
                id = int(request.form['id'])
            name = request.form['name'].strip()
            permanent = request.form.get('permanent', 'off')
            warning = request.form.get('warning', 'off')
            notify = request.form.get('notify', 'off')
            case_sensitive = request.form.get('case_sensitive', 'off')
            length = int(request.form['length'])
            phrase = request.form['phrase'].strip()
            operator = request.form['operator'].strip().lower()
        except (KeyError, ValueError):
            abort(403)

        permanent = True if permanent == 'on' else False
        warning = True if warning == 'on' else False
        notify = True if notify == 'on' else False
        case_sensitive = True if case_sensitive == 'on' else False

        if len(name) == 0:
            abort(403)

        if len(phrase) == 0:
            abort(403)

        if length < 0 or length > 1209600:
            abort(403)

        valid_operators = ['contains', 'startswith', 'endswith']
        if operator not in valid_operators:
            abort(403)

        user = options.get('user', None)

        if user is None:
            abort(403)

        options = {
                'name': name,
                'phrase': phrase,
                'permanent': permanent,
                'warning': warning,
                'notify': notify,
                'case_sensitive': case_sensitive,
                'length': length,
                'added_by': user.id,
                'operator': operator,
                }

        if id is None:
            banphrase = Banphrase(**options)
            banphrase.data = BanphraseData(banphrase.id, added_by=options['added_by'])

        with DBManager.create_session_scope(expire_on_commit=False) as db_session:
            if id is not None:
                banphrase = db_session.query(Banphrase).filter_by(id=id).one_or_none()
                if banphrase is None:
                    return redirect('/admin/banphrases/', 303)
                banphrase.set(**options)
            else:
                log.info('adding...')
                db_session.add(banphrase)
                log.info('adding data..')
                db_session.add(banphrase.data)
                log.info('should commit now...')
        log.info('commited')

        SocketClientManager.send('banphrase.update', {'banphrase_id': banphrase.id})
        if id is None:
            session['banphrase_created_id'] = banphrase.id
        else:
            session['banphrase_edited_id'] = banphrase.id
        return redirect('/admin/banphrases/', 303)
    else:
        return render_template('admin/create_banphrase.html')
Ejemplo n.º 40
0
    def timers_create(**options):
        session.pop("timer_created_id", None)
        session.pop("timer_edited_id", None)
        if request.method != "POST":
            return render_template("admin/create_timer.html")
        id = None
        try:
            if "id" in request.form:
                id = int(request.form["id"])
            name = request.form["name"].strip()
            interval_online = int(request.form["interval_online"])
            interval_offline = int(request.form["interval_offline"])
            message_type = request.form["message_type"]
            message = request.form["message"].strip()
        except (KeyError, ValueError):
            abort(403)

        if interval_online < 0 or interval_offline < 0:
            abort(403)

        if message_type not in ["say", "me"]:
            abort(403)

        if not message:
            abort(403)

        user = options.get("user", None)

        if user is None:
            abort(403)

        options = {"name": name, "interval_online": interval_online, "interval_offline": interval_offline}

        action = {"type": message_type, "message": message}
        options["action"] = action

        if id is None:
            timer = Timer(**options)

        with DBManager.create_session_scope(expire_on_commit=False) as db_session:
            if id is not None:
                timer = db_session.query(Timer).filter_by(id=id).one_or_none()
                if timer is None:
                    return redirect("/admin/timers/", 303)

                old_message = ""
                new_message = ""
                try:
                    old_message = timer.action.response
                    new_message = action["message"]
                except:
                    pass

                timer.set(**options)

                if old_message and old_message != new_message:
                    log_msg = f'Timer "{timer.name}" has been updated from "{old_message}" to "{new_message}"'
                else:
                    log_msg = f'Timer "{timer.name}" has been updated'

                AdminLogManager.add_entry(
                    "Timer edited", user, log_msg, data={"old_message": old_message, "new_message": new_message}
                )
            else:
                db_session.add(timer)
                AdminLogManager.post("Timer added", user, timer.name)

        SocketClientManager.send("timer.update", {"id": timer.id})
        if id is None:
            session["timer_created_id"] = timer.id
        else:
            session["timer_edited_id"] = timer.id
        return redirect("/admin/timers/", 303)
Ejemplo n.º 41
0
def command_update(command_id, **options):
    if not request.method == "POST":
        return make_response(jsonify({"error": "Invalid request method. (Expected POST)"}), 400)
    if len(request.form) == 0:
        return make_response(jsonify({"error": "Missing parameter to edit."}), 400)

    valid_names = ["enabled", "level", "delay_all", "delay_user", "cost", "can_execute_with_whisper", "sub_only"]

    valid_action_names = ["type", "message"]

    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()
        )
        if command is None:
            return make_response(jsonify({"error": "Invalid command ID"}), 404)
        if command.level > options["user"].level:
            abort(403)
        parsed_action = json.loads(command.action_json)
        options = {"edited_by": options["user"].id}

        for key in request.form:
            if key.startswith("data_"):
                name = key[5:]
                value = request.form[key]

                if name.startswith("action_"):
                    name = name[7:]
                    if name in valid_action_names and name in parsed_action and command.action.type == "message":
                        value_type = type(parsed_action[name])
                        if value_type is bool:
                            parsed_value = True if value == "1" else False
                        elif value_type is int:
                            try:
                                parsed_value = int(value)
                            except ValueError:
                                continue
                        else:
                            parsed_value = value
                        parsed_action[name] = parsed_value
                    command.action_json = json.dumps(parsed_action)
                else:
                    if name in valid_names:
                        value_type = type(getattr(command, name))
                        if value_type is bool:
                            parsed_value = True if value == "1" else False
                        elif value_type is int:
                            try:
                                parsed_value = int(value)
                            except ValueError:
                                continue
                        else:
                            parsed_value = value
                        options[name] = parsed_value

        command.set(**options)
        command.data.set(**options)

    if SocketClientManager.send("command.update", {"command_id": command_id}) is True:
        return make_response(jsonify({"success": "good job"}))
    else:
        return make_response(jsonify({"error": "Could not push update"}))
Ejemplo n.º 42
0
def init(args):
    import configparser
    import datetime
    import logging
    import subprocess
    import sys

    from flask import request
    from flask import session
    from flask_scrypt import generate_random_salt

    import pajbot.web.common
    import pajbot.web.routes
    from pajbot.bot import Bot
    from pajbot.managers.db import DBManager
    from pajbot.managers.redis import RedisManager
    from pajbot.managers.time import TimeManager
    from pajbot.models.module import ModuleManager
    from pajbot.models.sock import SocketClientManager
    from pajbot.streamhelper import StreamHelper
    from pajbot.utils import load_config
    from pajbot.web.models import errors
    from pajbot.web.utils import download_logo

    log = logging.getLogger(__name__)

    config = configparser.ConfigParser()

    config = load_config(args.config)
    config.read('webconfig.ini')

    if 'web' not in config:
        log.error('Missing [web] section in config.ini')
        sys.exit(1)

    if 'pleblist_password_salt' not in config['web']:
        salt = generate_random_salt()
        config.set('web', 'pleblist_password_salt', salt.decode('utf-8'))

    if 'pleblist_password' not in config['web']:
        salt = generate_random_salt()
        config.set('web', 'pleblist_password', salt.decode('utf-8'))

    if 'secret_key' not in config['web']:
        salt = generate_random_salt()
        config.set('web', 'secret_key', salt.decode('utf-8'))

    if 'logo' not in config['web']:
        res = download_logo(config['webtwitchapi']['client_id'], config['main']['streamer'])
        if res:
            config.set('web', 'logo', 'set')

    StreamHelper.init_web(config['main']['streamer'])

    redis_options = {}
    if 'redis' in config:
        redis_options = config._sections['redis']

    RedisManager.init(**redis_options)

    with open(args.config, 'w') as configfile:
        config.write(configfile)

    app.bot_modules = config['web'].get('modules', '').split()
    app.bot_commands_list = []
    app.bot_config = config
    app.secret_key = config['web']['secret_key']

    if 'sock' in config and 'sock_file' in config['sock']:
        SocketClientManager.init(config['sock']['sock_file'])

    DBManager.init(config['main']['db'])
    TimeManager.init_timezone(config['main'].get('timezone', 'UTC'))

    app.module_manager = ModuleManager(None).load()

    pajbot.web.routes.admin.init(app)
    pajbot.web.routes.api.init(app)
    pajbot.web.routes.base.init(app)

    pajbot.web.common.filters.init(app)
    pajbot.web.common.assets.init(app)
    pajbot.web.common.tasks.init(app)
    pajbot.web.common.menu.init(app)

    app.register_blueprint(pajbot.web.routes.clr.page)

    errors.init(app, config)
    pajbot.web.routes.clr.config = config

    version = Bot.version
    last_commit = ''
    commit_number = 0
    try:
        current_branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode('utf8').strip()
        latest_commit = subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('utf8').strip()[:8]
        commit_number = subprocess.check_output(['git', 'rev-list', 'HEAD', '--count']).decode('utf8').strip()
        last_commit = subprocess.check_output(['git', 'log', '-1', '--format=%cd']).decode('utf8').strip()
        version = '{0} DEV ({1}, {2}, commit {3})'.format(version, current_branch, latest_commit, commit_number)
    except:
        pass

    default_variables = {
            'version': version,
            'last_commit': last_commit,
            'commit_number': commit_number,
            'bot': {
                'name': config['main']['nickname'],
                },
            'site': {
                'domain': config['web']['domain'],
                'deck_tab_images': config.getboolean('web', 'deck_tab_images'),
                'websocket': {
                    'host': config['websocket'].get('host', config['web']['domain']),
                    'port': config['websocket']['port'],
                    'ssl': config.getboolean('websocket', 'ssl')
                    }
                },
            'streamer': {
                'name': config['web']['streamer_name'],
                'full_name': config['main']['streamer']
                },
            'modules': app.bot_modules,
            'request': request,
            'session': session,
            'google_analytics': config['web'].get('google_analytics', None),
            }

    @app.context_processor
    def current_time():
        current_time = {}
        current_time['current_time'] = datetime.datetime.now()
        return current_time

    @app.context_processor
    def inject_default_variables():
        return default_variables
Ejemplo n.º 43
0
def command_update(command_id, **options):
    if not request.method == 'POST':
        return make_response(jsonify({'error': 'Invalid request method. (Expected POST)'}), 400)
    if len(request.form) == 0:
        return make_response(jsonify({'error': 'Missing parameter to edit.'}), 400)

    valid_names = [
            'enabled',
            'level',
            'delay_all',
            'delay_user',
            'cost',
            'can_execute_with_whisper',
            'sub_only'
            ]

    valid_action_names = [
            'type',
            'message'
            ]

    with DBManager.create_session_scope() as db_session:
        command = db_session.query(Command).filter_by(id=command_id).one_or_none()
        if command is None:
            return make_response(jsonify({'error': 'Invalid command ID'}), 404)
        if command.level > options['user'].level:
            abort(403)
        parsed_action = json.loads(command.action_json)
        options = {}

        for key in request.form:
            if key.startswith('data_'):
                name = key[5:]
                value = request.form[key]

                if name.startswith('action_'):
                    name = name[7:]
                    if name in valid_action_names and name in parsed_action and command.action.type == 'message':
                        value_type = type(parsed_action[name])
                        if value_type is bool:
                            parsed_value = True if value == '1' else False
                        elif value_type is int:
                            try:
                                parsed_value = int(value)
                            except ValueError:
                                continue
                        else:
                            parsed_value = value
                        parsed_action[name] = parsed_value
                    command.action_json = json.dumps(parsed_action)
                else:
                    if name in valid_names:
                        value_type = type(getattr(command, name))
                        if value_type is bool:
                            parsed_value = True if value == '1' else False
                        elif value_type is int:
                            try:
                                parsed_value = int(value)
                            except ValueError:
                                continue
                        else:
                            parsed_value = value
                        options[name] = parsed_value

        command.set(**options)

    if SocketClientManager.send('command.update', {'command_id': command_id}) is True:
        return make_response(jsonify({'success': 'good job'}))
    else:
        return make_response(jsonify({'error': 'Could not push update'}))
Ejemplo n.º 44
0
    def timers_create(**options):
        session.pop('timer_created_id', None)
        session.pop('timer_edited_id', None)
        if request.method == 'POST':
            id = None
            try:
                if 'id' in request.form:
                    id = int(request.form['id'])
                name = request.form['name'].strip()
                interval_online = int(request.form['interval_online'])
                interval_offline = int(request.form['interval_offline'])
                message_type = request.form['message_type']
                message = request.form['message'].strip()
            except (KeyError, ValueError):
                abort(403)

            if interval_online < 0 or interval_offline < 0:
                abort(403)

            if message_type not in ['say', 'me']:
                abort(403)

            if len(message) == 0:
                abort(403)

            user = options.get('user', None)

            if user is None:
                abort(403)

            options = {
                    'name': name,
                    'interval_online': interval_online,
                    'interval_offline': interval_offline,
                    }

            action = {
                    'type': message_type,
                    'message': message
                    }
            options['action'] = action

            if id is None:
                timer = Timer(**options)

            with DBManager.create_session_scope(expire_on_commit=False) as db_session:
                if id is not None:
                    timer = db_session.query(Timer).filter_by(id=id).one_or_none()
                    if timer is None:
                        return redirect('/admin/timers/', 303)

                    old_message = ''
                    new_message = ''
                    try:
                        old_message = timer.action.response
                        new_message = action['message']
                    except:
                        pass

                    timer.set(**options)

                    if len(old_message) > 0 and old_message != new_message:
                        log_msg = 'Timer "{0}" has been updated from "{1}" to "{2}"'.format(
                                timer.name,
                                old_message,
                                new_message)
                    else:
                        log_msg = 'Timer "{0}" has been updated'.format(timer.name)

                    AdminLogManager.add_entry('Timer edited',
                            user,
                            log_msg,
                            data={
                                'old_message': old_message,
                                'new_message': new_message,
                                })
                else:
                    db_session.add(timer)
                    AdminLogManager.post('Timer added', user, timer.name)

            SocketClientManager.send('timer.update', {'timer_id': timer.id})
            if id is None:
                session['timer_created_id'] = timer.id
            else:
                session['timer_edited_id'] = timer.id
            return redirect('/admin/timers/', 303)
        else:
            return render_template('admin/create_timer.html')
Ejemplo n.º 45
0
    def post(self, command_id, **extra_args):
        args = pajbot.utils.remove_none_values(self.post_parser.parse_args())
        if len(args) == 0:
            return {
                    'error': 'Missing parameter to edit.'
                    }, 400

        valid_names = [
                'enabled',
                'level',
                'delay_all',
                'delay_user',
                'cost',
                'can_execute_with_whisper',
                'sub_only'
                ]

        valid_action_names = [
                'type',
                'message'
                ]

        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()
            if command is None:
                return {'error': 'Invalid command ID'}, 404

            if command.level > extra_args['user'].level:
                return {'error': 'Unauthorized'}, 403
            parsed_action = json.loads(command.action_json)
            options = {
                'edited_by': extra_args['user'].id,
            }

            for key in args:
                if key.startswith('data_'):
                    name = key[5:]
                    value = args[key]

                    if name.startswith('action_'):
                        name = name[7:]
                        if name in valid_action_names and name in parsed_action and command.action.type == 'message':
                            value_type = type(parsed_action[name])
                            if value_type is bool:
                                parsed_value = True if value == '1' else False
                            elif value_type is int:
                                try:
                                    parsed_value = int(value)
                                except ValueError:
                                    continue
                            else:
                                parsed_value = value
                            parsed_action[name] = parsed_value
                        command.action_json = json.dumps(parsed_action)
                    else:
                        if name in valid_names:
                            value_type = type(getattr(command, name))
                            if value_type is bool:
                                parsed_value = True if value == '1' else False
                            elif value_type is int:
                                try:
                                    parsed_value = int(value)
                                except ValueError:
                                    continue
                            else:
                                parsed_value = value
                            options[name] = parsed_value

            aj = json.loads(command.action_json)
            old_message = ''
            new_message = ''
            try:
                old_message = command.action.response
                new_message = aj['message']
            except:
                pass

            command.set(**options)
            command.data.set(**options)

            if len(old_message) > 0 and old_message != new_message:
                log_msg = 'The !{} command has been updated from "{}" to "{}"'.format(
                        command.command.split('|')[0],
                        old_message,
                        new_message)
            else:
                log_msg = 'The !{} command has been updated'.format(command.command.split('|')[0])

            AdminLogManager.add_entry('Command edited',
                    extra_args['user'],
                    log_msg,
                    data={
                        'old_message': old_message,
                        'new_message': new_message,
                        })

        if SocketClientManager.send('command.update', {'command_id': command_id}) is True:
            return {'success': 'good job'}, 200
        else:
            return {'error': 'could not push update'}, 500
Ejemplo n.º 46
0
    def commands_create(**options):
        session.pop('command_created_id', None)
        session.pop('command_edited_id', None)
        if request.method == 'POST':
            if 'aliases' not in request.form:
                abort(403)
            alias_str = request.form.get('aliases', '').replace('!', '').lower()
            delay_all = request.form.get('cd', Command.DEFAULT_CD_ALL)
            delay_user = request.form.get('usercd', Command.DEFAULT_CD_USER)
            level = request.form.get('level', Command.DEFAULT_LEVEL)
            cost = request.form.get('cost', 0)

            try:
                delay_all = int(delay_all)
                delay_user = int(delay_user)
                level = int(level)
                cost = int(cost)
            except ValueError:
                abort(403)

            if len(alias_str) == 0:
                abort(403)
            if delay_all < 0 or delay_all > 9999:
                abort(403)
            if delay_user < 0 or delay_user > 9999:
                abort(403)
            if level < 0 or level > 2000:
                abort(403)
            if cost < 0 or cost > 9999999:
                abort(403)

            user = options.get('user', None)

            if user is None:
                abort(403)

            options = {
                'delay_all': delay_all,
                'delay_user': delay_user,
                'level': level,
                'cost': cost,
                'added_by': user.id,
            }

            valid_action_types = ['say', 'me', 'whisper', 'reply']
            action_type = request.form.get('reply', 'say').lower()
            if action_type not in valid_action_types:
                abort(403)

            response = request.form.get('response', '')
            if len(response) == 0:
                abort(403)

            action = {
                'type': action_type,
                'message': response
            }
            options['action'] = action

            command_manager = (
                CommandManager(
                    socket_manager=None,
                    module_manager=ModuleManager(None).load(),
                    bot=None).load(enabled=None))

            command_aliases = []

            for alias, command in command_manager.items():
                command_aliases.append(alias)
                if command.command and len(command.command) > 0:
                    command_aliases.extend(command.command.split('|'))

            command_aliases = set(command_aliases)

            alias_str = alias_str.replace(' ', '').replace('!', '').lower()
            alias_list = alias_str.split('|')

            alias_list = [alias for alias in alias_list if len(alias) > 0]

            if len(alias_list) == 0:
                return render_template('admin/create_command_fail.html')

            for alias in alias_list:
                if alias in command_aliases:
                    return render_template('admin/create_command_fail.html')

            alias_str = '|'.join(alias_list)

            command = Command(command=alias_str, **options)
            command.data = CommandData(command.id, **options)
            log_msg = 'The !{} command has been created'.format(command.command.split('|')[0])
            AdminLogManager.add_entry('Command created',
                    user,
                    log_msg)
            with DBManager.create_session_scope(expire_on_commit=False) as db_session:
                db_session.add(command)
                db_session.add(command.data)
                db_session.commit()
                db_session.expunge(command)
                db_session.expunge(command.data)

            SocketClientManager.send('command.update', {'command_id': command.id})
            session['command_created_id'] = command.id
            return redirect('/admin/commands/', 303)
        else:
            return render_template('admin/create_command.html')
Ejemplo n.º 47
0
    def banphrases_create(**options):
        session.pop('banphrase_created_id', None)
        session.pop('banphrase_edited_id', None)
        if request.method == 'POST':
            id = None
            try:
                if 'id' in request.form:
                    id = int(request.form['id'])
                name = request.form['name'].strip()
                permanent = request.form.get('permanent', 'off')
                warning = request.form.get('warning', 'off')
                notify = request.form.get('notify', 'off')
                case_sensitive = request.form.get('case_sensitive', 'off')
                sub_immunity = request.form.get('sub_immunity', 'off')
                remove_accents = request.form.get('remove_accents', 'off')
                length = int(request.form['length'])
                phrase = request.form['phrase']
                operator = request.form['operator'].strip().lower()
            except (KeyError, ValueError):
                abort(403)

            permanent = True if permanent == 'on' else False
            warning = True if warning == 'on' else False
            notify = True if notify == 'on' else False
            case_sensitive = True if case_sensitive == 'on' else False
            sub_immunity = True if sub_immunity == 'on' else False
            remove_accents = True if remove_accents == 'on' else False

            if len(name) == 0:
                abort(403)

            if len(phrase) == 0:
                abort(403)

            if length < 0 or length > 1209600:
                abort(403)

            valid_operators = ['contains', 'startswith', 'endswith', 'exact', 'regex']
            if operator not in valid_operators:
                abort(403)

            user = options.get('user', None)

            if user is None:
                abort(403)

            options = {
                    'name': name,
                    'phrase': phrase,
                    'permanent': permanent,
                    'warning': warning,
                    'notify': notify,
                    'case_sensitive': case_sensitive,
                    'sub_immunity': sub_immunity,
                    'remove_accents': remove_accents,
                    'length': length,
                    'added_by': user.id,
                    'edited_by': user.id,
                    'operator': operator,
                    }

            if id is None:
                banphrase = Banphrase(**options)
                banphrase.data = BanphraseData(banphrase.id, added_by=options['added_by'])

            with DBManager.create_session_scope(expire_on_commit=False) as db_session:
                if id is not None:
                    banphrase = db_session.query(Banphrase).options(joinedload(Banphrase.data)).filter_by(id=id).one_or_none()
                    if banphrase is None:
                        return redirect('/admin/banphrases/', 303)
                    banphrase.set(**options)
                    banphrase.data.set(edited_by=options['edited_by'])
                    log.info('Updated banphrase ID {} by user ID {}'.format(banphrase.id, options['edited_by']))
                    AdminLogManager.post('Banphrase edited', user, banphrase.phrase)
                else:
                    db_session.add(banphrase)
                    db_session.add(banphrase.data)
                    log.info('Added a new banphrase by user ID {}'.format(options['added_by']))
                    AdminLogManager.post('Banphrase added', user, banphrase.phrase)

            SocketClientManager.send('banphrase.update', {'id': banphrase.id})
            if id is None:
                session['banphrase_created_id'] = banphrase.id
            else:
                session['banphrase_edited_id'] = banphrase.id
            return redirect('/admin/banphrases/', 303)
        else:
            return render_template('admin/create_banphrase.html')
Ejemplo n.º 48
0
                except:
                    pass
            config.set('web', 'logo', 'set')
            log.info('set logo')
    except:
        pass

with open(args.config, 'w') as configfile:
    config.write(configfile)

app.secret_key = config['web']['secret_key']
oauth = OAuth(app)


if 'sock' in config and 'sock_file' in config['sock']:
    SocketClientManager.init(config['sock']['sock_file'])

twitch = oauth.remote_app(
        'twitch',
        consumer_key=config['webtwitchapi']['client_id'],
        consumer_secret=config['webtwitchapi']['client_secret'],
        request_token_params={'scope': 'user_read'},
        base_url='https://api.twitch.tv/kraken/',
        request_token_url=None,
        access_token_method='POST',
        access_token_url='https://api.twitch.tv/kraken/oauth2/token',
        authorize_url='https://api.twitch.tv/kraken/oauth2/authorize',
        )

DBManager.init(config['main']['db'])
TimeManager.init_timezone(config['main'].get('timezone', 'UTC'))
Ejemplo n.º 49
0
    def commands_create(**options) -> ResponseReturnValue:
        session.pop("command_created_id", None)
        session.pop("command_edited_id", None)
        if request.method != "POST":
            return render_template("admin/create_command.html")

        if "aliases" not in request.form:
            abort(403)
        alias_str = request.form.get("aliases", "").replace("!", "").lower()
        delay_all = request.form.get("cd", Command.DEFAULT_CD_ALL)
        delay_user = request.form.get("usercd", Command.DEFAULT_CD_USER)
        level = request.form.get("level", Command.DEFAULT_LEVEL)
        cost = request.form.get("cost", 0)
        can_execute_with_whisper = request.form.get("whisperable",
                                                    "off") == "on"
        sub_only = request.form.get("subonly", "off") == "on"
        mod_only = request.form.get("modonly", "off") == "on"
        run_through_banphrases = request.form.get("checkmsg", "off") == "on"

        try:
            delay_all = int(delay_all)
            delay_user = int(delay_user)
            level = int(level)
            cost = int(cost)
        except ValueError:
            abort(403)

        if not alias_str:
            abort(403)
        if delay_all < 0 or delay_all > 9999:
            abort(403)
        if delay_user < 0 or delay_user > 9999:
            abort(403)
        if level < 0 or level > 2000:
            abort(403)
        if cost < 0 or cost > 9999999:
            abort(403)

        user = options.get("user", None)

        if user is None:
            abort(403)

        options = {
            "delay_all": delay_all,
            "delay_user": delay_user,
            "level": level,
            "cost": cost,
            "added_by": user.id,
            "can_execute_with_whisper": can_execute_with_whisper,
            "sub_only": sub_only,
            "mod_only": mod_only,
            "run_through_banphrases": run_through_banphrases,
        }

        valid_action_types = ["say", "me", "announce", "whisper", "reply"]
        action_type = request.form.get("reply", "say").lower()
        if action_type not in valid_action_types:
            abort(403)

        response = request.form.get("response", "")
        if not response:
            abort(403)

        action = {"type": action_type, "message": response}
        options["action"] = action

        command_manager = pajbot.managers.command.CommandManager(
            socket_manager=None,
            module_manager=ModuleManager(None).load(),
            bot=None).load(enabled=None)

        command_aliases_list = []

        for alias, command in command_manager.items():
            command_aliases_list.append(alias)
            if command.command and len(command.command) > 0:
                command_aliases_list.extend(command.command.split("|"))

        command_aliases = set(command_aliases_list)

        alias_str = alias_str.replace(" ", "").replace("!", "").lower()
        alias_list = alias_str.split("|")

        alias_list = [alias for alias in alias_list if len(alias) > 0]

        if not alias_list:
            return render_template("admin/create_command_fail.html")

        for alias in alias_list:
            if alias in command_aliases:
                return render_template("admin/create_command_fail.html")

        alias_str = "|".join(alias_list)

        command = Command(command=alias_str, **options)
        command.data = CommandData(command.id, **options)
        log_msg = f"The !{command.command.split('|')[0]} command has been created"
        AdminLogManager.add_entry("Command created", user, log_msg)
        with DBManager.create_session_scope(
                expire_on_commit=False) as db_session:
            db_session.add(command)
            db_session.add(command.data)
            db_session.commit()
            db_session.expunge(command)
            db_session.expunge(command.data)

        SocketClientManager.send("command.update", {"command_id": command.id})
        session["command_created_id"] = command.id
        return redirect("/admin/commands", 303)
Ejemplo n.º 50
0
def init(args):
    import subprocess
    import sys

    from flask import request
    from flask import session

    import pajbot.utils
    import pajbot.web.common
    import pajbot.web.routes
    from pajbot.managers.db import DBManager
    from pajbot.managers.redis import RedisManager
    from pajbot.models.module import ModuleManager
    from pajbot.models.sock import SocketClientManager
    from pajbot.streamhelper import StreamHelper
    from pajbot.utils import load_config
    from pajbot.web.models import errors
    from pajbot.web.utils import download_logo
    from pajbot.web.utils import download_sub_badge

    config = load_config(args.config)

    api_client_credentials = ClientCredentials(
        config["twitchapi"]["client_id"],
        config["twitchapi"]["client_secret"],
        config["twitchapi"].get(
            "redirect_uri",
            f"https://{config['web']['domain']}/login/authorized"),
    )

    redis_options = {}
    if "redis" in config:
        redis_options = dict(config["redis"])

    RedisManager.init(redis_options)

    twitch_id_api = TwitchIDAPI(api_client_credentials)
    app_token_manager = AppAccessTokenManager(twitch_id_api,
                                              RedisManager.get())
    twitch_helix_api = TwitchHelixAPI(RedisManager.get(), app_token_manager)
    twitch_badges_api = TwitchBadgesAPI(RedisManager.get())

    app.api_client_credentials = api_client_credentials
    app.twitch_id_api = twitch_id_api
    app.twitch_helix_api = twitch_helix_api

    if "web" not in config:
        log.error("Missing [web] section in config.ini")
        sys.exit(1)

    app.streamer = cfg.load_streamer(config, twitch_helix_api)

    app.streamer_display = app.streamer.name
    if "streamer_name" in config["web"]:
        app.streamer_display = config["web"]["streamer_name"]

    app.bot_user = cfg.load_bot(config, twitch_helix_api)

    StreamHelper.init_streamer(app.streamer.login, app.streamer.id,
                               app.streamer.name)

    try:
        download_logo(twitch_helix_api, app.streamer)
    except:
        log.exception("Error downloading the streamers profile picture")

    subscriber_badge_version = config["web"].get("subscriber_badge_version",
                                                 "0")

    # Specifying a value of -1 in the config will disable sub badge downloading. Useful if you want to keep a custom version of a sub badge for a streamer
    if subscriber_badge_version != "-1":
        try:
            download_sub_badge(twitch_badges_api, app.streamer,
                               subscriber_badge_version)
        except:
            log.exception("Error downloading the streamers subscriber badge")

    SocketClientManager.init(app.streamer.login)

    app.bot_modules = config["web"].get("modules", "").split()
    app.bot_commands_list = []
    app.bot_config = config

    # https://flask.palletsprojects.com/en/1.1.x/quickstart/#sessions
    # https://flask.palletsprojects.com/en/1.1.x/api/#sessions
    # https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.secret_key
    app.secret_key = _load_secret_key(app.bot_user.id, app.streamer.id)
    app.bot_dev = "flags" in config and "dev" in config["flags"] and config[
        "flags"]["dev"] == "1"

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

    app.module_manager = ModuleManager(None).load()

    pajbot.web.routes.admin.init(app)
    pajbot.web.routes.api.init(app)
    pajbot.web.routes.base.init(app)

    # Make a CSRF exemption for the /api/v1/banphrases/test endpoint
    csrf.exempt("pajbot.web.routes.api.banphrases.apibanphrasetest")

    pajbot.web.common.filters.init(app)
    pajbot.web.common.assets.init(app)
    pajbot.web.common.menu.init(app)

    app.register_blueprint(pajbot.web.routes.clr.page)

    errors.init(app, config)
    pajbot.web.routes.clr.config = config

    version = VERSION
    last_commit = None

    if app.bot_dev:
        version = extend_version_if_possible(VERSION)

        try:
            last_commit = subprocess.check_output(
                ["git", "log", "-1", "--format=%cd"]).decode("utf8").strip()
        except:
            log.exception(
                "Failed to get last_commit, will not show last commit")

    default_variables = {
        "version": version,
        "last_commit": last_commit,
        "bot": {
            "name": app.bot_user.login
        },
        "site": {
            "domain":
            config["web"]["domain"],
            "deck_tab_images":
            cfg.get_boolean(config["web"], "deck_tab_images", False),
            "websocket": {
                "host":
                config["websocket"].get(
                    "host", f"wss://{config['web']['domain']}/clrsocket")
            },
        },
        "streamer": {
            "name": app.streamer_display,
            "full_name": app.streamer.login,
            "id": app.streamer.id
        },
        "modules": app.bot_modules,
        "request": request,
        "session": session,
        "google_analytics": config["web"].get("google_analytics", None),
    }

    @app.context_processor
    def current_time():
        current_time = {}
        current_time["current_time"] = pajbot.utils.now()
        return current_time

    @app.context_processor
    def inject_default_variables():
        return default_variables
Ejemplo n.º 51
0
def command_update(command_id, **options):
    if not request.method == 'POST':
        return make_response(jsonify({'error': 'Invalid request method. (Expected POST)'}), 400)
    if len(request.form) == 0:
        return make_response(jsonify({'error': 'Missing parameter to edit.'}), 400)

    valid_names = [
            'enabled',
            'level',
            'delay_all',
            'delay_user',
            'cost',
            'can_execute_with_whisper',
            'sub_only'
            ]

    valid_action_names = [
            'type',
            'message'
            ]

    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()
        if command is None:
            return make_response(jsonify({'error': 'Invalid command ID'}), 404)
        if command.level > options['user'].level:
            abort(403)
        parsed_action = json.loads(command.action_json)
        options = {
            'edited_by': options['user'].id,
        }

        for key in request.form:
            if key.startswith('data_'):
                name = key[5:]
                value = request.form[key]

                if name.startswith('action_'):
                    name = name[7:]
                    if name in valid_action_names and name in parsed_action and command.action.type == 'message':
                        value_type = type(parsed_action[name])
                        if value_type is bool:
                            parsed_value = True if value == '1' else False
                        elif value_type is int:
                            try:
                                parsed_value = int(value)
                            except ValueError:
                                continue
                        else:
                            parsed_value = value
                        parsed_action[name] = parsed_value
                    command.action_json = json.dumps(parsed_action)
                else:
                    if name in valid_names:
                        value_type = type(getattr(command, name))
                        if value_type is bool:
                            parsed_value = True if value == '1' else False
                        elif value_type is int:
                            try:
                                parsed_value = int(value)
                            except ValueError:
                                continue
                        else:
                            parsed_value = value
                        options[name] = parsed_value

        command.set(**options)
        command.data.set(**options)

    if SocketClientManager.send('command.update', {'command_id': command_id}) is True:
        return make_response(jsonify({'success': 'good job'}))
    else:
        return make_response(jsonify({'error': 'Could not push update'}))
Ejemplo n.º 52
0
    def banphrases_create(**options):
        session.pop("banphrase_created_id", None)
        session.pop("banphrase_edited_id", None)
        if request.method == "POST":
            id = None
            try:
                if "id" in request.form:
                    id = int(request.form["id"])
                name = request.form["name"].strip()
                permanent = request.form.get("permanent", "off")
                warning = request.form.get("warning", "off")
                notify = request.form.get("notify", "off")
                case_sensitive = request.form.get("case_sensitive", "off")
                sub_immunity = request.form.get("sub_immunity", "off")
                remove_accents = request.form.get("remove_accents", "off")
                length = int(request.form["length"])
                phrase = request.form["phrase"]
                operator = request.form["operator"].strip().lower()
            except (KeyError, ValueError):
                abort(403)

            permanent = permanent == "on"
            warning = warning == "on"
            notify = notify == "on"
            case_sensitive = case_sensitive == "on"
            sub_immunity = sub_immunity == "on"
            remove_accents = remove_accents == "on"

            if not name:
                abort(403)

            if not phrase:
                abort(403)

            if length < 0 or length > 1209600:
                abort(403)

            valid_operators = [
                "contains", "startswith", "endswith", "exact", "regex"
            ]
            if operator not in valid_operators:
                abort(403)

            user = options.get("user", None)

            if user is None:
                abort(403)

            options = {
                "name": name,
                "phrase": phrase,
                "permanent": permanent,
                "warning": warning,
                "notify": notify,
                "case_sensitive": case_sensitive,
                "sub_immunity": sub_immunity,
                "remove_accents": remove_accents,
                "length": length,
                "added_by": user.id,
                "edited_by": user.id,
                "operator": operator,
            }

            if id is None:
                banphrase = Banphrase(**options)
                banphrase.data = BanphraseData(banphrase.id,
                                               added_by=options["added_by"])

            with DBManager.create_session_scope(
                    expire_on_commit=False) as db_session:
                if id is not None:
                    banphrase = (db_session.query(Banphrase).options(
                        joinedload(
                            Banphrase.data)).filter_by(id=id).one_or_none())
                    if banphrase is None:
                        return redirect("/admin/banphrases/", 303)
                    banphrase.set(**options)
                    banphrase.data.set(edited_by=options["edited_by"])
                    log.info(
                        f"Updated banphrase ID {banphrase.id} by user ID {options['edited_by']}"
                    )
                    AdminLogManager.post("Banphrase edited", user,
                                         banphrase.id, banphrase.phrase)
                else:
                    db_session.add(banphrase)
                    db_session.add(banphrase.data)
                    db_session.flush()
                    log.info(
                        f"Added a new banphrase by user ID {options['added_by']}"
                    )
                    AdminLogManager.post("Banphrase added", user, banphrase.id,
                                         banphrase.phrase)

            SocketClientManager.send("banphrase.update", {"id": banphrase.id})
            if id is None:
                session["banphrase_created_id"] = banphrase.id
            else:
                session["banphrase_edited_id"] = banphrase.id
            return redirect("/admin/banphrases/", 303)
        else:
            return render_template("admin/create_banphrase.html")
Ejemplo n.º 53
0
def generic_toggle(route_key, row_id, **options):
    valid_routes = {
        'timer': Timer,
        'banphrase': Banphrase,
        'module': Module,
    }

    route_name = {
        'timer': lambda x: x.name,
        'banphrase': lambda x: x.phrase,
        'module': lambda x: x.id,
    }

    route_title = {
        'timer': 'Timer',
        'banphrase': 'Banphrase',
        'module': 'Module',
    }

    route_validator = {'module': lambda x: validate_module(x.id)}

    if route_key not in valid_routes:
        return make_response(jsonify({'error': 'Invalid route.'}), 400)
    if 'new_state' not in request.form:
        return make_response(
            jsonify({'error': 'Missing `new_state` parameter.'}), 400)
    try:
        new_state = int(request.form['new_state'])
    except (ValueError, KeyError):
        return make_response(
            jsonify({'error': 'Invalid `new_state` parameter.'}), 400)

    route_value = valid_routes[route_key]

    with DBManager.create_session_scope() as db_session:
        row = db_session.query(route_value).filter_by(id=row_id).one_or_none()
        if row:
            validator = route_validator.get(route_key, None)

            if validator is not None:
                res = validator(row)
                if not res:
                    return make_response(
                        jsonify(
                            {'error': 'cannot modify {}'.format(route_key)}),
                        400)

            row.enabled = True if new_state == 1 else False
            db_session.commit()
            payload = {
                '{}_id'.format(route_key): row.id,  # remove this
                'id': row.id,
                'new_state': row.enabled,
            }
            AdminLogManager.post(
                '{title} toggled'.format(title=route_title[route_key]),
                options['user'], 'Enabled' if row.enabled else 'Disabled',
                route_name[route_key](row))
            SocketClientManager.send('{}.update'.format(route_key), payload)
            return make_response(
                jsonify({
                    'success': 'successful toggle',
                    'new_state': new_state
                }))
        else:
            return make_response(
                jsonify({'error': 'invalid {} id'.format(route_key)}))