From 27db823c46c83b13b4cf36c865471633da74816e Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sat, 12 Oct 2024 21:29:51 +0200 Subject: Use pretalx instead of frab --- config-example.json | 14 ++++----- export.py | 15 +++++----- instance/.gitignore | 0 rater.py | 84 ++++++++++++++++++++++++---------------------------- requirements.txt | 28 +++++++++--------- static/rater.css | 23 +++++++++++++- templates/index.html | 21 +++++++------ 7 files changed, 99 insertions(+), 86 deletions(-) create mode 100644 instance/.gitignore diff --git a/config-example.json b/config-example.json index 5c4e4bc..6afccea 100644 --- a/config-example.json +++ b/config-example.json @@ -1,19 +1,19 @@ { "track": "polsoc", "track-name": "Ethics%2C+Society+%26+Politics", + "track-id": 7, "host": "127.0.0.1", "port": 5000, - "frab-url": "https://frab.cccv.de/", - "frab-user": "", - "frab-password": "", - "frab-conference": "36C3", + "pretalx-url": "https://cfp.cccv.de/", + "pretalx-token": "", + "pretalx-conference": "38c3", "rt-url": "https://rt.cccv.de/", "rt-user": "", "rt-password": "", "categories": [ "Relevanz", "Expertise", "Praesentation", "Nachfrage" ], - "frab-person-map": { - "anna": 12345, - "ben": 6789 + "pretalx-person-map": { + "anna": "", + "ben": "" }, "rt-person-map": { "anna": "anna@mail.org", diff --git a/export.py b/export.py index 97ad669..8ddff42 100755 --- a/export.py +++ b/export.py @@ -11,7 +11,7 @@ import sys dryrun=False parser = ArgumentParser(description="C3 rating helper") -parser.add_argument("-d", action="store_true", dest="dryrun", default=False, help="Don't actually execute anything on frab or rt, just show what would have been done") +parser.add_argument("-d", action="store_true", dest="dryrun", default=False, help="Don't actually execute anything on pretalx or rt, just show what would have been done") args = parser.parse_args() if args.dryrun: @@ -21,7 +21,7 @@ with open(args.config, mode="r", encoding="utf-8") as json_file: cfg = json.load(json_file) app = Flask(__name__) -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + cfg['frab-conference'] + '-' + cfg['track'] + '.db' +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + cfg['pretalx-conference'] + '-' + cfg['track'] + '.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' app.jinja_env.trim_blocks = True @@ -30,13 +30,12 @@ app.jinja_env.lstrip_blocks = True db = SQLAlchemy(app) config['rt-rest-url'] = cfg['rt-url'] + 'REST/1.0/' -config['frab-conf-url'] = config['frab-url'] + config['frab-conference'] +config['pretalx-conf-url'] = config['pretalx-url'] + config['pretalx-conference'] class Event(db.Model): - """An event as dumped from frab""" - frab_id = db.Column(db.Integer, primary_key=True) + """An event as dumped from pretalx""" + pretalx_id = db.Column(db.String(16), 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)) @@ -49,13 +48,13 @@ 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_id = db.Column(db.Integer, db.ForeignKey('event.pretalx_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="{}") def add_coordinator(sess, person, event): - edit_person_page = sess.get(config['frab-conf-url'] + '/events/' + event + '/edit_people') + edit_person_page = sess.get(config['pretalx-conf-url'] + '/events/' + event + '/edit_people') tree = etree.HTML(edit_person_page.text) for option in tree.xpath('//option[@selected]'): if option.text.lower() == 'coordinator': diff --git a/instance/.gitignore b/instance/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/rater.py b/rater.py index 247c1d2..6302d64 100755 --- a/rater.py +++ b/rater.py @@ -12,7 +12,7 @@ import json # 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("-i", action="store_true", dest="pretalx_import", default=False, help="import events from pretalx") parser.add_argument("-c", "--config", help="Config file location", default="./config.json") args = parser.parse_args() @@ -20,7 +20,7 @@ with open(args.config, mode="r", encoding="utf-8") as json_file: config = json.load(json_file) app = Flask(__name__) -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + config['frab-conference'] + '-' + config['track'] + '.db' +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + config['pretalx-conference'] + '-' + config['track'] + '.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' app.jinja_env.trim_blocks = True @@ -28,11 +28,12 @@ app.jinja_env.lstrip_blocks = True db = SQLAlchemy(app) -config['frab-conf-url'] = config['frab-url'] + config['frab-conference'] +config['pretalx-conf-url'] = config['pretalx-url'] + 'orga/event/' + config['pretalx-conference'] +config['pretalx-api-url'] = config['pretalx-url'] + 'api/events/' + config['pretalx-conference'] + '/submissions?track_id' + str(config['track-id']) class Event(db.Model): - """An event as dumped from frab""" - frab_id = db.Column(db.Integer, primary_key=True) + """An event as dumped from pretalx""" + pretalx_id = db.Column(db.String(64), primary_key=True) title = db.Column(db.String(1024)) subtitle = db.Column(db.String(1024)) abstract = db.Column(db.Text()) @@ -42,12 +43,13 @@ class Event(db.Model): speakers = db.Column(db.String(1024)) coordinator = db.Column(db.String(1024)) notes = db.Column(db.Text()) + duration = db.Column(db.Integer()) 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')) + pretalx_id = db.Column(db.String(64), db.ForeignKey('event.pretalx_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="{}") @@ -64,7 +66,7 @@ def get_ratings(): @app.route('/api/set_event_state/', methods=['POST']) def set_sevent_state(eventid): content = request.json - dbevent = Event.query.get(eventid) + dbevent = db.session.get(Event, eventid) dbevent.state = content.get('state', 'new') db.session.commit() return jsonify({"result":"ok"}) @@ -72,14 +74,14 @@ def set_sevent_state(eventid): @app.route('/api/set_event_coordinator/', methods=['POST']) def set_sevent_coordinator(eventid): content = request.json - dbevent = Event.query.get(eventid) + dbevent = db.session.get(Event, 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) + dbevent = db.session.get(Event, eventid) if dbevent.state == 'gone': db.session.delete(dbevent) db.session.commit() @@ -88,7 +90,7 @@ def remove_event(eventid): @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() + rating = EventRating.query.filter_by(pretalx_id = eventid, submitter = content['author']).first() if rating: db.session.delete(rating) db.session.commit() @@ -100,7 +102,7 @@ def add_rating(eventid): print ( str(eventid) + " " + str(content)) r = content.get('ratings', '{}'); - rating = EventRating.query.filter_by(event_id = eventid, submitter = content['author']).first() + rating = EventRating.query.filter_by(pretalx_id = eventid, submitter = content['author']).first() rd = json.dumps({ k: r.get(k,'0') for k in ['category1', 'category2', 'category3', 'category4'] }) if rating: @@ -108,65 +110,57 @@ def add_rating(eventid): 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.add( EventRating( submitter = content.get('author','anonymous'), pretalx_id = eventid, comment = content['comment'], rating_dict = rd)) db.session.commit() return jsonify({"result":"ok"}) def fetch_talks(): sess = requests.Session() - new_session_page = sess.get(config['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['frab-user'] - login_data['user[password]'] = config['frab-password'] - login_data['user[remember_me]'] = 1 - login_data['authenticity_token'] = auth_token - - sess.post(config['frab-url'] + 'users/sign_in?conference_acronym=' + config['frab-conference'] + '&locale=en', login_data, verify=False) - response = sess.get(config['frab-conf-url'] + '/events?track_name=' + config['track-name'] + '&format=json', verify=False, stream=True) + + response = sess.get(config['pretalx-api-url'] + '&format=json&limit=20000' , verify=False, stream=True, headers={'Authorization': "Token " + config['pretalx-token']}) talks_json = json.loads(response.text) -# with open('dump.txt', mode='wb') as localfile: -# localfile.write(response.content) + # with open('dump.txt', mode='wb') as localfile: + # localfile.write(response.content) + + submissions = [s for s in talks_json['results'] if s['track_id'] == config['track-id'] ] imported = 0 - for json_event in talks_json['events']: -# print (json_event) - rawhtml = sess.get(config['frab-conf-url'] + '/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'] } + for json_event in submissions: + print (json_event) + + dbevent = db.session.get(Event, json_event['code']) + speakers = { speaker['code']: speaker['name'] for speaker in json_event['speakers'] } + submission_type = json_event['submission_type'].get('de') or json_event['submission_type'].get('en') 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 + dbevent.event_type = submission_type + dbevent.notes = json_event.get('notes') + dbevent.duration = int(json_event['duration']) if 'state' in json_event: - if json_event['state'] != 'new' or dbevent.state == 'gone': + if json_event['state'] != 'submitted' 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) ) + db.session.add( Event( pretalx_id = json_event['code'], title = json_event['title'], abstract = json_event['abstract'], description = json_event['description'], speakers = json.dumps(speakers), state = json_event.get('state', 'submitted'), event_type = submission_type, notes = json_event.get('notes'), duration = int(json_event['duration'])) ) imported += 1 - for goner in Event.query.filter( Event.frab_id.notin_([ ev['id'] for ev in talks_json['events'] ])).all(): + for goner in Event.query.filter( Event.pretalx_id.notin_([ ev['code'] for ev in submissions ])).all(): goner.state = 'gone' db.session.commit() - print ('Conference: ' + config['track'] + ', track: ' + config['track'] + ', imported ' + str(len(talks_json['events'])) + ' events, ' + str(imported) + ' new.') + print ('Conference: ' + config['track'] + ', track: ' + config['track'] + ', imported ' + str(len(submissions)) + ' events, ' + str(imported) + ' new.') if __name__ == "__main__": - db.create_all() - if args.frab_import: - fetch_talks() - else: - app.run(host=config.get('host', '127.0.0.1'), port=int(config.get('port', '8080'))) + with app.app_context(): + db.create_all() + if args.pretalx_import: + fetch_talks() + else: + app.run(host=config.get('host', '127.0.0.1'), port=int(config.get('port', '8080'))) diff --git a/requirements.txt b/requirements.txt index fa92333..1f599f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,14 @@ -certifi==2017.7.27.1 -chardet==3.0.4 -click==6.7 -Flask==0.12.2 -Flask-SQLAlchemy==2.2 -idna==2.6 -itsdangerous==0.24 -Jinja2==2.9.6 -lxml==3.8.0 -MarkupSafe==1.0 -requests==2.18.4 -SQLAlchemy==1.1.14 -urllib3==1.22 -Werkzeug==0.12.2 +certifi +chardet +click +Flask +Flask-SQLAlchemy +idna +itsdangerous +Jinja2 +lxml +MarkupSafe +requests +SQLAlchemy +urllib3 +Werkzeug diff --git a/static/rater.css b/static/rater.css index ae54a13..b73f4a0 100644 --- a/static/rater.css +++ b/static/rater.css @@ -112,10 +112,31 @@ body.four-column .event-list-item { font-weight: bold; } +.event-duration, +.event-speaker-count, .event-subtitle { font-size: smaller; } +.event-speaker-count, +.event-duration { + display: inline; + font-weight: bold; + background-color: cyan; + border-radius: 2px; + margin: 0.2em; + padding: 0.2em; +} + +.event-duration:before { content: '🕒 '; } +.event-speaker-count:before { content: '👥 '; } + +.event-duration:before, +.event-speaker-count:before { + font-size: smaller; + padding-bottom: 0.2rem; +} + .event-rating-comment { min-height: 3em; margin-top: 0.1em; @@ -283,7 +304,7 @@ meter.meter-4::-webkit-meter-bar { clear: both; } -body.only-lectures .event-list-item:not([event_type="lecture"]), +body.only-lectures .event-list-item:not([event_type="Talk"]), body.only-todo .event-list-item.has-own-rating, .filtered, .hidden { diff --git a/templates/index.html b/templates/index.html index c8ccf71..1d42018 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,5 +1,5 @@ -{{ config.get('frab-conference') }} {{ config.get('track') }} rating helper +{{ config.get('pretalx-conference') }} {{ config.get('track') }} rating helper