/
app.py
148 lines (114 loc) · 4.53 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
""" This file sets up the Flask Application for sniper.
Sniper is an application that hits the Rutgers SOC API and notifies users when a class opens up. """
from flask import Flask, render_template, request
from wtforms import Form, TextField, validators
from wtforms.validators import StopValidation
from models import Snipe, db, User
from flaskext.mail import Mail
from secrets import mail_username, mail_password
from soc import Soc
from werkzeug.contrib.fixers import ProxyFix
import re
import json
import logging
from logging import Formatter, FileHandler
# Set up the Flask application
app = Flask(__name__)
# Set up a file for logging
file_handler = FileHandler('everything.log')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
app.logger.addHandler(file_handler)
app.wsgi_app = ProxyFix(app.wsgi_app)
app.config['MAIL_SERVER'] = 'smtp.sendgrid.net'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = mail_username
app.config['MAIL_PASSWORD'] = mail_password
mail = Mail(app)
class SnipeForm(Form):
""" Represents the Snipe form on the homepage. """
email = TextField('Email', [validators.Email(), validators.Required()])
subject = TextField('Subject')
course_number = TextField('Course Number', [validators.Length(min=2, max=4), validators.NumberRange()])
section = TextField('Section', [validators.Length(min=1, max=4)])
def validate_subject(form, field):
if not form.subject.data.isdigit():
m = re.search('(\d+)', form.subject.data)
if m:
form.subject.data = m.group(1)
else:
raise StopValidation('Please enter a valid subject')
return True
def validate_course_number(form, field):
# course numbers sometime have leading zeroes
if form.course_number.data.isdigit():
form.course_number.data = str(int(form.course_number.data))
return True
def validate_section(form, field):
if form.section.data.isdigit():
form.section.data = str(int(form.section.data))
return True
def save(self):
""" Saves to SQLAlchemy User and Snipe models """
snipe = Snipe.create(self.email.data, self.subject.data, self.course_number.data, self.section.data)
db.session.add(snipe)
db.session.commit()
@app.route('/', methods=['GET', 'POST'])
def home():
""" Handles the home page rendering."""
soc = Soc()
subjects = soc.get_subjects()
form = SnipeForm(request.form)
if request.method == 'POST' and form.validate():
form.save()
return render_template('success.html', form=form)
if not request.form:
# this trick allows us to prepopulate entries using links sent out in emails.
form = SnipeForm(request.args)
return render_template('home.html', form=form, subjects=subjects)
@app.route('/faq', methods=['GET'])
def faq():
return render_template('faq.html')
@app.route('/test', methods=['GET', 'POST'])
def ajaxtest():
result = {
'success': test(),
}
if not result['success']:
from cron import EMAIL_SENDER
from flaskext.mail import Message
message = Message('Sniper tests are failing', sender=EMAIL_SENDER)
message.body = 'FIX IT'
message.add_recipient('vaibhav2614@gmail.com')
mail.send(message)
return json.dumps(result)
def test():
from cron import poll
# Make sure tables exist. If not, create them
try:
db.session.query(User).first()
db.session.query(Snipe).first()
except Exception:
db.create_all()
soc = Soc()
math_courses = soc.get_courses(640)
open_courses = poll(640, result = True)
for dept, sections in open_courses.iteritems():
open_courses[dept] = [section.number for section in sections]
success = True
for math_course in math_courses:
course_number = math_course['courseNumber']
if course_number.isdigit():
course_number = str(int(course_number))
for section in math_course['sections']:
section_number = section['number']
if section_number.isdigit():
section_number = str(int(section_number))
if section['openStatus'] and not section_number in open_courses[course_number]:
raise Exception('Test failed')
success = False
return success
if __name__ == '__main__':
test()
app.run(host='0.0.0.0', debug=True)