From cd9e07341c2eebba1ed6980acdd07acc6ab9c9f4 Mon Sep 17 00:00:00 2001 From: User Erdgeist Date: Wed, 30 Oct 2019 14:24:31 +0000 Subject: Add export to RT tool --- export.py | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100755 export.py diff --git a/export.py b/export.py new file mode 100755 index 0000000..97ad669 --- /dev/null +++ b/export.py @@ -0,0 +1,162 @@ +#!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 +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") +args = parser.parse_args() + +if args.dryrun: + dryrun=True + +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_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) + +config['rt-rest-url'] = cfg['rt-url'] + 'REST/1.0/' +config['frab-conf-url'] = config['frab-url'] + config['frab-conference'] + +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="{}") + +def add_coordinator(sess, person, event): + edit_person_page = sess.get(config['frab-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': + print ('Not patching: ' + person + ' on event ' + event + ', coordinator found') + return + # print (option.text) + print ('Patching: ' + person + ' on event ' + event) + + if dryrun: + return + + add_person_data = dict() + add_person_data['utf8'] = '✓' + add_person_data['commit'] = 'Update event' + add_person_data['_method'] = 'PATCH' + add_person_data['filter'] = '' + add_person_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content") + add_person_data['event[event_people_attributes][1510531378][person_id]'] = person + add_person_data['event[event_people_attributes][1510531378][event_role]'] = 'coordinator' + add_person_data['event[event_people_attributes][1510531378][role_state]'] = '' + add_person_data['event[event_people_attributes][1510531378][_destroy]'] = 'false' + response = sess.post(config['frab-conf-url'] + '/events/' + event, add_person_data) + # print (response.text) + +def add_ticket(sess, rt_sess, event, person): + event_page = sess.get(config['frab-conf-url'] + '/events/' + event) + tree = etree.HTML(event_page.text) + click = '' + for button in tree.xpath('//a[@class="btn primary"]/@href'): + if '/tickets/' in button: + click = button + break + if not click: + print ('No add ticket link found, event already has a ticket?') + return + print ('Using add ticket link: ' + click) + + if dryrun: + return + + ticket_data = dict() + ticket_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content") + ticket_data['_method'] = 'POST' + response = sess.post(cfg['frab-url'] + click, ticket_data) + tree = etree.HTML(response.text) + ticket_id = '' + for link in tree.xpath('//a/@href'): + if '/Ticket/Display.html?' in link: + ticket_id = link.split('=')[1] + print ('Found new ticket, #'+ticket_id) + response = rt_sess.post(config['rt-rest-url'] + 'ticket/' + ticket_id + '/edit', { "content": "id: ticket/"+ticket_id + '\nOwner: ' + person + '\n' }, headers={ 'referer': config['rt-rest-url']}) + print (response.text) + if not ticket_id: + print ('Failed to add ticket to event ' + event) + +def set_state(sess, event, state): + event_page = sess.get(config['frab-conf-url'] + '/events/' + event) + tree = etree.HTML(event_page.text) + click = '' + for button in tree.xpath('//a[starts-with(@class,"btn")]/@href'): + if '?transition=' + state in button: + click = button + break + if not click: + print ('No ' + state + ' button found. State already set?') + return + print ('Using set state link: ' + click) + if dryrun: + return + set_state_data = dict() + set_state_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content") + set_state_data['_method'] = 'PUT' + response = sess.post(cgf['frab-url'] + click, set_state_data) + +def put_talks(): + sess = requests.Session() + new_session_page = sess.get(cfg['frab-url']) + tree = etree.HTML(new_session_page.text) + login_data = dict() + login_data['user[email]'] = cfg['frab-user'] + login_data['user[password]'] = cfg['frab-password'] + login_data['user[remember_me]'] = 1 + login_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content") + sess.post(cfg['frab-url'] + 'users/sign_in?conference_acronym=' + cfg['frab-conference'] + '&locale=en', login_data) + + rt_sess = requests.Session() + rt_sess.post(cfg['rt-url']+'index.html', {"user": cfg['rt-user'], "pass": cfg['rt-password'] }) + + for event in Event.query.all(): + if event.coordinator: + if event.coordinator in person_map: + print (str(event.frab_id) + ': ' + event.coordinator + '(' + cfg.get('frab-person-map')[event.coordinator]+')') + add_coordinator(sess, cfg.get('frab-person-map')[event.coordinator], str(event.frab_id)) + add_ticket(sess, rt_sess, str(event.frab_id), cfg.get('rt-person-map')[event.coordinator]) + else: + print ('Unknown coordinator '+event.coordinator+' for event '+str(event.frab_id)) + if event.state in [ 'accepted', 'rejected' ]: + set_state(sess, str(event.frab_id), 'accept' if event.state == 'accepted' else 'reject') + else: + print ('Unknown state ' + event.state + ' for event ' + str(event.frab_id)) + +if __name__ == "__main__": + db.create_all() + put_talks() -- cgit v1.2.3