mirror of https://github.com/lukechilds/lnbits.git
committed by
GitHub
7 changed files with 583 additions and 0 deletions
@ -0,0 +1,8 @@ |
|||
from flask import Blueprint |
|||
|
|||
|
|||
tpos_ext = Blueprint("tpos", __name__, static_folder="static", template_folder="templates") |
|||
|
|||
|
|||
from .views_api import * # noqa |
|||
from .views import * # noqa |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"name": "TPOS", |
|||
"short_description": "A shareable POS.", |
|||
"ion_icon": "calculator" |
|||
} |
@ -0,0 +1,9 @@ |
|||
/* create your extensions table and the variables needed here */ |
|||
CREATE TABLE IF NOT EXISTS tpos ( |
|||
key INTEGER PRIMARY KEY AUTOINCREMENT, |
|||
nme TEXT, |
|||
uni TEXT, |
|||
usr TEXT, |
|||
invkey TEXT |
|||
); |
|||
|
@ -0,0 +1,211 @@ |
|||
<!-- @format --> |
|||
|
|||
{% extends "base.html" %} {% block messages %} |
|||
|
|||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> |
|||
<i class="fa fa-bell-o"></i> |
|||
<span class="label label-danger">!</span> |
|||
</a> |
|||
<ul class="dropdown-menu"> |
|||
<li class="header"><b>Instant wallet, bookmark to save</b></li> |
|||
<li></li> |
|||
</ul> |
|||
{% endblock %} |
|||
|
|||
|
|||
{% block menuitems %} |
|||
<li class="treeview"> |
|||
<a href="#"> |
|||
<i class="fa fa-bitcoin"></i> <span>Wallets</span> |
|||
<i class="fa fa-angle-left pull-right"></i> |
|||
</a> |
|||
<ul class="treeview-menu"> |
|||
{% for w in user_wallets %} |
|||
<li> |
|||
<a href="{{ url_for('wallet') }}?wal={{ w.id }}&usr={{ w.user }}"><i class="fa fa-bolt"></i> {{ w.name }}</a> |
|||
</li> |
|||
{% endfor %} |
|||
<li><a onclick="sidebarmake()">Add a wallet +</a></li> |
|||
<div id="sidebarmake"></div> |
|||
</ul> |
|||
</li> |
|||
<li class="active treeview"> |
|||
<a href="#"> |
|||
<i class="fa fa-th"></i> <span>Extensions</span> |
|||
<i class="fa fa-angle-left pull-right"></i> |
|||
</a> |
|||
<ul class="treeview-menu"> |
|||
{% for extension in EXTENSIONS %} |
|||
{% if extension.code in user_ext %} |
|||
<li> |
|||
<a href="{{ url_for(extension.code + '.index') }}?usr={{ user }}"><i class="fa fa-plus"></i> {{ extension.name }}</a> |
|||
</li> |
|||
{% endif %} |
|||
{% endfor %} |
|||
<li> |
|||
<a href="{{ url_for('extensions') }}?usr={{ user }}">Manager</a></li> |
|||
</ul> |
|||
</li> |
|||
{% endblock %} |
|||
|
|||
{% block body %} |
|||
<!-- Right side column. Contains the navbar and content of the page --> |
|||
<div class="content-wrapper"> |
|||
<!-- Content Header (Page header) --> |
|||
<section class="content-header"> |
|||
<h1> |
|||
Withdraw link maker |
|||
<small>powered by LNURL</small> |
|||
|
|||
</h1> |
|||
<ol class="breadcrumb"> |
|||
<li> |
|||
<a href="{{ url_for('wallet') }}?usr={{ user }}"><i class="fa fa-dashboard"></i> Home</a> |
|||
</li> |
|||
<li> |
|||
<a href="{{ url_for('extensions') }}?usr={{ user }}"><li class="fa fa-dashboard">Extensions</li></a> |
|||
</li> |
|||
<li> |
|||
<i class="active" class="fa fa-dashboard">example</i> |
|||
</li> |
|||
</ol> |
|||
<br /><br /> |
|||
|
|||
|
|||
|
|||
<!-- DOWNLOAD AND SEARCH ADMINLITE2 FOR HTML--> |
|||
|
|||
<section class="content"> |
|||
<!-- Small boxes (Stat box) --> |
|||
<div class="row"> |
|||
|
|||
<div class="col-md-6"> |
|||
<!-- general form elements --> |
|||
<div class="box box-primary"> |
|||
<div class="box-header"> |
|||
<h3 class="box-title"> Make a POS</h3> |
|||
</div><!-- /.box-header --> |
|||
<!-- form start --> |
|||
<form role="form"> |
|||
<div class="box-body"> |
|||
|
|||
<div class="form-group"> |
|||
<label for="exampleInputEmail1">PoS Name</label> |
|||
<input id="nme" type="text" pattern="^[A-Za-z]+$" class="form-control" > |
|||
</div> |
|||
|
|||
|
|||
</div><!-- /.box-body --> |
|||
|
|||
<div class="box-footer"> |
|||
|
|||
<button onclick="postfau()" type="button" class="btn btn-info">Create POS</button><p style="color:red;" id="error"></p> |
|||
</div> |
|||
</form> |
|||
</div><!-- /.box --> |
|||
|
|||
|
|||
<div class="box box-primary"> |
|||
<div class="box-header"> |
|||
<h3 class="box-title">Select POS</h3> |
|||
</div><!-- /.box-header --> |
|||
<form role="form"> |
|||
<div class="box-body"> |
|||
<div class="form-group"> |
|||
|
|||
<select class="form-control" id="fauselect" onchange="drawwithdraw()"> |
|||
<option></option> |
|||
{% for w in user_fau %} |
|||
<option id="{{w.uni}}" >{{w.nme}}-{{w.uni}}</option> |
|||
{% endfor %} |
|||
</select> |
|||
</div> |
|||
|
|||
<center> <br/><div id="qrcode" style="width:340px" ></div><br/><div style="width:75%;word-wrap: break-word;" id="qrcodetxt" ></div></center> |
|||
</div> |
|||
</form> |
|||
|
|||
</div><!-- /.box --> |
|||
|
|||
|
|||
</div> |
|||
|
|||
|
|||
|
|||
</div> |
|||
|
|||
<!-- /.content --> |
|||
</section> |
|||
|
|||
<script> |
|||
|
|||
window.user = {{ usr | megajson | safe }} |
|||
window.user_wallets = {{ user_wallets | megajson | safe }} |
|||
window.user_ext = {{ user_ext | megajson | safe }} |
|||
window.user_fau = {{ user_fau | megajson | safe }} |
|||
|
|||
|
|||
function getAjax(url, thekey, success) { |
|||
var xhr = window.XMLHttpRequest |
|||
? new XMLHttpRequest() |
|||
: new ActiveXObject('Microsoft.XMLHTTP') |
|||
xhr.open('GET', url, true) |
|||
xhr.onreadystatechange = function() { |
|||
if (xhr.readyState > 3 && xhr.status == 200) { |
|||
success(xhr.responseText) |
|||
} |
|||
} |
|||
xhr.setRequestHeader('Grpc-Metadata-macaroon', thekey) |
|||
xhr.setRequestHeader('Content-Type', 'application/json') |
|||
|
|||
xhr.send() |
|||
return xhr |
|||
} |
|||
|
|||
|
|||
//draws withdraw QR code |
|||
function drawwithdraw() { |
|||
|
|||
|
|||
|
|||
walname = document.getElementById("fauselect").value |
|||
|
|||
thewithdraw = walname.split("-"); |
|||
theurl = window.location.hostname + "{{ url_for('tpos.tpos') }}?pos=" + thewithdraw[1] + "&exc=9000" |
|||
|
|||
new QRCode(document.getElementById('qrcode'), { |
|||
text: theurl, |
|||
width: 300, |
|||
height: 300, |
|||
colorDark: '#000000', |
|||
colorLight: '#ffffff', |
|||
correctLevel: QRCode.CorrectLevel.M |
|||
}) |
|||
|
|||
|
|||
document.getElementById('qrcodetxt').innerHTML = |
|||
"<a target='_blank' href='{{ url_for('tpos.tpos') }}?pos=" + thewithdraw[1] + "&exc=9000" + "'><h4>Shareable link</h4></a>" |
|||
document.getElementById("qrcode").style.backgroundColor = "white"; |
|||
document.getElementById("qrcode").style.padding = "20px"; |
|||
|
|||
|
|||
} |
|||
|
|||
function postfau(){ |
|||
|
|||
nme = document.getElementById('nme').value |
|||
|
|||
getAjax( |
|||
"{{ url_for('tpos.index') }}?nme=" + nme + "&usr=" + user, |
|||
"filla", |
|||
|
|||
function(data) { location.replace("{{ url_for('tpos.index') }}?usr=" + user) |
|||
}) |
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
</script> |
|||
</div> |
|||
{% endblock %} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,64 @@ |
|||
import uuid |
|||
import json |
|||
import requests |
|||
|
|||
from flask import jsonify, render_template, request, redirect, url_for |
|||
from lnbits.db import open_db, open_ext_db |
|||
from lnbits.extensions.tpos import tpos_ext |
|||
|
|||
#add your endpoints here |
|||
|
|||
@tpos_ext.route("/") |
|||
def index(): |
|||
"""Try to add descriptions for others.""" |
|||
usr = request.args.get("usr") |
|||
nme = request.args.get("nme") |
|||
|
|||
if usr: |
|||
if not len(usr) > 20: |
|||
return redirect(url_for("home")) |
|||
|
|||
# Get all the data |
|||
with open_db() as db: |
|||
user_wallets = db.fetchall("SELECT * FROM wallets WHERE user = ?", (usr,)) |
|||
user_ext = db.fetchall("SELECT extension FROM extensions WHERE user = ? AND active = 1", (usr,)) |
|||
user_ext = [v[0] for v in user_ext] |
|||
|
|||
if nme: |
|||
uni = uuid.uuid4().hex |
|||
with open_ext_db("tpos") as pos_ext_db: |
|||
pos_ext_db.execute( |
|||
""" |
|||
INSERT OR IGNORE INTO tpos |
|||
(nme, uni, usr, invkey) |
|||
VALUES (?, ?, ?, ?) |
|||
""", |
|||
( |
|||
nme, |
|||
uni, |
|||
usr, |
|||
user_wallets[0][3], |
|||
|
|||
), |
|||
) |
|||
with open_ext_db("tpos") as pos_ext_dbb: |
|||
user_fau = pos_ext_dbb.fetchall("SELECT * FROM tpos WHERE usr = ?", (usr,)) |
|||
|
|||
return render_template( |
|||
"tpos/index.html", user_wallets=user_wallets, user_ext=user_ext, usr=usr, user_fau=user_fau |
|||
) |
|||
|
|||
@tpos_ext.route("/tpos") |
|||
def tpos(): |
|||
"""Try to add descriptions for others.""" |
|||
pos = request.args.get("pos") |
|||
exc = request.args.get("exc") |
|||
|
|||
with open_ext_db("tpos") as pos_ext_dbb: |
|||
user_fau = pos_ext_dbb.fetchall("SELECT * FROM tpos WHERE uni = ?", (pos,)) |
|||
if not user_fau: |
|||
return jsonify({"status": "ERROR", "reason":"NO POS"}), 400 |
|||
|
|||
return render_template( |
|||
"tpos/tpos.html", pos=pos, exchange=exc |
|||
) |
@ -0,0 +1,37 @@ |
|||
#views_api.py is for you API endpoints that could be hit by another service |
|||
|
|||
#add your dependencies here |
|||
|
|||
import json |
|||
import requests |
|||
from flask import jsonify, render_template, request, redirect, url_for |
|||
from lnbits.db import open_db, open_ext_db |
|||
from lnbits.extensions.tpos import tpos_ext |
|||
|
|||
#add your endpoints here |
|||
|
|||
@tpos_ext.route("/api/v1/fetch", methods=["GET","POST"]) |
|||
def api_tpos(): |
|||
"""Try to add descriptions for others.""" |
|||
|
|||
data = request.json |
|||
sats = data["sats"] |
|||
pos = data["pos"] |
|||
|
|||
with open_ext_db("tpos") as events_ext_db: |
|||
user_pos = events_ext_db.fetchall("SELECT * FROM tpos WHERE uni = ?", (pos,)) |
|||
if not user_pos: |
|||
return jsonify({"status": "ERROR", "reason":"NO POS"}), 400 |
|||
print(user_pos[0][4]) |
|||
header = {"Content-Type": "application/json", "Grpc-Metadata-macaroon": user_pos[0][4]} |
|||
data = {"value": sats, "memo": "TPOS"} |
|||
print(url_for("api_invoices", _external=True)) |
|||
r = requests.post(url=url_for("api_invoices", _external=True), headers=header, data=json.dumps(data)) |
|||
r_json = r.json() |
|||
|
|||
if "ERROR" in r_json: |
|||
return jsonify({"status": "ERROR", "reason": r_json["ERROR"]}), 400 |
|||
|
|||
return jsonify({"status": "TRUE"}), 200 |
|||
|
|||
|
Loading…
Reference in new issue