213 lines
5.4 KiB
Python
Raw Normal View History

from flask import Flask, request
import psycopg2 as psql
from os import environ as env
import datetime
import time
import threading
import uuid
app = Flask(__name__)
db_params = {
'database': env.get('DB_NAME'),
'user': env.get('DB_USER'),
'password': env.get('DB_PASS'),
'host': env.get('DB_HOST'),
'port': int(env.get('DB_PORT'))
}
db = psql.connect(**db_params)
class PassQueue:
def __init__(self):
self.queue = []
def start(self):
while True:
if not self.queue:
time.sleep(1)
continue
p = self.queue.pop(0)
c = db.cursor()
try:
c.execute("BEGIN")
c.execute(f"INSERT INTO public.pass (uuid, movie_uuid, user_first, user_last, user_email, pass_type, pass_price, pass_requested_at, payment_received)"
f"VALUES ('{uuid.uuid4().hex}', '{p.movie_uuid}', '{p.first}', '{p.last}', '{p.email}', {p.type}, {p.price}, '{time.strftime('%Y-%m-%d %H:%M:%S')}', false)")
c.execute("COMMIT")
db.commit()
except Exception as e:
print(e)
c.execute("ROLLBACK")
db.rollback()
pq = PassQueue()
pq_thread = threading.Thread(target = pq.start, args = [])
pq_thread.start()
@app.route("/movies", methods = ['GET'])
def movies():
c = db.cursor()
fields = ['uuid',
'name',
'scheduled_datetime',
'movie_details',
'image_url',
'max_passes']
try:
c.execute(f"SELECT {','.join(fields)} FROM public.movie")
except Exception as e:
c.close()
print(e)
return {
"error": "Failed to list movies",
"result": None
}, 503
res = c.fetchall()
c.close()
return {
"error": "",
"result": [{fields[i]: v
if type(v) != datetime.datetime
else v.strftime("%Y-%m-%d %H:%M:%S")
for i, v in enumerate(r)}
for r in res]
}
@app.route("/movie/<movie_uuid>", methods = ['GET'])
def movie_byid(movie_uuid):
c = db.cursor()
fields = ['name',
'scheduled_datetime',
'movie_details',
'image_url',
'max_passes']
try:
c.execute(f"SELECT {','.join(fields)} FROM public.movie WHERE uuid='{movie_uuid}'")
except Exception as e:
c.close()
print(e)
return {
"error": "Failed to search for a movie",
"result": None
}, 503
res = c.fetchone()
c.close()
if res:
return {
"error": "",
"result": {fields[i]: v
if type(v) != datetime.datetime
else v.strftime("%Y-%m-%d %H:%M:%S")
for i, v in enumerate(res)}
}
else:
return {
"error": f"No movie with uuid={movie_uuid} has been found",
"result": None
}, 404
@app.route("/passes", methods = ['GET'])
def passes():
c = db.cursor()
fields = ["uuid",
"movie_uuid",
"user_first",
"user_last",
"user_email",
"pass_type",
"pass_price",
"pass_requested_at",
"payment_received",
"payment_received_at"]
try:
c.execute(f"SELECT {','.join(fields)} FROM public.pass")
except Exception as e:
c.close()
print(e)
return {
"error": "Failed to list out passes",
"result": None
}
res = c.fetchall()
c.close()
return {
"error": "",
"result": [{fields[i]: v
if type(v) != datetime.datetime
else v.strftime("%Y-%m-%d %H:%M:%S")
for i, v in enumerate(r)}
for r in res]}
class PassValidator:
def __init__(self):
self.first = None
self.last = None
self.email = None
self.type = None
self.price = None
self.movie_uuid = None
def validate(self):
if not self.first:
return "First name missing"
elif not self.last:
return "Last name missing"
elif not self.email:
return "Email missing"
elif not self.type:
return "Pass type missing"
elif not self.price:
return "Pass price missing"
elif not self.movie_uuid:
return "Movie uuid missing"
def queue(self):
pq.queue.append(self)
def fill_pass_from_form(p, f):
print(f)
def fill_pass_from_json(p, j):
fields = ("first",
"last",
"email",
"type",
"price",
"movie_uuid")
for i in fields:
exec(f"p.{i} = j.get('{i}')")
@app.route("/apply_for_pass", methods = ['POST'])
def apply_for_pass():
p = PassValidator()
if request.form:
fill_pass_from_form(p, request.form)
elif request.is_json:
fill_pass_from_json(p, request.json)
else:
return {"error": "only form and json interfaces are supported", "result": None}, 403
v = p.validate()
if not v:
p.queue()
return {"error": None, "result": "OK"}
else:
return {"error": v, "result": None}