<commit_before>from flask import abort, flash, jsonify, render_template, \
        render_template_string, redirect, request, url_for, Response, session
from sqlalchemy import func, desc
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

import email.utils
import datetime
import json
import smtplib
import netaddr
import dateutil.parser

from wuvt import app
from wuvt import db
from wuvt import csrf
from wuvt import format_datetime
from wuvt import redis_conn
from wuvt.trackman import bp
from wuvt.trackman.lib import log_track, email_playlist, disable_automation, \
        enable_automation, logout_recent
from wuvt.trackman.models import DJ, DJSet, Track, TrackLog, AirLog, Rotation
from wuvt.trackman.view_utils import local_only, dj_interact


#############################################################################
### Login
#############################################################################

@bp.route('/', methods=['GET', 'POST'])
@local_only
@dj_interact
def login():
#    if not request.remote_addr in netaddr.IPSet(app.config['INTERNAL_IPS']):
#        abort(403)
    logout_recent()

    if 'dj' in request.form:
        disable_automation()

        dj = DJ.query.get(request.form['dj'])
        djset = DJSet(dj.id)
        db.session.add(djset)
        db.session.commit()

        redis_conn.delete('dj_timeout')

        return redirect(url_for('trackman.log', setid=djset.id))

    automation = redis_conn.get('automation_enabled') == "true"

    djs = DJ.query.filter(DJ.visible == True).order_by(DJ.airname).all()
    return render_template('trackman/login.html',
            trackman_name=app.config['TRACKMAN_NAME'],
            automation=automation, djs=djs)

#############################################################################
### Automation Control
#############################################################################

@bp.route('/automation/start', methods=['POST'])
@local_only
def start_automation():
    logout_recent()
    enable_automation()

    return redirect(url_for('trackman.login'))

@bp.route('/api/automation/log', methods=['POST'])
@local_only
@csrf.exempt
def automation_log():
    if 'password' not in request.form or \
        request.form['password'] != app.config['AUTOMATION_PASSWORD']:
        return jsonify(success=False, error="Invalid password")

    automation = redis_conn.get('automation_enabled') == "true"
    if not automation:
        return jsonify(success=False, error="Automation not enabled")

    if 'title' in request.form and len(request.form['title']) > 0:
        title = request.form['title'].strip()
    else:
        title = "Not Available"

    if 'artist' in request.form and len(request.form['artist']) > 0:
        artist = request.form['artist'].strip()
    else:
        artist = "Not Available"

    if 'album' in request.form and len(request.form['album']) > 0:
        album = request.form['album'].strip()
    else:
        album = "Not Available"

    if artist.lower() in ("wuvt", "pro", "soo", "psa", "lnr",
            "ua"):
        # ignore PSAs and other traffic for now!
        return jsonify(success=False, error='AirLog logging not yet implemented')

    if 'label' in request.form and len(request.form['label']) > 0:
        label = request.form['label'].strip()
        tracks = Track.query.filter(Track.title == title).filter(Track.artist == artist).filter(Track.album == album).filter(Track.label == label)
        if len(tracks.all()) == 0:
            track = Track(title, artist, album, label)
            db.session.add(track)
            db.session.commit()
        else:
            track = tracks.one()

    else:
        # Handle automation not providing a label
        label = "Not Available"
        tracks = Track.query.filter(Track.title == title).filter(Track.artist == artist).filter(Track.album == album)
        if len(tracks.all()) == 0:
            track = Track(title, artist, album, label)
            db.session.add(track)
            db.session.commit()
        else:
            notauto = tracks.filter(Track.label != "Not Available")
            if len(notauto.all()) == 0:
                # The only option is "not available label"
                track = tracks.one()
            else:
                track = notauto.one()

    dj = DJ.query.filter_by(name="Automation").first()

    djset_id = redis_conn.get('automation_set')
    if djset_id != None:
        djset_id = int(djset_id)
    log_track(track.id, djset_id)

    return jsonify(success=True)

#############################################################################
### DJ Control
#############################################################################

# Deprecated
@bp.route('/log/<int:setid>', methods=['GET'])
@local_only
def log(setid):
<commit_msg>Make automation logging more resilient of bad tracks.<commit_after>from flask import abort, flash, jsonify, render_template, \
        render_template_string, redirect, request, url_for, Response, session
