407 lines
14 KiB
Python
407 lines
14 KiB
Python
# encoding=utf8
|
|
import sys
|
|
import pypandoc
|
|
import PyPDF2
|
|
from PyPDF2 import PdfFileMerger, PdfFileReader
|
|
from weasyprint import HTML, CSS
|
|
from weasyprint.fonts import FontConfiguration
|
|
|
|
from flask import send_file, Flask, Response, url_for, render_template, Markup, jsonify, redirect, request, flash, session, make_response
|
|
from config import Config
|
|
import json
|
|
import os
|
|
import datetime as dt
|
|
from datetime import datetime
|
|
from pprint import pprint
|
|
import re
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
import numpy as np
|
|
from itertools import zip_longest
|
|
import collections
|
|
import random
|
|
import string
|
|
|
|
|
|
app = Flask(__name__, static_url_path='', static_folder="static", template_folder="templates")
|
|
app.jinja_env.add_extension('jinja2.ext.loopcontrols')
|
|
app.config.from_object(Config)
|
|
|
|
######################################################################################
|
|
# SETTING THE VARIABLES
|
|
######################################################################################
|
|
|
|
# setting variables for holding paths, folder names and the one file for description
|
|
path = "/static/files/"
|
|
jsonfiles = [] #json files
|
|
fullpathjsonfiles = [] #fullpath for some situations
|
|
listingfiles= [] #fullpaths
|
|
listingdirectories = [] #paths
|
|
thefile = None #selected file for description
|
|
positioninarray = 8 #counter
|
|
listofdicts=[] #to be able to import and use json content
|
|
datafromjson = []
|
|
max_wordpath_items = 500 # limit the nr. of items, as to prevent possible glitches with bots
|
|
|
|
pathofwords = []
|
|
pathofnumbers = []
|
|
|
|
#VARS FOR THE SESSIONS
|
|
# We don't want to store the secret key in git, but also don't really care what it is
|
|
# so generate it and store it to a file that's not in git:
|
|
current_dir = os.path.dirname(os.path.realpath(__file__))
|
|
secret_key_file = os.path.join(current_dir, 'secret.key')
|
|
if os.path.exists(secret_key_file):
|
|
with open(secret_key_file, 'r') as fp:
|
|
secret_key = fp.read()
|
|
else:
|
|
secret_key = ''.join(random.choice(string.ascii_lowercase) for i in range(100))
|
|
with open(secret_key_file, 'w') as fp:
|
|
fp.write(secret_key)
|
|
app.secret_key = secret_key
|
|
#app.config['SESSION_TYPE'] = 'filesystem' # works only for flask-session (we use native flask cookie-sessions)
|
|
|
|
def clearSession():
|
|
# Flask sessions are serialised into a cookie, so we cannot use the deque here
|
|
session['wordpath'] = []
|
|
session['clicktime'] = []
|
|
session['id'] = []
|
|
session['veryfirstnow'] = datetime.now().isoformat()
|
|
|
|
def setupSession():
|
|
# session should be configured from within request context
|
|
# so this function should be called on each request
|
|
if 'veryfirstnow' not in session:
|
|
clearSession()
|
|
|
|
# preparing the index.json file for the navbar
|
|
index_dict = {}
|
|
|
|
|
|
######################################################################################
|
|
#SOME JSON AND WALK OS REALTED THINGIES
|
|
######################################################################################
|
|
|
|
|
|
#reading wordlist.json
|
|
with open('wordlist.json', 'r', encoding='utf8') as f:
|
|
wordlist_dict = json.load(f)
|
|
|
|
|
|
#listing the json paths simultaneously generating a new index.json for the navbar
|
|
for path, subdirs, files in os.walk('./static/files/'):
|
|
for name in files:
|
|
if name.endswith(".json"):
|
|
fullpath = os.path.join(path, name)
|
|
jsonfiles.append(fullpath[8:])
|
|
fullpathjsonfiles.append(fullpath)
|
|
with open (fullpath) as f:
|
|
temp_dict = json.load(f)
|
|
index_dict[temp_dict["id"]] = temp_dict["title"]
|
|
|
|
|
|
######################################################################################
|
|
#NOW THE REAL DEAL
|
|
######################################################################################
|
|
|
|
@app.route("/")
|
|
def home():
|
|
setupSession()
|
|
|
|
return render_template('home.html', wordlist_dict=wordlist_dict)
|
|
|
|
def functionsession():
|
|
return(session)
|
|
|
|
# THIS IS NOT WORKING YET DUNNO WHY
|
|
@app.context_processor
|
|
def context_processor():
|
|
functionsession = session['wordpath']
|
|
return dict(functionsession=functionsession)
|
|
|
|
@app.route('/about/')
|
|
def about():
|
|
setupSession()
|
|
return render_template('about.html')
|
|
|
|
@app.route('/clear')
|
|
def clear():
|
|
# return to a refer if its set, default to root
|
|
return_url = request.environ.get("HTTP_REFERER", '/')
|
|
clearSession()
|
|
return redirect(return_url)
|
|
|
|
@app.route('/description')
|
|
def description():
|
|
setupSession()
|
|
|
|
idno=request.args.get('id')
|
|
jsonfilefordescription = "files/"+idno+"/"+idno+".json"
|
|
with open("static/"+jsonfilefordescription, 'r') as f:
|
|
data_dict = json.load(f)
|
|
datafromjson = data_dict["files"]
|
|
|
|
#open json file, list filepaths in array and loop with thefile
|
|
textfile=""
|
|
textfiles=[]
|
|
namefile=[]
|
|
with open("static/"+jsonfilefordescription, 'r') as f:
|
|
data_dict = json.load(f)
|
|
datafromjson = data_dict["files"]
|
|
itemid = data_dict["id"]
|
|
# a glitch of Flask sessions: if you do session['wordpath'].append() it creates an empty list
|
|
# hence we get it, append it, and set it.
|
|
# since Flask's session variables are json serialised (to be stored in a cookie), they do not
|
|
# support collections.deque, therefore we create that on each request to limit the items
|
|
ids = collections.deque(session['id'], maxlen=max_wordpath_items)
|
|
ids.append(itemid)
|
|
session["id"] = list(ids) # ... and therefore, we have to convert it back
|
|
for file in datafromjson:
|
|
if file.lower().endswith(('.html')):
|
|
namefile.append(file)
|
|
with open("static/"+file,"r", encoding='utf-8') as f:
|
|
textfile = f.read()
|
|
textfile = Markup(textfile)
|
|
textfiles.append(textfile)
|
|
return render_template('description.html', datafromjson=datafromjson, itemid=itemid, textfiles=textfiles, idno=idno, index_dict=index_dict, namefile=namefile)
|
|
|
|
@app.route('/diverge', methods=['GET'])
|
|
def diverge():
|
|
setupSession()
|
|
|
|
searchterm=request.args.get('search')
|
|
now = datetime.now() #description time
|
|
# a glitch of Flask sessions: if you do session['wordpath'].append() it creates an empty list
|
|
# hence we get it, append it, and set it.
|
|
wp = collections.deque(session['wordpath'], maxlen=max_wordpath_items)
|
|
wp.append(searchterm)
|
|
session['wordpath'] = list(wp)
|
|
clicktime = collections.deque(session['clicktime'], maxlen=max_wordpath_items)
|
|
clicktime.append(now.isoformat()) # make sure we have a determined format to stringify
|
|
session['clicktime'] = list(clicktime)
|
|
return render_template('diverge.html', wordlist_dict=wordlist_dict, searchterm=searchterm, index_dict=index_dict)
|
|
|
|
######################################################################################
|
|
#THE SCORE STUFF
|
|
######################################################################################
|
|
|
|
### Add : if score is empty then add some sentence like "your score is empty"
|
|
### to be printed to the text document
|
|
|
|
@app.route("/get-file")
|
|
|
|
def get_file():
|
|
setupSession()
|
|
fullscore = None
|
|
wordpath = session["wordpath"]
|
|
idlist = session["id"]
|
|
timelist = session["clicktime"]
|
|
veryfirstnow = session['veryfirstnow']
|
|
clickongetfiletime = datetime.now()
|
|
tadam = None
|
|
initialtime = None
|
|
|
|
# # USER IP ADDRESS OBTENTION
|
|
if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
|
|
userip = request.environ['REMOTE_ADDR']
|
|
else:
|
|
userip = request.environ['HTTP_X_FORWARDED_FOR'] # if behind a proxy
|
|
|
|
# Proxy might add multiple ips, take only one:
|
|
if ',' in userip:
|
|
userip = userip.split(',')[0]
|
|
|
|
# # CALCULATION OF INITIAL TIME BEFORE FIRST CLICK
|
|
if len(timelist) and not (timelist[0] is None):
|
|
thetime = timelist[0]
|
|
thetime = str(thetime)
|
|
print(thetime)
|
|
thetime = dt.datetime.strptime(thetime, "%Y-%m-%dT%H:%M:%S.%f")
|
|
firsttime = dt.datetime.strptime(veryfirstnow, "%Y-%m-%dT%H:%M:%S.%f")
|
|
initialtime = thetime - firsttime
|
|
initialtime = initialtime.total_seconds()
|
|
initialtime = int(initialtime)
|
|
initialtime = "."*initialtime
|
|
|
|
print(initialtime)
|
|
# #CALCULATE FILE NUMBER
|
|
|
|
dirListing = os.listdir("scores/")
|
|
scorenumber = len(dirListing)
|
|
|
|
# CONVERSION OF TIME INTO FORMATS THAT CAN BE USED FOR CALCULATIONS
|
|
timelistforoperations = []
|
|
for t in timelist :
|
|
t = str(t)
|
|
yo = dt.datetime.strptime(t, "%Y-%m-%dT%H:%M:%S.%f")
|
|
timelistforoperations.append(yo)
|
|
|
|
prev = None
|
|
wholestringy = None
|
|
|
|
# print("veryfirstnow : "+str(veryfirstnow)+"\n")
|
|
|
|
print(wordpath)
|
|
print(timelistforoperations)
|
|
print(idlist)
|
|
|
|
# WEAVING DELAYS AND WORDS TOGETHER AS A HUGE STRING OF CHARACTERS
|
|
for (word, time) in zip(wordpath,timelistforoperations):
|
|
upperword = word.upper()
|
|
|
|
#get previous time for substraction
|
|
if not (prev is None):
|
|
difftime = time - prev
|
|
difftime = difftime.total_seconds()
|
|
difftime = int(difftime)
|
|
# print(difftime)
|
|
else:
|
|
yo = str(veryfirstnow)
|
|
yoyo = dt.datetime.strptime(yo, '%Y-%m-%dT%H:%M:%S.%f')
|
|
|
|
difftime = time - yoyo
|
|
difftime = difftime.total_seconds()
|
|
difftime = int(difftime)
|
|
|
|
test = difftime
|
|
prev = time
|
|
diffpattern = test * '.'
|
|
stringy = diffpattern + upperword
|
|
|
|
if not (wholestringy is None):
|
|
wholestringy = wholestringy+stringy
|
|
fullscore = wholestringy
|
|
else:
|
|
wholestringy = upperword
|
|
fullscore = wholestringy
|
|
|
|
if not (fullscore is None):
|
|
# outside of the loop calculate seconds from "clickongetfiletime" minus the last "time" from the loop
|
|
lastdifftime = clickongetfiletime - prev
|
|
lastdifftime = lastdifftime.total_seconds()
|
|
lastdifftime = int(lastdifftime)
|
|
lastdifftime = lastdifftime * '.'
|
|
#the 60 seconds thing
|
|
# print(lastdifftime+"\n")
|
|
fullscore = initialtime+fullscore+lastdifftime
|
|
# Defining splitting point
|
|
n = 60
|
|
# Using list comprehension
|
|
out = [(fullscore[i:i+n]) for i in range(0, len(fullscore), n)]
|
|
#joining the strings with linebreaks
|
|
# tadam = '\n'.join(out) +"\n\n\n\nScore number : "+str(scorenumber)+ "\nGenerated at : "+str(clickongetfiletime)+"\nBy author : "+ userip
|
|
tadam = '\n'.join(out)
|
|
|
|
# have a message in file if no nav has been recorded so it's less dull than error page
|
|
if tadam is None:
|
|
tadam = "This score is Null"
|
|
|
|
uniquename = str(clickongetfiletime)
|
|
|
|
# with open('scores/'+uniquename+'.txt', 'a+') as f:
|
|
# f.write(tadam)
|
|
|
|
# print(tadam)
|
|
|
|
###### SCORE FIST PAGE
|
|
globalname = "Pushing scores"
|
|
print(tadam)
|
|
|
|
scorefirstpage = '''<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<link rel="stylesheet" type="text/css" href="static/css/stylepandoc.css">
|
|
</head>
|
|
<body>
|
|
<style>
|
|
body{background-color:magenta;}
|
|
</style>
|
|
<div id="coverpage">
|
|
<div class="infos scorenumber">SCORE #'''+str(scorenumber)+'''</div>
|
|
<div class="infos author">By '''+userip+'''</div>
|
|
<!--<div class="infos globalname">Part of the Pushing Scores series</div>-->
|
|
<div class="infos publisher">Part of the <i>Pushing Scores</i> series<br>
|
|
Published and distributed by <img src="static/logo/logo.png"></div>
|
|
<div class="infos time">On '''+str(clickongetfiletime)+'''</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
'''
|
|
|
|
scorecontentpage = '''<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<link rel="stylesheet" type="text/css" href="static/css/stylepandoc.css">
|
|
</head>
|
|
<body>
|
|
<div id="scorecontentpage">
|
|
{}
|
|
</div>
|
|
</body>
|
|
</html>
|
|
'''.format(tadam)
|
|
|
|
############# GENERATE SCORE PDF
|
|
|
|
pathnamefilepdf = "scores/"+uniquename+"test.pdf"
|
|
font_config = FontConfiguration()
|
|
HTML(string=scorecontentpage, base_url='./').write_pdf(pathnamefilepdf, stylesheets=[CSS('static/css/stylepandoc.css', font_config=font_config)], font_config=font_config)
|
|
|
|
############# GENERATE FIRST PAGE PDF
|
|
|
|
pathnamefilecoverpdf = "scores/"+uniquename+"testcover.pdf"
|
|
font_config = FontConfiguration()
|
|
HTML(string=scorefirstpage, base_url='./').write_pdf(pathnamefilecoverpdf, stylesheets=[CSS('static/css/stylepandoc.css', font_config=font_config)], font_config=font_config)
|
|
|
|
############# ASSEMBLE PDFS
|
|
|
|
merger = PdfFileMerger()
|
|
file1 = open(pathnamefilecoverpdf,"rb")
|
|
file2 = open(pathnamefilepdf,"rb")
|
|
|
|
pdf1 = PyPDF2.PdfFileReader(file1)
|
|
pdf2 = PyPDF2.PdfFileReader(file2)
|
|
|
|
pdf1_pages = pdf1.getNumPages()
|
|
pdf2_pages = pdf2.getNumPages()
|
|
|
|
outputfile = open("scores/"+uniquename+".pdf", "wb")
|
|
writer = PyPDF2.PdfFileWriter()
|
|
|
|
for i in range(pdf1_pages):
|
|
writer.addPage(pdf1.getPage(i))
|
|
|
|
for j in range(pdf2_pages):
|
|
writer.addPage(pdf2.getPage(j))
|
|
|
|
writer.write(outputfile)
|
|
|
|
file1.close()
|
|
file2.close()
|
|
outputfile.close()
|
|
|
|
clearSession()
|
|
os.remove(pathnamefilecoverpdf)
|
|
os.remove(pathnamefilepdf)
|
|
print("files removed")
|
|
|
|
try:
|
|
return send_file("scores/"+uniquename+".pdf", attachment_filename="olala.pdf")
|
|
except Exception as e:
|
|
return str(e)
|
|
|
|
|
|
######################################################################################
|
|
#INDEX PAGE
|
|
######################################################################################
|
|
@app.route("/index")
|
|
def index():
|
|
return render_template('theindex.html', wordlist_dict=wordlist_dict, index_dict=index_dict)
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True)
|