2015-08-01 23:27:08 +00:00
|
|
|
from functools import lru_cache
|
2015-07-28 18:04:11 +00:00
|
|
|
import json
|
|
|
|
import os
|
2015-08-01 23:16:09 +00:00
|
|
|
import random
|
2015-07-28 18:04:11 +00:00
|
|
|
import time
|
|
|
|
from sys import argv
|
|
|
|
from tempfile import mkdtemp, mkstemp
|
2015-10-15 23:58:22 +00:00
|
|
|
import logging
|
2015-08-03 02:02:39 +00:00
|
|
|
|
|
|
|
from pyhocon import ConfigFactory
|
|
|
|
import requests
|
2015-07-28 18:04:11 +00:00
|
|
|
from flask import Flask, render_template, request, redirect
|
2015-08-03 02:02:39 +00:00
|
|
|
|
2015-10-05 20:20:22 +00:00
|
|
|
from tildetown.stats import get_data
|
2015-07-28 18:04:11 +00:00
|
|
|
|
2015-08-03 02:02:39 +00:00
|
|
|
## disgusting hack for python 3.4.0
|
2015-08-01 23:23:54 +00:00
|
|
|
import pkgutil
|
|
|
|
orig_get_loader = pkgutil.get_loader
|
|
|
|
def get_loader(name):
|
|
|
|
try:
|
|
|
|
return orig_get_loader(name)
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
|
|
|
pkgutil.get_loader = get_loader
|
2015-08-03 02:02:39 +00:00
|
|
|
##########
|
2015-08-01 23:23:54 +00:00
|
|
|
|
2015-07-28 18:04:11 +00:00
|
|
|
SITE_NAME = 'tilde.town'
|
|
|
|
|
|
|
|
app = Flask('~cgi')
|
|
|
|
|
2015-08-01 23:27:08 +00:00
|
|
|
@lru_cache(maxsize=32)
|
2015-08-01 23:16:09 +00:00
|
|
|
def site_context():
|
2015-08-01 23:27:08 +00:00
|
|
|
return get_data()
|
2015-08-01 23:16:09 +00:00
|
|
|
|
2015-07-28 18:04:11 +00:00
|
|
|
def slurp(file_path):
|
|
|
|
contents = None
|
|
|
|
with open(file_path, 'r') as f:
|
|
|
|
contents = f.read()
|
|
|
|
return contents
|
|
|
|
|
|
|
|
def save_post(name, message):
|
|
|
|
timestamp = time.time()
|
|
|
|
data = {
|
|
|
|
'name': name,
|
|
|
|
'message': message,
|
|
|
|
'timestamp': timestamp,
|
|
|
|
}
|
|
|
|
_, file_path = mkstemp(dir=app.config['DATA_DIR'])
|
|
|
|
with open(file_path, 'w') as f:
|
|
|
|
f.write(json.dumps(data))
|
|
|
|
|
|
|
|
@app.route('/random', methods=['GET'])
|
|
|
|
def get_random():
|
2015-08-01 23:16:09 +00:00
|
|
|
user = random.choice(site_context()['live_users'])
|
|
|
|
return redirect('http://tilde.town/~{}'.format(user['username']))
|
2015-07-28 18:04:11 +00:00
|
|
|
|
|
|
|
@app.route('/guestbook', methods=['GET'])
|
|
|
|
def get_guestbook():
|
2015-10-15 23:58:22 +00:00
|
|
|
logging.debug('loading guestbook')
|
2015-07-28 18:04:11 +00:00
|
|
|
data_dir = app.config['DATA_DIR']
|
|
|
|
# TODO sort by timestamp
|
2015-08-02 00:16:36 +00:00
|
|
|
filename_to_json = lambda p: json.loads(slurp(os.path.join(data_dir, p)))
|
|
|
|
posts = map(filename_to_json, os.listdir(data_dir))
|
2015-08-02 00:19:56 +00:00
|
|
|
sorted_posts = sorted(posts, key=lambda p: p['timestamp'], reverse=True)
|
2015-07-28 18:04:11 +00:00
|
|
|
|
2015-10-15 23:58:22 +00:00
|
|
|
logging.debug('found {} posts'.format(len(sorted_posts)))
|
|
|
|
|
2015-08-01 23:16:09 +00:00
|
|
|
context = {
|
2015-08-02 00:16:36 +00:00
|
|
|
"posts": sorted_posts,
|
2015-07-28 18:04:11 +00:00
|
|
|
}
|
2015-08-01 23:16:09 +00:00
|
|
|
context.update(site_context())
|
2015-10-15 23:58:22 +00:00
|
|
|
logging.debug('rendering template...')
|
2015-07-28 18:04:11 +00:00
|
|
|
return render_template('guestbook.html', **context)
|
|
|
|
|
|
|
|
@app.route('/guestbook', methods=['POST'])
|
|
|
|
def post_guestbook():
|
2015-08-01 23:36:22 +00:00
|
|
|
message = request.form['message'][0:400]
|
|
|
|
name = request.form['name'][0:140]
|
|
|
|
captcha = request.form['hmm']
|
2015-08-01 23:59:46 +00:00
|
|
|
if captcha == "scrop":
|
2015-08-01 23:58:45 +00:00
|
|
|
save_post(name, message)
|
2015-07-28 18:04:11 +00:00
|
|
|
return redirect("/guestbook")
|
|
|
|
|
|
|
|
@app.route('/helpdesk', methods=['GET'])
|
2015-08-03 02:02:39 +00:00
|
|
|
def get_helpdesk():
|
|
|
|
status = request.args.get('status', 'unsubmitted')
|
|
|
|
desc = request.args.get('desc', '')
|
|
|
|
context = {
|
|
|
|
'status': status,
|
|
|
|
'desc': desc,
|
|
|
|
}
|
|
|
|
context.update(site_context())
|
|
|
|
return render_template('helpdesk.html', **context)
|
|
|
|
|
|
|
|
def send_email(data):
|
|
|
|
name = data.get('name', 'anonymous')
|
|
|
|
email = data['email']
|
|
|
|
request_type = data['type']
|
|
|
|
desc = request.form['desc']
|
|
|
|
response = requests.post(
|
2015-10-15 21:58:54 +00:00
|
|
|
app.config['MAILGUN_URL'],
|
|
|
|
auth=("api", app.config['MAILGUN_KEY']),
|
2015-08-03 02:02:39 +00:00
|
|
|
data={"from": "root@tilde.town",
|
2015-10-15 21:58:54 +00:00
|
|
|
"to": app.config['TRELLO_EMAIL'],
|
2015-08-03 02:02:39 +00:00
|
|
|
"subject": "{} from {} <{}>".format(request_type, name, email),
|
|
|
|
"text": desc})
|
|
|
|
|
|
|
|
return response.status_code == 200
|
|
|
|
|
|
|
|
@app.route('/helpdesk', methods=['POST'])
|
|
|
|
def post_helpdesk():
|
|
|
|
desc = request.form['desc']
|
|
|
|
captcha = request.form['hmm']
|
|
|
|
|
|
|
|
if captcha == 'scrop':
|
|
|
|
status = "success" if send_email(request.form) else "fail"
|
|
|
|
else:
|
|
|
|
status = "fail"
|
|
|
|
|
|
|
|
# should we bother restoring other fields beside desc?
|
|
|
|
return redirect('/helpdesk?status={}&desc={}'.format(status, desc))
|
2015-07-28 18:04:11 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
app.config['DEBUG'] = True
|
2015-10-15 21:58:54 +00:00
|
|
|
# tension between this and cfg function...
|
|
|
|
|
|
|
|
conf = ConfigFactory.parse_file('cfg.conf')
|
|
|
|
|
2015-10-15 23:58:22 +00:00
|
|
|
logfile = conf.get('logfile', '/tmp/cgi.log')
|
|
|
|
logging.basicConfig(filename=logfile, level=logging.DEBUG)
|
|
|
|
|
2015-10-15 21:58:54 +00:00
|
|
|
app.config['DATA_DIR'] = conf['guestbook_dir']
|
|
|
|
app.config['TRELLO_EMAIL'] = conf['trello_email']
|
|
|
|
app.config['MAILGUN_URL'] = conf['mailgun_url']
|
|
|
|
app.config['MAILGUN_KEY'] = conf['mailgun_key']
|
2015-07-28 18:04:11 +00:00
|
|
|
|
2015-10-15 23:58:22 +00:00
|
|
|
logging.debug("Running with data_dir=", app.config['DATA_DIR'])
|
|
|
|
logging.debug(app.config)
|
2015-08-02 00:01:29 +00:00
|
|
|
|
2015-07-28 18:04:11 +00:00
|
|
|
app.run()
|