コード例 #1
0
ファイル: api.py プロジェクト: sbezboro/standard-web-flask
def audit_log():
    body = request.json

    type = body.get('type')
    data = body.get('data')
    uuid = body.get('uuid')

    if not type:
        return jsonify({
            'err': 1,
            'message': 'Missing type'
        }), 400

    player_id = None

    if uuid:
        player = Player.query.filter_by(uuid=uuid).first()
        if player:
            player_id = player.id

    AuditLog.create(
        type,
        data=data,
        server_id=g.server.id,
        player_id=player_id,
        commit=True
    )

    return jsonify({
        'err': 0
    })
コード例 #2
0
ファイル: auth.py プロジェクト: sbezboro/standard-web-flask
def login():
    form = LoginForm()

    if form.validate_on_submit():
        username = request.form['username']
        password = request.form['password']
        next_path = request.form.get('next')

        username = username.strip()

        player = Player.query.filter_by(username=username).first()
        if player:
            user = player.user
        else:
            # TODO: check renames
            user = User.query.filter(
                or_(User.username == username, User.email == username)
            ).first()

        if user and user.check_password(password):
            if not user.session_key:
                user.generate_session_key(commit=False)

            session['user_session_key'] = user.session_key
            session.permanent = True

            if not user.last_login:
                session['first_login'] = True

            user.last_login = datetime.utcnow()
            user.save(commit=True)

            stats.incr('login.success')

            if user.mfa_login:
                session['mfa_stage'] = 'password-verified'
                return redirect(url_for('verify_mfa', next=next_path))

            flash('Successfully logged in', 'success')

            return redirect(next_path or url_for('index'))
        else:
            flash('Invalid username/password combination', 'error')

            stats.incr('login.invalid')

            AuditLog.create(
                AuditLog.INVALID_LOGIN,
                username=username,
                matched_user_id=user.id if user else None,
                ip=request.remote_addr,
                commit=True
            )

            return render_template('login.html', form=form), 401

    return render_template('login.html', form=form)
コード例 #3
0
ファイル: api.py プロジェクト: sbezboro/standard-web-flask
def register():
    uuid = request.form.get('uuid')
    email = request.form.get('email')
    username = request.form.get('username')

    player = Player.query.filter_by(uuid=uuid).first()
    if not player:
        return jsonify({
            'err': 1,
            'message': 'Please try again later'
        })

    user = User.query.filter_by(player=player).first()
    if user and user.email:
        return jsonify({
            'err': 1,
            'message': 'You are already registered!'
        })

    if not h.is_valid_email(email):
        return jsonify({
            'err': 1,
            'message': 'Not a valid email address'
        })

    other_user = User.query.filter_by(email=email).first()
    if other_user:
        return jsonify({
            'err': 1,
            'message': 'Email already in use'
        })

    email_tokens = EmailToken.query.filter_by(uuid=uuid)
    for email_token in email_tokens:
        db.session.delete(email_token)

    # old-style user without an email, just let them verify an email
    if user:
        send_verify_email(email, user)
    else:
        send_creation_email(email, uuid, username)

    total_time = libplayer.get_total_player_time(player.id)
    if total_time < app.config['MINIMUM_REGISTER_PLAYER_TIME']:
        rollbar.report_message('Player creating user account super quickly', level='error', request=request)
        AuditLog.create(
            AuditLog.QUICK_USER_CREATE,
            player_id=player.id,
            username=player.username,
            commit=True
        )

    return jsonify({
        'err': 0,
        'message': 'Email sent! Check your inbox for further instructions'
    })