from sqlalchemy import func, desc
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

import email.utils
import datetime
import json
import smtplib
import netaddr
import dateutil.parser

from wuvt import app
from wuvt import db
from wuvt import csrf
from wuvt import format_datetime
from wuvt import redis_conn
from wuvt.trackman import bp
from wuvt.trackman.lib import log_track, email_playlist, disable_automation, \
        enable_automation, logout_recent
from wuvt.trackman.models import DJ, DJSet, Track, TrackLog, AirLog, Rotation
from wuvt.trackman.view_utils import local_only, dj_interact


#############################################################################
### Login
#############################################################################

@bp.route('/', methods=['GET', 'POST'])
@local_only
@dj_interact
def login():
#    if not request.remote_addr in netaddr.IPSet(app.config['INTERNAL_IPS']):
#        abort(403)
    logout_recent()

    if 'dj' in request.form:
        disable_automation()

        dj = DJ.query.get(request.form['dj'])
        djset = DJSet(dj.id)
        db.session.add(djset)
        db.session.commit()

        redis_conn.delete('dj_timeout')

        return redirect(url_for('trackman.log', setid=djset.id))

    automation = redis_conn.get('automation_enabled') == "true"

    djs = DJ.query.filter(DJ.visible == True).order_by(DJ.airname).all()
    return render_template('trackman/login.html',
            trackman_name=app.config['TRACKMAN_NAME'],
            automation=automation, djs=djs)

#############################################################################
### Automation Control
#############################################################################

@bp.route('/automation/start', methods=['POST'])
@local_only
def start_automation():
    logout_recent()
    enable_automation()

    return redirect(url_for('trackman.login'))

@bp.route('/api/automation/log', methods=['POST'])
@local_only
@csrf.exempt
def automation_log():
    if 'password' not in request.form or \
        request.form['password'] != app.config['AUTOMATION_PASSWORD']:
        return jsonify(success=False, error="Invalid password")

    automation = redis_conn.get('automation_enabled') == "true"
    if not automation:
        return jsonify(success=False, error="Automation not enabled")

    if 'title' in request.form and len(request.form['title']) > 0:
        title = request.form['title'].strip()
    else:
        title = "Not Available"

    if 'artist' in request.form and len(request.form['artist']) > 0:
        artist = request.form['artist'].strip()
    else:
        artist = "Not Available"

    if 'album' in request.form and len(request.form['album']) > 0:
        album = request.form['album'].strip()
    else:
        album = "Not Available"

    if artist.lower() in ("wuvt", "pro", "soo", "psa", "lnr",
            "ua"):
        # ignore PSAs and other traffic for now!
        return jsonify(success=False, error='AirLog logging not yet implemented')

    if 'label' in request.form and len(request.form['label']) > 0:
        label = request.form['label'].strip()
        tracks = Track.query.filter(Track.title == title).filter(Track.artist == artist).filter(Track.album == album).filter(Track.label == label)
        if len(tracks.all()) == 0:
            track = Track(title, artist, album, label)
            db.session.add(track)
            db.session.commit()
        else:
            track = tracks.first()

    else:
        # Handle automation not providing a label
        label = "Not Available"
        tracks = Track.query.filter(Track.title == title).filter(Track.artist == artist).filter(Track.album == album)
        if len(tracks.all()) == 0:
            track = Track(title, artist, album, label)
            db.session.add(track)
            db.session.commit()
        else:
            notauto = tracks.filter(Track.label != "Not Available")
            if len(notauto.all()) == 0:
                # The only option is "not available label"
                track = tracks.first()
            else:
                track = notauto.first()

    dj = DJ.query.filter_by(name="Automation").first()

    djset_id = redis_conn.get('automation_set')
    if djset_id != None:
        djset_id = int(djset_id)
    log_track(track.id, djset_id)

    return jsonify(success=True)

#############################################################################
### DJ Control
#############################################################################

# Deprecated
@bp.route('/log/<int:setid>', methods=['GET'])
@local_only
def log(setid):

{'fraction_non_alphanumeric': 0.2131367292225201, 'fraction_numerical': 0.0020622808826562177, 'mean_word_length': 3.484049930651872, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3369837', 'n_tokens_mistral': 2891, 'n_tokens_neox': 2753, 'n_words': 649}