heartranked

git clone https://git.tarina.org/heartranked
Log | Files | Refs

server.py (124198B)


      1 #!/usr/bin/python3
      2 # -*- coding: utf-8 -*-
      3 
      4 import time, datetime, os, sys
      5 
      6 file_dir = os.path.dirname(__file__)
      7 sys.path.append(file_dir)
      8 
      9 import json
     10 import requests
     11 import subprocess
     12 import web
     13 import hashlib
     14 import random
     15 import time
     16 import shutil
     17 import settings
     18 import binascii
     19 import base64
     20 import markdown
     21 import re
     22 import bcrypt
     23 import unicodedata
     24 import urllib
     25 from pathlib import Path
     26 from mutagen.flac import FLAC
     27 from mutagen.easyid3 import EasyID3
     28 from mutagen.oggvorbis import OggVorbis
     29 from PIL import Image
     30 from PIL import ImageSequence
     31 import settings
     32 
     33 urls = (
     34     '/shop?', 'index',
     35     '/?', 'almost',
     36     '/putinbag/(.*)', 'putinbag',
     37     '/dropitem/(.*)?', 'dropitem',
     38     '/payln/(.*)', 'payln',
     39     '/paymobile/(.*)', 'paymobile',
     40     '/goodies/(.*)', 'goodies',
     41     "/stats?", "stats",
     42     '/lightning?', 'lightning',
     43     '/paybtc/(.*)', 'paybtc',
     44     '/payment/(.*)', 'payment',
     45     '/orders?', 'orders',
     46     '/checkout?', 'checkout',
     47     '/pending', 'pending',
     48     '/thankyou', 'thankyou',
     49     "/login?", "login",
     50     "/logout", "logout",
     51     "/invites?", "invites",
     52     "/users","users",
     53     "/like?","like",
     54     "/imageapi?","imageapi",
     55     "/u/(.*)?", "user",
     56     "/forgotpass?", "forgotpass",
     57     "/register?", "register",
     58     "/tuning?", "tuning",
     59     '/products/(.*)?', 'products',
     60     '/bigpic/(.*)?', 'bigpic',
     61     '/categories?', 'categories',
     62     '/op', 'op',
     63     '/bitcoin', 'bitcoin',
     64     '/shipping/(.*)', 'shipping',
     65     '/propaganda?', 'propaganda',
     66     '/editor?', 'editor',
     67     '/heartranked?','heartranked',
     68     '/save', 'save',
     69     '/upload', 'upload',
     70     '/rendered', 'rendered',
     71     '/uploads?', 'uploads',
     72     '/config', 'config',
     73     '/payments?', 'payments',
     74 
     75 bag = ''
     76 
     77 #Load from settings
     78 
     79 rtl = settings.rtl
     80 rpcauth = settings.rpcauth
     81 webmaster = settings.webmaster
     82 baseurl = settings.baseurl
     83 siteurl = baseurl
     84 allowed = settings.allowed
     85 postadmin = settings.postadmin
     86 postadmin_signature = settings.postadmin_signature
     87 
     88 basedir = os.path.dirname(os.path.realpath(__file__))+'/'
     89 templatedir = basedir + 'public_html/templates/'
     90 staticdir = basedir + 'public_html/static/'
     91 web.config.debug = False
     92 app = web.application(urls, globals())
     93 store = web.session.DiskStore(basedir + 'sessions')
     94 render = web.template.render(templatedir, base="base")
     95 renderop = web.template.render(templatedir, base="op")
     96 rendersplash = web.template.render(templatedir, base="splash")
     97 db = web.database(dbn='sqlite', db=basedir + "db/cyberpunkcafe.db", timeout=10)
     98 session = web.session.Session(app,store,initializer={'login':0, 'privilege':0, 'bag':[], 'sessionkey':'empty','soundlink':'','backurl':'','user':'','search':'', 'bildsida':'', 'feedbase':'', 'timebase':''})
     99 
    100 allowedchar = '_','-','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0'
    101 
    102 #----------- Database setup -------------
    103 
    104 #Remeber to store Euros in cents
    105 
    106 #CREATE TABLE products (id integer PRIMARY KEY, name text NOT NULL, description text, price integer NOT NULL, available integer, sold integer, priority integer, dateadded integer, datelastsold integer, daterunout integer, dateavailable integer);
    107 
    108 #CREATE TABLE shipping (id integer PRIMARY KEY, country text NOT NULL, cost integer NOT NULL, days integer NOT NULL);
    109 
    110 #should rename to customer 
    111 #CREATE TABLE pending (id integer PRIMARY KEY, invoice_key text NOT NULL, country text NOT NULL, firstname text NOT NULL, lastname text NOT NULL, address text NOT NULL, town text NOT NULL, postalcode integer NOT NULL, email text NOT NULL, dateadded integer)
    112 
    113 #CREATE TABLE invoices (id INT AUTO_INCREMENT, invoice_key TEXT, btc TEXT, ln TEXT, products TEXT, payment TEXT, amount INT, totsats INT, timestamp TIMESTAMP, status TEXT, datepaid TIMESTAMP, dateshipped TIMESTAMP);
    114 
    115 
    116 def logged():
    117     if session.login > 0:
    118         return True
    119     else:
    120         return False
    121 
    122 def savetofile(thename, thingstosave, overwrite):
    123     #full path to filename
    124     #save to next line make an ID automatically, you have to check the save to know how to load it.
    125     #loadfile check if record exist, first in line is the record hash and update if it exists
    126     #make users in a folder as files first is username username will always be user record
    127     #hearts will be files as usernames with timestamp in a hearts folder in post folder. be stored and checked in u/hearts and post/hearts
    128     # be sure to add home domain setting to username
    129     with open(thename, "w") as f:
    130         for i in thingstosave:
    131             f.write(str(i) + ',')
    132         
    133 
    134 def loadfile(thename, keyword):
    135     #search for keyword to get the list
    136 
    137 
    138 def adduser(name, password, mail):
    139     originalname=name
    140     name=safe_filename(name[:12])
    141     password = password.encode("utf-8")
    142     salt = bcrypt.gensalt()
    143     password_hashed = bcrypt.hashpw(password, salt)
    144     #check user db, if empty create admin
    145     #users = db.query("SELECT COUNT(*) AS users FROM rymdadmin")[0]
    146     #tot = int(users.users)
    147     tot = len(os.listdir(basedir+'users/'))
    148     print('users alltsomallt: ' + str(tot))
    149     if tot > 1:
    150         adminlevel=3
    151     else:
    152         adminlevel=5
    153     #db.insert('rymdadmin', name=name, displayname=originalname, password=password_hashed, mail=mail, subscribe='aldrig', adminlevel=3)
    154     savethis=[name,originalname, password_hashed, mail, adminlevel]
    155     savefile(basedir+'users/'+name, savethis)
    156     print("new user added")
    157     return
    158 
    159 def adminlevel(user):
    160     #level = db.query("SELECT adminlevel FROM rymdadmin WHERE name='"+user+"';")[0]
    161     level=loadfile(basedir+'users', user)
    162     #1 session logout, web.py bug
    163     #2 rights to see pics and comment
    164     #3 rights to upoload
    165     #5 superadmin
    166     session.login = int(level.adminlevel)
    167     return
    168 
    169 def stopresetpass(mail):
    170     t = None
    171     try:
    172         t = db.select('stopresetpass', where='mail="'+mail+'"', what='tid')[0]
    173         print(t)
    174     except Exception as e:
    175         db.insert('stopresetpass', mail=mail, tid=time.time())
    176         print(e)
    177         return False
    178     try:
    179         db.update('stopresetpass', where='mail="'+mail+'"', tid=time.time())
    180         print('okkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk')
    181     except Exception as e:
    182         print(e)
    183     try:
    184         senast = time.time() - t.tid
    185         print(senast)
    186         if senast < 600:
    187             print('mail is in password reset spam filter')
    188             return True
    189         else:
    190             return False
    191     except Exception as e:
    192         print(e)
    193         return True
    194 
    195 def stopflood(ip,referer):
    196     time.sleep(0.2)
    197     try:
    198         t = db.select('stopflood', where='ip="'+ip+'"', what='tid')[0]
    199     except:
    200         print('notin in db about ip')
    201         pass
    202     try:
    203         if t:
    204             db.update('stopflood', where='ip="'+ip+'"', tid=time.time())
    205             print('found ip, update stopflood time')
    206     except:
    207         db.insert('stopflood', ip=ip, tid=time.time())
    208         print('no ip adding flood ban time')
    209     try:
    210         senast = time.time() - t.tid
    211         print(senast)
    212         if senast < 2:
    213             #ban_for_flood(ip)
    214             return True
    215         else:
    216             return False
    217     except:
    218         return False
    219 
    220 def getinvitation(secretinvitation):
    221     invites=db.query("SELECT * FROM invites;")
    222     for i in invites:
    223         if i.secretinvitation == secretinvitation:
    224             if i.accepted == None:
    225                 return True
    226     return False
    227 
    228 class login():
    229     form = web.form.Form(
    230     web.form.Textbox('user', web.form.notnull, description="your registered mail account:"),
    231     web.form.Password('password', web.form.notnull, description="and your passcode please:"),
    232     web.form.Button('Login'))
    233     def GET(self):
    234         fejl = ''
    235         resetpasslink = False
    236         i = web.input(error=None)
    237         if i.error == 'fejl':
    238             fejl = 'wrong passcode!'
    239             resetpasslink = True
    240         if i.error == 'tom':
    241             fejl = 'didnt work'
    242         if session.login < 3:
    243             loginform = self.form()
    244             return render.login(loginform, fejl, resetpasslink)
    245         if session.login == 3:
    246             return web.seeother('/heartranked')
    247         if session.login == 5:
    248             raise web.seeother('/heartranked')
    249     def POST(self):
    250         referer = web.ctx.env.get('HTTP_REFERER',baseurl)
    251         ip = web.ctx['ip']
    252         stopflood(ip, referer)
    253         loginform = self.form()
    254         i = web.input()
    255         if i.user == '' or i.password == '':
    256             raise web.seeother('/login?error=tom')
    257         rymdadmins = []
    258         rymdadmins = bildhistoriker()
    259         #if not rymdadmins:
    260         #    raise web.seeother('/register')
    261         for p in rymdadmins:
    262             if p.name.lower() == i.user.lower() or p.mail.lower() == i.user.lower():
    263                 try:
    264                     encodepass = p.password.encode("utf-8")
    265                     print('nooooooooooooooooooooooooooooooooo')
    266                 except:
    267                     encodepass = p.password
    268                 if bcrypt.checkpw(i.password.encode('utf-8'), encodepass) == True:
    269                     session.user = p.name
    270                     adminlevel(p.name)
    271                     print('BACKURL: '+session.backurl)
    272                     if session.login == 5:
    273                         raise web.seeother('/heartranked')
    274                     if session.backurl != '':
    275                         backurl = session.backurl
    276                         session.backurl = ''
    277                         raise web.seeother(backurl)
    278                     else:
    279                         raise web.seeother('/heartranked')
    280         return web.seeother('/login?error=fejl')
    281 
    282 class register():
    283     form = web.form.Form(
    284     web.form.Textbox('invite', description="invitation code (do not edit):"),
    285     web.form.Textbox('user', description="name:"),
    286     web.form.Password('password', description="passcode:"),
    287     web.form.Textbox('mail', description="mail:"),
    288     web.form.Button('JOIN'))
    289     def GET(self):
    290         registerform = self.form()
    291         w = web.input(invite=None)
    292         formfail = ''
    293         n = ''
    294         m = ''
    295         if getinvitation(w.invite):
    296             try:
    297                 if w.fail == 'namn':
    298                     formfail = 'hey, need a name. If ya don lik ya real name imagination buddy'
    299                 if w.namn:
    300                     n = w.namn
    301                 if w.epost:
    302                     m = w.epost
    303                 elif w.epost == '':
    304                     formfail = 'we need an email, if u loose your passcode for example...'
    305                 if w.fail == 'notmail':
    306                     formfail = 'uhm, this is not an email'
    307                 elif w.fail == 'nametaken':
    308                     formfail = 'Name already taken'
    309                 elif w.fail == 'mailtaken':
    310                     formfail = 'You already got a account on this email. Try reset your passcode'
    311                 elif w.fail == 'kortlosen':
    312                     formfail = 'Too shoort passcode. Min 5 char.'
    313             except:
    314                 pass
    315             #check user db, if empty create admin
    316             users = db.query("SELECT COUNT(*) AS users FROM rymdadmin")[0]
    317             totusers = int(users.users)
    318             registerform.fill(user=urllib.parse.unquote_plus(n), mail=urllib.parse.unquote_plus(m), invite=w.invite)
    319             return render.register(registerform, formfail, totusers)
    320         else:
    321             return web.seeother('/oopsie')
    322     def POST(self):
    323         registerform = self.form()
    324         i = web.input(invite=None)
    325         if getinvitation(i.invite):
    326             r = '&namn=' + i.user + '&epost=' + i.mail
    327             urllib.parse.quote_plus(r)
    328             if i.user == '':
    329                 raise web.seeother('/register?invite='+i.invite+'&fail=namn'+r)
    330             if '@' not in i.mail:
    331                 raise web.seeother('/register?invite='+i.invite+'&fail=notmail'+r)
    332             if len(i.password) < 5:
    333                 raise web.seeother('/register?invite='+i.invite+'&fail=kortlosen'+r)
    334             rymdadmins = db.select('rymdadmin', what='name, mail')
    335             for p in rymdadmins:
    336                 if p.name.lower() == i.user.lower():
    337                     raise web.seeother('/register?invite='+i.invite+'&fail=nametaken' +r)
    338                 if p.mail.lower() == i.mail.lower():
    339                     raise web.seeother('/register?invite='+i.invite+'&fail=mailtaken' +r)
    340             adduser(i.user, i.password, i.mail.lower())
    341             #Send mail to Madbaker
    342             msg = "Wowowowoweeewaaa! Lets Ride The INTERNET Wave Together, Bee as home, HEART RANKED ftw! " + i.user + ' ' + i.mail
    343             sendmail(postadmin, 'Wowowoweewaaa!', msg)
    344             #Send mail to new user
    345             msg = "Wowowowoweeewaaa! "+i.user+" Lets Ride INTERNET Wave Together, Bee as home, HEART RANKED ftw! https://robinbackman.com/heartranked"
    346             sendmail(i.mail, 'HEART RANKED VISIONARY Fleet', msg)
    347             #session.login = 3
    348             #session.user = safe_filename(i.user)
    349             #add user to matrix
    350             #os.system("register_new_matrix_user -u "+i.user+" -p "+i.password+" --no-admin -c /etc/matrix-synapse/homeserver.yaml") 
    351             #db.update('invites', where='secretinvitation="'+i.invite+'"', accepted=datetime.datetime.now())
    352             return web.seeother('/login')
    353         else:
    354             raise web.seeother('/oopsie')
    355 
    356 class welcome():
    357     def GET(self):
    358         if session.login > 2:
    359             backurl = ''
    360             if session.backurl != '':
    361                 backurl = session.backurl
    362                 session.backurl = ''
    363             return render.ny(session.user, backurl)
    364 
    365 class like:
    366     def POST(self):
    367         if session.user != '':
    368             i = web.input(unlike=None, like=None, hate=None, unhate=None, user=None, imghash=None)
    369             user = i.user
    370             imghash = i.imghash
    371             l = db.query("SELECT * FROM likes WHERE bild='"+imghash+"' AND user='"+session.user+"';")
    372             print(session.user)
    373             print(session.user)
    374             print('fuuuuuuuuuuuuuuuuu')
    375             if l:
    376                 user_likes = True
    377             else:
    378                 user_likes = False
    379             if user_likes == False:
    380                 db.insert('likes', user=session.user, bild=imghash, datum=datetime.datetime.now())
    381                 user_likes = True
    382             elif user_likes == True:
    383                 db.query("DELETE FROM likes WHERE bild='"+imghash+"' AND user='"+session.user+"';")
    384                 user_likes = False
    385             likes = db.query("SELECT Count(*) AS likes FROM likes WHERE bild='"+imghash+"';")[0]
    386             # Example: Update like count in your database
    387             # This is a placeholder; replace with your database logic
    388             # Return JSON response
    389             web.header('Content-Type', 'application/json')
    390             return json.dumps({'likes': likes.likes, 'user_likes': user_likes })
    391 
    392 class user():
    393     def GET(self, user):
    394         data = web.input(soundname=None, onair=None, public=None, showuploads=None)
    395         if user == session.user:
    396             if data.public and data.soundname:
    397                 db.update('published', where="soundlink='" + data.soundname +"'", public=data.public)
    398             elif data.showuploads=='yes':
    399                 uploads = []
    400                 uploads = get_files_by_modtime(basedir+'public_html/static/users/' + user + '/images/web/',newest_first=True)
    401                 return render.showuploads(uploads,user,allowedchar, random)
    402             elif data.onair and data.soundname:
    403                 db.update('published', where="soundlink='" + data.soundname +"'", playing=data.onair)
    404             #soundname='aurora_ruderalis-greatful_bread'
    405             #filetype='flac'
    406             #soundlink = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    407             #db.insert('sound', soundlink=soundlink, filename=soundname, sort=filetype, title=soundname, uploaddate=datetime.datetime.now(), uppladdare=user, lastmod=datetime.datetime.now(), moddedby=user)
    408             usersounds = db.query("SELECT * FROM published WHERE creator='"+user+"' ORDER BY timeadded DESC;")
    409             sounds = db.select('published')
    410             creditsounds = []
    411             for i in sounds:
    412                 try:
    413                     credits=i.musicians.split(',')
    414                 except:
    415                     credits=''
    416                 for u in credits:
    417                     if u.strip().lower() == user.strip().lower():
    418                         creditsounds.append(i.title)
    419             return render.user(usersounds,creditsounds,user,datetime,str,int)
    420         return web.seeother('/login')
    421 
    422 class invites():
    423     form = web.form.Form(
    424     web.form.Textbox('mail', description="epost:"), 
    425     web.form.Button('Skicka'))
    426     def GET(self):
    427         if session.login > 2:
    428             user = db.select('rymdadmin', where='name="'+session.user+'"')[0]
    429             invites = db.select('invites', where='createdby="'+session.user+'"')
    430             tuningform = self.form()
    431             w = web.input(epost=None, render=None)
    432             formfail = ''
    433             if w.epost == '':
    434                 formfail = formfail + 'you have to put your email in'
    435             if w.render == 'yes':
    436                 secret_invite = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    437                 db.insert('invites', secretinvitation=secret_invite, created=datetime.datetime.now(), createdby=session.user)
    438             return render.invites(tuningform, formfail, user.name, invites)
    439     def POST(self):
    440         if session.login > 2:
    441             user = db.select('rymdadmin', where='name="'+session.user+'"')[0]
    442             tuningform = self.form()
    443             i = web.input()
    444             if i.mail == '':
    445                 raise web.seeother('/invites?fail=nomail')
    446             if '@' not in i.mail:
    447                 raise web.seeother('/tuning?fail=notmail') 
    448             secret_invite = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    449             db.insert('invites', secretinvitation=secret_invite, created=datetime.datetime.now(), createdby=session.user)
    450             msg = "YO! You are the One! " + user.name + " is your Morpheous. Follow this rabbit https://robinbackman.com/register?invite="+secret_invite 
    451             sendmail(i.mail, 'Invitation to HEART RANKED!', msg)
    452         return web.seeother('/heartranked')
    453 
    454 class tuning():
    455     form = web.form.Form(
    456     web.form.Textbox('user', description="synligt namn:"),
    457     web.form.Password('password', description="lösenord:"),
    458     web.form.Password('newpassword', description="nytt lösen (ifall du vill byta):"),
    459     web.form.Password('newpassword2', description="nytt lösen igen:"),
    460     web.form.Textbox('mail', description="epost:"), 
    461     web.form.Button('Spara'))
    462     def GET(self):
    463         if session.login > 2:
    464             print('asdfasdfasdf')
    465             user = db.select('rymdadmin', where='name="'+session.user+'"')[0]
    466             tuningform = self.form()
    467             w = web.input(namn=None,epost=None,fail=None,upd=None)
    468             print('asdfasdfasdfkdakkakka')
    469             formfail = ''
    470             if w.fail == 'wrongpass':
    471                 formfail = formfail + 'wrong passcode'
    472             if w.fail == 'nopass':
    473                 formfail = formfail + 'you have to write passcode'
    474             if w.namn == '':
    475                 formfail = formfail + 'whats your displayname'
    476             if w.epost == '':
    477                 formfail = formfail + 'write your email please'
    478             elif w.fail == 'notmail':
    479                 formfail = formfail + 'email please'
    480             if w.fail == 'nametaken':
    481                 formfail = formfail + 'name is taken! choose another'
    482             if w.fail == 'mailtaken':
    483                 formfail = formfail + 'mail address taken'
    484             if w.fail == 'kortlosen':
    485                 formfail = formfail + '5 characters minimum'
    486             if w.fail == 'newpass':
    487                 formfail = formfail + 'new passcode doesnt match'
    488             if w.upd == 'yes':
    489                 formfail = 'Yes, your account has been tuned in thanks!'
    490             tuningform.fill(user=user.displayname, mail=user.mail, subscribe=user.subscribe)
    491             return render.tuning(tuningform, formfail, user.name)
    492         else:
    493             return web.seeother('/register')
    494     def POST(self):
    495         if session.login > 2:
    496             tuningform = self.form()
    497             i = web.input()
    498             if i.password == '':
    499                 raise web.seeother('/tuning?fail=nopass')
    500             rymdadmins = bildhistoriker()
    501             for p in rymdadmins:
    502                 print(p)
    503                 if p.name == session.user:
    504                     if bcrypt.checkpw(i.password.encode('utf-8'), p.password):
    505                         #check if display name taken
    506                         b_displayname = bildhistoriker()
    507                         for a in b_displayname:
    508                             if i.user in a.displayname and a.name != session.user:
    509                                 raise web.seeother('/tuning?fail=nametaken')
    510                             if i.mail in a.mail and i.mail != p.mail:
    511                                 raise web.seeother('/tuning?fail=mailtaken')
    512                         if i.newpassword != '':
    513                             if i.newpassword != i.newpassword2:
    514                                 raise web.seeother('/tuning?fail=newpass')
    515                             if len(i.newpassword) < 5:
    516                                 raise web.seeother('/tuning?fail=kortlosen')
    517                             else:
    518                                 #update with password change
    519                                 password = i.newpassword.encode("utf-8")
    520                                 salt = bcrypt.gensalt()
    521                                 password_hashed = bcrypt.hashpw(password, salt)
    522                                 db.update('rymdadmin', where='name="'+session.user+'"', displayname=i.user, password=password_hashed, mail=i.mail.lower())
    523                                 return web.seeother('/tuning?upd=yes')
    524                         if '@' not in i.mail:
    525                             raise web.seeother('/tuning?fail=notmail')
    526                         #update without passwordchange
    527                         db.update('rymdadmin', where='name="'+session.user+'"', displayname=i.user, mail=i.mail.lower())
    528                         return web.seeother('/tuning?upd=yes')
    529                     else:
    530                         raise web.seeother('/tuning?fail=wrongpass')
    531 
    532 class forgotpass():
    533     form = web.form.Form(
    534             web.form.Textbox('mail', web.form.notnull, description="email:"),
    535             web.form.Button('Send me new passcode'))
    536     def GET(self):
    537         fejl = ''
    538         i = web.input(error=None)
    539         if i.error == 'fejl':
    540             fejl = 'no email like that sorry!'
    541         elif i.error == 'done':
    542             fejl = 'your passcode is updated and sent to your mail'
    543         elif i.error == 'nej':
    544             fejl = 'nope, dont worky'
    545         elif i.error == 'stopresetpass':
    546             fejl = 'Already sent passcode to mail'
    547         if session.login < 3:
    548             loginform = self.form()
    549             return render.forgotpass(loginform, fejl)
    550         if session.login == 3:
    551             return web.seeother('/s')
    552         if session.login == 5:
    553             raise web.seeother('/s')
    554     def POST(self):
    555         referer = web.ctx.env.get('HTTP_REFERER',baseurl)
    556         ip = web.ctx['ip']
    557         stopflood(ip, referer)
    558         sendpassform = self.form()
    559         if not sendpassform.validates():
    560             raise web.seeother('/forgotpass?error=fejl')
    561         else:
    562             i = web.input()
    563             if '@' not in i.mail:
    564                 raise web.seeother('/forgotpass?error=fejl')
    565             rymdadmin = []
    566             rymdadmins = bildhistoriker()
    567             for p in rymdadmins:
    568                 if p.mail.lower() == i.mail.lower():
    569                     passfilter = stopresetpass(i.mail.lower())
    570                     if passfilter == True:
    571                         raise web.seeother('/forgotpass?error=stopresetpass')
    572                     unencrypted_password = ('%06x' % random.randrange(16**6))
    573                     password = unencrypted_password.encode("utf-8")
    574                     salt = bcrypt.gensalt()
    575                     password_hashed = bcrypt.hashpw(password, salt)
    576                     db.update('rymdadmin', where='name="'+p.name+'"', password=password_hashed)
    577                     print("lösenordet uppdaterat!")
    578                     msg = "Your new passcode is: " + unencrypted_password + ' , once you logg in with this enter a new passcode by pressin your name, it a um link. Take care now bye bye then.'
    579                     sendmail(p.mail, 'Heart Ranked Passcode', msg)
    580                     raise web.seeother('/forgotpass?error=done')
    581             raise web.seeother('/forgotpass?error=fejl')
    582 
    583 def sendmail(email, subject, msg):
    584     #Send mail
    585     echomsg = subprocess.Popen(('echo', msg+'\n'+postadmin_signature), stdout=subprocess.PIPE)
    586     sendmsg = subprocess.check_output(('mail', '-r', postadmin, '-s', subject, email), stdin=echomsg.stdout)
    587     echomsg.wait()
    588     #subprocess.call(['echo', msg, '|', 'mail', '-r', postadmin,'-s', subject, email])
    589 
    590 def resize_gif(input_path, output_path, max_size):
    591     input_image = Image.open(input_path)
    592     frames = list(_thumbnail_frames(input_image,max_size))
    593     output_image = frames[0]
    594     output_image.save(
    595         output_path,
    596         save_all=True,
    597         append_images=frames[1:],
    598         disposal=input_image.disposal_method,
    599         **input_image.info,
    600     )
    601 
    602 def _thumbnail_frames(image,max_size):
    603     for frame in ImageSequence.Iterator(image):
    604         new_frame = frame.copy()
    605         new_frame.thumbnail(max_size, Image.Resampling.LANCZOS)
    606         yield new_frame
    607 
    608 def scale_gif(path, scale, new_path=None):
    609     gif = Image.open(path)
    610     if not new_path:
    611         new_path = path
    612     old_gif_information = {
    613         'loop': bool(gif.info.get('loop', 1)),
    614         'duration': gif.info.get('duration', 40),
    615         'background': gif.info.get('background', 223),
    616         'extension': gif.info.get('extension', (b'NETSCAPE2.0')),
    617         'transparency': gif.info.get('transparency', 223)
    618     }
    619     new_frames = get_new_frames(gif, scale)
    620     save_new_gif(new_frames, old_gif_information, new_path)
    621 
    622 def get_new_frames(gif, scale):
    623     new_frames = []
    624     actual_frames = gif.n_frames
    625     for frame in range(actual_frames):
    626         gif.seek(frame)
    627         new_frame = Image.new('RGBA', gif.size)
    628         new_frame.paste(gif)
    629         new_frame.thumbnail(scale, Image.Resampling.LANCZOS)
    630         new_frames.append(new_frame)
    631     return new_frames
    632 
    633 def save_new_gif(new_frames, old_gif_information, new_path):
    634     new_frames[0].save(new_path,
    635                        save_all = True,
    636                        append_images = new_frames[1:],
    637                        duration = old_gif_information['duration'],
    638                        loop = old_gif_information['loop'],
    639                        background = old_gif_information['background'],
    640                        extension = old_gif_information['extension'] ,
    641                        transparency = old_gif_information['transparency'])
    642 
    643 def getdisplayname(user):
    644     try:
    645         displayname = db.query("SELECT displayname FROM rymdadmin WHERE name='"+user+"';")[0]
    646         displayname = displayname.displayname
    647     except:
    648         displayname = user
    649     return displayname
    650 
    651 def safe_filename(name: str, max_length: int = 100, replacement: str = "-") -> str:
    652     """
    653     Convert a filename into a web-safe version.
    654     """
    655     if not name:
    656         return "file"
    657 
    658     # Normalize unicode (é → e, etc.)
    659     name = unicodedata.normalize('NFKD', name)
    660     name = name.encode('ascii', 'ignore').decode('ascii')
    661 
    662     # Replace spaces and common separators with the replacement char
    663     name = re.sub(r'[\s_]+', replacement, name)
    664 
    665     # Remove any character that is not alphanumeric, hyphen, underscore, or dot
    666     name = re.sub(r'[^a-zA-Z0-9.\-_]', '', name)
    667 
    668     # Replace multiple replacement chars with single one
    669     name = re.sub(re.escape(replacement) + r'+', replacement, name)
    670 
    671     # Remove leading/trailing replacement chars and dots
    672     name = name.strip(replacement + '.')
    673 
    674     # Prevent empty or hidden files
    675     if not name or name.startswith('.'):
    676         name = "file" + name
    677 
    678     # Enforce max length (leave room for extension)
    679     if len(name) > max_length:
    680         name = name[:max_length]
    681 
    682     return name.lower()
    683 
    684 #-------------Get files and sort em by date modified---------------
    685 
    686 def get_files_by_modtime(directory: str = ".", newest_first: bool = True):
    687     """
    688     Returns a list of file names in the directory sorted by last modified time.
    689     
    690     - newest_first=True  → Newest files first (most recent modification)
    691     - newest_first=False → Oldest files first
    692     """
    693     path = Path(directory)
    694     
    695     # Get all files (exclude directories and hidden files if you want)
    696     files = [f for f in path.iterdir() if f.is_file()]
    697     
    698     # Sort by modification time
    699     sorted_files = sorted(
    700         files,
    701         key=lambda f: f.stat().st_mtime,   # last modified timestamp
    702         reverse=newest_first
    703     ) 
    704     # Return just the file names (as strings)
    705     return [f.name for f in sorted_files]
    706 
    707 
    708 def getfiles(filmfolder):
    709     #get a list of films, in order of settings.p file last modified
    710     films_sorted = []
    711     print(filmfolder+'FUUUUUUUUUUUUUUUUUUUUUU')
    712     films = next(os.walk(filmfolder))[1]
    713     for i in films:
    714         uploaded = os.listdir(filmfolder + i + '/')
    715         for f in uploaded:
    716             if os.path.isfile(filmfolder + i + '/'+f) == True:
    717                 lastupdate = os.path.getmtime(filmfolder + i + '/' + f)
    718                 films_sorted.append((i,f,lastupdate))
    719         else:
    720             films_sorted.append((i,f,0))
    721     films_sorted = sorted(films_sorted, key=lambda tup: tup[2], reverse=True)
    722     return films_sorted
    723 
    724 def getmacaroon():
    725     with open(basedir+'access.macaroon', 'rb') as f:
    726         m = f.read()
    727     #m = binascii.hexlify(m).decode()
    728     m = base64.b64encode(m).decode()
    729     return m
    730 
    731 def createinvoice(amount, description, label):
    732     #Cents to EUR
    733     amount = str(amount*1000)
    734     invoice_details = {"amount":amount, "description": description, "label": label}
    735     print(invoice_details)
    736     macaroon = getmacaroon()
    737     headers = {'macaroon': macaroon} 
    738     resp = requests.post(rtl+'invoice/genInvoice', json=invoice_details, headers=headers,verify=False)
    739     print(resp.json())
    740     return resp.json()
    741 
    742 def getinvoice(label):
    743     macaroon = getmacaroon()
    744     headers = {'macaroon': macaroon}
    745     resp = requests.get(rtl+'invoice/listInvoices?label='+label, headers=headers, verify=False)
    746     return resp.json()['invoices'][0]
    747 
    748 def getnewaddr():
    749     macaroon = getmacaroon()
    750     headers = {'macaroon': macaroon}
    751     resp = requests.get(rtl+'invoice/newaddr', headers=headers, verify=False)
    752     return resp.json()['address'][0]
    753 
    754 def callsubprocess(cmd):
    755     subprocess.call(cmd.split())
    756 
    757 def dropitems(d):
    758     i = getproduct(d)
    759     try:
    760         product = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"' AND product='"+str(i.id)+"';")[0]
    761     except:
    762         return 'empty'
    763     if product.quantity > 1:
    764         db.update('customerbag', where="sessionkey='" + session.sessionkey +"' and product='"+str(i.id)+"'", quantity=product.quantity-1)
    765         db.update('products', where="id='"+str(i.id)+"'", available=i.available+1)
    766     else:
    767         db.query("DELETE FROM customerbag WHERE sessionkey='" + session.sessionkey +"' AND product='"+str(i.id)+"';")
    768         db.update('products', where="id='"+str(i.id)+"'", available=i.available+1)
    769         return 'empty'
    770 
    771 def addtobag(p):
    772     i = getproduct(p)
    773     if i.available > 0:
    774         #session.bag += (i.name, i.price, i.id),
    775         db.update('products', where="id='"+str(i.id)+"'", available=i.available-1)
    776         product = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"' AND product='"+str(i.id)+"';")
    777         if product:
    778             product = product[0]
    779             print(product)
    780             db.update('customerbag', where="sessionkey='" + session.sessionkey +"' and product='"+str(i.id)+"'", quantity=product.quantity+1)
    781             print('gwtdafaakouttahere')
    782         else:
    783             db.insert('customerbag', sessionkey=session.sessionkey, product=i.id, type=i.type, currency=i.currency, price=i.price, quantity=1, timeadded=datetime.datetime.now())
    784 
    785 def productname(productid):
    786     try:
    787         name = db.query("SELECT name FROM products WHERE id='"+str(productid)+"';")[0]
    788     except:
    789         return ''
    790     return name.name
    791 
    792 def getproduct(productid):
    793     try:
    794         product = db.query("SELECT * FROM products WHERE id='"+str(productid)+"';")[0]
    795     except:
    796         return ''
    797     return product
    798 
    799 def getcategories():
    800     try:
    801         categories = db.query("SELECT * FROM categories;")[0]
    802     except:
    803         return ''
    804     return categories
    805 
    806 def ordertype():
    807     physical=False
    808     bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    809     for b in bag:
    810         if b.type=='physical':
    811             return 'physical'
    812     return 'digital'
    813 
    814 def getavailable(productid):
    815     try:
    816         name = db.query("SELECT available FROM products WHERE id='"+str(productid)+"';")[0]
    817     except:
    818         return ''
    819     return name.available
    820 
    821 def getbtcrate():
    822     btc_to_euro = db.select("btcrate", where="currency='EUR'")
    823     #shippinginfo = db.select('shipping', where="country='" + pendinginfo.country + "'", what='price, days')[0]
    824     btcrate = 65619         
    825     return btcrate
    826     try:
    827         if time.time() - btc_to_euro[0].timeadded > 6000:
    828             btcrate = 64485
    829             b = BtcConverter()
    830             btcrate = int(b.get_latest_price('EUR'))
    831             db.update('btcrate', where='currency="EUR"', rate=btcrate, timeadded=time.time())
    832         else:
    833             btc_to_euro = db.select("btcrate", where="currency='EUR'")
    834             btcrate = btc_to_euro[0].rate
    835     except:
    836         db.insert('btcrate', currency='EUR', rate=64485, timeadded=time.time())
    837 
    838 def getbtcratetime():
    839     btc_to_euro = db.select("btcrate", where="currency='EUR'")
    840     btctime = btc_to_euro[0].timeadded
    841     return datetime.datetime.fromtimestamp(btctime).strftime('%c')
    842 
    843 def getprice(productid):
    844     p = db.query("SELECT * FROM products WHERE id='"+str(productid)+"';")[0]
    845     #b = BtcConverter()
    846     btcrate=getbtcrate()
    847     if p.currency=='euro':
    848         sat = 1/btcrate*(p.price/100) * 100000000
    849         #sat = b.convert_to_btc(p.price/100, 'EUR') * 100000000
    850         euro = p.price/100
    851     if p.currency=='bitcoin':
    852         euro = btcrate*p.price/100000000
    853         #euro = b.convert_btc_to_cur(p.price/100000000,'EUR')
    854         sat = p.price
    855     return int(sat), round(euro,2)
    856 
    857 def btc_to_eur(amount):
    858     #b = BtcConverter()
    859     btcrate=getbtcrate()
    860     #euro = round(b.convert_btc_to_cur(amount/100000000,'EUR'),2)
    861     euro = round(btcrate*amount/100000000)
    862     return euro
    863 
    864 def eur_to_sat(amount):
    865     btcrate=getbtcrate()
    866     #b = BtcConverter()
    867     #btc = b.convert_to_btc(amount/100, 'EUR')
    868     btc = 1/btcrate*(amount/100)
    869     sat=btc*100000000
    870     return int(sat)
    871 
    872 def getrate():
    873     #b = BtcConverter()
    874     btcrate=getbtcrate()
    875     #return int(b.get_latest_price('EUR'))
    876     return int(btcrate)
    877 
    878 def checkforoldbags():
    879     print('checking for old bags')
    880     bags = db.select('customerbag')
    881     for bag in bags:
    882         if datetime.datetime.now() - bag.timeadded > datetime.timedelta(minutes=6000):
    883             print(datetime.datetime.now() - bag.timeadded)
    884             print(datetime.timedelta(hours=1))
    885             print("Fuck")
    886             product = getproduct(bag.product)
    887             try:
    888                 print('found a bag at door! goddamit, got to put ' + str(bag.quantity) + ' x '  + product.name + ' back on the shelf')
    889                 if product.available > 1:
    890                     q = product.available + bag.quantity
    891                 else:
    892                     q = bag.quantity
    893                 db.update('products', where="id='"+str(bag.product)+"'", available=str(q))
    894                 db.query("DELETE FROM customerbag WHERE sessionkey='" + bag.sessionkey + "'")
    895             except:
    896                 pass
    897 
    898 def checkavailable():
    899     print('check items from availability')
    900     bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey + "'")
    901     for i in bag:
    902         q = getavailable(i.product)
    903         soldout = q - i.quantity
    904         if soldout < 0:
    905             web.seeother('/?error=soldout&prod='+str(i.product))
    906         else:
    907             return
    908 
    909 def sold():
    910     print('remove items from availability')
    911     bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey + "'")
    912     for i in bag:
    913         q = getavailable(i.product)
    914         soldout = q - i.quantity
    915         if soldout < 0:
    916             web.seeother('/?error=soldout')
    917         else:
    918             db.update('products', where="id='"+str(i.product)+"'", available=str(q - i.quantity))
    919 
    920 
    921 def organizepics(product):
    922     imgdir = basedir+'public_html/static/img/' + str(product) + '/'
    923     imgdirlist = [imgdir, imgdir + 'web/', imgdir + 'thumb/']
    924     for d in imgdirlist:
    925         pics = next(os.walk(d))[2]
    926         organized_nr = 0
    927         for s in sorted(pics):
    928             if '.jpeg' in s:
    929                 #print(s)
    930                 unorganized_nr = int(s[0:3])
    931                 if organized_nr == unorganized_nr:
    932                     print('correcto pic numbering')
    933                     pass
    934                 if organized_nr != unorganized_nr:
    935                     print('false, correcting pic from ' + str(unorganized_nr) + ' to ' + str(organized_nr))
    936                     mv = 'mv ' + d + str(unorganized_nr).zfill(3) + '.jpeg'
    937                     mv2 = ' ' + d + str(organized_nr).zfill(3) + '.jpeg'
    938                     os.system(mv + mv2)
    939                 organized_nr += 1
    940 
    941 def getpendinginfo():
    942     try:
    943         pendinginfo = db.select('pending', where="invoice_key='" + session.sessionkey + "'", what='country, firstname, lastname, address, town, postalcode, email')[0]
    944     except:
    945         pendinginfo = ''
    946     return pendinginfo
    947 
    948 class index():
    949     def GET(self):
    950         ip = web.ctx['ip']
    951         referer = web.ctx.env.get('HTTP_REFERER', 'none')
    952         environ = web.ctx.env.get('HTTP_USER_AGENT', 'dunno')
    953         visitorlog(ip,referer,environ)
    954         checkforoldbags()
    955         i = web.input(dropitem=None, putinbag=None,error=None,prod=None,category=None)
    956         if session.sessionkey == 'empty':
    957             session.sessionkey = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[15:35]
    958         if i.dropitem != None:
    959             session.bag = dropitems(i.dropitem)
    960             print(session.bag)
    961         if i.putinbag != None:
    962             addtobag(i.putinbag)
    963             return web.seeother('/shop#' + i.putinbag)
    964         print('Cyberpunk cafe')
    965         #print(session.bag)
    966         products = db.query("SELECT * FROM products ORDER BY priority DESC")
    967         try:
    968             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    969         except:
    970             bag = None
    971         try:
    972             inbag = db.query("SELECT COUNT(*) AS inbag FROM customerbag where sessionkey='" + session.sessionkey +"';")[0]
    973             inbag = int(inbag.inbag)
    974         except:
    975             inbag = None
    976         if inbag < 1:
    977             session.sessionkey = 'empty'
    978         return render.index(products,bag,session.sessionkey,productname,inbag,db,getprice,getrate,i.category, markdown)
    979 
    980 class almost():
    981     def GET(self):
    982         ip = web.ctx['ip']
    983         referer = web.ctx.env.get('HTTP_REFERER', 'none')
    984         environ = web.ctx.env.get('HTTP_USER_AGENT', 'dunno')
    985         visitorlog(ip,referer,environ)
    986         visitors, total, unique = getvisits()
    987         checkforoldbags()
    988         i = web.input(dropitem=None, putinbag=None,error=None,prod=None,category=None,show=None)
    989         if session.sessionkey == 'empty':
    990             session.sessionkey = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[15:35]
    991         if i.dropitem != None:
    992             session.bag = dropitems(i.dropitem)
    993             print(session.bag)
    994         if i.putinbag != None:
    995             addtobag(i.putinbag)
    996             return web.seeother('/#' + i.putinbag)
    997         print('Cyberpunk cafe')
    998         #print(session.bag)
    999         products = db.query("SELECT * FROM products ORDER BY priority DESC")
   1000         try:
   1001             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
   1002         except:
   1003             bag = None
   1004         try:
   1005             inbag = db.query("SELECT COUNT(*) AS inbag FROM customerbag where sessionkey='" + session.sessionkey +"';")[0]
   1006             inbag = int(inbag.inbag)
   1007         except:
   1008             inbag = None
   1009         if inbag < 1:
   1010             session.sessionkey = 'empty'
   1011         return rendersplash.almost(products,bag,session.sessionkey,productname,inbag,db,getprice,getrate,i.category, markdown, visitors, total, unique, i.show)
   1012 
   1013 def visitorlog(ip, referer, environ):
   1014     last = db.query('SELECT ip AS ip FROM visitors WHERE id=(SELECT MAX(id) FROM visitors)')
   1015     try:
   1016         lastip = last[0].ip
   1017     except:
   1018         lastip = 'none'
   1019     if lastip != ip:
   1020         country = ''
   1021         country = os.popen('geoiplookup '+ip).read()
   1022         #print(soundtype)
   1023         countrycode = country.split(':')[1].split(',')[0].lower().strip()
   1024         country = country.split(':')[1].split(',')[1].strip()
   1025         #print('fuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu: '+ country)
   1026         try:
   1027             db.insert('visitors', ip=ip, referer=referer, environ=environ, country=country,  countrycode=countrycode, time=datetime.datetime.now())
   1028         except:
   1029             pass
   1030         print("added to visitor log")
   1031     return
   1032 
   1033 def getvisitors():
   1034     #visitors = db.select('visitors')
   1035     visitors = db.query('SELECT * FROM visitors ORDER BY time DESC LIMIT 10000')
   1036     total = db.query('SELECT COUNT(*) AS total_visits FROM visitors')
   1037     unique = db.query('SELECT COUNT(DISTINCT ip) AS unique_visits FROM visitors')
   1038     return visitors, total[0].total_visits, unique[0].unique_visits
   1039 
   1040 def getvisits():
   1041     limit=100
   1042     visits = db.query("SELECT * FROM visitors ORDER BY time DESC LIMIT " + str(limit))
   1043     visitors = db.select('visitors')
   1044     total = db.query('SELECT COUNT(*) AS total_visits FROM visitors')
   1045     unique = db.query('SELECT COUNT(DISTINCT ip) AS unique_visits FROM visitors')
   1046     countrylist=[]
   1047     for i in visits:
   1048         if i.countrycode not in countrylist:
   1049             countrylist.append(i.countrycode)
   1050             #print('fuuuuuuuuuuuuuuu: '+i.countrycode)
   1051     return countrylist, total[0].total_visits, unique[0].unique_visits
   1052 
   1053 class stats:
   1054     def GET(self):
   1055         p = web.input(logfilter=None)
   1056         visitors, total, unique = getvisitors()
   1057         return rendersplash.stats(visitors, total, unique, p.logfilter)
   1058 
   1059 class putinbag:
   1060     def GET(self, p):
   1061         addtobag(p)
   1062         raise web.seeother('/')
   1063 
   1064 class dropitem():
   1065     def GET(self, d):
   1066         referer = web.ctx.env.get('HTTP_REFERER', 'none')
   1067         p = web.input()
   1068         i = 0
   1069         empty=dropitems(d)
   1070         if empty=='empty':
   1071             return web.seeother('/shop?#'+d)
   1072         return web.seeother(referer)
   1073 
   1074 class bigpic():
   1075     def GET(self, i):
   1076         print('faaaakyeee ' + i)
   1077         p = web.input(pic=None)
   1078         name=productname(i)
   1079         goodies = db.query("SELECT * FROM soundlink WHERE id='"+i+"';")
   1080         #if p.pic != None:
   1081         return render.bigpic(i,name,goodies)
   1082 
   1083 class checkout():
   1084     t = []
   1085     shippingcountries = db.select('shipping', what='country', order='country ASC')
   1086     shippingcountries = list(shippingcountries)
   1087     #t.append('Finland')
   1088     for i in shippingcountries:
   1089         if i.country != 'NO-SHIPPING':
   1090             t.append(i.country)
   1091     shipping = web.form.Form(
   1092     web.form.Textbox('email', web.form.notnull, description="Email:"),
   1093     web.form.Dropdown('country', t, web.form.notnull, description="Country"),
   1094     web.form.Textbox('firstname', web.form.notnull, description="First Name:"),
   1095     web.form.Textbox('lastname', web.form.notnull, description="Last Name:"),
   1096     web.form.Textbox('address', web.form.notnull, description="Shipping Address:"),
   1097     web.form.Textbox('town', web.form.notnull, description="Town / City:"),
   1098     web.form.Textbox('postalcode', web.form.notnull, description="Postalcode / zip"),
   1099     web.form.Button('Calculate shipping cost'))
   1100     email = web.form.Form(
   1101     web.form.Textbox('email', web.form.notnull, description="Email:"),
   1102     web.form.Button('Okey, lets do it!'))
   1103     def GET(self):
   1104         i = web.input(error=None)
   1105         pendinginfo = getpendinginfo()
   1106         if ordertype()=='digital':
   1107             checkoutform = self.email()
   1108             if pendinginfo:
   1109                 checkoutform.fill(email=pendinginfo.email)
   1110         if ordertype()=='physical':
   1111             checkoutform = self.shipping()
   1112             if pendinginfo:
   1113                 checkoutform.fill(country=pendinginfo.country, firstname=pendinginfo.firstname, lastname=pendinginfo.lastname, address=pendinginfo.address, town=pendinginfo.town, postalcode=pendinginfo.postalcode, email=pendinginfo.email)
   1114         errormsg=''
   1115         if i.error == 'mail':
   1116             errormsg = 'Check your mail!'
   1117         if i.error == 'shipping':
   1118             errormsg = 'Check your shipping address!'
   1119         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
   1120         return render.checkout(checkoutform,bag,productname,errormsg,db,getprice)
   1121     def POST(self):
   1122         physical=False
   1123         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
   1124         checkoutform = self.email()
   1125         for b in bag:
   1126             if b.type=='physical':
   1127                 checkoutform = self.shipping()
   1128                 physical=True
   1129                 break
   1130         errormsg=''
   1131         pendinginfo = getpendinginfo()
   1132         i = web.input()
   1133         if pendinginfo:
   1134             if physical==True:
   1135                 db.update('pending', where="invoice_key='"+session.sessionkey+"'", invoice_key=session.sessionkey, country=i.country, firstname=i.firstname, lastname=i.lastname, address=i.address, town=i.town, postalcode=str(i.postalcode), email=i.email, dateadded=datetime.datetime.now())
   1136             else:
   1137                 db.update('pending', where="invoice_key='"+session.sessionkey+"'", invoice_key=session.sessionkey, email=i.email, dateadded=datetime.datetime.now())
   1138         else:
   1139             if physical==True:
   1140                 db.insert('pending', invoice_key=session.sessionkey, country=i.country, firstname=i.firstname, lastname=i.lastname, address=i.address, town=i.town, postalcode=str(i.postalcode), email=i.email, dateadded=datetime.datetime.now())
   1141             else:
   1142                 db.insert('pending', invoice_key=session.sessionkey, email=i.email, dateadded=datetime.datetime.now())
   1143         if '@' not in i.email:
   1144             web.seeother('/checkout?error=mail')
   1145         elif not checkoutform.validates():
   1146             return web.seeother('/checkout?error=shipping')
   1147         else:
   1148             return web.seeother('/pending')
   1149 
   1150 class pending:
   1151     #form = web.form.Form(
   1152     #web.form.Dropdown('payment', ['Bitcoin Lightning', 'Bitcoin'], web.form.notnull, description="Select payment method"),
   1153     #web.form.Button('Pay'))
   1154     form = web.form.Form(
   1155     web.form.Button('Pay'))
   1156     def GET(self):
   1157         pendingform = self.form()
   1158         pendinginfo = getpendinginfo()
   1159         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
   1160         return render.pending(session.sessionkey,pendingform,pendinginfo,bag,productname,db,getprice,eur_to_sat,ordertype)
   1161     def POST(self):
   1162         pendingform = self.form()
   1163         pendinginfo = getpendinginfo()
   1164         i = web.input()
   1165 
   1166         #Calculate total amount of bag
   1167         totalamount = 0
   1168         description = ''
   1169         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
   1170         comma = ''
   1171         for s in bag:
   1172             totalamount += getprice(s.product)[0] * s.quantity
   1173             description += comma + str(s.quantity) + ' x ' + productname(s.product)
   1174             comma = ', '
   1175         if ordertype()=='physical':
   1176             shippinginfo = db.select('shipping', where="country='" + pendinginfo.country + "'", what='price, days')[0]
   1177             totalamount += eur_to_sat(shippinginfo.price)
   1178         totsats=totalamount
   1179         totbtc=totsats/100000000
   1180 
   1181         #make lightning invoice
   1182         
   1183         #print(str(totalamount) + ' | ' +  description)
   1184         #print(str(totsats) + ' | ' +  description)
   1185         #label = hashlib.sha256(str(random.getrandbits(64)).encode('utf-8')).hexdigest()[15:35]
   1186         #invoice = createinvoice(totsats, description, label)
   1187         #time.sleep(1)
   1188         
   1189         #print(invoice)
   1190         #callsubprocess('qrencode -s 3 -o '+ staticdir + 'qr/' + session.sessionkey+'.png '+invoice['bolt11'])
   1191         #make bitcoin address
   1192         #bitcoinrpc = AuthServiceProxy(rpcauth)
   1193         #newaddress = bitcoinrpc.getnewaddress('Tarina Shop Butik')
   1194         #bitcoinrpc = None
   1195         #btcuri = 'bitcoin:' + newaddress + '?amount=' + str(totbtc) + '&label=' + description
   1196         #callsubprocess('qrencode -s 5 -o '+ staticdir + 'qr/' + newaddress +'.png ' + btcuri)
   1197         #try:
   1198         #    db.query("DELETE FROM invoices WHERE invoice_key='"+session.sessionkey+"';")
   1199         #except:
   1200         #    print('no old invoices to delete')
   1201         db.insert('invoices', invoice_key=session.sessionkey, products=description, amount=totalamount, totsats=totsats, status='unpaid', timestamp=time.strftime('%Y-%m-%d %H:%M:%S'))
   1202         msg="sup Robin? wowoweewaa! someone made an order."
   1203         sendmail('me@robinbackman.com', 'A message from Robins webshop', msg)
   1204         return web.seeother('/paymobile/' + session.sessionkey)
   1205 
   1206 class paymobile:
   1207     def GET(self, invoice_key):
   1208         digitalkey = None
   1209         invoice = db.select('invoices', where="invoice_key='"+invoice_key+"'")[0]
   1210         lninvoice=''
   1211         #lninvoice = getinvoice(invoice['ln'])
   1212         if invoice.status == 'paid' and session.sessionkey != 'empty':
   1213             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
   1214             customer = db.select('pending', where="invoice_key='"+invoice_key+"'")[0]
   1215             db.query("INSERT INTO paidbags SELECT * FROM customerbag WHERE sessionkey='" + invoice_key + "'")
   1216             db.query("DELETE FROM customerbag WHERE sessionkey='" + invoice_key + "'")
   1217             db.update("invoices",where='invoice_key="'+invoice_key+'"', status='paid')
   1218             digitalkey=hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[15:35]
   1219             db.insert('digitalkey', invoice_key=invoice_key, digitalkey=digitalkey, email=customer.email)
   1220             session.sessionkey = 'empty'
   1221             # send mail to op
   1222             if ordertype()=='physical':
   1223                 msg = 'You got a new order, from ' + customer.firstname + ' ' + customer.lastname + ' from ' + customer.country + ' email: ' + customer.email + ' this dude wantz ' + invoice.products
   1224             else:
   1225                 msg='sup?'
   1226             sendmail(webmaster, 'Robs Shop', msg)
   1227             # send mail to customer
   1228             if ordertype()=='physical':
   1229                 msg = "Thank you for order " + invoice.products + " at Robins webshop, we'll be processing your order as soon as possible and send it to " + customer.firstname + ' ' + customer.lastname + ', ' + customer.address + ', ' + str(customer.postalcode) + ', ' + customer.town + ', ' + customer.country + '. To pay/view status or take a look at the digital goodies of your order please visit ' + baseurl + '/goodies/'+digitalkey
   1230             else:
   1231                 msg="sup? thanks! here's a link to the digital goodies "+baseurl+'/goodies/'+digitalkey
   1232             sendmail(customer.email, 'A message from Robins webshop', msg)
   1233             web.seeother('/paymobile/'+invoice_key)
   1234         elif invoice.status == 'paid':
   1235             bag = db.query("SELECT * FROM paidbags WHERE sessionkey='"+invoice_key+"';")
   1236             digitalkey = db.select('digitalkey', where="invoice_key='"+invoice_key+"'")[0]
   1237         elif invoice.status != 'paid':
   1238             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
   1239         pendinginfo = getpendinginfo()
   1240         return render.paymobile(lninvoice,invoice,bag,productname,digitalkey,db,getprice,getrate,ordertype,pendinginfo,eur_to_sat)
   1241 
   1242 class payln:
   1243     def GET(self, invoice_key):
   1244         digitalkey = None
   1245         invoice = db.select('invoices', where="invoice_key='"+invoice_key+"'")[0]
   1246         lninvoice = getinvoice(invoice['ln'])
   1247         if lninvoice['status'] == 'paid' and session.sessionkey != 'empty':
   1248             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
   1249             customer = db.select('pending', where="invoice_key='"+invoice_key+"'")[0]
   1250             db.query("INSERT INTO paidbags SELECT * FROM customerbag WHERE sessionkey='" + invoice_key + "'")
   1251             db.query("DELETE FROM customerbag WHERE sessionkey='" + invoice_key + "'")
   1252             db.update("invoices",where='invoice_key="'+invoice_key+'"', status='paid')
   1253             digitalkey=hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[15:35]
   1254             db.insert('digitalkey', invoice_key=invoice_key, digitalkey=digitalkey, email=customer.email)
   1255             session.sessionkey = 'empty'
   1256             # send mail to op
   1257             if ordertype()=='physical':
   1258                 msg = 'You got a new order, from ' + customer.firstname + ' ' + customer.lastname + ' from ' + customer.country + ' email: ' + customer.email + ' this dude wantz ' + lninvoice['description']
   1259             else:
   1260                 msg='sup?'
   1261             sendmail(webmaster, 'Robs Shop', msg)
   1262             # send mail to customer
   1263             if ordertype()=='physical':
   1264                 msg = "Thank you for order " + lninvoice['description'] + " at Robins webshop, we'll be processing your order as soon as possible and send it to " + customer.firstname + ' ' + customer.lastname + ', ' + customer.address + ', ' + str(customer.postalcode) + ', ' + customer.town + ', ' + customer.country + '. To pay/view status or take a look at the digital goodies of your order please visit ' + baseurl + '/goodies/'+digitalkey
   1265             else:
   1266                 msg="sup? thanks! here's a link to the digital goodies "+baseurl+'/goodies/'+digitalkey
   1267             sendmail(customer.email, 'A message from Robins webshop', msg)
   1268             web.seeother('/payln/'+invoice_key)
   1269         if lninvoice['status'] == 'paid':
   1270             bag = db.query("SELECT * FROM paidbags WHERE sessionkey='"+invoice_key+"';")
   1271             digitalkey = db.select('digitalkey', where="invoice_key='"+invoice_key+"'")[0]
   1272         if lninvoice['status'] != 'paid':
   1273             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
   1274         pendinginfo = getpendinginfo()
   1275         return render.payln(lninvoice,invoice,bag,productname,digitalkey,db,getprice,getrate,ordertype,pendinginfo,eur_to_sat)
   1276 
   1277 class goodies():
   1278     def GET(self, digitalkey):
   1279         digitalkey = db.select('digitalkey', where="digitalkey='"+digitalkey+"'")[0]
   1280         #digitalkeys = db.select('digitalkey', where="email='"+digitalkey.email+"'")
   1281         digitalkeys = db.query("SELECT * FROM digitalkey WHERE email='"+digitalkey.email+"' ORDER BY timeadded DESC;")
   1282         return render.goodies(digitalkey,digitalkeys,productname,db,getprice)
   1283         #check all puraches with same email fuck ye
   1284 
   1285 class paybtc:
   1286     def GET(self, invoice_key):
   1287         invoice = db.select('invoices', where="invoice_key='" + invoice_key + "'", what='invoice_key, btc, ln, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped')[0]
   1288         totbtc = float(invoice.totsats * 0.00000001)
   1289         btcaddress = invoice.btc
   1290         btcuri = 'bitcoin:' + btcaddress + '?amount=' + str(totbtc) + '&label=' + invoice.products
   1291         bitcoinrpc = AuthServiceProxy(rpcauth)
   1292         showpayment = bitcoinrpc.listreceivedbyaddress(0, True, True, btcaddress)
   1293         bitcoinrpc = None
   1294         if showpayment:
   1295             for i in showpayment:
   1296                 confirmations = int(i['confirmations'])
   1297                 print(str(confirmations))
   1298             if invoice.datepaid == None and confirmations > 6:
   1299                 msg = 'Robins webshop order update! someone sent you Bitcoin! ' + baseurl + '/paybtc/' + invoice.invoice_key
   1300                 print(msg)
   1301                 sendmail(webmaster, 'Robs Shop', msg)
   1302                 db.update('invoices', where="invoice_key='" + invoice.invoice_key + "'", status='paid', datepaid=time.strftime('%Y-%m-%d %H:%M:%S'))
   1303         pendinginfo = getpendinginfo()
   1304         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
   1305         return render.paybtc(invoice, btcaddress, btcuri, showpayment, bag, productname, db, getprice, getrate, ordertype, pendinginfo, eur_to_sat)
   1306 
   1307 class orders():
   1308     def GET(self):
   1309         if logged():
   1310             referer = web.ctx.env.get('HTTP_REFERER', 'none')
   1311             listpayments=[]
   1312             i=web.input(key=None,status=None)
   1313             if i.key != None and i.status != None:
   1314                 db.update('invoices', where="invoice_key='" + i.key + "'", status=i.status)
   1315                 #get the right invoice send mail
   1316                 customer = db.select('pending', where="invoice_key='" + i.key + "'", what='country, firstname, lastname, address, town, postalcode, email')[0]
   1317                 payment = db.select('invoices', where="invoice_key='" + i.key + "'", what='btc, ln, invoice_key, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped')[0]
   1318                 if payment.payment == 'Bitcoin':
   1319                     paylink = 'paybtc/'
   1320                 elif payment.payment == 'Bitcoin Lightning':
   1321                     paylink = 'payln/'
   1322                 elif payment.payment == 'Mobile Pay':
   1323                     paylink = 'paymobile/'
   1324                 if i.status == 'thankyou':
   1325                     msg="Hi " + customer.email + ", thank you for your order! You can track the status of your order at "+baseurl+'/'+paylink+i.key
   1326                     sendmail(customer.email, 'Robs Shop, a thank you!', msg)
   1327                 elif i.status == 'shipped':
   1328                     digitalkey = db.query("SELECT * FROM digitalkey WHERE email='"+customer.email+"' ORDER BY timeadded ASC;")[0]
   1329                     # send mail to customer
   1330                     try:
   1331                         msg = "Your order at Robins webshop has been shipped to " + customer.firstname + ' ' + customer.lastname + ', ' + customer.address + ', ' + str(customer.postalcode) + ', ' + customer.town + ', ' + customer.country + '. To pay/view status or take a look at the digital goodies of your order please visit ' + baseurl + '/goodies/'+digitalkey.digitalkey
   1332                     except:
   1333                         msg = "Hi " + customer.email + ". To pay/view status or take a look at the digital goodies of your order please visit " + baseurl + '/goodies/'+digitalkey.digitalkey
   1334                     sendmail(customer.email, 'Rob Shop, your order has been shipped!', msg)
   1335                 elif i.status == 'paynotice':
   1336                     msg="Hi " + customer.email + ", we noticed you have an unpaid order in our shop, thank you. You can track the status of your order at " + baseurl + paylink + payment.invoice_key
   1337                     sendmail(customer.email, 'Rob Shop, order waiting for payment!', msg)
   1338                 elif i.status == 'paid':
   1339                     digitalkey = db.query("SELECT * FROM digitalkey WHERE email='"+customer.email+"' ORDER BY timeadded ASC;")[0]
   1340                     # send mail to customer
   1341                     msg="Hi " + customer.email + ", thank you! payment received. You can track the status of your order and view the status or take a look at the digital goodies of your order at " + baseurl + '/goodies/'+digitalkey.digitalkey
   1342                     sendmail(customer.email, 'Rob Shop, order payment received', msg)
   1343                 raise web.seeother(referer)
   1344             payments = db.select('invoices', what='btc, ln, invoice_key, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped', order='timestamp DESC')
   1345             if i.key == None and i.status != None:
   1346                 status = i.status
   1347             else:
   1348                 status = ''
   1349             totsats = 0
   1350             paid = 0
   1351             unpaid = 0
   1352             shipped = 0
   1353             nonshipped = 0
   1354             pickup = 0
   1355             removed=0
   1356             thankyou=0
   1357             for i in payments:
   1358                 if i.status == 'paid':
   1359                     paid=paid+1
   1360                     nonshipped=nonshipped+1
   1361                 elif i.status == 'unpaid':
   1362                     unpaid=unpaid+1
   1363                     nonshipped=nonshipped+1
   1364                 elif i.status == 'shipped':
   1365                     shipped=shipped+1
   1366                 elif i.status == 'paid':
   1367                     nonshipped=nonshipped+1
   1368                 elif i.status == 'pickup':
   1369                     pickup=pickup+1
   1370                 elif i.status == "removed":
   1371                     removed=removed+1
   1372                 elif i.status != "thankyou":
   1373                     thankyou=thankyou+1
   1374             payments = db.select('invoices', order='timestamp DESC')
   1375             return renderop.orders(payments,db,getinvoice,totsats,status,paid,unpaid,shipped,nonshipped,pickup,removed,thankyou,productname,getprice)
   1376         else:
   1377             raise web.seeother('/login')
   1378 
   1379 class ordersbtcold():
   1380     def GET(self):
   1381         referer = web.ctx.env.get('HTTP_REFERER', 'none')
   1382         listpayments=[]
   1383         i=web.input(key=None,status=None)
   1384         if i.key != None and i.status != None:
   1385             db.update('invoices', where="invoice_key='" + i.key + "'", status=i.status)
   1386             #get the right invoice send mail
   1387             customer = db.select('pending', where="invoice_key='" + i.key + "'", what='country, firstname, lastname, address, town, postalcode, email')[0]
   1388             payment = db.select('invoices', where="invoice_key='" + i.key + "'", what='btc, ln, invoice_key, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped')[0]
   1389             if payment.payment == 'Bitcoin':
   1390                 paylink = 'paybtc/'
   1391             elif payment.payment == 'Bitcoin Lightning':
   1392                 paylink = 'payln/'
   1393             if i.status == 'thankyou':
   1394                 msg="Hi " + customer.email + ", thank you for your order! You can track the status of your order at "+baseurl+'/'+paylink+i.key
   1395                 sendmail(customer.email, 'Robs Shop, a thank you!', msg)
   1396             elif i.status == 'shipped':
   1397                 msg="Hi " + customer.email + ", your order has been shipped!. You can track the status of your order at "+baseurl+'/'+paylink+i.key
   1398                 sendmail(customer.email, 'Rob Shop, your order has been shipped!', msg)
   1399             elif i.status == 'paynotice':
   1400                 msg="Hi " + customer.email + ", we noticed you have an unpaid order in our shop, thank you. You can track the status of your order at " + baseurl + paylink + payment.invoice_key
   1401                 sendmail(customer.email, 'Rob Shop, order waiting for payment!', msg)
   1402             elif i.status == 'paid':
   1403                 msg="Hi " + customer.email + ", thank you! payment received. You can track the status of your order at " + baseurl + paylink + payment.invoice_key
   1404                 sendmail(customer.email, 'Rob Shop, order payment received', msg)
   1405             raise web.seeother(referer)
   1406         payments = db.select('invoices', what='btc, ln, invoice_key, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped', order='timestamp DESC')
   1407         if i.key == None and i.status != None:
   1408             status = i.status
   1409         else:
   1410             status = ''
   1411         totsats = 0
   1412         paid = 0
   1413         unpaid = 0
   1414         shipped = 0
   1415         nonshipped = 0
   1416         pickup = 0
   1417         removed=0
   1418         for i in payments:
   1419             ln = getinvoice(i.ln)
   1420             print(ln)
   1421             if ln['status'] == 'paid':
   1422                 totsats=totsats+ln['amount_msat']
   1423                 paid=paid+1
   1424                 s = db.select('invoices', where="invoice_key='"+i.invoice_key+"'", what='status')[0]
   1425                 if s.status == None:
   1426                     db.update('invoices', where="invoice_key='"+i.invoice_key+"'", status='paid', datepaid=time.strftime('%Y-%m-%d %H:%M:%S'))
   1427                 if i.status == 'shipped':
   1428                     shipped=shipped+1
   1429                 if i.status == 'paid':
   1430                     nonshipped=nonshipped+1
   1431                 if i.status == 'pickup':
   1432                     pickup=pickup+1
   1433                 if i.status == "removed":
   1434                     removed=removed+1
   1435             else:
   1436                 s = db.select('invoices', where="invoice_key='"+i.invoice_key+"'", what='status')[0]
   1437                 if s.status == None:
   1438                     db.update('invoices', where="invoice_key='"+i.invoice_key+"'", status='unpaid', datepaid=time.strftime('%Y-%m-%d %H:%M:%S'))
   1439                 if i.status != "removed":
   1440                     unpaid=unpaid+1
   1441                 if i.status == "removed":
   1442                     removed=removed+1
   1443         payments = db.select('invoices', order='timestamp DESC')
   1444         return renderop.orders(payments,db,getinvoice,totsats,status,paid,unpaid,shipped,nonshipped,pickup,removed,productname,getprice)
   1445 
   1446 class payment:
   1447     def GET(self, invoice_key):
   1448         id = db.where('invoices', invoice_key=invoice_key)[0]['ln']
   1449         invoice = getinvoice(id)
   1450         return render.payment(invoice)
   1451 
   1452 class thankyou:
   1453     def GET(self, id):
   1454         return render.thankyou(id)
   1455 
   1456 class loginold:
   1457     form = web.form.Form(
   1458     web.form.Textbox('user', web.form.notnull, description="User"),
   1459     web.form.Password('password', web.form.notnull, description="Passcode"),
   1460     web.form.Button('Login'))
   1461     def GET(self):
   1462         if not logged():
   1463             loginform = self.form()
   1464             return render.login(loginform)
   1465         else:
   1466             raise web.seeother('/op')
   1467     def POST(self):
   1468         loginform = self.form()
   1469         if not loginform.validates():
   1470             return render.login(loginform)
   1471         else:
   1472             i = web.input()
   1473             if (i.user,i.password) in allowed:
   1474                 session.login = 1
   1475                 raise web.seeother('/op')
   1476             else:
   1477                 return render.login(loginform)
   1478 
   1479 class logout:
   1480     def GET(self):
   1481         session.login = 0
   1482         session.user = None
   1483         raise web.seeother('/heartranked')
   1484 
   1485 class op:
   1486     def GET(self):
   1487         if logged():
   1488             return renderop.operator()
   1489         else:
   1490             raise web.seeother('/login')
   1491 
   1492 class propaganda:
   1493     form = web.form.Form(
   1494     web.form.Textbox('name', web.form.notnull, description="site name"),
   1495     web.form.Textarea('description', web.form.notnull, description="write here"),
   1496     web.form.Textarea('description2', web.form.notnull, description="write more here"),
   1497     web.form.Button('Save'))
   1498     picform = web.form.Form(
   1499     web.form.Textbox('name', web.form.notnull, description="upload images"),
   1500     web.form.Textarea('description', web.form.notnull, description="write even more here"),
   1501     web.form.Textarea('description2', web.form.notnull, description="write even here more"),
   1502     web.form.Textarea('id', web.form.notnull, description="id:"),
   1503     web.form.Button('Save'))
   1504     def GET(self):
   1505         if logged():
   1506             i = web.input(cmd=None,soundname=None)
   1507             nocache = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[11:15]
   1508             story = None
   1509             if i.cmd == 'remove' and i.soundname != None:
   1510                 try:
   1511                     os.remove(staticdir+'/img/thumb/'+i.soundname)
   1512                     os.remove(staticdir+'/img/web/'+i.soundname)
   1513                 except:
   1514                     print('notin to delete')
   1515                 goodies = db.query("DELETE FROM propagandapics WHERE soundname='"+i.soundname+"';")
   1516                 raise web.seeother('/propaganda')
   1517             elif i.cmd == 'flipright' and i.soundname != None:
   1518                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
   1519                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
   1520                 o_thumb=original_thumb.rotate(270)
   1521                 o_web=original_web.rotate(270)
   1522                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
   1523                 o_web.save(staticdir+'/img/web/'+i.soundname)
   1524                 raise web.seeother('/propaganda')
   1525             elif i.cmd == 'flipleft' and i.soundname != None:
   1526                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
   1527                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
   1528                 o_thumb=original_thumb.rotate(90)
   1529                 o_web=original_web.rotate(90)
   1530                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
   1531                 o_web.save(staticdir+'/img/web/'+i.soundname)
   1532                 raise web.seeother('/propaganda')
   1533             elif i.soundname != None:
   1534                 story = db.query("SELECT * FROM propagandapics WHERE soundlink='"+i.soundname+"';")
   1535             goodies = db.query("SELECT * FROM propagandapics;")
   1536             configsite = self.form()
   1537             picturetext = self.picform()
   1538             try:
   1539                 oldsiteconfig = db.select('propaganda', what='id, name, description, description2')[0]
   1540                 configsite.fill(name=oldsiteconfig.name, description=oldsiteconfig.description, description2=oldsiteconfig.description2)
   1541             except:
   1542                 print('no non no')
   1543             bilder_totalt = db.query("SELECT COUNT(*) AS stories FROM propagandapics")[0]
   1544             return renderop.propaganda(configsite, picturetext, goodies, nocache, story)
   1545         else:
   1546             raise web.seeother('/login')
   1547     def POST(self):
   1548         addcategory = self.form()
   1549         i = web.input(imgfile={}, name=None, id=None)
   1550         if i.id != None:
   1551             db.update('propagandapics', where='soundlink="'+i.id+'"', name=i.name, description=i.description, description2=i.description2, soundlink=i.id)
   1552             raise web.seeother('/propaganda')
   1553         if i.name != None:
   1554             #db.insert('propaganda', name=i.name, description=i.description, description2=i.description2 )
   1555             db.update('propaganda', where='id=1', name=i.name, description=i.description, description2=i.description2 )
   1556         if i.imgfile != {}:
   1557             if i.imgfile.filename == '':
   1558                 print('hmmm... no image to upload')
   1559                 raise web.seeother('/config/')
   1560             print('YEAH, Upload image!')
   1561             ##---------- UPLOAD IMAGE ----------
   1562             filepath=i.imgfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
   1563             #split and only take the filename with extension
   1564             #soundpath=filepath.split('/')[-1]
   1565             #if soundpath == '':
   1566             #    return render.nope("strange, no filename found!")
   1567             #get filetype, last three 
   1568             imgname=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
   1569             filetype = imgname.split('.')[-1].lower()
   1570             if filetype == 'jpg':
   1571                 filetype = 'jpeg'
   1572             soundname = imgname.split('.')[0]
   1573             #lets remove unwanted characters yes please!
   1574             sound = ''
   1575             for p in soundname.lower():
   1576                 if p in allowedchar:
   1577                     sound = sound + p
   1578             if sound == '':
   1579                 raise web.seeother('/upload?fail=wierdname')
   1580             soundname = sound + '_Gonzo_Pi.' + filetype
   1581             print(soundname)
   1582             print("filename is " + imgname + " filetype is " + filetype + " soundname is " + soundname + " trying to upload file from: " + filepath)
   1583             #if filetype != 'wav' or 'ogg' or 'flac' or 'jpeg' or 'jpg' or 'mp3':
   1584             #    web.seeother('/upload?fail=notsupported')
   1585             #imghash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
   1586             #imgname = imghash
   1587             #imgname = str(len(os.listdir(imgdir))).zfill(3) + '.jpeg'
   1588             soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   1589             imgdir = staticdir+'upload/'+soundlink+'/'
   1590             os.system('mkdir -p ' + imgdir)
   1591             fout = open(imgdir + soundname,'wb') # creates the file where the uploaded file should be stored
   1592             fout.write(i.imgfile.file.read()) # writes the uploaded file to the newly created file.
   1593             fout.close() # closes the file, upload complete. 
   1594             db.insert('propagandapics', soundlink=soundlink, soundname=soundname, name='', description='', description2='',timeadded=datetime.datetime.now())
   1595             if filetype == 'jpeg' or filetype == 'png':
   1596                 ##---------- OPEN FILE & CHEKC IF JPEG --------
   1597                 image = Image.open(imgdir + soundname)
   1598                 #if image.format != 'JPEG':
   1599                 #    os.remove(imgdir +'/'+ soundname)
   1600                 #    raise web.seeother('/products/' + idvalue)
   1601 
   1602                 ##---------- RESIZE IMAGE SAVE TO PRODUCT-----------
   1603                 imgdir=staticdir+'img'
   1604                 try:
   1605                     os.makedirs(imgdir + '/web/', exist_ok=True)
   1606                     os.makedirs(imgdir + '/thumb/', exist_ok=True)
   1607                 except:
   1608                     print('Folders is')
   1609                 image.resize((1500,1500), Image.LANCZOS)
   1610                 image.save(imgdir + '/web/'+soundname)
   1611                 image.resize((500,500), Image.LANCZOS)
   1612                 image.save(imgdir + '/thumb/'+soundname) 
   1613         raise web.seeother('/propaganda')
   1614 
   1615 def word_break(text: str, width: int = 140) -> str:
   1616     """
   1617     Breaks text into lines at word boundaries, with max line length = width.
   1618     Returns a single string with '\n' inserted.
   1619     """
   1620     if not text:
   1621         return ""
   1622     
   1623     words = text.split()
   1624     if not words:
   1625         return ""
   1626     
   1627     lines = []
   1628     current_line = []
   1629     current_length = 0
   1630     
   1631     for word in words:
   1632         # Length if we add this word (+ space if not first word in line)
   1633         word_len = len(word)
   1634         if current_line:
   1635             added_len = word_len + 1  # +1 for space
   1636         else:
   1637             added_len = word_len
   1638         
   1639         if current_length + added_len > width:
   1640             # Finish current line and start new one
   1641             lines.append(" ".join(current_line))
   1642             current_line = [word]
   1643             current_length = word_len
   1644         else:
   1645             current_line.append(word)
   1646             current_length += added_len
   1647     
   1648     # Don't forget the last line
   1649     if current_line:
   1650         lines.append(" ".join(current_line))
   1651     
   1652     return "\n".join(lines)
   1653 
   1654 def getlikes(postid, user):
   1655     user_likes = False
   1656     l = db.query("SELECT Count(*) AS likes FROM likes WHERE bild='"+postid+"';")[0]
   1657     db.update('published', where='soundlink="'+postid+'"', hearts=l.likes)
   1658     if user:
   1659         m = db.query("SELECT * FROM likes WHERE bild='"+postid+"' AND user='"+user+"';")
   1660         if m:
   1661             user_likes = True
   1662         else:
   1663             user_likes = False
   1664     if l.likes >= 0:
   1665         if user_likes: 
   1666             likes = "❤️ " + str(l.likes)
   1667         else: 
   1668             if l.likes > 0:
   1669                 likes = "🤍 " + str(l.likes)
   1670             else:
   1671                 likes = "🤍 "
   1672         return likes
   1673 
   1674 def postexist(postid):
   1675     return False
   1676     try:
   1677         l = db.select('published', where="soundlink='"+postid+"'")[0]
   1678     except:
   1679         return False
   1680     try:
   1681         if l.soundname != None:
   1682             return True
   1683         else:
   1684             return False
   1685     except:
   1686         return False
   1687     return False
   1688 
   1689 def getcombines(postid):
   1690     l = db.query("SELECT Count(*) AS combines FROM published WHERE combine='"+postid+"';")[0]
   1691     #m = db.query("SELECT * FROM likes WHERE bild='"+postid+"' AND user='"+user+"';")
   1692     #db.update('published', where='soundlink="'+postid+'"', combines=0)
   1693     if l.combines > 0:
   1694             return "⚭ " + str(l.combines)
   1695     else:
   1696         return ''
   1697 
   1698 def pushcombines(postid):
   1699     l = db.query("SELECT Count(*) AS combines FROM published WHERE soundlink='"+postid+"';")[0]
   1700     #m = db.query("SELECT * FROM likes WHERE bild='"+postid+"' AND user='"+user+"';")
   1701     db.update('published', where='soundlink="'+postid+'"', combines=l.combines)
   1702     if l.combines >= 0:
   1703             return "⚭ " + str(l.combines)
   1704     else:
   1705         return ''
   1706 
   1707 def formattime(timeadded):
   1708     return timeadded.strftime("%Y-%m-%d %H:%M:%S")
   1709 
   1710 def getfeed():
   1711     timebase=session.timebase
   1712     feedbase=session.feedbase
   1713     if feedbase == '':
   1714         feedbase = 'time'
   1715     now = datetime.datetime.now()
   1716     #HEARTS
   1717     if feedbase == "heart" and timebase == "today":
   1718         now = datetime.datetime.now()
   1719         one_day_before = now - datetime.timedelta(days=1)
   1720         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1721         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1722         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY hearts DESC LIMIT 1000;")
   1723     elif feedbase == "heart" and timebase == "week":
   1724         now = datetime.datetime.now()
   1725         one_day_before = now - datetime.timedelta(weeks=1)
   1726         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1727         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1728         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY hearts DESC LIMIT 1000;")
   1729     elif feedbase == "heart" and timebase == "month":
   1730         now = datetime.datetime.now()
   1731         one_day_before = now - datetime.timedelta(weeks=4)
   1732         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1733         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1734         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY hearts DESC LIMIT 1000;")
   1735     elif feedbase == "heart" and timebase == "year":
   1736         now = datetime.datetime.now()
   1737         one_day_before = now - datetime.timedelta(weeks=54)
   1738         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1739         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1740         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY hearts DESC LIMIT 1000;")
   1741     elif feedbase == "heart" and timebase == "" or feedbase == "heart" and timebase == "all":
   1742         goodies = db.query("SELECT * FROM published ORDER BY hearts DESC LIMIT 1000;")
   1743     #TIME
   1744     elif feedbase == "time" and timebase == "today":
   1745         one_day_before = now - datetime.timedelta(days=1)
   1746         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1747         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1748         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY ID DESC LIMIT 1000;")
   1749     elif feedbase == "time" and timebase == "week":
   1750         now = datetime.datetime.now()
   1751         one_day_before = now - datetime.timedelta(weeks=1)
   1752         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1753         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1754         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY ID DESC LIMIT 1000;")
   1755     elif feedbase == "time" and timebase == "month":
   1756         now = datetime.datetime.now()
   1757         one_day_before = now - datetime.timedelta(weeks=4)
   1758         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1759         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1760         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY ID DESC LIMIT 1000;")
   1761     elif feedbase == "time" and timebase == "year":
   1762         now = datetime.datetime.now()
   1763         one_day_before = now - datetime.timedelta(weeks=54)
   1764         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1765         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1766         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY ID DESC LIMIT 1000;")
   1767     elif feedbase == "time" and timebase == "" or  feedbase == "time" and timebase == "all":
   1768         goodies = db.query("SELECT * FROM published ORDER BY ID DESC LIMIT 1000;")
   1769     #COMBO
   1770     elif feedbase == "combo" and timebase == "today":
   1771         one_day_before = now - datetime.timedelta(days=1)
   1772         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1773         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1774         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY combines DESC LIMIT 1000;")
   1775     elif feedbase == "combo" and timebase == "week":
   1776         now = datetime.datetime.now()
   1777         one_day_before = now - datetime.timedelta(weeks=1)
   1778         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1779         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1780         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY combines DESC LIMIT 1000;")
   1781     elif feedbase == "combo" and timebase == "month":
   1782         now = datetime.datetime.now()
   1783         one_day_before = now - datetime.timedelta(weeks=4)
   1784         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1785         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1786         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY combines DESC LIMIT 1000;")
   1787     elif feedbase == "combo" and timebase == "year":
   1788         now = datetime.datetime.now()
   1789         one_day_before = now - datetime.timedelta(weeks=54)
   1790         now = now.strftime('%Y-%m-%d %H:%M:%S')
   1791         one_day_before=one_day_before.strftime('%Y-%m-%d %H:%M:%S')
   1792         goodies = db.query("SELECT * FROM published WHERE timeadded BETWEEN '"+one_day_before+"' AND '"+now+"' ORDER BY combines DESC LIMIT 1000;")
   1793     elif feedbase == "combo" and timebase == "" or  feedbase == "combo" and timebase == "all":
   1794         goodies = db.query("SELECT * FROM published ORDER BY combines DESC LIMIT 1000;")
   1795     elif feedbase == "Idontevenknow":
   1796         goodies = db.query("SELECT * FROM published ORDER BY combines DESC LIMIT 1000;")
   1797     else:
   1798         goodies = db.query("SELECT * FROM published ORDER BY ID DESC LIMIT 1000;")
   1799     return goodies
   1800 
   1801 def getcombofeed(show):
   1802     timebase=session.timebase
   1803     feedbase=session.feedbase
   1804     if feedbase == "heart":
   1805         comboposts = db.query("SELECT * FROM published WHERE combine='"+show+"' ORDER BY hearts DESC LIMIT 1000;")
   1806     elif feedbase == "combo":
   1807         comboposts = db.query("SELECT * FROM published WHERE combine='"+show+"' ORDER BY combines DESC LIMIT 1000;")
   1808     elif feedbase == "idontknow":
   1809         comboposts = db.query("SELECT * FROM published WHERE combine='"+show+"' ORDER BY hearts DESC LIMIT 1000;")
   1810     else:
   1811         comboposts = db.query("SELECT * FROM published WHERE combine='"+show+"' ORDER BY ID DESC LIMIT 1000;")
   1812     return comboposts
   1813 
   1814 def userimage(user):
   1815     usrimg = ''
   1816     i = staticdir+'users/'+user+'/images/thumb/'+user
   1817     print(i)
   1818     if os.path.isfile(i+'.jpeg'):
   1819         usrimg='/static/users/'+user+'/images/thumb/'+user+'.jpeg'
   1820     elif os.path.isfile(i+'.jpg'):
   1821         usrimg='/static/users/'+user+'/images/thumb/'+user+'.jpg'
   1822     elif os.path.isfile(i+'.png'):
   1823         usrimg='/static/users/'+user+'/images/thumb/'+user+'.png'
   1824     elif os.path.isfile(i+'.gif'):
   1825         usrimg='/static/users/'+user+'/images/thumb/'+user+'.gif'
   1826     if usrimg != '':
   1827         imghtml='<img class="usrimg" src="'+usrimg+'">'
   1828         return imghtml
   1829     else:
   1830         print('FUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU')
   1831         return 
   1832 
   1833 class heartranked:
   1834     form = web.form.Form(web.form.Textbox('search', web.form.notnull, description="or search"))
   1835     def GET(self):
   1836         searchform = self.form()
   1837         bildpersida = 1000
   1838         session.search = ''
   1839         session.bildsida = 0
   1840         i = web.input(publised=None, public=None, show=None, remove=None, edit=None, feedbase=None, timebase=None)
   1841         #search
   1842         try:
   1843             bilder_totalt = db.query("SELECT COUNT(*) AS sound FROM published")[0]
   1844             tot = int(bilder_totalt.sound)
   1845             print('bilder alltsomallt: ' + str(tot))
   1846         except:
   1847             print("inga bilder")
   1848             tot = 0
   1849         #print('session search: ' + session.search)
   1850         try:
   1851             if i.search == '':
   1852                 session.search = ''
   1853                 session.bildsida = 0
   1854             elif i.search != "":
   1855                 session.search = urllib.parse.unquote_plus(i.search)
   1856                 session.bildsida = 0
   1857         except:
   1858             pass
   1859         if session.search != '':
   1860             search_result = []
   1861             tot = 0
   1862             b1, b2, b3 = 0,0,0
   1863             try:
   1864                 search_result.append(db.query("SELECT * FROM published WHERE creator LIKE '%"+session.search+"%' ORDER BY ID DESC LIMIT 1000;"))
   1865                 tot = db.query("SELECT Count(*) AS sound FROM published WHERE creator LIKE '%"+session.search+"%';")[0]
   1866                 b1 = tot.sound
   1867             except:
   1868                 pass
   1869             try:
   1870                 search_result.append(db.query("SELECT * FROM published WHERE description LIKE '%"+session.search+"%' ORDER BY ID DESC LIMIT 1000;"))
   1871                 tot = db.query("SELECT Count(*) AS sound FROM published WHERE description LIKE '%"+session.search+"%';")[0]
   1872                 b2 = tot.sound
   1873             except:
   1874                 pass
   1875             try:
   1876                 search_result.append(db.query("SELECT * FROM published WHERE description2 LIKE '%"+session.search+"%' ORDER BY ID DESC LIMIT 1000;"))
   1877                 tot = db.query("SELECT Count(*) AS sound FROM published WHERE description2 LIKE '%"+session.search+"%';")[0]
   1878                 b3 = tot.sound
   1879             except:
   1880                 pass
   1881             tot = b1 + b2 + b3
   1882             try:
   1883                 print(search_result)
   1884                 print('sökta bilder: ' + str(tot))
   1885             except:
   1886                 pass
   1887         try:
   1888             if i.page == "next":
   1889                 if session.bildsida < tot:
   1890                     session.bildsida += bildpersida
   1891             if i.page == "back":
   1892                 if session.bildsida > bildpersida:
   1893                     session.bildsida -= bildpersida
   1894                 else:
   1895                     session.bildsida = 0
   1896         except:
   1897             pass
   1898         limit = session.bildsida + bildpersida
   1899         offset = session.bildsida
   1900         #EOF search
   1901         print(session.bildsida)
   1902         if session.search == '':
   1903             bilder = db.query("SELECT * FROM published ORDER BY id DESC LIMIT " + str(limit) + " OFFSET " + str(offset))
   1904         else:
   1905             bilder = search_result
   1906         if i.feedbase == None:
   1907             feedbase = ''
   1908         else:
   1909             feedbase = i.feedbase
   1910             session.feedbase = feedbase
   1911         if i.timebase == None:
   1912             timebase = ''
   1913         else:
   1914             timebase = i.timebase
   1915             session.timebase = timebase
   1916         if session.user=='':
   1917             free_hash_for_user = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[:4]
   1918             #session.user = 'rocker_'+free_hash_for_user
   1919             session.user = None
   1920         ip = web.ctx['ip']
   1921         referer = web.ctx.env.get('HTTP_REFERER', 'none')
   1922         environ = web.ctx.env.get('HTTP_USER_AGENT', 'dunno')
   1923         visitorlog(ip,referer,environ)
   1924         visitors, total, unique = getvisits()
   1925         if i.edit != None:
   1926             session.soundlink=i.edit
   1927             raise web.seeother('/editor?public=yes') 
   1928         if i.remove != None:
   1929             try:
   1930                 user = db.select('published', where="soundlink='"+i.remove+"'")[0]
   1931             except:
   1932                 pass
   1933             try:
   1934                 user = user.creator
   1935             except:
   1936                 user = ''
   1937             if user == session.user:
   1938                 db.query("INSERT INTO deleted SELECT * FROM published WHERE soundlink = '"+i.remove+"'")
   1939                 db.delete('published', where='soundlink="' + i.remove + '"')
   1940                 #db.query("DELETE * FROM published WHERE soundlink ="+i.remove)
   1941         if session.login > 3:
   1942             try:
   1943                 if i.delete != '':
   1944                     return web.seeother('/remove/' + i.delete)
   1945             except:
   1946                 pass
   1947             rights = 'admin'
   1948         elif session.login > 2:
   1949             rights = 'mod'
   1950         else:
   1951             rights = 'spacer'
   1952         return rendersplash.heartranked(db,markdown, visitors, total, unique, i.show, logged(), rights, session.user, getlikes, formattime, feedbase, tot, limit, offset, bildpersida, session.search, bilder, searchform, getcombines, timebase, getfeed, getcombofeed, userimage, postexist)
   1953     def POST(self):
   1954         searchform = self.form()
   1955         i = web.input()
   1956         if i.search != '':
   1957             raise web.seeother('/heartranked?search='+i.search)
   1958 
   1959 storage = {"content": ""}
   1960 class editor:
   1961     def GET(self):
   1962         if logged():
   1963             i = web.input(publish=None, public=None, new=None, combine=None, remix=None)
   1964             if i.combine != None:
   1965                 if session.user:
   1966                     session.soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   1967                     db.insert('unpublished', soundlink=session.soundlink, description='', description2='', timeadded=datetime.datetime.now(), creator=session.user, combine=i.combine)
   1968             if i.remix != None:
   1969                 if session.user:
   1970                     text=''
   1971                     text2=''
   1972                     try:
   1973                         olduser = db.select('unpublished', where="soundlink='"+i.remix+"'")[0]
   1974                         text = db.select('unpublished', where="soundlink='"+i.remix+"'")[0]
   1975                         text2 = db.select('unpublished', where="soundlink='"+i.remix+"'")[0]
   1976                     except:
   1977                         pass
   1978                     try:
   1979                         olduser = olduser.creator
   1980                         text = text.description
   1981                         text2 = text2.description2
   1982                     except:
   1983                         olduser = ''
   1984                     if olduser != '':
   1985                         allcreators = olduser+','+session.user
   1986                     else:
   1987                         allcreators = session.user
   1988                     session.soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   1989                     db.insert('unpublished', soundlink=session.soundlink, description=text, description2=text2, timeadded=datetime.datetime.now(), creator=allcreators, remix=i.remix)
   1990             if session.soundlink != '':
   1991                 if i.public=='yes':
   1992                     try:
   1993                         text = db.select('published', where="soundlink='"+session.soundlink+"'")[0]
   1994                     except:
   1995                         session.soundlink = ''
   1996                 else:
   1997                     try:
   1998                         text = db.select('unpublished', where="soundlink='"+session.soundlink+"'")[0]
   1999                     except:
   2000                         pass
   2001                 try:
   2002                     text = text.description
   2003                 except:
   2004                     text = ''
   2005                 if i.public=='yes':
   2006                     try:
   2007                         text2 = db.select('published', where="soundlink='"+session.soundlink+"'")[0]
   2008                     except:
   2009                         session.soundlink = ''
   2010                 else:
   2011                     try:
   2012                         text2 = db.select('unpublished', where="soundlink='"+session.soundlink+"'")[0]
   2013                     except:
   2014                         pass
   2015                 try:
   2016                     text2 = text2.description2
   2017                 except:
   2018                     text2 = ''
   2019             else:
   2020                 text = ''
   2021                 text2 = ''
   2022 
   2023             if i.new == 'yes':
   2024                 session.soundlink = ''
   2025                 raise web.seeother('/editor')
   2026             if i.publish == 'yes' and text != '' and i.public == None and logged() and len(text) < 256:
   2027                 description1 = text
   2028                 description2 = text2
   2029                 soundname = safe_filename(description1[0:27])
   2030                 #session.soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   2031                 createpost=True
   2032                 try:
   2033                     iftext = db.select('published', where="soundlink='"+session.soundlink+"'")[0]
   2034                     iftext = iftext.description
   2035                     createpost=False
   2036                 except:
   2037                     iftext = ''
   2038                 if createpost == False:
   2039                     db.update('published', where='soundlink="'+session.soundlink+'"', soundlink=session.soundlink, soundname=soundname, description=description1, description2=description2, timeadded=datetime.datetime.now(), creator=session.user)
   2040                     raise web.seeother('/editor?public=yes')
   2041                 else:
   2042                     print('make a new post')
   2043                 try:
   2044                     db.update('unpublished', where='soundlink="'+session.soundlink+'"', soundlink=session.soundlink, soundname=soundname, description=description1, description2=description2, timeadded=datetime.datetime.now(), creator=session.user)
   2045                 except:
   2046                     print('update unpublished')
   2047                 if createpost == True:
   2048                     try:
   2049                         combine = db.select('unpublished', where="soundlink='"+session.soundlink+"'")[0]
   2050                     except:
   2051                         pass
   2052                     try:
   2053                         combine = combine.combine
   2054                     except:
   2055                         combine = ''
   2056                     try:
   2057                         remix = db.select('unpublished', where="soundlink='"+session.soundlink+"'")[0]
   2058                     except:
   2059                         pass
   2060                     try:
   2061                         remix = remix.remix
   2062                     except:
   2063                         remix = ''
   2064                     db.insert('published', soundlink=session.soundlink, soundname=soundname, description=description1, description2=description2, timeadded=datetime.datetime.now(), creator=session.user, combine=combine, remix=remix)
   2065                     try:
   2066                         l = db.query("SELECT Count(*) AS combines FROM published WHERE combine='"+combine+"';")[0]
   2067                         #m = db.query("SELECT * FROM likes WHERE bild='"+postid+"' AND user='"+user+"';")
   2068                         db.update('published', where='soundlink="'+combine+'"', combines=l.combines)
   2069                     except:
   2070                         print('fuuuuuuuuuuuuuuuuuuuuuuu COMBINES NOT UPDATING! WARNING WARNING!')
   2071                         pass
   2072                     raise web.seeother('/editor?public=yes')
   2073                 raise web.seeother('/editor?public=yes')
   2074                 #db.insert('pawning', pawning=i.remix, name=session.user, timeadded=datetime.datetime.now())
   2075             return rendersplash.editor(storage, text, text2, markdown, safe_filename, session.soundlink, i.public, logged(), session.user, i.combine, i.remix)
   2076 
   2077 class save:
   2078     def POST(self):
   2079         data = json.loads(web.data())
   2080         text = data.get("text", "")
   2081         text2 = data.get("text2", "")
   2082         print(text)
   2083         print(text2 +'fuuuuuuuuuuuuu')
   2084         if session.soundlink == '':
   2085             session.soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   2086             db.insert('unpublished', soundlink=session.soundlink, description=text, description2=text2, timeadded=datetime.datetime.now(), creator=session.user)
   2087         else:
   2088             iftext = ''
   2089             try:
   2090                 iftext = db.select('unpublished', where="soundlink='"+session.soundlink+"'")[0]
   2091                 iftext = iftext.soundlink
   2092             except:
   2093                 iftext = ''
   2094             if iftext != '':
   2095                 db.update('unpublished', where='soundlink="'+session.soundlink+'"', description=text, description2=text2, timeadded=datetime.datetime.now(), creator=session.user)
   2096             else:
   2097                 db.insert('unpublished', soundlink=session.soundlink, description=text, description2=text2, timeadded=datetime.datetime.now(), creator=session.user)
   2098         return "ok"  # simple response
   2099 
   2100 class imageapi:
   2101     def POST(self):
   2102         action = ''
   2103         data = json.loads(web.data())
   2104         image = data.get("image", "")
   2105         action = data.get("action", "")
   2106         original_thumb = Image.open(staticdir+'users/'+session.user+'/images/thumb/'+image) 
   2107         original_web = Image.open(staticdir+'users/'+session.user+'/images/web/'+image) 
   2108         if action != '':
   2109             if action == 'rotateright' and image != None:
   2110                 o_thumb=original_thumb.rotate(270)
   2111                 o_web=original_web.rotate(270)
   2112             if action == 'rotateleft' and image != None:
   2113                 o_thumb=original_thumb.rotate(90)
   2114                 o_web=original_web.rotate(90)
   2115             o_thumb.save(staticdir+'users/'+session.user+'/images/thumb/'+image)
   2116             o_web.save(staticdir+'users/'+session.user+'/images/web/'+image)
   2117         return  # simple response
   2118 
   2119 class rendered:
   2120     def GET(self):
   2121         i = web.input(public=None)
   2122         if session.soundlink != '':
   2123             if i.public == None:
   2124                 try:
   2125                     unpublished = db.select('unpublished', where='soundlink="'+session.soundlink+'"')[0]
   2126                     if unpublished.description == None:
   2127                         return ''
   2128                 except:
   2129                     print('can not find any post')
   2130                 else:
   2131                     return markdown.markdown(unpublished.description+'\n\n---\n\n'+unpublished.description2)
   2132             elif i.public == 'yes':
   2133                 published = db.select('published', where='soundlink="'+session.soundlink+'"')[0]
   2134                 if published.description1 == None:
   2135                     return ''
   2136                 else:
   2137                     return markdown.markdown(published.description1+'\n\n---\n\n'+published.description2)
   2138             else:
   2139                 return ''
   2140 
   2141 def resize_gif(input_path, output_path, max_size):
   2142     input_image = Image.open(input_path)
   2143     frames = list(_thumbnail_frames(input_image,max_size))
   2144     output_image = frames[0]
   2145     output_image.save(
   2146         output_path,
   2147         save_all=True,
   2148         append_images=frames[1:],
   2149         disposal=input_image.disposal_method,
   2150         **input_image.info,
   2151     )
   2152 
   2153 def _thumbnail_frames(image,max_size):
   2154     for frame in ImageSequence.Iterator(image):
   2155         new_frame = frame.copy()
   2156         new_frame.thumbnail(max_size, Image.Resampling.LANCZOS)
   2157         yield new_frame
   2158 
   2159 def scale_gif(path, scale, new_path=None):
   2160     gif = Image.open(path)
   2161     if not new_path:
   2162         new_path = path
   2163     old_gif_information = {
   2164         'loop': bool(gif.info.get('loop', 1)),
   2165         'duration': gif.info.get('duration', 40),
   2166         'background': gif.info.get('background', 223),
   2167         'extension': gif.info.get('extension', (b'NETSCAPE2.0')),
   2168         'transparency': gif.info.get('transparency', 223)
   2169     }
   2170     new_frames = get_new_frames(gif, scale)
   2171     save_new_gif(new_frames, old_gif_information, new_path)
   2172 
   2173 def get_new_frames(gif, scale):
   2174     new_frames = []
   2175     actual_frames = gif.n_frames
   2176     for frame in range(actual_frames):
   2177         gif.seek(frame)
   2178         new_frame = Image.new('RGBA', gif.size)
   2179         new_frame.paste(gif)
   2180         new_frame.thumbnail(scale, Image.Resampling.LANCZOS)
   2181         new_frames.append(new_frame)
   2182     return new_frames
   2183 
   2184 def save_new_gif(new_frames, old_gif_information, new_path):
   2185     new_frames[0].save(new_path,
   2186                        save_all = True,
   2187                        append_images = new_frames[1:],
   2188                        duration = old_gif_information['duration'],
   2189                        loop = old_gif_information['loop'],
   2190                        background = old_gif_information['background'],
   2191                        extension = old_gif_information['extension'] ,
   2192                        transparency = old_gif_information['transparency'])
   2193 
   2194 class upload:
   2195     def POST(self):
   2196         if logged():
   2197             saved_files = []
   2198             
   2199             try:
   2200                 # Best way for multiple files in web.py
   2201                 input_data = web.webapi.rawinput()
   2202                 uploaded = input_data.get('files')
   2203                 
   2204                 # Make sure it's always a list
   2205                 if not isinstance(uploaded, list):
   2206                     uploaded = [uploaded] if uploaded else []
   2207                 
   2208                 for f in uploaded:
   2209                     if f and hasattr(f, 'filename') and f.filename:
   2210                         # Sanitize filename a bit
   2211                         imgdir = staticdir + 'users/' + session.user + '/temp/'
   2212                         os.system('mkdir -p ' + imgdir)
   2213                         safe_name = safe_filename(os.path.basename(f.filename))
   2214                         filepath = os.path.join(imgdir, safe_name) 
   2215         
   2216                         with open(filepath, 'wb') as out:
   2217                             out.write(f.file.read())  # Important: use .file.read()
   2218                         
   2219                         saved_files.append(safe_name)
   2220 
   2221                         ##---------- UPLOAD SOUND ----------
   2222                         imgname=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
   2223                         filetype = imgname.split('.')[-1].lower()
   2224                         soundfile=safe_name
   2225                         if filetype == 'pdf' or filetype == 'txt' or filetype == 'md':
   2226                             usersound = staticdir + 'users/' + session.user + '/docs/'
   2227                             os.system('mkdir -p ' + usersound)
   2228                             os.system('mv ' + imgdir + soundfile + ' ' + usersound + soundfile)
   2229                         elif filetype == 'mp4':
   2230                             usersound = staticdir + 'users/' + session.user + '/films/'
   2231                             os.system('mkdir -p ' + usersound)
   2232                             os.system('mv ' + imgdir + soundfile + ' ' + usersound + soundfile)
   2233                         elif filetype == 'jpeg' or filetype == 'jpg' or filetype == 'png' or filetype == 'gif':
   2234                             userpics = staticdir + 'users/' + session.user + '/images/'
   2235                             os.system('mkdir -p ' + userpics)
   2236                             os.system('mv ' + imgdir + soundfile + ' ' + userpics + soundfile)
   2237                             if filetype == 'gif':
   2238                                 scale_gif(userpics+soundfile, [900,900], userpics+'web/'+soundfile)
   2239                                 scale_gif(userpics+soundfile, [300,300], userpics+'thumb/'+soundfile)
   2240                             else:
   2241                                 ##---------- OPEN FILE & CHEKC IF JPEG --------
   2242                                 image = Image.open(userpics + soundfile)
   2243                                 try:
   2244                                     os.makedirs(userpics + 'web/', exist_ok=True)
   2245                                     os.makedirs(userpics + 'thumb/', exist_ok=True)
   2246                                 except:
   2247                                     print('Folders is')
   2248 
   2249                                 ##---------- RESIZE IMAGE -----------
   2250                                 image.thumbnail((900,900), Image.Resampling.LANCZOS)
   2251                                 image.save(userpics + 'web/' + soundfile)
   2252                                 image.thumbnail((300,300), Image.Resampling.LANCZOS)
   2253                                 image.save(userpics + 'thumb/' + soundfile)
   2254 
   2255                         elif filetype == 'wav' or filetype == 'flac' or filetype == 'mp3' or filetype == 'ogg':
   2256                             usersound = staticdir + 'users/' + session.user + '/sounds/'
   2257                             os.system('mkdir -p ' + usersound)
   2258                             os.system('mv ' + imgdir + soundfile + ' ' + usersound + soundfile)
   2259                             soundlenght = os.popen('mediainfo --Inform="General;%Duration%" ' + usersound + soundfile).read()
   2260                             print('sound lenght:' + str(soundlenght))
   2261                             soundtype = os.popen('mediainfo --Inform="General;%Format%" ' + usersound + soundfile).read()
   2262                             print(soundtype)
   2263                             if 'Ogg' in soundtype:
   2264                                 #os.system('ffmpeg -i '+usersound+soundfile+' '+usersound+soundname+'.wav')
   2265                                 print('ogg file found, converting to flac')
   2266                                 os.system('ffmpeg -i ' + usersound + soundfile +' '+ usersound + soundname + '.flac') 
   2267                                 print('converting to mp3')
   2268                                 os.system('ffmpeg -y -loglevel 1 -i ' + usersound + soundname + '.flac -c:a libmp3lame -b:a 192k ' + usersound + soundname + '.mp3') 
   2269                             if 'MPEG Audio' in soundtype:
   2270                                 print('mp3 file found, converting to flac')
   2271                                 os.system('ffmpeg -i ' + usersound + soundfile + ' ' + usersound + soundname + '.flac') 
   2272                                 print('converting to ogg')
   2273                                 os.system('ffmpeg -i ' + usersound + soundname +'.flac '+ usersound + soundname + '.ogg') 
   2274                                 print('Wave file found, converting to flac')
   2275                             if 'Wave' in soundtype:
   2276                                 print('Wave file found, converting to flac')
   2277                                 os.system('flac ' + usersound + soundfile + ' ' + usersound + soundname + '.flac') 
   2278                                 os.system('sox -V1 ' + usersound + soundfile + ' ' + usersound + soundname + '.ogg') 
   2279                                 os.system('ffmpeg -y -loglevel 1 -i ' + usersound + soundfile + ' -c:a libmp3lame -b:a 192k ' + usersound + soundname + '.mp3') 
   2280                             if 'FLAC' in soundtype:
   2281                                 print('FLAC file found, converting to mp3 and ogg')
   2282                                 os.system('sox -V1 ' + usersound + soundfile + ' ' + usersound + soundname + '.ogg') 
   2283                                 os.system('ffmpeg -y -loglevel 1 -i ' + usersound + soundfile + ' -c:a libmp3lame -b:a 192k ' + usersound + soundname + '.mp3')
   2284                         saved_files.append(safe_name)
   2285                         print(f"✅ Saved: {safe_name}")  # This will show in console for debugging
   2286                     else:
   2287                         print("⚠️ Skipped invalid file object")
   2288                         
   2289             except Exception as e:
   2290                 print("Upload error:", str(e))
   2291                 return f"❌ Error: {str(e)}"
   2292             
   2293             if saved_files:
   2294                 return f"✅ Successfully uploaded {len(saved_files)} file(s): {', '.join(saved_files)}"
   2295             else:
   2296                 return "❌ No files received. Check console for details."
   2297 
   2298 class uploads:
   2299     def GET(self):
   2300         if logged():
   2301             uploaded = getfiles(staticdir+'upload/')
   2302             return render.uploads(uploaded)
   2303 
   2304 class config:
   2305     form = web.form.Form(
   2306     web.form.Textbox('name', web.form.notnull, description="Site name:"),
   2307     web.form.Textarea('description', web.form.notnull, description="Slogan:"),
   2308     web.form.Textarea('description2', web.form.notnull, description="Description:"),
   2309     web.form.Button('Save'))
   2310     def GET(self):
   2311         if logged():
   2312             configsite = self.form()
   2313             try:
   2314                 oldsiteconfig = db.select('siteconfig', what='id, name, description, description2')[0]
   2315                 configsite.fill(name=oldsiteconfig.name, description=oldsiteconfig.description, description2=oldsiteconfig.description2)
   2316             except:
   2317                 print('no non no')
   2318             return renderop.config(configsite)
   2319         else:
   2320             raise web.seeother('/login')
   2321     def POST(self):
   2322         if logged():
   2323             addcategory = self.form()
   2324             i = web.input(imgfile={}, name=None)
   2325             if i.name != None:
   2326                 db.update('siteconfig', where='id=1', name=i.name, description=i.description, description2=i.description2 )
   2327             if i.imgfile != {}:
   2328                 if i.imgfile.filename == '':
   2329                     print('hmmm... no image to upload')
   2330                     raise web.seeother('/config/')
   2331                 print('YEAH, Upload image!')
   2332 
   2333                 ##---------- UPLOAD IMAGE ----------
   2334 
   2335                 filepath=i.imgfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
   2336                 #split and only take the filename with extension
   2337                 #soundpath=filepath.split('/')[-1]
   2338                 #if soundpath == '':
   2339                 #    return render.nope("strange, no filename found!")
   2340                 #get filetype, last three 
   2341                 imgname=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
   2342                 filetype = imgname.split('.')[-1].lower()
   2343                 if filetype == 'jpg':
   2344                     filetype = 'jpeg'
   2345                 soundname = imgname.split('.')[0]
   2346                 #lets remove unwanted characters yes please!
   2347                 sound = ''
   2348                 for p in soundname.lower():
   2349                     if p in allowedchar:
   2350                         sound = sound + p
   2351                 if sound == '':
   2352                     raise web.seeother('/upload?fail=wierdname')
   2353                 soundname = 'logo.' + filetype
   2354                 print(soundname)
   2355                 print("filename is " + imgname + " filetype is " + filetype + " soundname is " + soundname + " trying to upload file from: " + filepath)
   2356                 #if filetype != 'wav' or 'ogg' or 'flac' or 'jpeg' or 'jpg' or 'mp3':
   2357                 #    web.seeother('/upload?fail=notsupported')
   2358                 #imghash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
   2359                 #imgname = imghash
   2360                 #imgname = str(len(os.listdir(imgdir))).zfill(3) + '.jpeg'
   2361                 soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   2362                 imgdir = staticdir+'upload/'
   2363                 os.system('mkdir -p ' + imgdir)
   2364                 fout = open(imgdir + soundname,'wb') # creates the file where the uploaded file should be stored
   2365                 fout.write(i.imgfile.file.read()) # writes the uploaded file to the newly created file.
   2366                 fout.close() # closes the file, upload complete.
   2367                 
   2368                 if filetype == 'jpeg' or filetype == 'png':
   2369                     ##---------- OPEN FILE & CHEKC IF JPEG --------
   2370 
   2371                     image = Image.open(imgdir + soundname)
   2372                     #if image.format != 'JPEG':
   2373                     #    os.remove(imgdir +'/'+ soundname)
   2374                     #    raise web.seeother('/products/' + idvalue)
   2375 
   2376                     ##---------- RESIZE IMAGE SAVE TO PRODUCT-----------
   2377 
   2378                     imgdir=staticdir+'img'
   2379                     try:
   2380                         os.makedirs(imgdir + '/web/', exist_ok=True)
   2381                         os.makedirs(imgdir + '/thumb/', exist_ok=True)
   2382                     except:
   2383                         print('Folders is')
   2384                     image.resize((900,900), Image.LANCZOS)
   2385                     image.save(imgdir + '/web/'+soundname)
   2386                     image.resize((300,300), Image.LANCZOS)
   2387                     image.save(imgdir + '/thumb/'+soundname) 
   2388             raise web.seeother('/config')
   2389         else:
   2390             raise web.seeother('/login')
   2391 
   2392 class categories:
   2393     form = web.form.Form(
   2394     web.form.Textbox('category', web.form.notnull, description="Add Category:"),    
   2395     web.form.Button('Add'))
   2396     def GET(self):
   2397         if logged():
   2398             i = web.input(delete=None)
   2399             if i.delete:
   2400                 db.delete('categories', where='id='+i.delete)
   2401             listcategories = db.query("SELECT * FROM categories ORDER BY id DESC")
   2402             addcategory = self.form()
   2403             return renderop.categories(listcategories,addcategory)
   2404         else:
   2405             raise web.seeother('/login')
   2406     def POST(self):
   2407         addcategory = self.form()
   2408         i = web.input()
   2409         db.insert('categories', category=i.category)
   2410         raise web.seeother('/categories')
   2411 
   2412 
   2413 class products:
   2414     listcategories = db.query("SELECT * FROM categories ORDER BY id DESC")
   2415     p = []
   2416     for i in listcategories:
   2417         p.append(i.category)
   2418     #p = listcategories[0]
   2419     form = web.form.Form(
   2420     web.form.Dropdown('category', p, web.form.notnull, description="Category:"),
   2421     web.form.Textbox('name', web.form.notnull, description="Name:"),
   2422     web.form.Textarea('description', web.form.notnull, description="Description:"),
   2423     web.form.Radio('type', ['digital', 'physical'],description="Type:"),
   2424     web.form.Radio('currency', ['euro', 'bitcoin'],description="Currency:"),
   2425     web.form.Textbox('price', web.form.notnull, description="Price:"),
   2426     web.form.Textbox('available', web.form.notnull, web.form.regexp(r'\d+', 'number dumbass!'), description="Available"),
   2427     web.form.Textbox('priority', web.form.notnull, web.form.regexp(r'\d+', 'number dumbass!'), description="Priority (high value more priority)"),
   2428     web.form.Button('Save'))
   2429     def GET(self, idvalue):
   2430         if logged():
   2431             i = web.input(cmd=None,soundname=None)
   2432             nocache = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[11:15]
   2433             if i.cmd == 'del':
   2434                 db.delete('products', where='id="'+idvalue+'"')
   2435                 imgdir = staticdir + 'img/' + idvalue
   2436                 try:
   2437                     shutil.rmtree(imgdir,ignore_errors=True,onerror=None)
   2438                 except:
   2439                     print('no picture folder, nothing to remove...')
   2440                     pass
   2441                 raise web.seeother('/products/')
   2442             if i.cmd == 'remove' and i.soundname != None:
   2443                 try:
   2444                     os.remove(staticdir+'/img/thumb/'+i.soundname)
   2445                     os.remove(staticdir+'/img/web/'+i.soundname)
   2446                 except:
   2447                     print('notin to delete')
   2448                 goodies = db.query("DELETE FROM soundlink WHERE id='"+idvalue+"' AND soundname='"+i.soundname+"';")
   2449                 raise web.seeother('/products/' + idvalue)
   2450             if i.cmd == 'flipright' and i.soundname != None:
   2451                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
   2452                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
   2453                 o_thumb=original_thumb.rotate(270)
   2454                 o_web=original_web.rotate(270)
   2455                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
   2456                 o_web.save(staticdir+'/img/web/'+i.soundname)
   2457                 raise web.seeother('/products/' + idvalue)
   2458             if i.cmd == 'flipleft' and i.soundname != None:
   2459                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
   2460                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
   2461                 o_thumb=original_thumb.rotate(90)
   2462                 o_web=original_web.rotate(90)
   2463                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
   2464                 o_web.save(staticdir+'/img/web/'+i.soundname)
   2465                 raise web.seeother('/products/' + idvalue)
   2466             addproduct = self.form()
   2467             addproduct.fill(available='1', priority='1', type='physical',currency='euro')
   2468             goodies = None
   2469             if idvalue:
   2470                 oldinfo = db.query("SELECT * FROM products WHERE id='"+idvalue+"';")[0]
   2471                 addproduct.fill(name=oldinfo.name, description=oldinfo.description, type=oldinfo.type, currency=oldinfo.currency, price=oldinfo.price, available=oldinfo.available, priority=oldinfo.priority, category=oldinfo.category)
   2472                 goodies = db.query("SELECT * FROM soundlink WHERE id='"+idvalue+"';")
   2473             listproducts = db.query("SELECT * FROM products ORDER BY priority DESC")
   2474             return renderop.products(addproduct, listproducts, goodies, idvalue, nocache)
   2475         else:
   2476             raise web.seeother('/login') 
   2477     def POST(self, idvalue):
   2478         listproducts = db.query("SELECT * FROM products ORDER BY priority DESC")
   2479         addproduct = self.form()
   2480         if logged():
   2481             i = web.input(imgfile={},name=None,description=None,price=1,available=1)
   2482             #for p in i:q
   2483             #    print(p)
   2484             if i.name != None:
   2485                 if idvalue:
   2486                     db.update('products', where='id="'+idvalue+'"', category=i.category,name=i.name,description=i.description,type=i.type,currency=i.currency,price=i.price,available=i.available,priority=i.priority,dateadded=datetime.datetime.now())
   2487                 else:
   2488                     idvalue = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[11:36]
   2489                     db.insert('products', id=idvalue, category=i.category, name=i.name, description=i.description, type=i.type,currency=i.currency, price=i.price, available=i.available, sold=0, priority=i.priority, dateadded=datetime.datetime.now())
   2490             if i.imgfile != {}:
   2491                 if idvalue == '':
   2492                     print('cant upload a picture to a non existing product')
   2493                     raise web.seeother('/products/')
   2494                 print(i.imgfile.filename)
   2495                 if i.imgfile.filename == '':
   2496                     print('hmmm... no image to upload')
   2497                     raise web.seeother('/products/' + idvalue)
   2498                 print('YEAH, Upload image!')
   2499 
   2500                 ##---------- UPLOAD IMAGE ----------
   2501 
   2502                 filepath=i.imgfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
   2503                 #split and only take the filename with extension
   2504                 #soundpath=filepath.split('/')[-1]
   2505                 #if soundpath == '':
   2506                 #    return render.nope("strange, no filename found!")
   2507                 #get filetype, last three 
   2508                 imgname=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
   2509                 filetype = imgname.split('.')[-1].lower()
   2510                 if filetype == 'jpg':
   2511                     filetype = 'jpeg'
   2512                 soundname = imgname.split('.')[0]
   2513                 #lets remove unwanted characters yes please!
   2514                 sound = ''
   2515                 for p in soundname.lower():
   2516                     if p in allowedchar:
   2517                         sound = sound + p
   2518                 if sound == '':
   2519                     raise web.seeother('/upload?fail=wierdname')
   2520                 soundname = sound + '.' + filetype
   2521                 print(soundname)
   2522                 print("filename is " + imgname + " filetype is " + filetype + " soundname is " + soundname + " trying to upload file from: " + filepath)
   2523                 #if filetype != 'wav' or 'ogg' or 'flac' or 'jpeg' or 'jpg' or 'mp3':
   2524                 #    web.seeother('/upload?fail=notsupported')
   2525                 #imghash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
   2526                 #imgname = imghash
   2527                 #imgname = str(len(os.listdir(imgdir))).zfill(3) + '.jpeg'
   2528                 soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   2529                 imgdir = staticdir+'upload/'+soundlink+'/'
   2530                 os.system('mkdir -p ' + imgdir)
   2531                 fout = open(imgdir + soundname,'wb') # creates the file where the uploaded file should be stored
   2532                 fout.write(i.imgfile.file.read()) # writes the uploaded file to the newly created file.
   2533                 fout.close() # closes the file, upload complete.
   2534                 
   2535                     ##----------CHECK IF SAME NAME THEN UPDATE-------
   2536                 slink = db.query("SELECT * FROM soundlink WHERE id='"+idvalue+"' AND soundname='"+soundname+"';")
   2537                 if slink:
   2538                     db.update('soundlink', where='"id='+idvalue+'"', soundlink=soundlink, soundname=soundname, timeadded=datetime.datetime.now())
   2539                 else:
   2540                     db.insert('soundlink', id=idvalue, soundlink=soundlink, soundname=soundname, timeadded=datetime.datetime.now())
   2541 
   2542                 if filetype == 'jpeg' or filetype == 'png':
   2543                     ##---------- OPEN FILE & CHEKC IF JPEG --------
   2544 
   2545                     image = Image.open(imgdir +'/'+ soundname)
   2546                     #if image.format != 'JPEG':
   2547                     #    os.remove(imgdir +'/'+ soundname)
   2548                     #    raise web.seeother('/products/' + idvalue)
   2549 
   2550                     ##---------- RESIZE IMAGE SAVE TO PRODUCT-----------
   2551 
   2552                     imgdir=staticdir+'img'
   2553                     try:
   2554                         os.makedirs(imgdir + '/web/', exist_ok=True)
   2555                         os.makedirs(imgdir + '/thumb/', exist_ok=True)
   2556                     except:
   2557                         print('Folders is')
   2558                     image.resize((900,900), Image.LANCZOS)
   2559                     image.save(imgdir + '/web/'+soundname)
   2560                     image.resize((300,300), Image.LANCZOS)
   2561                     image.save(imgdir + '/thumb/'+soundname) 
   2562 
   2563             return web.seeother('/products/' + idvalue)
   2564         else:
   2565             return web.seeother('/login')
   2566 
   2567 class shipping:
   2568     form = web.form.Form(
   2569     web.form.Textbox('country', web.form.notnull, description="Country:"),
   2570     web.form.Textbox('price', web.form.regexp(r'\d+', 'number thanx!'), web.form.notnull, description="Price in cents"),
   2571     web.form.Textbox('days', web.form.regexp(r'\d+', 'number thanx!'), web.form.notnull, description="Shipping in days"),
   2572     web.form.Button('Add shipping country'))
   2573     def GET(self, idvalue):
   2574         if logged():
   2575             addcountry = self.form()
   2576             if idvalue:
   2577                 oldinfo = db.select('shipping', where="id='"+idvalue+"'", what='country, price, days')
   2578                 oldinfo = oldinfo[0]
   2579                 addcountry.fill(country=oldinfo.country, price=oldinfo.price, days=oldinfo.days)
   2580             listcountries = db.query("SELECT * FROM shipping ORDER BY country DESC")
   2581             return renderop.shipping(addcountry, listcountries)
   2582         else:
   2583             raise web.seeother('/login')
   2584     def POST(self, idvalue):
   2585         if logged():
   2586             addcountry = self.form()
   2587             if not addcountry.validates():
   2588                 listcountries = db.query("SELECT * FROM shipping ORDER BY country DESC")
   2589                 return renderop.shipping(addcountry, listcountries)
   2590             else:
   2591                 i = web.input()
   2592                 if idvalue:
   2593                     db.update('shipping', where='id="'+idvalue+'"', country=i.country, price=i.price, days=i.days)
   2594                 else:
   2595                     db.insert('shipping', country=i.country, price=i.price, days=i.days)
   2596                 raise web.seeother('/shipping/')
   2597         else:
   2598             raise web.seeother('/login')
   2599 
   2600 class cv:
   2601     def GET(self):
   2602         return render.cv()
   2603 
   2604 class bitcoin:
   2605     def GET(self):
   2606         if logged():
   2607             bitcoinrpc = AuthServiceProxy(rpcauth)
   2608             wallet = bitcoinrpc.getwalletinfo()
   2609             bitcoinrpc = None
   2610             return renderop.bitcoin(wallet)
   2611 
   2612 
   2613 application = app.wsgifunc()