コード例 #4
0
def login():
    form = LoginForm()

    if form.validate_on_submit():
        username = request.form['username']
        password = request.form['password']
        next_path = request.form.get('next')

        username = username.strip()

        player = Player.query.filter_by(username=username).first()
        if player:
            user = player.user
        else:
            # TODO: check renames
            user = User.query.filter(
                or_(User.username == username,
                    User.email == username)).first()

        if user and user.check_password(password):
            if not user.session_key:
                user.generate_session_key(commit=False)

            session['user_session_key'] = user.session_key
            session.permanent = True

            if not user.last_login:
                session['first_login'] = True

            user.last_login = datetime.utcnow()
            user.save(commit=True)

            stats.incr('login.success')

            if user.mfa_login:
                session['mfa_stage'] = 'password-verified'
                return redirect(url_for('verify_mfa', next=next_path))

            flash('Successfully logged in', 'success')

            return redirect(next_path or url_for('index'))
        else:
            flash('Invalid username/password combination', 'error')

            stats.incr('login.invalid')

            AuditLog.create(AuditLog.INVALID_LOGIN,
                            username=username,
                            matched_user_id=user.id if user else None,
                            ip=request.remote_addr,
                            commit=True)

            return render_template('login.html', form=form), 401

    return render_template('login.html', form=form)
コード例 #5
0
def subscribe_to_topic(user, topic, commit=True):
    subscription = ForumTopicSubscription(
        user=user,
        topic=topic
    )

    subscription.save(commit=False)

    AuditLog.create('topic_subscribe', user_id=user.id, data={
        'topic_id': topic.id
    }, commit=commit)
コード例 #6
0
def subscribe_to_topic(user, topic, commit=True):
    subscription = ForumTopicSubscription(
        user=user,
        topic=topic
    )

    subscription.save(commit=False)

    AuditLog.create('topic_subscribe', user_id=user.id, data={
        'topic_id': topic.id
    }, commit=commit)
コード例 #7
0
def edit_post(post_id):
    post = ForumPost.query.options(
        joinedload(ForumPost.topic)
        .joinedload(ForumTopic.forum)
        .joinedload(Forum.moderators)
    ).options(
        joinedload(ForumPost.user)
        .joinedload(User.forum_profile)
    ).get(post_id)

    if not post or post.deleted:
        abort(404)

    user = g.user

    if user.forum_ban:
        abort(403)

    if user != post.user and not user.admin and user not in post.topic.forum.moderators:
        abort(403)

    form = PostForm(obj=post)

    if form.validate_on_submit():
        body = request.form['body']

        AuditLog.create(
            'forum_post_edit',
            user_id=user.id,
            post_id=post_id,
            old_text=post.body,
            new_text=body,
            commit=False
        )

        post.body = body

        post.updated = datetime.utcnow()
        post.updated_by = user

        post.save(commit=True)

        return redirect(post.url)

    retval = {
        'post': post,
        'form': form
    }

    return render_template('forums/edit_post.html', **retval)
コード例 #8
0
def unsubscribe(encoded_email, type, signature):
    if not verify_unsubscribe_request(encoded_email, type, signature):
        rollbar.report_message('Unsubscribe signature failure',
                               level='error',
                               extra_data={
                                   'current_user_id':
                                   g.user.id if g.user else None,
                                   'path': request.path,
                               })

        abort(403)

    email = urllib.unquote(encoded_email)

    user = User.query.filter_by(email=email).first()
    if not user:
        flash('Invalid link', 'error')
        return redirect(url_for('index'))

    if g.user and g.user != user:
        rollbar.report_message('Unsubscribing email of a different user',
                               level='warning',
                               extra_data={
                                   'current_user_id': g.user.id,
                                   'current_user_email': g.user.email,
                                   'target_user_id': user.id,
                                   'target_user_email': email
                               })

    AuditLog.create('unsubscribe',
                    user_id=g.user.id if g.user else user.id,
                    data={
                        'email': email,
                        'type': type
                    },
                    commit=False)

    preference = user.get_notification_preference(type, can_commit=False)
    preference.email = False
    preference.save(commit=True)

    email_preferences_url = url_for('notifications_settings')

    flash(
        Markup(
            'Successfully unsubscribed! Manage more email preferences <a href="%s">here</a>.'
            % email_preferences_url), 'success')

    return redirect(url_for('index'))
コード例 #9
0
def forum_ban():
    by_user = g.user

    user_id = request.args['user_id']

    AuditLog.create(AuditLog.USER_FORUM_BAN,
                    user_id=user_id,
                    by_user_id=by_user.id,
                    commit=False)

    ban = ForumBan(user_id=user_id, by_user_id=by_user.id)
    ban.save(commit=True)

    flash('User banned from forums', 'success')

    return redirect(request.referrer)
