2015-12-23 13:11:38 +00:00
|
|
|
#!/usr/bin/env python3
|
2015-12-24 23:32:58 +00:00
|
|
|
from flask import Flask, request, redirect, url_for, send_from_directory, abort, render_template
|
2015-12-23 13:11:38 +00:00
|
|
|
from werkzeug import secure_filename
|
2016-02-01 10:46:44 +00:00
|
|
|
from threading import Thread, Timer
|
2015-12-23 13:11:38 +00:00
|
|
|
import logging
|
|
|
|
import os
|
2015-12-28 17:56:26 +00:00
|
|
|
import random
|
2015-12-23 13:11:38 +00:00
|
|
|
import json
|
|
|
|
import time
|
|
|
|
from random import randint
|
|
|
|
|
|
|
|
# Import our configuration
|
|
|
|
from conf import config
|
|
|
|
|
2016-02-23 16:16:05 +00:00
|
|
|
# Import QuadFile stuff
|
2016-02-02 09:10:45 +00:00
|
|
|
from QuadFile import db
|
|
|
|
from QuadFile.output import print_log, time_to_string
|
2015-12-23 13:11:38 +00:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
|
|
|
2016-01-18 09:33:47 +00:00
|
|
|
# TODO: Try to turn these into functions or something I dunno
|
2015-12-23 13:41:25 +00:00
|
|
|
print_log('Main', 'Running in "' + os.getcwd() + '"')
|
2015-12-23 13:11:38 +00:00
|
|
|
print_log('Main', 'Checking for data folder')
|
|
|
|
if not os.path.exists(config['UPLOAD_FOLDER']):
|
|
|
|
print_log('Main', 'Data folder not found, creating')
|
|
|
|
os.makedirs(config['UPLOAD_FOLDER'])
|
|
|
|
log = logging.getLogger('werkzeug')
|
|
|
|
log.setLevel(logging.ERROR)
|
|
|
|
|
|
|
|
|
2015-12-23 22:27:12 +00:00
|
|
|
def cleaner_thread():
|
2016-02-02 20:06:25 +00:00
|
|
|
# Call itself again after the interval
|
|
|
|
cleaner = Timer(config["CLEAN_INTERVAL"], cleaner_thread)
|
|
|
|
cleaner.daemon = True # Daemons will attempt to exit cleanly along with the main process, which we want
|
|
|
|
cleaner.start()
|
|
|
|
|
|
|
|
# Actual function
|
2016-02-01 10:46:44 +00:00
|
|
|
delete_old()
|
2015-12-23 22:27:12 +00:00
|
|
|
|
|
|
|
|
2015-12-23 21:45:40 +00:00
|
|
|
def delete_old():
|
2016-03-11 15:44:45 +00:00
|
|
|
print_log('Notice', 'Cleaner running')
|
2015-12-23 21:45:40 +00:00
|
|
|
targetTime = time.time() - config["TIME"]
|
|
|
|
old = db.get_old_files(targetTime)
|
|
|
|
for file in old:
|
2015-12-23 22:27:12 +00:00
|
|
|
print_log('Notice', 'Removing old file "' + file["file"] + '"')
|
2015-12-23 21:45:40 +00:00
|
|
|
try:
|
|
|
|
os.remove(os.path.join(config["UPLOAD_FOLDER"], file["file"]))
|
|
|
|
except Exception:
|
2015-12-23 22:27:12 +00:00
|
|
|
print_log('Warning', 'Failed to delete old file "' + file["file"] + '"')
|
2015-12-23 21:45:40 +00:00
|
|
|
db.delete_entry(file["file"])
|
|
|
|
|
|
|
|
|
2015-12-23 13:11:38 +00:00
|
|
|
def auth(key):
|
|
|
|
if config["KEY"] == "":
|
|
|
|
return True
|
|
|
|
elif config["KEY"] == key:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2015-12-26 23:30:11 +00:00
|
|
|
def error_page(error, code):
|
|
|
|
return render_template('error.html', page=config["SITE_DATA"], error=error, code=code)
|
2015-12-24 20:46:28 +00:00
|
|
|
|
|
|
|
|
2015-12-23 13:11:38 +00:00
|
|
|
def allowed_file(filename):
|
2015-12-24 16:00:59 +00:00
|
|
|
if config["ALLOW_ALL_FILES"]:
|
|
|
|
return True
|
|
|
|
else:
|
2015-12-23 13:11:38 +00:00
|
|
|
return '.' in filename and filename.rsplit('.', 1)[1] in config["ALLOWED_EXTENSIONS"]
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/', methods=['GET', 'POST'])
|
|
|
|
def upload_file():
|
|
|
|
if request.method == 'POST':
|
2015-12-24 16:00:59 +00:00
|
|
|
print_log('Web', 'New file received')
|
2015-12-23 13:11:38 +00:00
|
|
|
if not auth(request.headers.get('X-Hyozan-Auth')):
|
|
|
|
abort(403)
|
|
|
|
data = dict()
|
|
|
|
file = request.files['file']
|
|
|
|
|
|
|
|
# Only continue if a file that's allowed gets submitted.
|
|
|
|
if file and allowed_file(file.filename):
|
|
|
|
filename = secure_filename(file.filename)
|
|
|
|
while os.path.exists(os.path.join(config["UPLOAD_FOLDER"], filename)):
|
|
|
|
filename = str(randint(1000,8999)) + '-' + secure_filename(filename)
|
|
|
|
|
|
|
|
thread1 = Thread(target = db.add_file, args = (filename,))
|
|
|
|
thread1.start()
|
|
|
|
print_log('Thread', 'Adding to DB')
|
|
|
|
file.save(os.path.join(config['UPLOAD_FOLDER'], filename))
|
|
|
|
thread1.join()
|
|
|
|
|
|
|
|
data["file"] = filename
|
|
|
|
data["url"] = config["DOMAIN"] + "/" + filename
|
2015-12-23 22:27:12 +00:00
|
|
|
print_log('Main', 'New file processed "' + filename + '"')
|
2015-12-23 13:11:38 +00:00
|
|
|
|
2015-12-24 11:14:55 +00:00
|
|
|
try:
|
|
|
|
if request.form["source"] == "web":
|
2015-12-24 23:32:58 +00:00
|
|
|
return render_template('link.html', data=data, page=config["SITE_DATA"])
|
2015-12-24 11:14:55 +00:00
|
|
|
except Exception:
|
2015-12-23 13:11:38 +00:00
|
|
|
return json.dumps(data)
|
2015-12-24 12:50:44 +00:00
|
|
|
else:
|
2015-12-24 16:00:59 +00:00
|
|
|
print_log('Notice', 'Forbidden file received')
|
2015-12-26 23:30:11 +00:00
|
|
|
return error_page(error="This file isn't allowed, sorry!", code=403)
|
2015-12-23 13:11:38 +00:00
|
|
|
|
|
|
|
# Return Web UI if we have a GET request
|
|
|
|
elif request.method == 'GET':
|
|
|
|
return render_template('upload.html', page=config["SITE_DATA"])
|
|
|
|
|
2015-12-24 14:26:55 +00:00
|
|
|
# Def all the static pages
|
2015-12-23 22:39:05 +00:00
|
|
|
@app.route('/about')
|
|
|
|
def about():
|
2015-12-24 12:46:05 +00:00
|
|
|
return render_template('about.html', page=config["SITE_DATA"])
|
2015-12-23 22:39:05 +00:00
|
|
|
@app.route('/terms')
|
|
|
|
def terms():
|
2015-12-24 12:46:05 +00:00
|
|
|
return render_template('terms.html', page=config["SITE_DATA"])
|
2015-12-24 14:26:55 +00:00
|
|
|
@app.route('/privacy')
|
|
|
|
def privacy():
|
|
|
|
return render_template('privacy.html', page=config["SITE_DATA"])
|
|
|
|
@app.route('/faq')
|
|
|
|
def faq():
|
|
|
|
return render_template('faq.html', page=config["SITE_DATA"])
|
2015-12-28 15:38:13 +00:00
|
|
|
@app.route('/dmca')
|
|
|
|
def dmca():
|
2015-12-28 17:56:26 +00:00
|
|
|
video = random.choice(os.listdir("static/dmca/"))
|
|
|
|
return render_template('dmca.html', page=config["SITE_DATA"], video=video)
|
2015-12-23 22:39:05 +00:00
|
|
|
|
2015-12-27 17:46:21 +00:00
|
|
|
# Static resources that browsers spam for
|
|
|
|
@app.route('/favicon.ico')
|
|
|
|
def favicon():
|
|
|
|
return send_from_directory('static', 'favicon.ico')
|
|
|
|
@app.route('/apple-touch-icon.png')
|
2015-12-27 17:48:16 +00:00
|
|
|
def appleTouch():
|
2015-12-27 17:46:21 +00:00
|
|
|
return send_from_directory('static', 'logo/152px.png')
|
2015-12-27 17:48:16 +00:00
|
|
|
@app.route('/robots.txt')
|
|
|
|
def robotsTxt():
|
2015-12-27 17:46:21 +00:00
|
|
|
return send_from_directory('static', 'robots.txt')
|
|
|
|
|
2015-12-24 20:46:28 +00:00
|
|
|
# Custom 404
|
|
|
|
@app.errorhandler(404)
|
|
|
|
def page_not_found(e):
|
2015-12-26 23:30:11 +00:00
|
|
|
return error_page(error="We couldn't find that. Are you sure you know what you're looking for?", code=404), 404
|
|
|
|
@app.errorhandler(500)
|
2015-12-29 15:49:59 +00:00
|
|
|
def internal_error(e):
|
2015-12-26 23:30:11 +00:00
|
|
|
return error_page(error="Oops, this is an unknown error, not good.", code=500), 500
|
|
|
|
@app.errorhandler(403)
|
2015-12-29 15:49:59 +00:00
|
|
|
def no_permission(e):
|
2015-12-26 23:30:11 +00:00
|
|
|
return error_page(error="Check your privilege yo", code=403), 403
|
2015-12-24 20:46:28 +00:00
|
|
|
|
2015-12-23 22:39:05 +00:00
|
|
|
|
2015-12-23 13:11:38 +00:00
|
|
|
@app.route('/<filename>', methods=['GET'])
|
|
|
|
def get_file(filename):
|
2015-12-23 22:27:12 +00:00
|
|
|
print_log('Web', 'Hit "' + filename + '" - ' + time_to_string(time.time()))
|
2015-12-24 12:06:34 +00:00
|
|
|
try:
|
|
|
|
db.update_file(filename)
|
|
|
|
except Exception:
|
|
|
|
print_log('Warning', 'Unable to update access time. Is the file in the database?')
|
2015-12-23 13:11:38 +00:00
|
|
|
return send_from_directory(config['UPLOAD_FOLDER'], filename)
|
|
|
|
|
2015-12-23 22:27:12 +00:00
|
|
|
@app.route('/share/<filename>')
|
|
|
|
@app.route('/file/<filename>')
|
|
|
|
def serve_legacy(filename):
|
|
|
|
return send_from_directory('legacy', filename)
|
2015-12-23 13:11:38 +00:00
|
|
|
|
2015-12-26 19:32:42 +00:00
|
|
|
|
|
|
|
# Configure nginx to use these urls as custom error pages
|
|
|
|
@app.route('/error/<int:error>')
|
|
|
|
def nginx_error(error):
|
|
|
|
if error == 413:
|
2015-12-26 23:30:11 +00:00
|
|
|
return error_page(error="O-o-onii-chan, noo it's too big ~~", code=413), 413
|
2015-12-26 19:32:42 +00:00
|
|
|
else:
|
2015-12-26 23:30:11 +00:00
|
|
|
return error_page(error="We literally have no idea what just happened", code="Unknown")
|
2015-12-26 19:32:42 +00:00
|
|
|
|
|
|
|
|
2016-02-14 11:22:26 +00:00
|
|
|
if config["DELETE_FILES"]:
|
|
|
|
cleaner_thread()
|
|
|
|
|
2015-12-23 13:11:38 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
app.run(
|
|
|
|
port=config["PORT"],
|
|
|
|
host=config["HOST"],
|
|
|
|
debug=config["DEBUG"]
|
2016-02-14 11:22:26 +00:00
|
|
|
)
|