def generate_playlist_cuesheet(djset, ext): cuesheet = """\ PERFORMER "{dj}" TITLE "{date}" """.format( dj=email.utils.quote(djset.dj.airname.encode("utf-8")), date=format_datetime(djset.dtstart, "%Y-%m-%d %H:%M") ) delta = timedelta(hours=1) start = djset.dtstart.replace(minute=0, second=0, microsecond=0) end = djset.dtend.replace(minute=59, second=59, microsecond=0) + timedelta(seconds=1) offset = 0 for loghour in perdelta(start, end, delta): tracks = ( TrackLog.query.filter( db.and_(TrackLog.djset_id == djset.id, TrackLog.played >= loghour, TrackLog.played <= loghour + delta) ) .order_by(TrackLog.played) .all() ) if len(tracks) > 0: filename = datetime.strftime(localize_datetime(loghour), "%Y%m%d%H0001{}".format(ext)) cuesheet += generate_cuesheet(filename, loghour, tracks, offset) offset += len(tracks) return cuesheet
def get_duplicates(model, attrs): dups = ( model.query.with_entities(*[getattr(model, attr) for attr in attrs]) .group_by(*[getattr(model, attr) for attr in attrs]) .having(db.and_(*[db.func.count(getattr(model, attr)) > 1 for attr in attrs])) .all() ) return dups
def library_track_similar(id, page=1): track = Track.query.get_or_404(id) edit_from = request.args.get('from', None) if request.method == 'POST': merge = [int(x) for x in request.form.getlist('merge[]')] if len(merge) > 0: # update TrackLogs TrackLog.query.filter(TrackLog.track_id.in_(merge)).update( {TrackLog.track_id: track.id}, synchronize_session=False) # update TrackReports TrackReport.query.filter(TrackReport.track_id.in_(merge)).update( { TrackReport.track_id: track.id, TrackReport.resolution: "Merged track", TrackReport.open: False }, synchronize_session=False) # delete existing Track entries Track.query.filter( Track.id.in_(merge)).delete(synchronize_session=False) db.session.commit() current_app.logger.warning( "Trackman: Merged tracks {0} into track {1}".format( ", ".join([str(x) for x in merge]), track.id)) flash("Tracks merged.") return redirect( url_for('admin.library_track', id=track.id, **{'from': edit_from})) similar_tracks = Track.query.\ filter(db.and_( db.func.lower(Track.artist) == db.func.lower(track.artist), db.func.lower(Track.album) == db.func.lower(track.album), db.func.lower(Track.title) == db.func.lower(track.title) )).\ group_by(Track.id).order_by(Track.artist).\ paginate(page, current_app.config['ARTISTS_PER_PAGE']) return render_template('admin/library_track_similar.html', track=track, edit_from=edit_from, similar_tracks=similar_tracks)
def playlist_cleanup(): app.logger.debug("Starting playlist cleanup...") empty = ( DJSet.query.outerjoin(TrackLog) .outerjoin(AirLog) .group_by(DJSet.id) .filter(DJSet.dtend != None) .having(db.and_(db.func.count(TrackLog.id) < 1, db.func.count(AirLog.id) < 1)) ) for djset in empty.all(): db.session.delete(djset) db.session.commit() app.logger.debug("Removed {} empty DJSets.".format(empty.count()))
def charts_artists(period=None): start, end = charts_period(period) results = Track.query.\ with_entities(Track.artist, db.func.count(TrackLog.id)).\ join(TrackLog).filter(db.and_( TrackLog.played >= start, TrackLog.played <= end)).\ group_by(Track.artist).\ order_by(db.func.count(TrackLog.id).desc()).limit(250) if request.wants_json(): return jsonify({'results': results}) return render_template('chart_artists.html', start=start, end=end, results=results)
def playlists_date_data(): try: start = datetime.datetime.strptime(request.args['start'], "%Y-%m-%dT%H:%M:%S.%fZ") end = datetime.datetime.strptime(request.args['end'], "%Y-%m-%dT%H:%M:%S.%fZ") except ValueError: abort(400) sets = DJSet.query.filter(db.and_(DJSet.dtstart >= start, DJSet.dtstart <= end)).\ order_by(db.desc(DJSet.dtstart)).limit(300).all() if request.wants_json(): return jsonify({'sets': [s.serialize() for s in sets]}) return Response("{start} {end}".format(start=start, end=end))
def charts_tracks(period=None): start, end = charts_period(period) results = Track.query.with_entities(Track, db.func.count(TrackLog.id)).\ join(TrackLog).filter(db.and_( TrackLog.played >= start, TrackLog.played <= end)).\ group_by(TrackLog.track_id).\ order_by(db.func.count(TrackLog.id).desc()).limit(250) if request.wants_json(): return jsonify({ 'results': [(x[0].serialize(), x[1]) for x in results], }) return render_template('chart_tracks.html', start=start, end=end, results=results)
def deduplicate_tracks(): dups = get_duplicates(Track, ["artist", "title", "album", "label"]) for artist, title, album, label in dups: track_query = Track.query.filter( db.and_(Track.artist == artist, Track.title == title, Track.album == album, Track.label == label) ).order_by(Track.id) count = track_query.count() tracks = track_query.all() track_id = int(tracks[0].id) # update TrackLogs TrackLog.query.filter(TrackLog.track_id.in_([track.id for track in tracks[1:]])).update( {TrackLog.track_id: track_id}, synchronize_session=False ) # delete existing Track entries map(db.session.delete, tracks[1:]) db.session.commit() app.logger.info("Removed {0:d} duplicates of track ID {1:d}".format(count - 1, track_id))
def playlist_cuesheet_ts(filename): match_re = re.compile(r'^(\d{10}0001)(.*)$') m = match_re.match(filename) if not m: abort(400) try: start = datetime.datetime.strptime(m.group(1), "%Y%m%d%H0001") except: abort(400) # assume time in URL is local time, so convert to UTC for DB lookup start = start.replace(tzinfo=dateutil.tz.tzlocal()).astimezone( dateutil.tz.tzutc()).replace(tzinfo=None) end = start + datetime.timedelta(hours=1) prev = db.session.query(TrackLog.id).filter(TrackLog.played <= start).\ order_by(db.desc(TrackLog.played)).limit(1) tracks = TrackLog.query.filter(db.and_( TrackLog.id >= prev.as_scalar(), TrackLog.played <= end)).order_by(TrackLog.played).all() return Response(generate_cuesheet(filename, start, tracks), mimetype="audio/x-cue")
def article_edit(art_id): article = Article.query.get_or_404(art_id) error_fields = [] if request.method == 'POST': # Title title = request.form.get('title', "").strip() if len(title) <= 0: error_fields.append('title') # Slug slug = request.form.get('slug', "").strip() if slug != "" or slug != article.slug: slug = slugify(slug) if len(slug) <= 0 or slug is None: error_fields.append('slug') elif len(slug) <= 0 and len(title) > 0: slug = slugify(title) # author_id author_id = request.form.get('author_id', "").strip() if User.query.filter_by(id=author_id).count() != 1: error_fields.append('author_id') # Category_id category_id = request.form.get('category_id', "").strip() if Category.query.filter_by(id=category_id).count() != 1: error_fields.append('category_id') # datetime (should update to published time) published = request.form.get('published', False) if published is not False: published = True #if article.published is False and published is not None: # article.datetime = datetime.datetime.utcnow() # front page front_page = request.form.get('front_page', False) if front_page is not False: front_page = True # summary summary = request.form.get('summary', "").strip() content = request.form.get('content', "").strip() # markdown if len(error_fields) <= 0: # ensure slug is unique, add - until it is (if we're changing the slug) if article.slug != slug: while Article.query.filter(db.and_( Article.slug == slug, Article.id != article.id)).count() > 0: slug += '-' article.title = title article.slug = slug article.category_id = category_id article.author_id = author_id article.published = published article.summary = summary article.content = content article.front_page = front_page db.session.commit() article.render_html() db.session.commit() flash("Article Saved") return redirect(url_for('admin.articles')) elif request.method == 'DELETE': db.session.delete(article) db.session.commit() return jsonify({ '_csrf_token': app.jinja_env.globals['csrf_token'](), }) categories = Category.query.all() authors = User.query.all() return render_template('admin/article_edit.html', article=article, categories=categories, authors=authors, error_fields=error_fields)
def article_edit(art_id): article = Article.query.get_or_404(art_id) form = ArticleForm() if request.method == 'POST' and form.validate(): slug = form.slug.data if len(slug) <= 0: slug = slugify(form.title.data) # ensure slug is unique, add - until it is (if we're changing the slug) if article.slug != slug: while Article.query.filter( db.and_(Article.slug == slug, Article.id != article.id)).count() > 0: slug += '-' article.title = form.title.data article.slug = slug article.category_id = form.category_id.data article.author_id = form.author_id.data article.published = form.published.data article.summary = form.summary.data article.content = form.content.data article.front_page = form.front_page.data article.render_html() try: db.session.commit() except: db.session.rollback() raise revision = ArticleRevision(article_id=article.id, author_id=current_user.id, title=form.title.data, summary=form.summary.data, content=form.content.data) revision.render_html() db.session.add(revision) try: db.session.commit() except: db.session.rollback() raise flash("Article Saved") return redirect(url_for('admin.articles')) elif request.method == 'DELETE': db.session.delete(article) try: db.session.commit() except: db.session.rollback() raise return jsonify({ '_csrf_token': app.jinja_env.globals['csrf_token'](), }) categories = Category.query.all() authors = User.query.all() return render_template('admin/article_edit.html', article=article, categories=categories, authors=authors, form=form)
def article_edit(art_id): article = Article.query.get_or_404(art_id) error_fields = [] if request.method == 'POST': # Title title = request.form.get('title', "").strip() if len(title) <= 0: error_fields.append('title') # Slug slug = request.form.get('slug', "").strip() if slug != "" or slug != article.slug: slug = slugify(slug) if len(slug) <= 0 or slug is None: error_fields.append('slug') elif len(slug) <= 0 and len(title) > 0: slug = slugify(title) # author_id author_id = request.form.get('author_id', "").strip() if User.query.filter_by(id=author_id).count() != 1: error_fields.append('author_id') # Category_id category_id = request.form.get('category_id', "").strip() if Category.query.filter_by(id=category_id).count() != 1: error_fields.append('category_id') # datetime (should update to published time) published = request.form.get('published', False) if published is not False: published = True if article.published is False and published is not None: article.datetime = datetime.datetime.now() # front page front_page = request.form.get('front_page', False) if front_page is not False: front_page = True # summary summary = request.form.get('summary', "").strip() print('summary: {0}', summary) content = request.form.get('content', "").strip() print('content: {0}', content) # markdown if len(error_fields) <= 0: # ensure slug is unique, add - until it is (if we're changing the slug) if article.slug != slug: while Article.query.filter(db.and_( Article.slug == slug, Article.id != article.id)).count() > 0: slug += '-' article.title = title article.slug = slug article.category_id = category_id article.author_id = author_id article.published = published article.summary = summary article.content = content article.front_page = front_page db.session.commit() article.render_html() db.session.commit() flash("Article Saved") return redirect(url_for('admin.articles')) elif request.method == 'DELETE': db.session.delete(article) db.session.commit() return jsonify({ '_csrf_token': app.jinja_env.globals['csrf_token'](), }) categories = Category.query.all() authors = User.query.all() return render_template('admin/article_edit.html', article=article, categories=categories, authors=authors, error_fields=error_fields)