コード例 #10
0
ファイル: api.py プロジェクト: shivam22222/standard-web-flask
def register():
    uuid = request.form.get('uuid')
    email = request.form.get('email')
    username = request.form.get('username')

    player = Player.query.filter_by(uuid=uuid).first()
    if not player:
        return jsonify({'err': 1, 'message': 'Please try again later'})

    user = User.query.filter_by(player=player).first()
    if user and user.email:
        return jsonify({'err': 1, 'message': 'You are already registered!'})

    if not h.is_valid_email(email):
        return jsonify({'err': 1, 'message': 'Not a valid email address'})

    other_user = User.query.filter_by(email=email).first()
    if other_user:
        return jsonify({'err': 1, 'message': 'Email already in use'})

    email_tokens = EmailToken.query.filter_by(uuid=uuid)
    for email_token in email_tokens:
        db.session.delete(email_token)

    # old-style user without an email, just let them verify an email
    if user:
        send_verify_email(email, user)
    else:
        send_creation_email(email, uuid, username)

    total_time = libplayer.get_total_player_time(player.id)
    if total_time < app.config['MINIMUM_REGISTER_PLAYER_TIME']:
        rollbar.report_message('Player creating user account super quickly',
                               level='error',
                               request=request)
        AuditLog.create(AuditLog.QUICK_USER_CREATE,
                        player_id=player.id,
                        username=player.username,
                        commit=True)

    return jsonify({
        'err':
        0,
        'message':
        'Email sent! Check your inbox for further instructions'
    })
コード例 #11
0
ファイル: forums.py プロジェクト: sbezboro/standard-web-flask
def forum_ban():
    by_user = g.user

    user_id = request.args['user_id']

    AuditLog.create(
        AuditLog.USER_FORUM_BAN,
        user_id=user_id,
        by_user_id=by_user.id,
        commit=False
    )

    ban = ForumBan(user_id=user_id, by_user_id=by_user.id)
    ban.save(commit=True)

    flash('User banned from forums', 'success')

    return redirect(request.referrer)
コード例 #12
0
ファイル: player.py プロジェクト: sbezboro/standard-web-flask
def ban_player(player, reason=None, with_ip=False, by_user_id=None, source=None, commit=True, **kwargs):
    reason = reason or 'The Ban Hammer has spoken!'

    api.ban_player(player, reason, with_ip)

    AuditLog.create(
        AuditLog.PLAYER_BAN,
        player_id=player.id,
        username=player.username,
        by_user_id=by_user_id,
        reason=reason,
        source=source,
        commit=False,
        **kwargs
    )

    player.banned = True
    player.save(commit=commit)
コード例 #13
0
def notifications_settings():
    user = g.user

    preferences = user.get_notification_preferences()

    form = generate_notification_settings_form(preferences)

    if form.validate_on_submit():
        for preference in preferences:
            preference.email = getattr(form, '%s_email' % preference.name).data
            preference.ingame = getattr(form,
                                        '%s_ingame' % preference.name).data

            preference.save(commit=False)

        db.session.commit()

        AuditLog.create('notification_settings_saved',
                        user_id=user.id,
                        data={
                            x.name: {
                                'email': x.email,
                                'ingame': x.ingame
                            }
                            for x in preferences
                        },
                        commit=True)

        flash('Notification settings saved!', 'success')

    grouped_preferences = {}
    for preference in preferences:
        definition = preference.definition
        grouped_preferences.setdefault(definition.setting_category,
                                       []).append(preference)

    template_vars = {
        'form': form,
        'grouped_preferences': grouped_preferences,
        'active_option': 'notifications'
    }

    return render_template('settings/notifications.html', **template_vars)
