144 lines
3.7 KiB
Python
144 lines
3.7 KiB
Python
from flask import Blueprint, render_template, redirect, request, flash, url_for, jsonify
|
|
from flask import current_app as app
|
|
import six
|
|
|
|
import qrcode
|
|
import qrcode.image.svg
|
|
|
|
from bitvend import dev, proc
|
|
from bitvend.models import db, User, Transaction, NoFunds
|
|
from bitvend.forms import TransferForm
|
|
from bitvend.graphs import gen_main_graph
|
|
|
|
from spaceauth import login_required, current_user, cap_required
|
|
|
|
bp = Blueprint("bitvend", __name__, template_folder="templates")
|
|
|
|
|
|
@bp.route("/")
|
|
def index():
|
|
transactions = []
|
|
hallofshame = (
|
|
User.query.with_entities(User, User.balance)
|
|
.order_by(User.balance.asc())
|
|
.filter(User.balance < 0)
|
|
.limit(5)
|
|
.all()
|
|
)
|
|
|
|
hallofaddicts = (
|
|
User.query.with_entities(User, User.purchase_amount, User.purchase_count)
|
|
.order_by(User.purchase_amount.desc())
|
|
.filter(User.purchase_amount > 0)
|
|
.limit(5)
|
|
.all()
|
|
)
|
|
|
|
bottles_purchased = Transaction.query.filter(
|
|
Transaction.amount.in_([-500, -600]), Transaction.type == "purchase"
|
|
).count()
|
|
|
|
if current_user.is_authenticated:
|
|
transactions = current_user.transactions.order_by(
|
|
Transaction.created.desc()
|
|
).limit(10)
|
|
|
|
return render_template(
|
|
"index.html",
|
|
items=app.config["ITEMS"],
|
|
transactions=transactions,
|
|
transfer_form=TransferForm(),
|
|
hallofshame=hallofshame,
|
|
hallofaddicts=hallofaddicts,
|
|
bottles_purchased=bottles_purchased,
|
|
)
|
|
|
|
|
|
@bp.route("/transactions/", defaults={"page": 1})
|
|
@bp.route("/transactions/p/<int:page>")
|
|
def transactions(page):
|
|
return render_template(
|
|
"transactions.html", transactions=current_user.transactions.paginate(page)
|
|
)
|
|
|
|
|
|
@bp.route("/transfer", methods=["GET", "POST"])
|
|
def transfer():
|
|
transfer_form = TransferForm()
|
|
|
|
if transfer_form.validate_on_submit():
|
|
try:
|
|
current_user.transfer(
|
|
User.query.get(transfer_form.target.data), transfer_form.amount.data
|
|
)
|
|
db.session.commit()
|
|
flash("Transfer succeeded.", "success")
|
|
except NoFunds:
|
|
flash("No funds.", "danger")
|
|
return redirect(url_for(".index"))
|
|
|
|
flash("; ".join(sum(transfer_form.errors.values(), [])), "danger")
|
|
|
|
return redirect(url_for(".index"))
|
|
|
|
|
|
@bp.route("/log")
|
|
@login_required
|
|
@cap_required("staff")
|
|
def log():
|
|
return render_template("log.html", transactions=Transaction.query.all())
|
|
|
|
|
|
@bp.route("/begin")
|
|
@login_required
|
|
def begin():
|
|
if Transaction.query.filter(Transaction.finished == False).count():
|
|
flash("Nope xD", "danger")
|
|
return redirect(url_for(".index"))
|
|
|
|
if current_user.amount_available <= 0:
|
|
flash("Nope xD", "danger")
|
|
return redirect(url_for(".index"))
|
|
|
|
tx = Transaction(type="purchase")
|
|
current_user.transactions.append(tx)
|
|
db.session.commit()
|
|
|
|
dev.begin_session(current_user.amount_available, tx.id)
|
|
return redirect(url_for(".index"))
|
|
|
|
|
|
@bp.route("/cancel")
|
|
@login_required
|
|
def cancel():
|
|
dev.cancel_session()
|
|
|
|
# FIXME racey
|
|
|
|
Transaction.query.filter(Transaction.finished == False).delete()
|
|
db.session.commit()
|
|
|
|
return redirect(url_for(".index"))
|
|
|
|
|
|
@bp.route("/qrcode/<path:data>")
|
|
def qrcode_gen(data):
|
|
bio = six.BytesIO()
|
|
qr = qrcode.QRCode(border=0, box_size=50)
|
|
qr.add_data(data)
|
|
img = qr.make_image(image_factory=qrcode.image.svg.SvgPathFillImage)
|
|
img.save(bio)
|
|
return (
|
|
bio.getvalue(),
|
|
200,
|
|
{
|
|
"Content-Type": "image/svg+xml",
|
|
"Cache-Control": "public,max-age=3600",
|
|
},
|
|
)
|
|
|
|
|
|
@bp.route("/api/1/history.json")
|
|
def history():
|
|
return jsonify(gen_main_graph())
|