diff options
| author | User Content <content@content.events.ccc.de> | 2019-10-30 01:11:47 +0000 |
|---|---|---|
| committer | User Content <content@content.events.ccc.de> | 2019-10-30 01:11:47 +0000 |
| commit | e8b020e28ca377868ff8aad8418372debc910ae6 (patch) | |
| tree | 53f318f05093e9cbde83e91f2c58035aedf2d7f0 /rater.py | |
Initial commit
Diffstat (limited to 'rater.py')
| -rwxr-xr-x | rater.py | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/rater.py b/rater.py new file mode 100755 index 0000000..e1ed9c5 --- /dev/null +++ b/rater.py | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | #!venv/bin/python | ||
| 2 | |||
| 3 | from flask import Flask, render_template, jsonify, request | ||
| 4 | from flask_sqlalchemy import SQLAlchemy | ||
| 5 | from lxml import etree | ||
| 6 | from argparse import ArgumentParser | ||
| 7 | import requests | ||
| 8 | import json | ||
| 9 | |||
| 10 | # Use this on FreeBSD when you've compiled pyopenssl with openssl from ports | ||
| 11 | # import urllib3.contrib.pyopenssl | ||
| 12 | # urllib3.contrib.pyopenssl.inject_into_urllib3() | ||
| 13 | |||
| 14 | parser = ArgumentParser(description="C3 rating helper") | ||
| 15 | parser.add_argument("-i", action="store_true", dest="frab_import", default=False, help="import events from frab") | ||
| 16 | parser.add_argument("-c", "--config", help="Config file location", default="./config.json") | ||
| 17 | args = parser.parse_args() | ||
| 18 | |||
| 19 | with open(args.config, mode="r", encoding="utf-8") as json_file: | ||
| 20 | config_data = json.load(json_file) | ||
| 21 | |||
| 22 | app = Flask(__name__) | ||
| 23 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+config_data.get('frab-conference')+'-'+config_data.get('track')+'.db' | ||
| 24 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | ||
| 25 | app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' | ||
| 26 | app.jinja_env.trim_blocks = True | ||
| 27 | app.jinja_env.lstrip_blocks = True | ||
| 28 | |||
| 29 | db = SQLAlchemy(app) | ||
| 30 | |||
| 31 | class Event(db.Model): | ||
| 32 | """An event as dumped from frab""" | ||
| 33 | frab_id = db.Column(db.Integer, primary_key=True) | ||
| 34 | title = db.Column(db.String(1024)) | ||
| 35 | subtitle = db.Column(db.String(1024)) | ||
| 36 | abstract = db.Column(db.Text()) | ||
| 37 | description = db.Column(db.Text()) | ||
| 38 | state = db.Column(db.String(64)) | ||
| 39 | event_type = db.Column(db.String(64)) | ||
| 40 | speakers = db.Column(db.String(1024)) | ||
| 41 | coordinator = db.Column(db.String(1024)) | ||
| 42 | notes = db.Column(db.Text()) | ||
| 43 | |||
| 44 | class EventRating(db.Model): | ||
| 45 | """A rating as given by a logged in user""" | ||
| 46 | id = db.Column(db.Integer, primary_key=True) | ||
| 47 | submitter = db.Column(db.String(1024)) | ||
| 48 | event_id = db.Column(db.Integer, db.ForeignKey('event.frab_id')) | ||
| 49 | event = db.relationship('Event', backref=db.backref('ratings', lazy='dynamic')) | ||
| 50 | comment = db.Column(db.Text()) | ||
| 51 | rating_dict = db.Column(db.String(1024), server_default="{}") | ||
| 52 | |||
| 53 | @app.route("/") | ||
| 54 | def root(): | ||
| 55 | events = Event.query.all() | ||
| 56 | return render_template('index.html', events=events, json=json, config=config_data, cat=config_data.get('categories')) | ||
| 57 | |||
| 58 | @app.route('/api/ratings') | ||
| 59 | def get_ratings(): | ||
| 60 | return jsonify(EventRating.query.all()) | ||
| 61 | |||
| 62 | @app.route('/api/set_event_state/<eventid>', methods=['POST']) | ||
| 63 | def set_sevent_state(eventid): | ||
| 64 | content = request.json | ||
| 65 | dbevent = Event.query.get(eventid) | ||
| 66 | dbevent.state = content.get('state', 'new') | ||
| 67 | db.session.commit() | ||
| 68 | return jsonify({"result":"ok"}) | ||
| 69 | |||
| 70 | @app.route('/api/set_event_coordinator/<eventid>', methods=['POST']) | ||
| 71 | def set_sevent_coordinator(eventid): | ||
| 72 | content = request.json | ||
| 73 | dbevent = Event.query.get(eventid) | ||
| 74 | dbevent.coordinator = content['coordinator'] | ||
| 75 | db.session.commit() | ||
| 76 | return jsonify({"result":"ok"}) | ||
| 77 | |||
| 78 | @app.route('/api/remove_event/<eventid>', methods=['POST']) | ||
| 79 | def remove_event(eventid): | ||
| 80 | dbevent = Event.query.get(eventid) | ||
| 81 | if dbevent.state == 'gone': | ||
| 82 | db.session.delete(dbevent) | ||
| 83 | db.session.commit() | ||
| 84 | return jsonify({"result":"ok"}) | ||
| 85 | |||
| 86 | @app.route('/api/remove_rating/<eventid>', methods=['POST']) | ||
| 87 | def remove_rating(eventid): | ||
| 88 | content = request.json | ||
| 89 | rating = EventRating.query.filter_by(event_id = eventid, submitter = content['author']).first() | ||
| 90 | if rating: | ||
| 91 | db.session.delete(rating) | ||
| 92 | db.session.commit() | ||
| 93 | return jsonify({"result":"ok"}) | ||
| 94 | |||
| 95 | @app.route('/api/add_rating/<eventid>', methods=['POST']) | ||
| 96 | def add_rating(eventid): | ||
| 97 | content = request.json | ||
| 98 | print ( str(eventid) + " " + str(content)) | ||
| 99 | r = content.get('ratings', '{}'); | ||
| 100 | |||
| 101 | rating = EventRating.query.filter_by(event_id = eventid, submitter = content['author']).first() | ||
| 102 | |||
| 103 | rd = json.dumps({ k: r.get(k,'0') for k in ['category1', 'category2', 'category3', 'category4'] }) | ||
| 104 | if rating: | ||
| 105 | if 'comment' in content: | ||
| 106 | rating.comment = content['comment'] | ||
| 107 | rating.rating_dict = rd | ||
| 108 | else: | ||
| 109 | db.session.add( EventRating( submitter = content.get('author','anonymous'), event_id = eventid, comment = content['comment'], rating_dict = rd)) | ||
| 110 | |||
| 111 | db.session.commit() | ||
| 112 | return jsonify({"result":"ok"}) | ||
| 113 | |||
| 114 | def fetch_talks(config): | ||
| 115 | sess = requests.Session() | ||
| 116 | new_session_page = sess.get(config.get('frab-url')) | ||
| 117 | tree = etree.HTML(new_session_page.text) | ||
| 118 | auth_token = tree.xpath("//meta[@name='csrf-token']")[0].get("content") | ||
| 119 | login_data = dict() | ||
| 120 | login_data['user[email]'] = config.get('frab-user') | ||
| 121 | login_data['user[password]'] = config.get('frab-password') | ||
| 122 | login_data['user[remember_me]'] = 1 | ||
| 123 | login_data['authenticity_token'] = auth_token | ||
| 124 | |||
| 125 | frab = config.get('frab-url') | ||
| 126 | conf = config.get('frab-conference') | ||
| 127 | track = config.get('track-name') | ||
| 128 | |||
| 129 | sess.post(frab + 'users/sign_in?conference_acronym=' + conf + '&locale=en', login_data, verify=False) | ||
| 130 | response = sess.get(frab + 'en/'+conf+'/events?track_name=' + track + '&format=json', verify=False, stream=True) | ||
| 131 | |||
| 132 | talks_json = json.loads(response.text) | ||
| 133 | |||
| 134 | # with open('dump.txt', mode='wb') as localfile: | ||
| 135 | # localfile.write(response.content) | ||
| 136 | |||
| 137 | imported = 0 | ||
| 138 | for json_event in talks_json['events']: | ||
| 139 | # print (json_event) | ||
| 140 | rawhtml = sess.get(frab + 'en/' + conf + '/events/'+ str(json_event['id']), verify=False, stream=True) | ||
| 141 | tree = etree.HTML(rawhtml.text) | ||
| 142 | submission_notes = tree.xpath('//b[text()="Submission Notes(user and admin):"]')[0].tail.strip() | ||
| 143 | |||
| 144 | dbevent = Event.query.get(json_event['id']) | ||
| 145 | speakers = { speaker['id']: speaker['full_public_name'] for speaker in json_event['speakers'] } | ||
| 146 | if dbevent: | ||
| 147 | dbevent.title = json_event['title'] | ||
| 148 | dbevent.subtitle = json_event['subtitle'] | ||
| 149 | dbevent.abstract = json_event['abstract'] | ||
| 150 | dbevent.description = json_event['description'] | ||
| 151 | dbevent.event_type = json_event['type'] | ||
| 152 | dbevent.notes = submission_notes | ||
| 153 | if 'state' in json_event: | ||
| 154 | if json_event['state'] != 'new' or dbevent.state == 'gone': | ||
| 155 | dbevent.state = json_event['state'] | ||
| 156 | dbevent.speakers = json.dumps(speakers) | ||
| 157 | else: | ||
| 158 | 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) ) | ||
| 159 | imported += 1 | ||
| 160 | for goner in Event.query.filter( Event.frab_id.notin_([ ev['id'] for ev in talks_json['events'] ])).all(): | ||
| 161 | goner.state = 'gone' | ||
| 162 | db.session.commit() | ||
| 163 | print ('Conference: ' + conf + ', track: ' + track + ', imported ' + str(len(talks_json['events'])) + ' events, ' + str(imported) + ' new.') | ||
| 164 | |||
| 165 | |||
| 166 | if __name__ == "__main__": | ||
| 167 | db.create_all() | ||
| 168 | if args.frab_import: | ||
| 169 | fetch_talks(config_data) | ||
| 170 | else: | ||
| 171 | app.run(host=config_data.get('host'), port=int(config_data.get('port'))) | ||
| 172 | |||