コード例 #14
0
def edit_post(post_id):
    post = ForumPost.query.options(
        joinedload(ForumPost.topic).joinedload(ForumTopic.forum)).options(
            joinedload(ForumPost.user).joinedload(
                User.forum_profile)).get(post_id)

    if not post or post.deleted:
        abort(404)

    user = g.user

    if user.forum_ban:
        abort(403)

    if user != post.user and not user.admin_or_moderator:
        abort(403)

    form = PostForm(obj=post)

    if form.validate_on_submit():
        body = request.form['body']

        AuditLog.create('forum_post_edit',
                        user_id=user.id,
                        post_id=post_id,
                        old_text=post.body,
                        new_text=body,
                        commit=False)

        post.body = body

        post.updated = datetime.utcnow()
        post.updated_by = user

        post.save(commit=True)

        return redirect(post.url)

    retval = {'post': post, 'form': form}

    return render_template('forums/edit_post.html', **retval)
コード例 #15
0
def unsubscribe(encoded_email, type, signature):
    if not verify_unsubscribe_request(encoded_email, type, signature):
        rollbar.report_message('Unsubscribe signature failure', level='error', extra_data={
            'current_user_id': g.user.id if g.user else None,
            'path': request.path,
        })

        abort(403)

    email = urllib.unquote(encoded_email)

    user = User.query.filter_by(email=email).first()
    if not user:
        flash('Invalid link', 'error')
        return redirect(url_for('index'))

    if g.user and g.user != user:
        rollbar.report_message('Unsubscribing email of a different user', level='warning', extra_data={
            'current_user_id': g.user.id,
            'current_user_email': g.user.email,
            'target_user_id': user.id,
            'target_user_email': email
        })

    AuditLog.create('unsubscribe', user_id=g.user.id if g.user else user.id, data={
        'email': email,
        'type': type
    }, commit=False)

    preference = user.get_notification_preference(type, can_commit=False)
    preference.email = False
    preference.save(commit=True)

    email_preferences_url = url_for('notifications_settings')

    flash(
        Markup('Successfully unsubscribed! Manage more email preferences <a href="%s">here</a>.' % email_preferences_url),
        'success'
    )

    return redirect(url_for('index'))
コード例 #16
0
def ban_player(player,
               reason=None,
               with_ip=False,
               by_user_id=None,
               source=None,
               commit=True,
               **kwargs):
    reason = reason or 'The Ban Hammer has spoken!'

    api.ban_player(player, reason, with_ip)

    AuditLog.create(AuditLog.PLAYER_BAN,
                    player_id=player.id,
                    username=player.username,
                    by_user_id=by_user_id,
                    reason=reason,
                    source=source,
                    commit=False,
                    **kwargs)

    player.banned = True
    player.save(commit=commit)
コード例 #17
0
def forum_unban():
    by_user = g.user

    user_id = request.args['user_id']

    ban = ForumBan.query.filter_by(user_id=user_id).first()

    if not ban:
        flash('User not forum banned', 'error')
        return redirect(request.referrer)

    AuditLog.create(AuditLog.USER_FORUM_UNBAN,
                    user_id=user_id,
                    by_user_id=by_user.id,
                    commit=False)

    db.session.delete(ban)
    db.session.commit()

    flash('User unbanned from forums', 'success')

    return redirect(request.referrer)
コード例 #18
0
def forum_topic_unsubscribe(topic_id):
    user = g.user

    topic = ForumTopic.query.get(topic_id)

    if not topic or topic.deleted:
        abort(404)

    subscription = ForumTopicSubscription.query.filter_by(user=user,
                                                          topic=topic).first()

    if subscription:
        db.session.delete(subscription)
        flash('Unsubscribed from the topic successfully!', 'success')

        AuditLog.create('topic_unsubscribe',
                        user_id=user.id,
                        data={'topic_id': topic.id})
    else:
        flash('You weren\'t subscribed to the topic', 'warning')

    return redirect(topic.url)
