thiswebshoprules

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

server.py (53559B)


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