Skip to content

Commit c97914f

Browse files
committed
make semester selector work
1 parent 4691415 commit c97914f

File tree

4 files changed

+87
-36
lines changed

4 files changed

+87
-36
lines changed

app/timetable/timetable_importer.py

+37-14
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
timetable_url='https://my.unsw.edu.au/active/studentTimetable/timetable.xml'
4646

4747
def getFlow(full_path):
48-
print full_path
4948
return OAuth2WebServerFlow(client_id='52070605511-3e5l10hi90c8t4t3foa0aptmhe5psgsr.apps.googleusercontent.com',
5049
client_secret='aKejP602Oz7Axrump73Oh1_R',
5150
scope='https://www.googleapis.com/auth/calendar',
@@ -54,15 +53,23 @@ def getFlow(full_path):
5453
def getGoogleRedirect(full_path):
5554
return getFlow(full_path).step1_get_authorize_url()
5655

57-
def getTimetable(zUser, zPass):
56+
def getTimetable(zUser, zPass, semester):
5857
jar = cookielib.CookieJar()
5958
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar))
6059
# CSRF Token or something. We need to steal it from SSO
6160
# into our cookie jar to go open the timetable page
6261
stupid_thing = re.findall(r'_cNoOpConversation.*?"', opener.open(login_url).read())[0].replace('"', '')
6362
data = {'username': zUser, 'password': zPass, '_eventId': 'submit', 'lt': stupid_thing}
6463
opener.open(login_url, urllib.urlencode(data))
65-
return opener.open(timetable_url).read()
64+
data = {}
65+
if semester:
66+
source = opener.open(timetable_url).read().replace('\n', '')
67+
if "sectionHeading" not in source:
68+
return ''
69+
s = BeautifulSoup(source)
70+
bsds = s.find('input', {'name': 'bsdsSequence'})['value']
71+
data = {'term': semester, 'bsdsSubmit-commit': 'Get Timetable', 'bsdsSequence': bsds}
72+
return opener.open(timetable_url, urllib.urlencode(data)).read()
6673

6774
def CreateClassEvent(title, content, where, start_time, end_time):
6875
event = {
@@ -80,22 +87,36 @@ def CreateClassEvent(title, content, where, start_time, end_time):
8087
}
8188
return event
8289

83-
def export(f, source, zu, zp, code, full_path):
84-
if f == 'use-login' and (not zu or not zp):
85-
return "No zPass details or timetable source"
90+
def getSemester(zu, zp):
91+
source = getTimetable(zu, zp, None)
92+
if "sectionHeading" not in source:
93+
return ("Bad timetable source, possibly incorrect login details or myunsw daily dose of downtime (12am-2am or whatever)", {})
94+
95+
# parsing shit
96+
s = BeautifulSoup(source.replace("\n",""))
97+
select_html = s.find("select", {'name': 'term'})
98+
select_html['style'] = 'width: 400px;'
99+
return (None,
100+
{
101+
'semester_select_html': select_html.prettify(),
102+
'source': source
103+
})
86104

87-
if f == 'use-login':
88-
print "getting timetable"
89-
f = getTimetable(zu, zp)
90-
print "got timetable!"
91-
else:
92-
f = source
105+
106+
def export(source, code, full_path):
107+
f = source.replace('\r', '')
93108

94109
if "sectionHeading" not in f:
95110
return "Bad timetable source, possibly incorrect login details or myunsw daily dose of downtime (12am-2am or whatever)"
96111

97112
# parsing shit
98113
s = BeautifulSoup(f.replace("\n",""))
114+
sem = re.sub(r'.*Semester (\d+) \S\S(\d+).*', u'\\2s\\1', s.find("option", {'selected':'true'}).text)
115+
title = sem + " Timetable"
116+
117+
if not re.match(r'\d\ds\d', sem):
118+
current_time = datetime.datetime.now()
119+
sem = '%ds%d' % (current_time.year % 100, 1 if current_time.month < 7 else 2)
99120

100121
credentials = getFlow(full_path).step2_exchange(code)
101122
http = httplib2.Http()
@@ -108,8 +129,6 @@ def export(f, source, zu, zp, code, full_path):
108129
####################################################
109130
zp = ''
110131

111-
sem = re.sub(u'.*Semester (\S+) \S\S(\S+).*', u'\\2s\\1', s.find("option", {'selected':'true'}).text)
112-
title = sem + " Timetable"
113132

114133

115134
# make gcal calendar
@@ -186,3 +205,7 @@ def export(f, source, zu, zp, code, full_path):
186205

187206
print "Probably success!"
188207

208+
209+
def exportByScraping(zu, zp, semester, code, full_path):
210+
source = getTimetable(zu, zp, None)
211+
return export(source, code, full_path)