コード例 #19
0
def notifications_settings():
    user = g.user

    preferences = user.get_notification_preferences()

    form = generate_notification_settings_form(preferences)

    if form.validate_on_submit():
        for preference in preferences:
            preference.email = getattr(form, '%s_email' % preference.name).data
            preference.ingame = getattr(form, '%s_ingame' % preference.name).data

            preference.save(commit=False)

        db.session.commit()

        AuditLog.create('notification_settings_saved', user_id=user.id, data={
            x.name: {
                'email': x.email,
                'ingame': x.ingame
            } for x in preferences
        }, commit=True)

        flash('Notification settings saved!', 'success')

    grouped_preferences = {}
    for preference in preferences:
        definition = preference.definition
        grouped_preferences.setdefault(definition.setting_category, []).append(preference)

    template_vars = {
        'form': form,
        'grouped_preferences': grouped_preferences,
        'active_option': 'notifications'
    }

    return render_template('settings/notifications.html', **template_vars)
コード例 #20
0
def forum_topic_unsubscribe(topic_id):
    user = g.user

    topic = ForumTopic.query.get(topic_id)

    if not topic or topic.deleted:
        abort(404)

    subscription = ForumTopicSubscription.query.filter_by(
        user=user,
        topic=topic
    ).first()

    if subscription:
        db.session.delete(subscription)
        flash('Unsubscribed from the topic successfully!', 'success')

        AuditLog.create('topic_unsubscribe', user_id=user.id, data={
            'topic_id': topic.id
        })
    else:
        flash('You weren\'t subscribed to the topic', 'warning')

    return redirect(topic.url)
コード例 #21
0
ファイル: forums.py プロジェクト: sbezboro/standard-web-flask
def forum_unban():
    by_user = g.user

    user_id = request.args['user_id']

    ban = ForumBan.query.filter_by(user_id=user_id).first()

    if not ban:
        flash('User not forum banned', 'error')
        return redirect(request.referrer)

    AuditLog.create(
        AuditLog.USER_FORUM_UNBAN,
        user_id=user_id,
        by_user_id=by_user.id,
        commit=False
    )

    db.session.delete(ban)
    db.session.commit()

    flash('User unbanned from forums', 'success')

    return redirect(request.referrer)
コード例 #22
0
ファイル: api.py プロジェクト: shivam22222/standard-web-flask
def audit_log():
    body = request.json

    type = body.get('type')
    data = body.get('data')
    uuid = body.get('uuid')

    if not type:
        return jsonify({'err': 1, 'message': 'Missing type'}), 400

    player_id = None

    if uuid:
        player = Player.query.filter_by(uuid=uuid).first()
        if player:
            player_id = player.id

    AuditLog.create(type,
                    data=data,
                    server_id=g.server.id,
                    player_id=player_id,
                    commit=True)

    return jsonify({'err': 0})
