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