summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUser Erdgeist <erdgeist@content.events.ccc.de>2019-10-30 14:24:31 +0000
committerUser Erdgeist <erdgeist@content.events.ccc.de>2019-10-30 14:24:31 +0000
commitcd9e07341c2eebba1ed6980acdd07acc6ab9c9f4 (patch)
treeffcff44a758dfe510b4e7be3fbb3839a69193abc
parent8bcbcea5580818661eebcd17190780feb6e5bb86 (diff)
Add export to RT tool
-rwxr-xr-xexport.py162
1 files changed, 162 insertions, 0 deletions
diff --git a/export.py b/export.py
new file mode 100755
index 0000000..97ad669
--- /dev/null
+++ b/export.py
@@ -0,0 +1,162 @@
1#!venv/bin/python
2
3from flask import Flask, render_template, jsonify, request
4from flask_sqlalchemy import SQLAlchemy
5from lxml import etree
6from argparse import ArgumentParser
7import requests
8import json
9import sys
10
11dryrun=False
12
13parser = ArgumentParser(description="C3 rating helper")
14parser.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")
15args = parser.parse_args()
16
17if args.dryrun:
18 dryrun=True
19
20with open(args.config, mode="r", encoding="utf-8") as json_file:
21 cfg = json.load(json_file)
22
23app = Flask(__name__)
24app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + cfg['frab-conference'] + '-' + cfg['track'] + '.db'
25app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
26app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.'
27app.jinja_env.trim_blocks = True
28app.jinja_env.lstrip_blocks = True
29
30db = SQLAlchemy(app)
31
32config['rt-rest-url'] = cfg['rt-url'] + 'REST/1.0/'
33config['frab-conf-url'] = config['frab-url'] + config['frab-conference']
34
35class Event(db.Model):
36 """An event as dumped from frab"""
37 frab_id = db.Column(db.Integer, primary_key=True)
38 title = db.Column(db.String(1024))
39 subtitle = db.Column(db.String(1024))
40 abstract = db.Column(db.Text())
41 description = db.Column(db.Text())
42 state = db.Column(db.String(64))
43 event_type = db.Column(db.String(64))
44 speakers = db.Column(db.String(1024))
45 coordinator = db.Column(db.String(1024))
46 notes = db.Column(db.Text())
47
48class EventRating(db.Model):
49 """A rating as given by a logged in user"""
50 id = db.Column(db.Integer, primary_key=True)
51 submitter = db.Column(db.String(1024))
52 event_id = db.Column(db.Integer, db.ForeignKey('event.frab_id'))
53 event = db.relationship('Event', backref=db.backref('ratings', lazy='dynamic'))
54 comment = db.Column(db.Text())
55 rating_dict = db.Column(db.String(1024), server_default="{}")
56
57def add_coordinator(sess, person, event):
58 edit_person_page = sess.get(config['frab-conf-url'] + '/events/' + event + '/edit_people')
59 tree = etree.HTML(edit_person_page.text)
60 for option in tree.xpath('//option[@selected]'):
61 if option.text.lower() == 'coordinator':
62 print ('Not patching: ' + person + ' on event ' + event + ', coordinator found')
63 return
64 # print (option.text)
65 print ('Patching: ' + person + ' on event ' + event)
66
67 if dryrun:
68 return
69
70 add_person_data = dict()
71 add_person_data['utf8'] = '✓'
72 add_person_data['commit'] = 'Update event'
73 add_person_data['_method'] = 'PATCH'
74 add_person_data['filter'] = ''
75 add_person_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content")
76 add_person_data['event[event_people_attributes][1510531378][person_id]'] = person
77 add_person_data['event[event_people_attributes][1510531378][event_role]'] = 'coordinator'
78 add_person_data['event[event_people_attributes][1510531378][role_state]'] = ''
79 add_person_data['event[event_people_attributes][1510531378][_destroy]'] = 'false'
80 response = sess.post(config['frab-conf-url'] + '/events/' + event, add_person_data)
81 # print (response.text)
82
83def add_ticket(sess, rt_sess, event, person):
84 event_page = sess.get(config['frab-conf-url'] + '/events/' + event)
85 tree = etree.HTML(event_page.text)
86 click = ''
87 for button in tree.xpath('//a[@class="btn primary"]/@href'):
88 if '/tickets/' in button:
89 click = button
90 break
91 if not click:
92 print ('No add ticket link found, event already has a ticket?')
93 return
94 print ('Using add ticket link: ' + click)
95
96 if dryrun:
97 return
98
99 ticket_data = dict()
100 ticket_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content")
101 ticket_data['_method'] = 'POST'
102 response = sess.post(cfg['frab-url'] + click, ticket_data)
103 tree = etree.HTML(response.text)
104 ticket_id = ''
105 for link in tree.xpath('//a/@href'):
106 if '/Ticket/Display.html?' in link:
107 ticket_id = link.split('=')[1]
108 print ('Found new ticket, #'+ticket_id)
109 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']})
110 print (response.text)
111 if not ticket_id:
112 print ('Failed to add ticket to event ' + event)
113
114def set_state(sess, event, state):
115 event_page = sess.get(config['frab-conf-url'] + '/events/' + event)
116 tree = etree.HTML(event_page.text)
117 click = ''
118 for button in tree.xpath('//a[starts-with(@class,"btn")]/@href'):
119 if '?transition=' + state in button:
120 click = button
121 break
122 if not click:
123 print ('No ' + state + ' button found. State already set?')
124 return
125 print ('Using set state link: ' + click)
126 if dryrun:
127 return
128 set_state_data = dict()
129 set_state_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content")
130 set_state_data['_method'] = 'PUT'
131 response = sess.post(cgf['frab-url'] + click, set_state_data)
132
133def put_talks():
134 sess = requests.Session()
135 new_session_page = sess.get(cfg['frab-url'])
136 tree = etree.HTML(new_session_page.text)
137 login_data = dict()
138 login_data['user[email]'] = cfg['frab-user']
139 login_data['user[password]'] = cfg['frab-password']
140 login_data['user[remember_me]'] = 1
141 login_data['authenticity_token'] = tree.xpath("//meta[@name='csrf-token']")[0].get("content")
142 sess.post(cfg['frab-url'] + 'users/sign_in?conference_acronym=' + cfg['frab-conference'] + '&locale=en', login_data)
143
144 rt_sess = requests.Session()
145 rt_sess.post(cfg['rt-url']+'index.html', {"user": cfg['rt-user'], "pass": cfg['rt-password'] })
146
147 for event in Event.query.all():
148 if event.coordinator:
149 if event.coordinator in person_map:
150 print (str(event.frab_id) + ': ' + event.coordinator + '(' + cfg.get('frab-person-map')[event.coordinator]+')')
151 add_coordinator(sess, cfg.get('frab-person-map')[event.coordinator], str(event.frab_id))
152 add_ticket(sess, rt_sess, str(event.frab_id), cfg.get('rt-person-map')[event.coordinator])
153 else:
154 print ('Unknown coordinator '+event.coordinator+' for event '+str(event.frab_id))
155 if event.state in [ 'accepted', 'rejected' ]:
156 set_state(sess, str(event.frab_id), 'accept' if event.state == 'accepted' else 'reject')
157 else:
158 print ('Unknown state ' + event.state + ' for event ' + str(event.frab_id))
159
160if __name__ == "__main__":
161 db.create_all()
162 put_talks()