コード例 #23
0
def _query_server(server, mojang_status):
    server_status = api.get_server_status(server) or {}

    player_stats = []

    players_to_sync_ban = Player.query.filter(
        Player.uuid.in_(server_status.get('banned_uuids', [])),
        Player.banned == False).all()

    if players_to_sync_ban:
        player_ids_to_sync_ban = [x.id for x in players_to_sync_ban]

        Player.query.filter(Player.id.in_(player_ids_to_sync_ban)).update(
            {
                'banned': True,
            }, synchronize_session=False)

        for player in players_to_sync_ban:
            AuditLog.create(AuditLog.PLAYER_BAN,
                            player_id=player.id,
                            username=player.username,
                            source='server_sync',
                            commit=False)

    online_player_ids = []
    for player_info in server_status.get('players', []):
        username = player_info['username']
        uuid = player_info['uuid']

        player = Player.query.options(joinedload(
            Player.titles)).filter_by(uuid=uuid).first()

        if player:
            if player.username != username:
                h.avoid_duplicate_username(username)

                player.set_username(username)
                player.save(commit=False)
        else:
            h.avoid_duplicate_username(username)

            player = Player(username=username, uuid=uuid)
            player.save(commit=False)

            statsd.incr('player.created')

        online_player_ids.append(player.id)

        last_activity = PlayerActivity.query.filter_by(
            server=server,
            player=player).order_by(PlayerActivity.timestamp.desc()).first()

        # if the last activity for this player is an 'exit' activity (or there isn't an activity),
        # create a new 'enter' activity since they just joined this minute
        if not last_activity or last_activity.activity_type == PLAYER_ACTIVITY_TYPES[
                'exit']:
            enter = PlayerActivity(
                server=server,
                player=player,
                activity_type=PLAYER_ACTIVITY_TYPES['enter'])
            enter.save(commit=False)

        if server.id == app.config['MAIN_SERVER_ID']:
            if player.banned:
                player.banned = False
                AuditLog.create(AuditLog.PLAYER_UNBAN,
                                player_id=player.id,
                                username=player.username,
                                source='server_sync',
                                commit=False)

            nickname_ansi = player_info.get('nickname_ansi')
            nickname = player_info.get('nickname')

            player.nickname_ansi = nickname_ansi
            player.nickname = nickname
            player.save(commit=False)

        ip = player_info.get('address')
        if ip:
            if not IPTracking.query.filter_by(ip=ip, player=player).first():
                existing_player_ip = IPTracking(ip=ip, player=player)
                existing_player_ip.save(commit=False)

            if geoip.is_nok(ip):
                libplayer.ban_player(player,
                                     with_ip=True,
                                     source='query',
                                     ip=ip,
                                     commit=False)

        stats = PlayerStats.query.filter_by(server=server,
                                            player=player).first()
        if not stats:
            stats = PlayerStats(server=server, player=player)

        stats.last_seen = datetime.utcnow()
        stats.pvp_logs = player_info.get('pvp_logs')
        stats.time_spent = (stats.time_spent or 0) + 1
        stats.save(commit=False)

        titles = [{
            'name': x.name,
            'broadcast': x.broadcast
        } for x in player.titles]

        player_stats.append({
            'username': player.username,
            'uuid': player.uuid,
            'minutes': stats.time_spent,
            'rank': stats.rank,
            'titles': titles
        })

    five_minutes_ago = datetime.utcnow() - timedelta(minutes=10)
    result = PlayerStats.query.filter(PlayerStats.server == server,
                                      PlayerStats.last_seen > five_minutes_ago)
    recent_player_ids = [x.player_id for x in result]

    # find all players that have recently left and insert an 'exit' activity for them
    # if their last activity was an 'enter'
    for player_id in set(recent_player_ids) - set(online_player_ids):
        latest_activity = PlayerActivity.query.filter_by(server=server, player_id=player_id)\
        .order_by(PlayerActivity.timestamp.desc()).first()

        if latest_activity and latest_activity.activity_type == PLAYER_ACTIVITY_TYPES[
                'enter']:
            ex = PlayerActivity(server=server,
                                player_id=player_id,
                                activity_type=PLAYER_ACTIVITY_TYPES['exit'])
            ex.save(commit=False)

    player_count = server_status.get('numplayers', 0) or 0
    cpu_load = server_status.get('load', 0) or 0
    tps = server_status.get('tps', 0) or 0

    status = ServerStatus(server=server,
                          player_count=player_count,
                          cpu_load=cpu_load,
                          tps=tps)
    status.save(commit=True)

    api.send_stats(
        server, {
            'player_stats': player_stats,
            'session': mojang_status.session,
            'account': mojang_status.account,
            'auth': mojang_status.auth
        })

    _handle_groups(server, server_status.get('groups', []))
