#!venv/bin/python from flask import Flask, render_template, jsonify, request from flask_sqlalchemy import SQLAlchemy from lxml import etree from argparse import ArgumentParser import requests import json # Use this on FreeBSD when you've compiled pyopenssl with openssl from ports # import urllib3.contrib.pyopenssl # urllib3.contrib.pyopenssl.inject_into_urllib3() parser = ArgumentParser(description="C3 rating helper") parser.add_argument("-i", action="store_true", dest="frab_import", default=False, help="import events from frab") parser.add_argument("-c", "--config", help="Config file location", default="./config.json") args = parser.parse_args() with open(args.config, mode="r", encoding="utf-8") as json_file: config_data = json.load(json_file) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+config_data.get('frab-conference')+'-'+config_data.get('track')+'.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True db = SQLAlchemy(app) class Event(db.Model): """An event as dumped from frab""" frab_id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(1024)) subtitle = db.Column(db.String(1024)) abstract = db.Column(db.Text()) description = db.Column(db.Text()) state = db.Column(db.String(64)) event_type = db.Column(db.String(64)) speakers = db.Column(db.String(1024)) coordinator = db.Column(db.String(1024)) notes = db.Column(db.Text()) class EventRating(db.Model): """A rating as given by a logged in user""" id = db.Column(db.Integer, primary_key=True) submitter = db.Column(db.String(1024)) event_id = db.Column(db.Integer, db.ForeignKey('event.frab_id')) event = db.relationship('Event', backref=db.backref('ratings', lazy='dynamic')) comment = db.Column(db.Text()) rating_dict = db.Column(db.String(1024), server_default="{}") @app.route("/") def root(): events = Event.query.all() return render_template('index.html', events=events, json=json, config=config_data, cat=config_data.get('categories')) @app.route('/api/ratings') def get_ratings(): return jsonify(EventRating.query.all()) @app.route('/api/set_event_state/', methods=['POST']) def set_sevent_state(eventid): content = request.json dbevent = Event.query.get(eventid) dbevent.state = content.get('state', 'new') db.session.commit() return jsonify({"result":"ok"}) @app.route('/api/set_event_coordinator/', methods=['POST']) def set_sevent_coordinator(eventid): content = request.json dbevent = Event.query.get(eventid) dbevent.coordinator = content['coordinator'] db.session.commit() return jsonify({"result":"ok"}) @app.route('/api/remove_event/', methods=['POST']) def remove_event(eventid): dbevent = Event.query.get(eventid) if dbevent.state == 'gone': db.session.delete(dbevent) db.session.commit() return jsonify({"result":"ok"}) @app.route('/api/remove_rating/', methods=['POST']) def remove_rating(eventid): content = request.json rating = EventRating.query.filter_by(event_id = eventid, submitter = content['author']).first() if rating: db.session.delete(rating) db.session.commit() return jsonify({"result":"ok"}) @app.route('/api/add_rating/', methods=['POST']) def add_rating(eventid): content = request.json print ( str(eventid) + " " + str(content)) r = content.get('ratings', '{}'); rating = EventRating.query.filter_by(event_id = eventid, submitter = content['author']).first() rd = json.dumps({ k: r.get(k,'0') for k in ['category1', 'category2', 'category3', 'category4'] }) if rating: if 'comment' in content: rating.comment = content['comment'] rating.rating_dict = rd else: db.session.add( EventRating( submitter = content.get('author','anonymous'), event_id = eventid, comment = content['comment'], rating_dict = rd)) db.session.commit() return jsonify({"result":"ok"}) def fetch_talks(config): sess = requests.Session() new_session_page = sess.get(config.get('frab-url')) tree = etree.HTML(new_session_page.text) auth_token = tree.xpath("//meta[@name='csrf-token']")[0].get("content") login_data = dict() login_data['user[email]'] = config.get('frab-user') login_data['user[password]'] = config.get('frab-password') login_data['user[remember_me]'] = 1 login_data['authenticity_token'] = auth_token frab = config.get('frab-url') conf = config.get('frab-conference') track = config.get('track-name') sess.post(frab + 'users/sign_in?conference_acronym=' + conf + '&locale=en', login_data, verify=False) response = sess.get(frab + 'en/'+conf+'/events?track_name=' + track + '&format=json', verify=False, stream=True) talks_json = json.loads(response.text) # with open('dump.txt', mode='wb') as localfile: # localfile.write(response.content) imported = 0 for json_event in talks_json['events']: # print (json_event) rawhtml = sess.get(frab + 'en/' + conf + '/events/'+ str(json_event['id']), verify=False, stream=True) tree = etree.HTML(rawhtml.text) submission_notes = tree.xpath('//b[text()="Submission Notes(user and admin):"]')[0].tail.strip() dbevent = Event.query.get(json_event['id']) speakers = { speaker['id']: speaker['full_public_name'] for speaker in json_event['speakers'] } if dbevent: dbevent.title = json_event['title'] dbevent.subtitle = json_event['subtitle'] dbevent.abstract = json_event['abstract'] dbevent.description = json_event['description'] dbevent.event_type = json_event['type'] dbevent.notes = submission_notes if 'state' in json_event: if json_event['state'] != 'new' or dbevent.state == 'gone': dbevent.state = json_event['state'] dbevent.speakers = json.dumps(speakers) else: db.session.add( Event( frab_id = json_event['id'], title = json_event['title'], subtitle = json_event['subtitle'], abstract = json_event['abstract'], description = json_event['description'], speakers = json.dumps(speakers), state = json_event.get('state', 'new'), event_type = json_event['type'], notes = submission_notes) ) imported += 1 for goner in Event.query.filter( Event.frab_id.notin_([ ev['id'] for ev in talks_json['events'] ])).all(): goner.state = 'gone' db.session.commit() print ('Conference: ' + conf + ', track: ' + track + ', imported ' + str(len(talks_json['events'])) + ' events, ' + str(imported) + ' new.') if __name__ == "__main__": db.create_all() if args.frab_import: fetch_talks(config_data) else: app.run(host=config_data.get('host'), port=int(config_data.get('port')))