thiswebshoprules

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

server.py (56156B)


      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 from PIL import Image
     22 from forex_python.bitcoin import BtcConverter
     23 from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
     24 
     25 urls = (
     26     '/shop?', 'index',
     27     '/?', 'almost',
     28     '/putinbag/(.*)', 'putinbag',
     29     '/dropitem/(.*)?', 'dropitem',
     30     '/payln/(.*)', 'payln',
     31     '/goodies/(.*)', 'goodies',
     32     "/stats", "stats",
     33     '/lightning?', 'lightning',
     34     '/paybtc/(.*)', 'paybtc',
     35     '/payment/(.*)', 'payment',
     36     '/orders?', 'orders',
     37     '/checkout?', 'checkout',
     38     '/pending', 'pending',
     39     '/thankyou', 'thankyou',
     40     '/login', 'login',
     41     '/logout', 'logout',
     42     '/products/(.*)?', 'products',
     43     '/bigpic/(.*)?', 'bigpic',
     44     '/categories?', 'categories',
     45     '/op', 'op',
     46     '/bitcoin', 'bitcoin',
     47     '/shipping/(.*)', 'shipping',
     48     '/propaganda?', 'propaganda',
     49     '/uploads?', 'uploads',
     50     '/config', 'config',
     51     '/payments?', 'payments')
     52 
     53 bag = ''
     54 
     55 #Load from settings
     56 
     57 rtl = settings.rtl
     58 rpcauth = settings.rpcauth
     59 webmaster = settings.webmaster
     60 baseurl = settings.baseurl
     61 allowed = settings.allowed
     62 
     63 basedir = os.path.dirname(os.path.realpath(__file__))+'/'
     64 templatedir = basedir + 'public_html/templates/'
     65 staticdir = basedir + 'public_html/static/'
     66 web.config.debug = False
     67 app = web.application(urls, globals())
     68 store = web.session.DiskStore(basedir + 'sessions')
     69 render = web.template.render(templatedir, base="base")
     70 renderop = web.template.render(templatedir, base="op")
     71 rendersplash = web.template.render(templatedir, base="splash")
     72 db = web.database(dbn='sqlite', db=basedir + "db/cyberpunkcafe.db")
     73 session = web.session.Session(app,store,initializer={'login':0, 'privilege':0, 'bag':[], 'sessionkey':'empty'})
     74 
     75 
     76 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'
     77 
     78 #----------- Database setup -------------
     79 
     80 #Remeber to store Euros in cents
     81 
     82 #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);
     83 
     84 #CREATE TABLE shipping (id integer PRIMARY KEY, country text NOT NULL, cost integer NOT NULL, days integer NOT NULL);
     85 
     86 #should rename to customer 
     87 #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)
     88 
     89 #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);
     90 
     91 
     92 def logged():
     93     if session.login == 1:
     94         return True
     95     else:
     96         return False
     97 
     98 def sendmail(email, subject, msg):
     99     #Send mail
    100     echomsg = subprocess.Popen(('echo', msg), stdout=subprocess.PIPE)
    101     sendmsg = subprocess.check_output(('mail', '-r', webmaster, '-s', subject, email), stdin=echomsg.stdout)
    102     echomsg.wait()
    103     #subprocess.call(['echo', msg, '|', 'mail', '-r', webmaster,'-s', subject, email])
    104 
    105 def getmacaroon():
    106     with open(basedir+'access.macaroon', 'rb') as f:
    107         m = f.read()
    108     #m = binascii.hexlify(m).decode()
    109     m = base64.b64encode(m).decode()
    110     return m
    111 
    112 def createinvoice(amount, description, label):
    113     #Cents to EUR
    114     amount = str(amount*1000)
    115     invoice_details = {"amount":amount, "description": description, "label": label}
    116     print(invoice_details)
    117     macaroon = getmacaroon()
    118     headers = {'macaroon': macaroon} 
    119     resp = requests.post(rtl+'invoice/genInvoice', json=invoice_details, headers=headers,verify=False)
    120     print(resp.json())
    121     return resp.json()
    122 
    123 def getinvoice(label):
    124     macaroon = getmacaroon()
    125     headers = {'macaroon': macaroon}
    126     resp = requests.get(rtl+'invoice/listInvoices?label='+label, headers=headers, verify=False)
    127     return resp.json()['invoices'][0]
    128 
    129 def getnewaddr():
    130     macaroon = getmacaroon()
    131     headers = {'macaroon': macaroon}
    132     resp = requests.get(rtl+'invoice/newaddr', headers=headers, verify=False)
    133     return resp.json()['address'][0]
    134 
    135 def callsubprocess(cmd):
    136     subprocess.call(cmd.split())
    137 
    138 def dropitems(d):
    139     i = getproduct(d)
    140     try:
    141         product = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"' AND product='"+str(i.id)+"';")[0]
    142     except:
    143         return 'empty'
    144     if product.quantity > 1:
    145         db.update('customerbag', where="sessionkey='" + session.sessionkey +"' and product='"+str(i.id)+"'", quantity=product.quantity-1)
    146         db.update('products', where="id='"+str(i.id)+"'", available=i.available+1)
    147     else:
    148         db.query("DELETE FROM customerbag WHERE sessionkey='" + session.sessionkey +"' AND product='"+str(i.id)+"';")
    149         db.update('products', where="id='"+str(i.id)+"'", available=i.available+1)
    150         return 'empty'
    151 
    152 def addtobag(p):
    153     i = getproduct(p)
    154     if i.available > 0:
    155         #session.bag += (i.name, i.price, i.id),
    156         db.update('products', where="id='"+str(i.id)+"'", available=i.available-1)
    157         product = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"' AND product='"+str(i.id)+"';")
    158         if product:
    159             product = product[0]
    160             print(product)
    161             db.update('customerbag', where="sessionkey='" + session.sessionkey +"' and product='"+str(i.id)+"'", quantity=product.quantity+1)
    162             print('gwtdafaakouttahere')
    163         else:
    164             db.insert('customerbag', sessionkey=session.sessionkey, product=i.id, type=i.type, currency=i.currency, price=i.price, quantity=1, timeadded=datetime.datetime.now())
    165 
    166 def productname(productid):
    167     try:
    168         name = db.query("SELECT name FROM products WHERE id='"+str(productid)+"';")[0]
    169     except:
    170         return ''
    171     return name.name
    172 
    173 def getproduct(productid):
    174     try:
    175         product = db.query("SELECT * FROM products WHERE id='"+str(productid)+"';")[0]
    176     except:
    177         return ''
    178     return product
    179 
    180 def getcategories():
    181     try:
    182         categories = db.query("SELECT * FROM categories;")[0]
    183     except:
    184         return ''
    185     return categories
    186 
    187 def ordertype():
    188     physical=False
    189     bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    190     for b in bag:
    191         if b.type=='physical':
    192             return 'physical'
    193     return 'digital'
    194             
    195 def getavailable(productid):
    196     try:
    197         name = db.query("SELECT available FROM products WHERE id='"+str(productid)+"';")[0]
    198     except:
    199         return ''
    200     return name.available
    201 
    202 def getbtcrate():
    203     btc_to_euro = db.select("btcrate", where="currency='EUR'")
    204     #shippinginfo = db.select('shipping', where="country='" + pendinginfo.country + "'", what='price, days')[0]
    205     try:
    206         if time.time() - btc_to_euro[0].timeadded > 6000:
    207             btcrate = 64485
    208             b = BtcConverter()
    209             btcrate = int(b.get_latest_price('EUR'))
    210             db.update('btcrate', where='currency="EUR"', rate=btcrate, timeadded=time.time())
    211         else:
    212             btc_to_euro = db.select("btcrate", where="currency='EUR'")
    213             btcrate = btc_to_euro[0].rate
    214     except:
    215         db.insert('btcrate', currency='EUR', rate=64485, timeadded=time.time())
    216     return btcrate
    217 
    218 def getbtcratetime():
    219     btc_to_euro = db.select("btcrate", where="currency='EUR'")
    220     btctime = btc_to_euro[0].timeadded
    221     return datetime.datetime.fromtimestamp(btctime).strftime('%c')
    222 
    223 def getprice(productid):
    224     p = db.query("SELECT * FROM products WHERE id='"+str(productid)+"';")[0]
    225     #b = BtcConverter()
    226     btcrate=getbtcrate()
    227     if p.currency=='euro':
    228         sat = 1/btcrate*(p.price/100) * 100000000
    229         #sat = b.convert_to_btc(p.price/100, 'EUR') * 100000000
    230         euro = p.price/100
    231     if p.currency=='bitcoin':
    232         euro = btcrate*p.price/100000000
    233         #euro = b.convert_btc_to_cur(p.price/100000000,'EUR')
    234         sat = p.price
    235     return int(sat), round(euro,2)
    236 
    237 def btc_to_eur(amount):
    238     #b = BtcConverter()
    239     btcrate=getbtcrate()
    240     #euro = round(b.convert_btc_to_cur(amount/100000000,'EUR'),2)
    241     euro = round(btcrate*amount/100000000)
    242     return euro
    243 
    244 def eur_to_sat(amount):
    245     btcrate=getbtcrate()
    246     #b = BtcConverter()
    247     #btc = b.convert_to_btc(amount/100, 'EUR')
    248     btc = 1/btcrate*(amount/100)
    249     sat=btc*100000000
    250     return int(sat)
    251 
    252 def getrate():
    253     #b = BtcConverter()
    254     btcrate=getbtcrate()
    255     #return int(b.get_latest_price('EUR'))
    256     return int(btcrate)
    257 
    258 def checkforoldbags():
    259     print('checking for old bags')
    260     bags = db.select('customerbag')
    261     for bag in bags:
    262         if datetime.datetime.now() - bag.timeadded > datetime.timedelta(minutes=10):
    263             print(datetime.datetime.now() - bag.timeadded)
    264             print(datetime.timedelta(hours=1))
    265             print("Fuck")
    266             product = getproduct(bag.product)
    267             try:
    268                 print('found a bag at door! goddamit, got to put ' + str(bag.quantity) + ' x '  + product.name + ' back on the shelf')
    269                 if product.available > 1:
    270                     q = product.available + bag.quantity
    271                 else:
    272                     q = bag.quantity
    273                 db.update('products', where="id='"+str(bag.product)+"'", available=str(q))
    274                 db.query("DELETE FROM customerbag WHERE sessionkey='" + bag.sessionkey + "'")
    275             except:
    276                 pass
    277 
    278 def checkavailable():
    279     print('check items from availability')
    280     bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey + "'")
    281     for i in bag:
    282         q = getavailable(i.product)
    283         soldout = q - i.quantity
    284         if soldout < 0:
    285             web.seeother('/?error=soldout&prod='+str(i.product))
    286         else:
    287             return
    288 
    289 def sold():
    290     print('remove items from availability')
    291     bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey + "'")
    292     for i in bag:
    293         q = getavailable(i.product)
    294         soldout = q - i.quantity
    295         if soldout < 0:
    296             web.seeother('/?error=soldout')
    297         else:
    298             db.update('products', where="id='"+str(i.product)+"'", available=str(q - i.quantity))
    299 
    300 
    301 def organizepics(product):
    302     imgdir = basedir+'public_html/static/img/' + str(product) + '/'
    303     imgdirlist = [imgdir, imgdir + 'web/', imgdir + 'thumb/']
    304     for d in imgdirlist:
    305         pics = next(os.walk(d))[2]
    306         organized_nr = 0
    307         for s in sorted(pics):
    308             if '.jpeg' in s:
    309                 #print(s)
    310                 unorganized_nr = int(s[0:3])
    311                 if organized_nr == unorganized_nr:
    312                     print('correcto pic numbering')
    313                     pass
    314                 if organized_nr != unorganized_nr:
    315                     print('false, correcting pic from ' + str(unorganized_nr) + ' to ' + str(organized_nr))
    316                     mv = 'mv ' + d + str(unorganized_nr).zfill(3) + '.jpeg'
    317                     mv2 = ' ' + d + str(organized_nr).zfill(3) + '.jpeg'
    318                     os.system(mv + mv2)
    319                 organized_nr += 1
    320 
    321 def getpendinginfo():
    322     try:
    323         pendinginfo = db.select('pending', where="invoice_key='" + session.sessionkey + "'", what='country, firstname, lastname, address, town, postalcode, email')[0]
    324     except:
    325         pendinginfo = ''
    326     return pendinginfo
    327 
    328 class index():
    329     def GET(self):
    330         ip = web.ctx['ip']
    331         referer = web.ctx.env.get('HTTP_REFERER', 'none')
    332         environ = web.ctx.env.get('HTTP_USER_AGENT', 'dunno')
    333         visitorlog(ip,referer,environ)
    334         checkforoldbags()
    335         i = web.input(dropitem=None, putinbag=None,error=None,prod=None,category=None)
    336         if session.sessionkey == 'empty':
    337             session.sessionkey = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[15:35]
    338         if i.dropitem != None:
    339             session.bag = dropitems(i.dropitem)
    340             print(session.bag)
    341         if i.putinbag != None:
    342             addtobag(i.putinbag)
    343             return web.seeother('/shop#' + i.putinbag)
    344         print('Cyberpunk cafe')
    345         #print(session.bag)
    346         products = db.query("SELECT * FROM products ORDER BY priority DESC")
    347         try:
    348             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    349         except:
    350             bag = None
    351         try:
    352             inbag = db.query("SELECT COUNT(*) AS inbag FROM customerbag where sessionkey='" + session.sessionkey +"';")[0]
    353             inbag = int(inbag.inbag)
    354         except:
    355             inbag = None
    356         if inbag < 1:
    357             session.sessionkey = 'empty'
    358         return render.index(products,bag,session.sessionkey,productname,inbag,db,getprice,getrate,i.category, markdown,getbtcratetime)
    359 
    360 class almost():
    361     def GET(self):
    362         ip = web.ctx['ip']
    363         referer = web.ctx.env.get('HTTP_REFERER', 'none')
    364         environ = web.ctx.env.get('HTTP_USER_AGENT', 'dunno')
    365         visitorlog(ip,referer,environ)
    366         visitors, total, unique = getvisits()
    367         checkforoldbags()
    368         i = web.input(dropitem=None, putinbag=None,error=None,prod=None,category=None)
    369         if session.sessionkey == 'empty':
    370             session.sessionkey = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[15:35]
    371         if i.dropitem != None:
    372             session.bag = dropitems(i.dropitem)
    373             print(session.bag)
    374         if i.putinbag != None:
    375             addtobag(i.putinbag)
    376             return web.seeother('/#' + i.putinbag)
    377         print('Cyberpunk cafe')
    378         #print(session.bag)
    379         products = db.query("SELECT * FROM products ORDER BY priority DESC")
    380         try:
    381             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    382         except:
    383             bag = None
    384         try:
    385             inbag = db.query("SELECT COUNT(*) AS inbag FROM customerbag where sessionkey='" + session.sessionkey +"';")[0]
    386             inbag = int(inbag.inbag)
    387         except:
    388             inbag = None
    389         if inbag < 1:
    390             session.sessionkey = 'empty'
    391         return rendersplash.almost(products,bag,session.sessionkey,productname,inbag,db,getprice,getrate,i.category, markdown, visitors, total, unique)
    392 
    393 def visitorlog(ip, referer, environ):
    394     last = db.query('SELECT ip AS ip FROM visitors WHERE id=(SELECT MAX(id) FROM visitors)')
    395     try:
    396         lastip = last[0].ip
    397     except:
    398         lastip = 'none'
    399     if lastip != ip:
    400         country = ''
    401         country = os.popen('geoiplookup '+ip).read()
    402         #print(soundtype)
    403         countrycode = country.split(':')[1].split(',')[0].lower().strip()
    404         country = country.split(':')[1].split(',')[1].strip()
    405         #print('fuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu: '+ country)
    406         db.insert('visitors', ip=ip, referer=referer, environ=environ, country=country,  countrycode=countrycode, time=datetime.datetime.now())
    407         print("added to visitor log")
    408     return
    409 
    410 def getvisitors():
    411     visitors = db.select('visitors')
    412     total = db.query('SELECT COUNT(*) AS total_visits FROM visitors')
    413     unique = db.query('SELECT COUNT(DISTINCT ip) AS unique_visits FROM visitors')
    414     return visitors, total[0].total_visits, unique[0].unique_visits
    415 
    416 def getvisits():
    417     limit=100
    418     visits = db.query("SELECT * FROM visitors ORDER BY time DESC LIMIT " + str(limit))
    419     visitors = db.select('visitors')
    420     total = db.query('SELECT COUNT(*) AS total_visits FROM visitors')
    421     unique = db.query('SELECT COUNT(DISTINCT ip) AS unique_visits FROM visitors')
    422     countrylist=[]
    423     for i in visits:
    424         if i.countrycode not in countrylist:
    425             countrylist.append(i.countrycode)
    426             #print('fuuuuuuuuuuuuuuu: '+i.countrycode)
    427     return countrylist, total[0].total_visits, unique[0].unique_visits
    428 
    429 class stats:
    430     def GET(self):
    431         if logged():
    432             visitors, total, unique = getvisitors()
    433             return render.stats(visitors, total, unique)
    434         else:
    435             raise web.seeother('/login')
    436 
    437 class putinbag:
    438     def GET(self, p):
    439         addtobag(p)
    440         raise web.seeother('/')
    441 
    442 class dropitem():
    443     def GET(self, d):
    444         referer = web.ctx.env.get('HTTP_REFERER', 'none')
    445         p = web.input()
    446         i = 0
    447         empty=dropitems(d)
    448         if empty=='empty':
    449             return web.seeother('/shop?#'+d)
    450         return web.seeother(referer)
    451 
    452 class bigpic():
    453     def GET(self, i):
    454         print('faaaakyeee ' + i)
    455         p = web.input(pic=None)
    456         name=productname(i)
    457         goodies = db.query("SELECT * FROM soundlink WHERE id='"+i+"';")
    458         #if p.pic != None:
    459         return render.bigpic(i,name,goodies)
    460 
    461 class checkout():
    462     t = []
    463     shippingcountries = db.select('shipping', what='country', order='country ASC')
    464     shippingcountries = list(shippingcountries)
    465     #t.append('Finland')
    466     for i in shippingcountries:
    467         if i.country != 'NO-SHIPPING':
    468             t.append(i.country)
    469     shipping = web.form.Form(
    470     web.form.Textbox('email', web.form.notnull, description="Email:"),
    471     web.form.Dropdown('country', t, web.form.notnull, description="Country"),
    472     web.form.Textbox('firstname', web.form.notnull, description="First Name:"),
    473     web.form.Textbox('lastname', web.form.notnull, description="Last Name:"),
    474     web.form.Textbox('address', web.form.notnull, description="Shipping Address:"),
    475     web.form.Textbox('town', web.form.notnull, description="Town / City:"),
    476     web.form.Textbox('postalcode', web.form.regexp('\d+', 'number thanx!'), web.form.notnull, description="Postalcode / zip"),
    477     web.form.Button('Calculate shipping cost'))
    478     email = web.form.Form(
    479     web.form.Textbox('email', web.form.notnull, description="Email:"),
    480     web.form.Button('Okey, lets do it!'))
    481     def GET(self):
    482         i = web.input(error=None)
    483         pendinginfo = getpendinginfo()
    484         if ordertype()=='digital':
    485             checkoutform = self.email()
    486             if pendinginfo:
    487                 checkoutform.fill(email=pendinginfo.email)
    488         if ordertype()=='physical':
    489             checkoutform = self.shipping()
    490             if pendinginfo:
    491                 checkoutform.fill(country=pendinginfo.country, firstname=pendinginfo.firstname, lastname=pendinginfo.lastname, address=pendinginfo.address, town=pendinginfo.town, postalcode=pendinginfo.postalcode, email=pendinginfo.email)
    492         errormsg=''
    493         if i.error == 'mail':
    494             errormsg = 'Check your mail!'
    495         if i.error == 'shipping':
    496             errormsg = 'Check your shipping address!'
    497         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    498         return render.checkout(checkoutform,bag,productname,errormsg,db,getprice)
    499     def POST(self):
    500         physical=False
    501         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    502         checkoutform = self.email()
    503         for b in bag:
    504             if b.type=='physical':
    505                 checkoutform = self.shipping()
    506                 physical=True
    507                 break
    508         errormsg=''
    509         pendinginfo = getpendinginfo()
    510         i = web.input()
    511         if pendinginfo:
    512             if physical==True:
    513                 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())
    514             else:
    515                 db.update('pending', where="invoice_key='"+session.sessionkey+"'", invoice_key=session.sessionkey, email=i.email, dateadded=datetime.datetime.now())
    516         else:
    517             if physical==True:
    518                 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())
    519             else:
    520                 db.insert('pending', invoice_key=session.sessionkey, email=i.email, dateadded=datetime.datetime.now())
    521         if '@' not in i.email:
    522             web.seeother('/checkout?error=mail')
    523         elif not checkoutform.validates():
    524             return web.seeother('/checkout?error=shipping')
    525         else:
    526             return web.seeother('/pending')
    527 
    528 class pending:
    529     form = web.form.Form(
    530     web.form.Dropdown('payment', ['Bitcoin Lightning', 'Bitcoin'], web.form.notnull, description="Select payment method"),
    531     web.form.Button('Pay'))
    532     def GET(self):
    533         pendingform = self.form()
    534         pendinginfo = getpendinginfo()
    535         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    536         return render.pending(session.sessionkey,pendingform,pendinginfo,bag,productname,db,getprice,eur_to_sat,ordertype)
    537     def POST(self):
    538         pendingform = self.form()
    539         pendinginfo = getpendinginfo()
    540         i = web.input()
    541 
    542         #Calculate total amount of bag
    543         totalamount = 0
    544         description = ''
    545         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='" + session.sessionkey +"';")
    546         comma = ''
    547         for s in bag:
    548             totalamount += getprice(s.product)[0] * s.quantity
    549             description += comma + str(s.quantity) + ' x ' + productname(s.product)
    550             comma = ', '
    551         if ordertype()=='physical':
    552             shippinginfo = db.select('shipping', where="country='" + pendinginfo.country + "'", what='price, days')[0]
    553             totalamount += eur_to_sat(shippinginfo.price)
    554         totsats=totalamount
    555         totbtc=totsats/100000000
    556 
    557         #make lightning invoice
    558         print(str(totalamount) + ' | ' +  description)
    559         print(str(totsats) + ' | ' +  description)
    560         label = hashlib.sha256(str(random.getrandbits(64)).encode('utf-8')).hexdigest()[15:35]
    561         invoice = createinvoice(totsats, description, label)
    562         time.sleep(1)
    563         #print(invoice)
    564         callsubprocess('qrencode -s 3 -o '+ staticdir + 'qr/' + session.sessionkey+'.png '+invoice['bolt11'])
    565         #make bitcoin address
    566         bitcoinrpc = AuthServiceProxy(rpcauth)
    567         newaddress = bitcoinrpc.getnewaddress('Tarina Shop Butik')
    568         bitcoinrpc = None
    569         btcuri = 'bitcoin:' + newaddress + '?amount=' + str(totbtc) + '&label=' + description
    570         callsubprocess('qrencode -s 5 -o '+ staticdir + 'qr/' + newaddress +'.png ' + btcuri)
    571         try:
    572             db.query("DELETE FROM invoices WHERE invoice_key='"+session.sessionkey+"';")
    573         except:
    574             print('no old invoices to delete')
    575         db.insert('invoices', invoice_key=session.sessionkey, btc=newaddress, ln=label, products=description, payment=i.payment, amount=totalamount, totsats=totsats, timestamp=time.strftime('%Y-%m-%d %H:%M:%S'))
    576         if i.payment == 'Bitcoin':
    577             return web.seeother('/paybtc/' + session.sessionkey)
    578         if i.payment == 'Bitcoin Lightning':
    579             return web.seeother('/payln/' + session.sessionkey)
    580         return web.seeother('/')
    581 
    582 class payln:
    583     def GET(self, invoice_key):
    584         digitalkey = None
    585         invoice = db.select('invoices', where="invoice_key='"+invoice_key+"'")[0]
    586         lninvoice = getinvoice(invoice['ln'])
    587         if lninvoice['status'] == 'paid' and session.sessionkey != 'empty':
    588             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
    589             customer = db.select('pending', where="invoice_key='"+invoice_key+"'")[0]
    590             db.query("INSERT INTO paidbags SELECT * FROM customerbag WHERE sessionkey='" + invoice_key + "'")
    591             db.query("DELETE FROM customerbag WHERE sessionkey='" + invoice_key + "'")
    592             db.update("invoices",where='invoice_key="'+invoice_key+'"', status='paid')
    593             digitalkey=hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[15:35]
    594             db.insert('digitalkey', invoice_key=invoice_key, digitalkey=digitalkey, email=customer.email)
    595             session.sessionkey = 'empty'
    596             # send mail to op
    597             if ordertype()=='physical':
    598                 msg = 'You got a new order, from ' + customer.firstname + ' ' + customer.lastname + ' from ' + customer.country + ' email: ' + customer.email + ' this dude wantz ' + lninvoice['description']
    599             else:
    600                 msg='sup?'
    601             sendmail(webmaster, 'Gonzo Pi Shop', msg)
    602             # send mail to customer
    603             if ordertype()=='physical':
    604                 msg = "Thank you for order " + lninvoice['description'] + " at Tarina shop, 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
    605             else:
    606                 msg='sup? thanks! here the goodies '+baseurl+'/goodies/'+digitalkey
    607             sendmail(customer.email, 'Gonzo Pi Shop', msg)
    608             web.seeother('/payln/'+invoice_key)
    609         if lninvoice['status'] == 'paid':
    610             bag = db.query("SELECT * FROM paidbags WHERE sessionkey='"+invoice_key+"';")
    611             digitalkey = db.select('digitalkey', where="invoice_key='"+invoice_key+"'")[0]
    612         if lninvoice['status'] != 'paid':
    613             bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
    614         pendinginfo = getpendinginfo()
    615         return render.payln(lninvoice,invoice,bag,productname,digitalkey,db,getprice,getrate,ordertype,pendinginfo,eur_to_sat)
    616 
    617 class goodies():
    618     def GET(self, digitalkey):
    619         digitalkey = db.select('digitalkey', where="digitalkey='"+digitalkey+"'")[0]
    620         #digitalkeys = db.select('digitalkey', where="email='"+digitalkey.email+"'")
    621         digitalkeys = db.query("SELECT * FROM digitalkey WHERE email='"+digitalkey.email+"' ORDER BY timeadded DESC;")
    622         return render.goodies(digitalkey,digitalkeys,productname,db,getprice)
    623         #check all puraches with same email fuck ye
    624 
    625 class paybtc:
    626     def GET(self, invoice_key):
    627         invoice = db.select('invoices', where="invoice_key='" + invoice_key + "'", what='invoice_key, btc, ln, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped')[0]
    628         totbtc = float(invoice.totsats * 0.00000001)
    629         btcaddress = invoice.btc
    630         btcuri = 'bitcoin:' + btcaddress + '?amount=' + str(totbtc) + '&label=' + invoice.products
    631         bitcoinrpc = AuthServiceProxy(rpcauth)
    632         showpayment = bitcoinrpc.listreceivedbyaddress(0, True, True, btcaddress)
    633         bitcoinrpc = None
    634         if showpayment:
    635             for i in showpayment:
    636                 confirmations = int(i['confirmations'])
    637                 print(str(confirmations))
    638             if invoice.datepaid == None and confirmations > 6:
    639                 msg = 'Gonzo Pi shop order update! someone sent you Bitcoin! ' + baseurl + '/paybtc/' + invoice.invoice_key
    640                 print(msg)
    641                 sendmail(webmaster, 'Gonzo Pi Shop', msg)
    642                 db.update('invoices', where="invoice_key='" + invoice.invoice_key + "'", status='paid', datepaid=time.strftime('%Y-%m-%d %H:%M:%S'))
    643         pendinginfo = getpendinginfo()
    644         bag = db.query("SELECT * FROM customerbag WHERE sessionkey='"+invoice_key+"';")
    645         return render.paybtc(invoice, btcaddress, btcuri, showpayment, bag, productname, db, getprice, getrate, ordertype, pendinginfo, eur_to_sat)
    646 
    647 class orders():
    648     def GET(self):
    649         referer = web.ctx.env.get('HTTP_REFERER', 'none')
    650         listpayments=[]
    651         i=web.input(key=None,status=None)
    652         if i.key != None and i.status != None:
    653             db.update('invoices', where="invoice_key='" + i.key + "'", status=i.status)
    654             #get the right invoice send mail
    655             customer = db.select('pending', where="invoice_key='" + i.key + "'", what='country, firstname, lastname, address, town, postalcode, email')[0]
    656             payment = db.select('invoices', where="invoice_key='" + i.key + "'", what='btc, ln, invoice_key, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped')[0]
    657             if payment.payment == 'Bitcoin':
    658                 paylink = 'paybtc/'
    659             elif payment.payment == 'Bitcoin Lightning':
    660                 paylink = 'payln/'
    661             if i.status == 'thankyou':
    662                 msg="Hi " + customer.email + ", thank you for your order! You can track the status of your order at "+baseurl+'/'+paylink+i.key
    663                 sendmail(customer.email, 'Gonzo Pi Shop, a thank you!', msg)
    664             elif i.status == 'shipped':
    665                 msg="Hi " + customer.email + ", your order has been shipped!. You can track the status of your order at "+baseurl+'/'+paylink+i.key
    666                 sendmail(customer.email, 'Gonzo Pi Shop, your order has been shipped!', msg)
    667             elif i.status == 'paynotice':
    668                 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
    669                 sendmail(customer.email, 'Gonzo Pi Shop, order waiting for payment!', msg)
    670             elif i.status == 'paid':
    671                 msg="Hi " + customer.email + ", thank you! payment received. You can track the status of your order at " + baseurl + paylink + payment.invoice_key
    672                 sendmail(customer.email, 'Gonzo Pi Shop, order payment received', msg)
    673             raise web.seeother(referer)
    674         payments = db.select('invoices', what='btc, ln, invoice_key, products, payment, amount, totsats, timestamp, status, datepaid, dateshipped', order='timestamp DESC')
    675         if i.key == None and i.status != None:
    676             status = i.status
    677         else:
    678             status = ''
    679         totsats = 0
    680         paid = 0
    681         unpaid = 0
    682         shipped = 0
    683         nonshipped = 0
    684         pickup = 0
    685         removed=0
    686         for i in payments:
    687             ln = getinvoice(i.ln)
    688             print(ln)
    689             if ln['status'] == 'paid':
    690                 totsats=totsats+ln['amount_msat']
    691                 paid=paid+1
    692                 s = db.select('invoices', where="invoice_key='"+i.invoice_key+"'", what='status')[0]
    693                 if s.status == None:
    694                     db.update('invoices', where="invoice_key='"+i.invoice_key+"'", status='paid', datepaid=time.strftime('%Y-%m-%d %H:%M:%S'))
    695                 if i.status == 'shipped':
    696                     shipped=shipped+1
    697                 if i.status == 'paid':
    698                     nonshipped=nonshipped+1
    699                 if i.status == 'pickup':
    700                     pickup=pickup+1
    701                 if i.status == "removed":
    702                     removed=removed+1
    703             else:
    704                 s = db.select('invoices', where="invoice_key='"+i.invoice_key+"'", what='status')[0]
    705                 if s.status == None:
    706                     db.update('invoices', where="invoice_key='"+i.invoice_key+"'", status='unpaid', datepaid=time.strftime('%Y-%m-%d %H:%M:%S'))
    707                 if i.status != "removed":
    708                     unpaid=unpaid+1
    709                 if i.status == "removed":
    710                     removed=removed+1
    711         payments = db.select('invoices', order='timestamp DESC')
    712         return renderop.orders(payments,db,getinvoice,totsats,status,paid,unpaid,shipped,nonshipped,pickup,removed,productname,getprice)
    713 
    714 class payment:
    715     def GET(self, invoice_key):
    716         id = db.where('invoices', invoice_key=invoice_key)[0]['ln']
    717         invoice = getinvoice(id)
    718         return render.payment(invoice)
    719 
    720 class thankyou:
    721     def GET(self, id):
    722         return render.thankyou(id)
    723 
    724 class login:
    725     form = web.form.Form(
    726     web.form.Textbox('user', web.form.notnull, description="User"),
    727     web.form.Password('password', web.form.notnull, description="Passcode"),
    728     web.form.Button('Login'))
    729     def GET(self):
    730         if not logged():
    731             loginform = self.form()
    732             return render.login(loginform)
    733         else:
    734             raise web.seeother('/op')
    735     def POST(self):
    736         loginform = self.form()
    737         if not loginform.validates():
    738             return render.login(loginform)
    739         else:
    740             i = web.input()
    741             if (i.user,i.password) in allowed:
    742                 session.login = 1
    743                 raise web.seeother('/op')
    744             else:
    745                 return render.login(loginform)
    746 
    747 class logout:
    748     def GET(self):
    749         session.login = 0
    750         raise web.seeother('/')
    751 
    752 class op:
    753     def GET(self):
    754         if logged():
    755             return renderop.operator()
    756         else:
    757             raise web.seeother('/login')
    758 
    759 class propaganda:
    760     form = web.form.Form(
    761     web.form.Textbox('name', web.form.notnull, description="Site name:"),
    762     web.form.Textarea('description', web.form.notnull, description="Slogan:"),
    763     web.form.Textarea('description2', web.form.notnull, description="Description:"),
    764     web.form.Button('Save'))
    765     picform = web.form.Form(
    766     web.form.Textbox('name', web.form.notnull, description="Picture header:"),
    767     web.form.Textarea('description', web.form.notnull, description="Description:"),
    768     web.form.Textarea('description2', web.form.notnull, description="More:"),
    769     web.form.Textarea('id', web.form.notnull, description="id:"),
    770     web.form.Button('Save'))
    771     def GET(self):
    772         if logged():
    773             i = web.input(cmd=None,soundname=None)
    774             nocache = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[11:15]
    775             if i.cmd == 'remove' and i.soundname != None:
    776                 try:
    777                     os.remove(staticdir+'/img/thumb/'+i.soundname)
    778                     os.remove(staticdir+'/img/web/'+i.soundname)
    779                 except:
    780                     print('notin to delete')
    781                 goodies = db.query("DELETE FROM propagandapics WHERE soundname='"+i.soundname+"';")
    782                 raise web.seeother('/propaganda')
    783             if i.cmd == 'flipright' and i.soundname != None:
    784                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
    785                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
    786                 o_thumb=original_thumb.rotate(270)
    787                 o_web=original_web.rotate(270)
    788                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
    789                 o_web.save(staticdir+'/img/web/'+i.soundname)
    790                 raise web.seeother('/propaganda')
    791             if i.cmd == 'flipleft' and i.soundname != None:
    792                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
    793                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
    794                 o_thumb=original_thumb.rotate(90)
    795                 o_web=original_web.rotate(90)
    796                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
    797                 o_web.save(staticdir+'/img/web/'+i.soundname)
    798                 raise web.seeother('/propaganda')
    799             configsite = self.form()
    800             picturetext = self.picform()
    801             try:
    802                 oldsiteconfig = db.select('propaganda', what='id, name, description, description2')[0]
    803                 configsite.fill(name=oldsiteconfig.name, description=oldsiteconfig.description, description2=oldsiteconfig.description2)
    804             except:
    805                 print('no non no')
    806             goodies = db.query("SELECT * FROM propagandapics;")
    807             return renderop.propaganda(configsite, picturetext, goodies, nocache)
    808         else:
    809             raise web.seeother('/login')
    810     def POST(self):
    811         addcategory = self.form()
    812         i = web.input(imgfile={}, name=None, id=None)
    813         if i.id != None:
    814             db.update('propagandapics', where='soundlink="'+i.id+'"', name=i.name, description=i.description, description2=i.description2 )
    815             raise web.seeother('/propaganda')
    816         if i.name != None:
    817             #db.insert('propaganda', name=i.name, description=i.description, description2=i.description2 )
    818             db.update('propaganda', where='id=1', name=i.name, description=i.description, description2=i.description2 )
    819         if i.imgfile != {}:
    820             if i.imgfile.filename == '':
    821                 print('hmmm... no image to upload')
    822                 raise web.seeother('/config/')
    823             print('YEAH, Upload image!')
    824             ##---------- UPLOAD IMAGE ----------
    825             filepath=i.imgfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
    826             #split and only take the filename with extension
    827             #soundpath=filepath.split('/')[-1]
    828             #if soundpath == '':
    829             #    return render.nope("strange, no filename found!")
    830             #get filetype, last three 
    831             imgname=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
    832             filetype = imgname.split('.')[-1].lower()
    833             if filetype == 'jpg':
    834                 filetype = 'jpeg'
    835             soundname = imgname.split('.')[0]
    836             #lets remove unwanted characters yes please!
    837             sound = ''
    838             for p in soundname.lower():
    839                 if p in allowedchar:
    840                     sound = sound + p
    841             if sound == '':
    842                 raise web.seeother('/upload?fail=wierdname')
    843             soundname = sound + '_Gonzo_Pi.' + filetype
    844             print(soundname)
    845             print("filename is " + imgname + " filetype is " + filetype + " soundname is " + soundname + " trying to upload file from: " + filepath)
    846             #if filetype != 'wav' or 'ogg' or 'flac' or 'jpeg' or 'jpg' or 'mp3':
    847             #    web.seeother('/upload?fail=notsupported')
    848             #imghash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    849             #imgname = imghash
    850             #imgname = str(len(os.listdir(imgdir))).zfill(3) + '.jpeg'
    851             soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
    852             imgdir = staticdir+'upload/'+soundlink+'/'
    853             os.system('mkdir -p ' + imgdir)
    854             fout = open(imgdir + soundname,'wb') # creates the file where the uploaded file should be stored
    855             fout.write(i.imgfile.file.read()) # writes the uploaded file to the newly created file.
    856             fout.close() # closes the file, upload complete. 
    857             db.insert('propagandapics', soundlink=soundlink, soundname=soundname, timeadded=datetime.datetime.now())
    858             if filetype == 'jpeg' or filetype == 'png':
    859                 ##---------- OPEN FILE & CHEKC IF JPEG --------
    860                 image = Image.open(imgdir + soundname)
    861                 #if image.format != 'JPEG':
    862                 #    os.remove(imgdir +'/'+ soundname)
    863                 #    raise web.seeother('/products/' + idvalue)
    864 
    865                 ##---------- RESIZE IMAGE SAVE TO PRODUCT-----------
    866                 imgdir=staticdir+'img'
    867                 try:
    868                     os.makedirs(imgdir + '/web/', exist_ok=True)
    869                     os.makedirs(imgdir + '/thumb/', exist_ok=True)
    870                 except:
    871                     print('Folders is')
    872                 image.thumbnail((1500,1500), Image.ANTIALIAS)
    873                 image.save(imgdir + '/web/'+soundname)
    874                 image.thumbnail((500,500), Image.ANTIALIAS)
    875                 image.save(imgdir + '/thumb/'+soundname) 
    876         raise web.seeother('/propaganda')
    877 
    878 class uploads:
    879     def GET(self):
    880         if logged():
    881             uploaded = getfiles(staticdir+'upload/')
    882             return render.uploads(uploaded)
    883 
    884 class config:
    885     form = web.form.Form(
    886     web.form.Textbox('name', web.form.notnull, description="Site name:"),
    887     web.form.Textarea('description', web.form.notnull, description="Slogan:"),
    888     web.form.Textarea('description2', web.form.notnull, description="Description:"),
    889     web.form.Button('Save'))
    890     def GET(self):
    891         if logged():
    892             configsite = self.form()
    893             try:
    894                 oldsiteconfig = db.select('siteconfig', what='id, name, description, description2')[0]
    895                 configsite.fill(name=oldsiteconfig.name, description=oldsiteconfig.description, description2=oldsiteconfig.description2)
    896             except:
    897                 print('no non no')
    898             return renderop.config(configsite)
    899         else:
    900             raise web.seeother('/login')
    901     def POST(self):
    902         addcategory = self.form()
    903         i = web.input(imgfile={}, name=None)
    904         if i.name != None:
    905             db.update('siteconfig', where='id=1', name=i.name, description=i.description, description2=i.description2 )
    906         if i.imgfile != {}:
    907             if i.imgfile.filename == '':
    908                 print('hmmm... no image to upload')
    909                 raise web.seeother('/config/')
    910             print('YEAH, Upload image!')
    911 
    912             ##---------- UPLOAD IMAGE ----------
    913 
    914             filepath=i.imgfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
    915             #split and only take the filename with extension
    916             #soundpath=filepath.split('/')[-1]
    917             #if soundpath == '':
    918             #    return render.nope("strange, no filename found!")
    919             #get filetype, last three 
    920             imgname=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
    921             filetype = imgname.split('.')[-1].lower()
    922             if filetype == 'jpg':
    923                 filetype = 'jpeg'
    924             soundname = imgname.split('.')[0]
    925             #lets remove unwanted characters yes please!
    926             sound = ''
    927             for p in soundname.lower():
    928                 if p in allowedchar:
    929                     sound = sound + p
    930             if sound == '':
    931                 raise web.seeother('/upload?fail=wierdname')
    932             soundname = 'logo.' + filetype
    933             print(soundname)
    934             print("filename is " + imgname + " filetype is " + filetype + " soundname is " + soundname + " trying to upload file from: " + filepath)
    935             #if filetype != 'wav' or 'ogg' or 'flac' or 'jpeg' or 'jpg' or 'mp3':
    936             #    web.seeother('/upload?fail=notsupported')
    937             #imghash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
    938             #imgname = imghash
    939             #imgname = str(len(os.listdir(imgdir))).zfill(3) + '.jpeg'
    940             soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
    941             imgdir = staticdir+'upload/'
    942             os.system('mkdir -p ' + imgdir)
    943             fout = open(imgdir + soundname,'wb') # creates the file where the uploaded file should be stored
    944             fout.write(i.imgfile.file.read()) # writes the uploaded file to the newly created file.
    945             fout.close() # closes the file, upload complete.
    946             
    947             if filetype == 'jpeg' or filetype == 'png':
    948                 ##---------- OPEN FILE & CHEKC IF JPEG --------
    949 
    950                 image = Image.open(imgdir + soundname)
    951                 #if image.format != 'JPEG':
    952                 #    os.remove(imgdir +'/'+ soundname)
    953                 #    raise web.seeother('/products/' + idvalue)
    954 
    955                 ##---------- RESIZE IMAGE SAVE TO PRODUCT-----------
    956 
    957                 imgdir=staticdir+'img'
    958                 try:
    959                     os.makedirs(imgdir + '/web/', exist_ok=True)
    960                     os.makedirs(imgdir + '/thumb/', exist_ok=True)
    961                 except:
    962                     print('Folders is')
    963                 image.thumbnail((900,900), Image.ANTIALIAS)
    964                 image.save(imgdir + '/web/'+soundname)
    965                 image.thumbnail((300,300), Image.ANTIALIAS)
    966                 image.save(imgdir + '/thumb/'+soundname) 
    967         raise web.seeother('/config')
    968 
    969 class categories:
    970     form = web.form.Form(
    971     web.form.Textbox('category', web.form.notnull, description="Add Category:"),    
    972     web.form.Button('Add'))
    973     def GET(self):
    974         if logged():
    975             i = web.input(delete=None)
    976             if i.delete:
    977                 db.delete('categories', where='id='+i.delete)
    978             listcategories = db.query("SELECT * FROM categories ORDER BY id DESC")
    979             addcategory = self.form()
    980             return renderop.categories(listcategories,addcategory)
    981         else:
    982             raise web.seeother('/login')
    983     def POST(self):
    984         addcategory = self.form()
    985         i = web.input()
    986         db.insert('categories', category=i.category)
    987         raise web.seeother('/categories')
    988 
    989 
    990 class products:
    991     listcategories = db.query("SELECT * FROM categories ORDER BY id DESC")
    992     p = []
    993     for i in listcategories:
    994         p.append(i.category)
    995     #p = listcategories[0]
    996     form = web.form.Form(
    997     web.form.Dropdown('category', p, web.form.notnull, description="Category:"),
    998     web.form.Textbox('name', web.form.notnull, description="Name:"),
    999     web.form.Textarea('description', web.form.notnull, description="Description:"),
   1000     web.form.Radio('type', ['digital', 'physical'],description="Type:"),
   1001     web.form.Radio('currency', ['euro', 'bitcoin'],description="Currency:"),
   1002     web.form.Textbox('price', web.form.regexp('\d+', 'number thanx!'), web.form.notnull, description="Price:"),
   1003     web.form.Textbox('available', web.form.notnull, web.form.regexp('\d+', 'number dumbass!'), description="Available"),
   1004     web.form.Textbox('priority', web.form.notnull, web.form.regexp('\d+', 'number dumbass!'), description="Priority (high value more priority)"),
   1005     web.form.Button('Save'))
   1006     def GET(self, idvalue):
   1007         if logged():
   1008             i = web.input(cmd=None,soundname=None)
   1009             nocache = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[11:15]
   1010             if i.cmd == 'del':
   1011                 db.delete('products', where='id="'+idvalue+'"')
   1012                 imgdir = staticdir + 'img/' + idvalue
   1013                 try:
   1014                     shutil.rmtree(imgdir,ignore_errors=True,onerror=None)
   1015                 except:
   1016                     print('no picture folder, nothing to remove...')
   1017                     pass
   1018                 raise web.seeother('/products/')
   1019             if i.cmd == 'remove' and i.soundname != None:
   1020                 try:
   1021                     os.remove(staticdir+'/img/thumb/'+i.soundname)
   1022                     os.remove(staticdir+'/img/web/'+i.soundname)
   1023                 except:
   1024                     print('notin to delete')
   1025                 goodies = db.query("DELETE FROM soundlink WHERE id='"+idvalue+"' AND soundname='"+i.soundname+"';")
   1026                 raise web.seeother('/products/' + idvalue)
   1027             if i.cmd == 'flipright' and i.soundname != None:
   1028                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
   1029                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
   1030                 o_thumb=original_thumb.rotate(270)
   1031                 o_web=original_web.rotate(270)
   1032                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
   1033                 o_web.save(staticdir+'/img/web/'+i.soundname)
   1034                 raise web.seeother('/products/' + idvalue)
   1035             if i.cmd == 'flipleft' and i.soundname != None:
   1036                 original_thumb = Image.open(staticdir+'/img/thumb/'+i.soundname) 
   1037                 original_web = Image.open(staticdir+'/img/web/'+i.soundname) 
   1038                 o_thumb=original_thumb.rotate(90)
   1039                 o_web=original_web.rotate(90)
   1040                 o_thumb.save(staticdir+'/img/thumb/'+i.soundname)
   1041                 o_web.save(staticdir+'/img/web/'+i.soundname)
   1042                 raise web.seeother('/products/' + idvalue)
   1043             addproduct = self.form()
   1044             addproduct.fill(available='1', priority='1', type='physical',currency='euro')
   1045             goodies = None
   1046             if idvalue:
   1047                 oldinfo = db.query("SELECT * FROM products WHERE id='"+idvalue+"';")[0]
   1048                 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)
   1049                 goodies = db.query("SELECT * FROM soundlink WHERE id='"+idvalue+"';")
   1050             listproducts = db.query("SELECT * FROM products ORDER BY priority DESC")
   1051             return renderop.products(addproduct, listproducts, goodies, idvalue, nocache)
   1052         else:
   1053             raise web.seeother('/login') 
   1054     def POST(self, idvalue):
   1055         listproducts = db.query("SELECT * FROM products ORDER BY priority DESC")
   1056         addproduct = self.form()
   1057         if logged():
   1058             i = web.input(imgfile={},name=None,description=None,price=1,available=1)
   1059             #for p in i:q
   1060             #    print(p)
   1061             if i.name != None:
   1062                 if idvalue:
   1063                     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())
   1064                 else:
   1065                     idvalue = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[11:36]
   1066                     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())
   1067             if i.imgfile != {}:
   1068                 if idvalue == '':
   1069                     print('cant upload a picture to a non existing product')
   1070                     raise web.seeother('/products/')
   1071                 print(i.imgfile.filename)
   1072                 if i.imgfile.filename == '':
   1073                     print('hmmm... no image to upload')
   1074                     raise web.seeother('/products/' + idvalue)
   1075                 print('YEAH, Upload image!')
   1076 
   1077                 ##---------- UPLOAD IMAGE ----------
   1078 
   1079                 filepath=i.imgfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
   1080                 #split and only take the filename with extension
   1081                 #soundpath=filepath.split('/')[-1]
   1082                 #if soundpath == '':
   1083                 #    return render.nope("strange, no filename found!")
   1084                 #get filetype, last three 
   1085                 imgname=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
   1086                 filetype = imgname.split('.')[-1].lower()
   1087                 if filetype == 'jpg':
   1088                     filetype = 'jpeg'
   1089                 soundname = imgname.split('.')[0]
   1090                 #lets remove unwanted characters yes please!
   1091                 sound = ''
   1092                 for p in soundname.lower():
   1093                     if p in allowedchar:
   1094                         sound = sound + p
   1095                 if sound == '':
   1096                     raise web.seeother('/upload?fail=wierdname')
   1097                 soundname = sound + '.' + filetype
   1098                 print(soundname)
   1099                 print("filename is " + imgname + " filetype is " + filetype + " soundname is " + soundname + " trying to upload file from: " + filepath)
   1100                 #if filetype != 'wav' or 'ogg' or 'flac' or 'jpeg' or 'jpg' or 'mp3':
   1101                 #    web.seeother('/upload?fail=notsupported')
   1102                 #imghash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
   1103                 #imgname = imghash
   1104                 #imgname = str(len(os.listdir(imgdir))).zfill(3) + '.jpeg'
   1105                 soundlink = hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()[9:36]
   1106                 imgdir = staticdir+'upload/'+soundlink+'/'
   1107                 os.system('mkdir -p ' + imgdir)
   1108                 fout = open(imgdir + soundname,'wb') # creates the file where the uploaded file should be stored
   1109                 fout.write(i.imgfile.file.read()) # writes the uploaded file to the newly created file.
   1110                 fout.close() # closes the file, upload complete.
   1111                 
   1112                     ##----------CHECK IF SAME NAME THEN UPDATE-------
   1113                 slink = db.query("SELECT * FROM soundlink WHERE id='"+idvalue+"' AND soundname='"+soundname+"';")
   1114                 if slink:
   1115                     db.update('soundlink', where='"id='+idvalue+'"', soundlink=soundlink, soundname=soundname, timeadded=datetime.datetime.now())
   1116                 else:
   1117                     db.insert('soundlink', id=idvalue, soundlink=soundlink, soundname=soundname, timeadded=datetime.datetime.now())
   1118 
   1119                 if filetype == 'jpeg' or filetype == 'png':
   1120                     ##---------- OPEN FILE & CHEKC IF JPEG --------
   1121 
   1122                     image = Image.open(imgdir +'/'+ soundname)
   1123                     #if image.format != 'JPEG':
   1124                     #    os.remove(imgdir +'/'+ soundname)
   1125                     #    raise web.seeother('/products/' + idvalue)
   1126 
   1127                     ##---------- RESIZE IMAGE SAVE TO PRODUCT-----------
   1128 
   1129                     imgdir=staticdir+'img'
   1130                     try:
   1131                         os.makedirs(imgdir + '/web/', exist_ok=True)
   1132                         os.makedirs(imgdir + '/thumb/', exist_ok=True)
   1133                     except:
   1134                         print('Folders is')
   1135                     image.thumbnail((900,900), Image.ANTIALIAS)
   1136                     image.save(imgdir + '/web/'+soundname)
   1137                     image.thumbnail((300,300), Image.ANTIALIAS)
   1138                     image.save(imgdir + '/thumb/'+soundname) 
   1139 
   1140             return web.seeother('/products/' + idvalue)
   1141         else:
   1142             return web.seeother('/login')
   1143 
   1144 class shipping:
   1145     form = web.form.Form(
   1146     web.form.Textbox('country', web.form.notnull, description="Country:"),
   1147     web.form.Textbox('price', web.form.regexp('\d+', 'number thanx!'), web.form.notnull, description="Price in cents"),
   1148     web.form.Textbox('days', web.form.regexp('\d+', 'number thanx!'), web.form.notnull, description="Shipping in days"),
   1149     web.form.Button('Add shipping country'))
   1150     def GET(self, idvalue):
   1151         if logged():
   1152             addcountry = self.form()
   1153             if idvalue:
   1154                 oldinfo = db.select('shipping', where="id='"+idvalue+"'", what='country, price, days')
   1155                 oldinfo = oldinfo[0]
   1156                 addcountry.fill(country=oldinfo.country, price=oldinfo.price, days=oldinfo.days)
   1157             listcountries = db.query("SELECT * FROM shipping ORDER BY country DESC")
   1158             return renderop.shipping(addcountry, listcountries)
   1159         else:
   1160             raise web.seeother('/login')
   1161     def POST(self, idvalue):
   1162         if logged():
   1163             addcountry = self.form()
   1164             if not addcountry.validates():
   1165                 listcountries = db.query("SELECT * FROM shipping ORDER BY country DESC")
   1166                 return renderop.shipping(addcountry, listcountries)
   1167             else:
   1168                 i = web.input()
   1169                 if idvalue:
   1170                     db.update('shipping', where='id="'+idvalue+'"', country=i.country, price=i.price, days=i.days)
   1171                 else:
   1172                     db.insert('shipping', country=i.country, price=i.price, days=i.days)
   1173                 raise web.seeother('/shipping/')
   1174         else:
   1175             raise web.seeother('/login')
   1176 
   1177 class bitcoin:
   1178     def GET(self):
   1179         if logged():
   1180             bitcoinrpc = AuthServiceProxy(rpcauth)
   1181             wallet = bitcoinrpc.getwalletinfo()
   1182             bitcoinrpc = None
   1183             return renderop.bitcoin(wallet)
   1184 
   1185 application = app.wsgifunc()