コード例 #24
0
def _query_server(server, mojang_status):
    server_status = api.get_server_status(server) or {}
    
    player_stats = []
    
    online_player_ids = []
    for player_info in server_status.get('players', []):
        username = player_info['username']
        uuid = player_info['uuid']

        player = Player.query.options(
            joinedload(Player.titles)
        ).filter_by(uuid=uuid).first()

        if player:
            if player.username != username:
                AuditLog.create(
                    AuditLog.PLAYER_RENAME,
                    player_id=player.id,
                    old_name=player.username,
                    new_name=username,
                    commit=False
                )

                player.username = username
                player.save(commit=False)
        else:
            player = Player(username=username, uuid=uuid)
            player.save(commit=False)
        
        online_player_ids.append(player.id)

        last_activity = PlayerActivity.query.filter_by(server=server, player=player)\
            .order_by(PlayerActivity.timestamp.desc()).first()
        
        # if the last activity for this player is an 'exit' activity (or there isn't an activity),
        # create a new 'enter' activity since they just joined this minute
        if not last_activity or last_activity.activity_type == PLAYER_ACTIVITY_TYPES['exit']:
            enter = PlayerActivity(server=server, player=player,
                                   activity_type=PLAYER_ACTIVITY_TYPES['enter'])
            enter.save(commit=False)
        
        # respect nicknames from the main server
        if server.id == app.config['MAIN_SERVER_ID']:
            nickname_ansi = player_info.get('nickname_ansi')
            nickname = player_info.get('nickname')

            player.nickname_ansi = nickname_ansi
            player.nickname = nickname
            player.save(commit=False)
        
        ip = player_info.get('address')
        
        if ip:
            if not IPTracking.query.filter_by(ip=ip, player=player).first():
                existing_player_ip = IPTracking(ip=ip, player=player)
                existing_player_ip.save(commit=False)

        stats = PlayerStats.query.filter_by(server=server, player=player).first()
        if not stats:
            stats = PlayerStats(server=server, player=player)

        stats.last_seen = datetime.utcnow()
        stats.pvp_logs = player_info.get('pvp_logs')
        stats.time_spent = (stats.time_spent or 0) + 1
        stats.save(commit=False)

        titles = [{'name': x.name, 'broadcast': x.broadcast} for x in player.titles]

        player_stats.append({
            'username': player.username,
            'uuid': player.uuid,
            'minutes': stats.time_spent,
            'rank': stats.rank,
            'titles': titles
        })

    five_minutes_ago = datetime.utcnow() - timedelta(minutes=10)
    result = PlayerStats.query.filter(PlayerStats.server == server,
                                      PlayerStats.last_seen > five_minutes_ago)
    recent_player_ids = [x.player_id for x in result]
    
    # find all players that have recently left and insert an 'exit' activity for them
    # if their last activity was an 'enter'
    for player_id in set(recent_player_ids) - set(online_player_ids):
        latest_activity = PlayerActivity.query.filter_by(server=server, player_id=player_id)\
        .order_by(PlayerActivity.timestamp.desc()).first()
        
        if latest_activity and latest_activity.activity_type == PLAYER_ACTIVITY_TYPES['enter']:
            ex = PlayerActivity(server=server, player_id=player_id,
                                activity_type=PLAYER_ACTIVITY_TYPES['exit'])
            ex.save(commit=False)
    
    player_count = server_status.get('numplayers', 0) or 0
    cpu_load = server_status.get('load', 0) or 0
    tps = server_status.get('tps', 0) or 0
    
    status = ServerStatus(server=server, player_count=player_count, cpu_load=cpu_load, tps=tps)
    status.save(commit=True)

    api.send_stats(server, {
        'player_stats': player_stats,
        'session': mojang_status.session,
        'account': mojang_status.account,
        'auth': mojang_status.auth
    })

    _handle_groups(server, server_status.get('groups', []))
