2020-05-26 17:24:29 +02:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
|
|
########################################################
|
|
|
|
# SSH Dialogs to manage Subscriptions on the RaspiBlitz
|
|
|
|
########################################################
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import math
|
|
|
|
import time
|
|
|
|
import toml
|
2020-05-26 20:08:32 +02:00
|
|
|
import os
|
2020-05-26 19:58:27 +02:00
|
|
|
import subprocess
|
2020-05-26 17:24:29 +02:00
|
|
|
|
2020-05-26 17:27:47 +02:00
|
|
|
from dialog import Dialog
|
|
|
|
|
2020-05-26 17:24:29 +02:00
|
|
|
from blitzpy import RaspiBlitzConfig
|
|
|
|
|
2020-05-26 22:56:06 +02:00
|
|
|
# constants for standard services
|
|
|
|
LND_REST_API = "LND-REST-API"
|
2020-05-26 23:19:38 +02:00
|
|
|
LND_GRPC_API = "LND-GRPC-API"
|
2020-05-26 22:56:06 +02:00
|
|
|
|
2020-05-26 17:24:29 +02:00
|
|
|
# load config
|
|
|
|
cfg = RaspiBlitzConfig()
|
2020-05-26 17:27:47 +02:00
|
|
|
cfg.reload()
|
2020-05-26 17:24:29 +02:00
|
|
|
|
2020-05-26 19:15:03 +02:00
|
|
|
# basic values
|
|
|
|
SUBSCRIPTIONS_FILE="/mnt/hdd/app-data/subscriptions/subscriptions.toml"
|
2020-05-26 17:24:29 +02:00
|
|
|
|
|
|
|
####### HELPER FUNCTIONS #########
|
|
|
|
|
|
|
|
def eprint(*args, **kwargs):
|
|
|
|
print(*args, file=sys.stderr, **kwargs)
|
|
|
|
|
|
|
|
def parseDateIP2TORSERVER(datestr):
|
|
|
|
return datetime.datetime.strptime(datestr,"%Y-%m-%dT%H:%M:%S.%fZ")
|
|
|
|
|
|
|
|
def secondsLeft(dateObj):
|
|
|
|
return round((dateObj - datetime.datetime.utcnow()).total_seconds())
|
|
|
|
|
|
|
|
####### SSH MENU FUNCTIONS #########
|
|
|
|
|
|
|
|
def mySubscriptions():
|
|
|
|
|
2020-05-26 17:40:35 +02:00
|
|
|
# check if any subscriptions are available
|
|
|
|
countSubscriptions=0
|
|
|
|
try:
|
|
|
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
|
|
|
countSubscriptions += len(subs['subscriptions_ip2tor'])
|
|
|
|
except Exception as e: pass
|
|
|
|
if countSubscriptions == 0:
|
|
|
|
Dialog(dialog="dialog",autowidgetsize=True).msgbox('''
|
2020-05-26 20:14:58 +02:00
|
|
|
You have no active or inactive subscriptions.
|
2020-05-26 17:40:35 +02:00
|
|
|
''',title="Info")
|
|
|
|
return
|
|
|
|
|
2020-05-26 17:43:59 +02:00
|
|
|
# load subscriptions and make dialog choices out of it
|
|
|
|
choices = []
|
|
|
|
lookup = {}
|
|
|
|
lookupIndex=0
|
|
|
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
2020-05-26 17:24:29 +02:00
|
|
|
|
2020-05-26 17:43:59 +02:00
|
|
|
# list ip2tor subscriptions
|
|
|
|
for sub in subs['subscriptions_ip2tor']:
|
|
|
|
# remember subscription under lookupindex
|
|
|
|
lookupIndex += 1
|
|
|
|
lookup[str(lookupIndex)]=sub
|
|
|
|
# add to dialog choices
|
|
|
|
if sub['active']:
|
2020-05-26 19:43:31 +02:00
|
|
|
activeState="active"
|
2020-05-26 17:43:59 +02:00
|
|
|
else:
|
2020-05-26 19:43:31 +02:00
|
|
|
activeState="in-active"
|
2020-05-26 23:29:17 +02:00
|
|
|
name="IP2TOR Bridge for {0}".format(sub['name'])
|
2020-05-26 19:43:31 +02:00
|
|
|
choices.append( ("{0}".format(lookupIndex), "{0} ({1})".format(name.ljust(30), activeState)) )
|
2020-05-26 17:24:29 +02:00
|
|
|
|
2020-05-26 17:43:59 +02:00
|
|
|
# show menu with options
|
|
|
|
d = Dialog(dialog="dialog",autowidgetsize=True)
|
|
|
|
d.set_background_title("RaspiBlitz Subscriptions")
|
|
|
|
code, tag = d.menu(
|
2020-05-26 19:43:31 +02:00
|
|
|
"\nYou have the following subscriptions - select for details:",
|
|
|
|
choices=choices, width=65, height=15, title="My Subscriptions")
|
2020-05-26 17:24:29 +02:00
|
|
|
|
2020-05-26 17:43:59 +02:00
|
|
|
# if user chosses CANCEL
|
|
|
|
if code != d.OK: return
|
|
|
|
|
|
|
|
# get data of selected subscrption
|
|
|
|
selectedSub = lookup[str(tag)]
|
|
|
|
|
|
|
|
# show details of selected
|
|
|
|
d = Dialog(dialog="dialog",autowidgetsize=True)
|
|
|
|
d.set_background_title("My Subscriptions")
|
|
|
|
if selectedSub['type'] == "ip2tor-v1":
|
|
|
|
if len(selectedSub['warning']) > 0:
|
|
|
|
selectedSub['warning'] = "\n{0}".formart(selectedSub['warning'])
|
|
|
|
text='''
|
2020-05-26 17:24:29 +02:00
|
|
|
This is a IP2TOR subscription bought on {initdate} at
|
|
|
|
{shop}
|
|
|
|
|
|
|
|
It forwards from the public address {publicaddress} to
|
|
|
|
{toraddress}
|
|
|
|
for the RaspiBlitz service: {service}
|
|
|
|
|
|
|
|
It will renew every {renewhours} hours for {renewsats} sats.
|
|
|
|
Total payed so far: {totalsats} sats
|
|
|
|
|
|
|
|
The state of the subscription is: {active} {warning}
|
|
|
|
|
|
|
|
The following additional information is available:
|
|
|
|
{description}
|
2020-05-26 17:27:47 +02:00
|
|
|
'''.format( initdate=selectedSub['time_created'],
|
2020-05-26 17:24:29 +02:00
|
|
|
shop=selectedSub['shop'],
|
|
|
|
publicaddress="{0}:{1}".format(selectedSub['ip'],selectedSub['port']),
|
|
|
|
toraddress=selectedSub['tor'],
|
|
|
|
renewhours=(round(int(selectedSub['duration'])/3600)),
|
|
|
|
renewsats=(round(int(selectedSub['price_extension'])/1000)),
|
|
|
|
totalsats=(round(int(selectedSub['price_extension'])/1000)),
|
2020-05-26 20:41:01 +02:00
|
|
|
active= "ACTIVE" if selectedSub['active'] else "NOT ACTIVE",
|
2020-05-26 17:24:29 +02:00
|
|
|
warning=selectedSub['warning'],
|
|
|
|
description=selectedSub['description'],
|
2020-05-26 23:29:17 +02:00
|
|
|
service=selectedSub['name']
|
2020-05-26 17:43:59 +02:00
|
|
|
)
|
2020-05-26 17:24:29 +02:00
|
|
|
|
2020-05-26 17:43:59 +02:00
|
|
|
if selectedSub['active']:
|
2020-05-26 20:13:40 +02:00
|
|
|
extraLable = "CANCEL SUBSCRIPTION"
|
2020-05-26 17:43:59 +02:00
|
|
|
else:
|
2020-05-26 20:13:40 +02:00
|
|
|
extraLable = "DELETE SUBSCRIPTION"
|
2020-05-26 20:28:49 +02:00
|
|
|
code = d.msgbox(text, title="Subscription Detail", ok_label="Back", extra_button=True, extra_label=extraLable ,width=75, height=30)
|
2020-05-26 17:24:29 +02:00
|
|
|
|
2020-05-26 17:43:59 +02:00
|
|
|
# user wants to delete this subscription
|
2020-05-26 20:09:35 +02:00
|
|
|
# call the responsible sub script for deletion just in case any subscription needs to do some extra api calls when canceling
|
2020-05-26 17:43:59 +02:00
|
|
|
if code == "extra":
|
2020-05-26 20:10:34 +02:00
|
|
|
os.system("clear")
|
2020-05-26 17:43:59 +02:00
|
|
|
if selectedSub['type'] == "ip2tor-v1":
|
2020-05-26 20:02:37 +02:00
|
|
|
cmd="python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py subscription-cancel {0}".format(selectedSub['id'])
|
2020-05-26 19:58:27 +02:00
|
|
|
print("# running: {0}".format(cmd))
|
2020-05-26 20:08:32 +02:00
|
|
|
os.system(cmd)
|
|
|
|
time.sleep(2)
|
2020-05-26 20:10:34 +02:00
|
|
|
else:
|
|
|
|
print("# FAIL: unknown subscription type")
|
|
|
|
time.sleep(3)
|
2020-05-26 20:08:32 +02:00
|
|
|
|
2020-05-26 17:43:59 +02:00
|
|
|
# loop until no more subscriptions or user chooses CANCEL on subscription list
|
|
|
|
mySubscriptions()
|
2020-05-26 17:24:29 +02:00
|
|
|
|
|
|
|
####### SSH MENU #########
|
|
|
|
|
2020-05-26 21:05:56 +02:00
|
|
|
choices = []
|
|
|
|
choices.append( ("LIST","My Subscriptions") )
|
|
|
|
choices.append( ("NEW1","+ new IP2TOR Bridge") )
|
2020-05-26 20:41:01 +02:00
|
|
|
|
2020-05-26 21:05:56 +02:00
|
|
|
d = Dialog(dialog="dialog",autowidgetsize=True)
|
|
|
|
d.set_background_title("RaspiBlitz Subscriptions")
|
|
|
|
code, tag = d.menu(
|
2020-05-26 21:10:43 +02:00
|
|
|
"\nCheck existing subscriptions or create new:",
|
|
|
|
choices=choices, width=50, height=10, title="Subscription Management")
|
2020-05-26 20:42:07 +02:00
|
|
|
|
2020-05-26 21:05:56 +02:00
|
|
|
# if user chosses CANCEL
|
2020-05-26 21:07:28 +02:00
|
|
|
if code != d.OK:
|
|
|
|
sys.exit(0)
|
2020-05-26 20:41:01 +02:00
|
|
|
|
2020-05-26 22:56:06 +02:00
|
|
|
####### MANAGE SUBSCRIPTIONS #########
|
|
|
|
|
2020-05-26 21:05:56 +02:00
|
|
|
if tag == "LIST":
|
|
|
|
mySubscriptions()
|
|
|
|
sys.exit(0)
|
2020-05-26 20:41:01 +02:00
|
|
|
|
2020-05-26 22:56:06 +02:00
|
|
|
####### NEW IP2TOR BRIDGE #########
|
|
|
|
|
2020-05-26 21:05:56 +02:00
|
|
|
if tag == "NEW1":
|
2020-05-26 21:16:35 +02:00
|
|
|
|
|
|
|
# check if Blitz is running behind TOR
|
|
|
|
cfg.reload()
|
2020-05-26 21:17:22 +02:00
|
|
|
if not cfg.run_behind_tor:
|
2020-05-26 21:16:35 +02:00
|
|
|
Dialog(dialog="dialog",autowidgetsize=True).msgbox('''
|
|
|
|
The IP2TOR service just makes sense if you run
|
|
|
|
your RaspiBlitz behind TOR.
|
|
|
|
''',title="Info")
|
|
|
|
sys.exit(1)
|
|
|
|
|
2020-05-26 22:56:06 +02:00
|
|
|
# check for which standard services already a active bridge exists
|
|
|
|
lnd_rest_api=False
|
|
|
|
lnd_grpc_api=False
|
|
|
|
try:
|
|
|
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
|
|
|
for sub in subs['subscriptions_ip2tor']:
|
2020-05-26 23:45:09 +02:00
|
|
|
if not sub['active']: next
|
2020-05-26 23:41:59 +02:00
|
|
|
if sub['active'] and sub['name'] == LND_REST_API: lnd_rest_api=True
|
|
|
|
if sub['active'] and sub['name'] == LND_GRPC_API: lnd_grpc_api=True
|
2020-05-26 22:56:06 +02:00
|
|
|
except Exception as e:
|
2020-05-26 23:45:09 +02:00
|
|
|
print(e)
|
2020-05-26 22:56:06 +02:00
|
|
|
|
|
|
|
# ask user for which RaspiBlitz service the bridge should be used
|
|
|
|
choices = []
|
|
|
|
choices.append( ("REST","LND REST API {0}".format("--> ALREADY BRIDGED" if lnd_rest_api else "")) )
|
2020-05-26 23:16:50 +02:00
|
|
|
choices.append( ("GRPC","LND gRPC API {0}".format("--> ALREADY BRIDGED" if lnd_grpc_api else "")) )
|
2020-05-26 22:56:06 +02:00
|
|
|
choices.append( ("SELF","Create a custom IP2TOR Bridge") )
|
|
|
|
|
|
|
|
d = Dialog(dialog="dialog",autowidgetsize=True)
|
|
|
|
d.set_background_title("RaspiBlitz Subscriptions")
|
|
|
|
code, tag = d.menu(
|
|
|
|
"\nChoose RaspiBlitz Service to create Bridge for:",
|
2020-05-26 23:12:55 +02:00
|
|
|
choices=choices, width=60, height=10, title="Select Service")
|
2020-05-26 22:56:06 +02:00
|
|
|
|
|
|
|
# if user chosses CANCEL
|
|
|
|
if code != d.OK:
|
2020-05-26 22:58:21 +02:00
|
|
|
sys.exit(0)
|
2020-05-26 22:56:06 +02:00
|
|
|
|
2020-05-26 23:19:38 +02:00
|
|
|
servicename=None
|
2020-05-26 22:56:06 +02:00
|
|
|
torAddress=None
|
|
|
|
torPort=None
|
|
|
|
if tag == "REST":
|
|
|
|
# get TOR address for REST
|
2020-05-26 23:19:38 +02:00
|
|
|
servicename=LND_REST_API
|
2020-05-26 23:14:35 +02:00
|
|
|
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrest8080/hostname'], stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
2020-05-26 23:12:55 +02:00
|
|
|
torPort=8080
|
2020-05-26 22:56:06 +02:00
|
|
|
if tag == "GRPC":
|
2020-05-26 22:58:21 +02:00
|
|
|
# get TOR address for GRPC
|
2020-05-26 23:19:38 +02:00
|
|
|
servicename=LND_GRPC_API
|
2020-05-26 23:14:35 +02:00
|
|
|
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrpc10009/hostname'], stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
2020-05-26 23:12:55 +02:00
|
|
|
torPort=10009
|
2020-05-26 22:56:06 +02:00
|
|
|
if tag == "SELF":
|
2020-05-26 23:19:38 +02:00
|
|
|
servicename="CUSTOM"
|
2020-05-26 22:56:06 +02:00
|
|
|
try:
|
|
|
|
# get custom TOR address
|
|
|
|
code, text = d.inputbox(
|
|
|
|
"Enter TOR Onion-Address:",
|
|
|
|
height=10, width=60, init="",
|
|
|
|
title="IP2TOR Bridge Target")
|
|
|
|
text = text.strip()
|
|
|
|
os.system("clear")
|
|
|
|
if code != d.OK: sys.exit(0)
|
|
|
|
if len(text) == 0: sys.exit(0)
|
|
|
|
if text.find('.onion') < 0 or text.find(' ') > 0 :
|
|
|
|
print("Not a TOR Onion Address")
|
|
|
|
time.sleep(3)
|
|
|
|
sys.exit(0)
|
|
|
|
torAddress = text
|
|
|
|
# get custom TOR port
|
|
|
|
code, text = d.inputbox(
|
|
|
|
"Enter TOR Port Number:",
|
|
|
|
height=10, width=40, init="80",
|
|
|
|
title="IP2TOR Bridge Target")
|
|
|
|
text = text.strip()
|
|
|
|
os.system("clear")
|
|
|
|
if code != d.OK: sys.exit(0)
|
|
|
|
if len(text) == 0: sys.exit(0)
|
|
|
|
torPort = int(text)
|
|
|
|
except Exception as e:
|
|
|
|
print(e)
|
|
|
|
time.sleep(3)
|
|
|
|
sys.exit(1)
|
|
|
|
|
2020-05-26 21:16:35 +02:00
|
|
|
# run creating a new IP2TOR subscription
|
|
|
|
os.system("clear")
|
2020-05-26 23:19:38 +02:00
|
|
|
cmd="python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py create-ssh-dialog {0} {1} {2}".format(servicename,torAddress,torPort)
|
2020-05-26 21:05:56 +02:00
|
|
|
print("# running: {0}".format(cmd))
|
2020-05-26 21:07:28 +02:00
|
|
|
os.system(cmd)
|
2020-05-26 23:12:55 +02:00
|
|
|
sys.exit(0)
|