app/timetable/views.py

+41-16
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,51 @@
44
import timetable_importer
55
import urlparse
66

7+
# TODO: it would be nice if somebody could figure out if we could make google
8+
# auth the last step in the flow.
79
def show(request):
810
this_url = urlparse.urlunsplit(urlparse.urlsplit(request.build_absolute_uri())[:3] + ('', ''))
911
if 'code' in request.REQUEST and 'fail' not in request.REQUEST:
1012
code = request.REQUEST['code']
13+
context = {'auth_code' : code}
1114
if request.method == 'POST':
12-
f = request.REQUEST['input-type']
13-
s = request.REQUEST['source']
14-
zu = request.REQUEST['zUser']
15-
zp = request.REQUEST['zPass']
16-
17-
result = timetable_importer.export(f, s, zu, zp, code, this_url)
18-
19-
if result != None:
20-
messages.error(request, result)
21-
return redirect(timetable_importer.getGoogleRedirect(this_url))
22-
else:
23-
messages.success(request, 'Success! Check <a href="http://calendar.google.com">Google Calendar</a>')
24-
return render_to_response('tools/timetable-importer.html', context_instance=RequestContext(request))
15+
f = request.REQUEST.get('input-type')
16+
s = request.REQUEST.get('source')
17+
zu = request.REQUEST.get('zUser')
18+
zp = request.REQUEST.get('zPass')
19+
semester = request.REQUEST.get('term')
20+
print semester
21+
result = None
22+
if f == 'use-source' and s:
23+
# source exists, parse it now.
24+
result = timetable_importer.export(s, code, this_url)
25+
if result == None:
26+
messages.success(request, 'Success! Check <a href="http://calendar.google.com">Google Calendar</a>')
27+
return render_to_response('tools/timetable-importer.html', context_instance=RequestContext(request))
28+
elif f == 'use-login' and zu and zp:
29+
# scrape myUNSW for available semesters
30+
(result, c) = timetable_importer.getSemester(zu, zp)
31+
if result == None:
32+
context = dict(c.items() + context.items())
33+
context['zu'] = zu
34+
context['zp'] = zp
35+
return render_to_response('tools/timetable-importer-select-term.html',
36+
context,
37+
context_instance=RequestContext(request))
38+
elif zu and zp and semester:
39+
# create calendar by scraping myUNSW
40+
result = timetable_importer.exportByScraping(zu, zp, semester, code, this_url)
41+
if result == None:
42+
messages.success(request, 'Success! Check <a href="http://calendar.google.com">Google Calendar</a>')
43+
return render_to_response('tools/timetable-importer.html', context_instance=RequestContext(request))
44+
messages.error(request, result)
45+
return render_to_response('tools/timetable-importer.html',
46+
context,
47+
context_instance=RequestContext(request))
2548
else:
26-
return render_to_response('tools/timetable-importer.html',
27-
{'auth_code' : code},
28-
context_instance=RequestContext(request))
49+
# get importer start page
50+
return render_to_response('tools/timetable-importer.html',
51+
context,
52+
context_instance=RequestContext(request))
53+
# get google auth page
2954
return redirect(timetable_importer.getGoogleRedirect(this_url))

app/views/tools/timetable-importer.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ <h4 id="source-help">Help</h4>
117117
</div>
118118
</div>
119119
<div>
120-
<p>Source at ~clam/public_html/timetable/timetable.py or <a href="http://www.nik3daz.com/timetable.py">here</a><br/>
120+
<p>Source at <a href="https://github.com/csesoc/csesoc-website/tree/master/app/timetable">github</a><br/>
121121
Original Timetable Parsing Code by Steven Fan (stevenf)<br/>
122122
Google Calendar integration and WebUI by Christopher Lam (clam)<br/>
123123
<b>Report bugs to <a href="mailto:dylank@cse.unsw.edu.au">dylank</a></b>

public/assets/js/timetable-importer.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@ function validate() {
4444
if (active == 'use-source') {
4545
$('#use-login :input').each(function(i, e) { e.value="" });
4646
}
47-
$('#importing-timetable-modal').modal({
48-
keyboard: false,
49-
backdrop: "static",
50-
});
51-
$('#importing-timetable-statusbar').animate({width:'100%'}, 60000, function() {});
5247
}
5348
return good;
5449
}
50+
51+
function activateModalStatusBar() {
52+
$('#importing-timetable-modal').modal({
53+
keyboard: false,
54+
backdrop: "static",
55+
});
56+
$('#importing-timetable-statusbar').animate({width:'100%'}, 60000, function() {});
57+
}

0 commit comments

Comments
 (0)