コード例 #25
0
ファイル: query.py プロジェクト: sbezboro/standard-web-flask
def _query_server(server, mojang_status):
    server_status = api.get_server_status(server) or {}
    
    player_stats = []

    players_to_sync_ban = Player.query.filter(
        Player.uuid.in_(server_status.get('banned_uuids', [])),
        Player.banned == False
    ).all()

    if players_to_sync_ban:
        player_ids_to_sync_ban = [x.id for x in players_to_sync_ban]

        Player.query.filter(
            Player.id.in_(player_ids_to_sync_ban)
        ).update({
            'banned': True,
        }, synchronize_session=False)

        for player in players_to_sync_ban:
            AuditLog.create(
                AuditLog.PLAYER_BAN,
                player_id=player.id,
                username=player.username,
                source='server_sync',
                commit=False
            )

    players = server_status.get('players', [])
    online_player_ids = []
    players_to_nok_ban = []
    for player_info in players:
        username = player_info['username']
        uuid = player_info['uuid']

        player = Player.query.options(
            joinedload(Player.titles)
        ).filter_by(uuid=uuid).first()

        if player:
            if player.username != username:
                h.avoid_duplicate_username(username)

                player.set_username(username)
                player.save(commit=False)
        else:
            h.avoid_duplicate_username(username)

            player = Player(username=username, uuid=uuid)
            player.save(commit=False)

            statsd.incr('player.created')
        
        online_player_ids.append(player.id)

        last_activity = PlayerActivity.query.filter_by(
            server=server, player=player
        ).order_by(
            PlayerActivity.timestamp.desc()
        ).first()
        
        # if the last activity for this player is an 'exit' activity (or there isn't an activity),
        # create a new 'enter' activity since they just joined this minute
        if not last_activity or last_activity.activity_type == PLAYER_ACTIVITY_TYPES['exit']:
            enter = PlayerActivity(server=server, player=player,
                                   activity_type=PLAYER_ACTIVITY_TYPES['enter'])
            enter.save(commit=False)

        if server.id == app.config['MAIN_SERVER_ID']:
            if player.banned:
                player.banned = False
                AuditLog.create(
                    AuditLog.PLAYER_UNBAN,
                    player_id=player.id,
                    username=player.username,
                    source='server_sync',
                    commit=False
                )

            nickname_ansi = player_info.get('nickname_ansi')
            nickname = player_info.get('nickname')

            player.nickname_ansi = nickname_ansi
            player.nickname = nickname
            player.save(commit=False)

        ip = player_info.get('address')
        if ip:
            if not IPTracking.query.filter_by(ip=ip, player=player).first():
                existing_player_ip = IPTracking(ip=ip, player=player)
                existing_player_ip.save(commit=False)

            if geoip.is_nok(ip):
                players_to_nok_ban.append((player, ip))

        stats = PlayerStats.query.filter_by(server=server, player=player).first()
        if not stats:
            stats = PlayerStats(server=server, player=player)

        stats.last_seen = datetime.utcnow()
        stats.pvp_logs = player_info.get('pvp_logs')
        stats.time_spent = (stats.time_spent or 0) + 1
        stats.save(commit=False)

        titles = [{'name': x.name, 'broadcast': x.broadcast} for x in player.titles]

        player_stats.append({
            'username': player.username,
            'uuid': player.uuid,
            'minutes': stats.time_spent,
            'rank': stats.rank,
            'titles': titles
        })

    if len(players) and (float(len(players_to_nok_ban)) / float(len(players))) < 0.5:
        for player, ip in players_to_nok_ban:
            libplayer.ban_player(player, with_ip=True, source='query', ip=ip, commit=False)

    five_minutes_ago = datetime.utcnow() - timedelta(minutes=10)
    result = PlayerStats.query.filter(PlayerStats.server == server,
                                      PlayerStats.last_seen > five_minutes_ago)
    recent_player_ids = [x.player_id for x in result]
    
    # find all players that have recently left and insert an 'exit' activity for them
    # if their last activity was an 'enter'
    for player_id in set(recent_player_ids) - set(online_player_ids):
        latest_activity = PlayerActivity.query.filter_by(server=server, player_id=player_id)\
        .order_by(PlayerActivity.timestamp.desc()).first()
        
        if latest_activity and latest_activity.activity_type == PLAYER_ACTIVITY_TYPES['enter']:
            ex = PlayerActivity(server=server, player_id=player_id,
                                activity_type=PLAYER_ACTIVITY_TYPES['exit'])
            ex.save(commit=False)
    
    player_count = server_status.get('numplayers', 0) or 0
    cpu_load = server_status.get('load', 0) or 0
    tps = server_status.get('tps', 0) or 0
    
    status = ServerStatus(server=server, player_count=player_count, cpu_load=cpu_load, tps=tps)
    status.save(commit=True)

    api.send_stats(server, {
        'player_stats': player_stats,
        'session': mojang_status.session,
        'account': mojang_status.account,
        'auth': mojang_status.auth
    })

    _handle_groups(server, server_status.get('groups', []))