mirror of
https://github.com/rootzoll/raspiblitz.git
synced 2025-02-25 07:07:46 +01:00
Merge pull request #1361 from frennkie/ip2tor-blitz-error
ip2tor: add blitz error + refactor
This commit is contained in:
commit
fd4647a605
9 changed files with 474 additions and 414 deletions
|
@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.3.0] - 2020-07-19
|
||||||
|
### Added
|
||||||
|
- add BlitzError Class
|
||||||
|
|
||||||
## [0.2.0] - 2020-05-23
|
## [0.2.0] - 2020-05-23
|
||||||
### Added
|
### Added
|
||||||
- add write() to BlitzPy config Classes
|
- add write() to BlitzPy config Classes
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from .config import RaspiBlitzConfig, RaspiBlitzInfo
|
from .config import RaspiBlitzConfig, RaspiBlitzInfo
|
||||||
|
from .exceptions import BlitzError
|
||||||
__all__ = [
|
|
||||||
'RaspiBlitzConfig',
|
__all__ = [
|
||||||
'RaspiBlitzInfo',
|
'RaspiBlitzConfig',
|
||||||
]
|
'RaspiBlitzInfo',
|
||||||
|
'BlitzError'
|
||||||
|
]
|
||||||
|
|
16
home.admin/BlitzPy/blitzpy/exceptions.py
Normal file
16
home.admin/BlitzPy/blitzpy/exceptions.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
TS_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
||||||
|
|
||||||
|
|
||||||
|
class BlitzError(Exception):
|
||||||
|
def __init__(self, short: str, details: dict = None, org: Exception = None):
|
||||||
|
self.short: str = str(short)
|
||||||
|
if details:
|
||||||
|
self.details: dict = details
|
||||||
|
self.details.update({'timestamp': datetime.utcnow().strftime(TS_FORMAT)})
|
||||||
|
else:
|
||||||
|
self.details = dict()
|
||||||
|
self.details['timestamp'] = datetime.utcnow().strftime(TS_FORMAT)
|
||||||
|
|
||||||
|
self.org: Exception = org
|
|
@ -4,5 +4,5 @@
|
||||||
# 3) we can import it into your module module
|
# 3) we can import it into your module module
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version_info__ = ('0', '2', '0')
|
__version_info__ = ('0', '3', '0')
|
||||||
__version__ = '.'.join(__version_info__)
|
__version__ = '.'.join(__version_info__)
|
||||||
|
|
BIN
home.admin/BlitzPy/dist/BlitzPy-0.3.0-py2.py3-none-any.whl
vendored
Normal file
BIN
home.admin/BlitzPy/dist/BlitzPy-0.3.0-py2.py3-none-any.whl
vendored
Normal file
Binary file not shown.
BIN
home.admin/BlitzPy/dist/BlitzPy-0.3.0.tar.gz
vendored
Normal file
BIN
home.admin/BlitzPy/dist/BlitzPy-0.3.0.tar.gz
vendored
Normal file
Binary file not shown.
|
@ -1,6 +1,5 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
import ast
|
|
||||||
import codecs
|
import codecs
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
|
@ -13,7 +12,7 @@ from pathlib import Path
|
||||||
import grpc
|
import grpc
|
||||||
import requests
|
import requests
|
||||||
import toml
|
import toml
|
||||||
from blitzpy import RaspiBlitzConfig
|
from blitzpy import RaspiBlitzConfig, BlitzError
|
||||||
from lndlibs import rpc_pb2 as lnrpc
|
from lndlibs import rpc_pb2 as lnrpc
|
||||||
from lndlibs import rpc_pb2_grpc as rpcstub
|
from lndlibs import rpc_pb2_grpc as rpcstub
|
||||||
|
|
||||||
|
@ -35,6 +34,12 @@ if len(sys.argv) <= 1 or sys.argv[1] == "-h" or sys.argv[1] == "help":
|
||||||
print("# blitz.subscriptions.ip2tor.py ip-by-tor onionaddress")
|
print("# blitz.subscriptions.ip2tor.py ip-by-tor onionaddress")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# constants for standard services
|
||||||
|
SERVICE_LND_REST_API = "LND-REST-API"
|
||||||
|
SERVICE_LND_GRPC_API = "LND-GRPC-API"
|
||||||
|
SERVICE_LNBITS = "LNBITS"
|
||||||
|
SERVICE_BTCPAY = "BTCPAY"
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
# BASIC SETTINGS
|
# BASIC SETTINGS
|
||||||
#####################
|
#####################
|
||||||
|
@ -70,17 +75,6 @@ else:
|
||||||
is_testnet = False
|
is_testnet = False
|
||||||
|
|
||||||
|
|
||||||
#####################
|
|
||||||
# HELPER CLASSES
|
|
||||||
#####################
|
|
||||||
|
|
||||||
class BlitzError(Exception):
|
|
||||||
def __init__(self, errorShort, errorLong="", errorException=None):
|
|
||||||
self.errorShort = str(errorShort)
|
|
||||||
self.errorLong = str(errorLong)
|
|
||||||
self.errorException = errorException
|
|
||||||
|
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
# HELPER FUNCTIONS
|
# HELPER FUNCTIONS
|
||||||
#####################
|
#####################
|
||||||
|
@ -91,9 +85,9 @@ def eprint(*args, **kwargs):
|
||||||
|
|
||||||
def handleException(e):
|
def handleException(e):
|
||||||
if isinstance(e, BlitzError):
|
if isinstance(e, BlitzError):
|
||||||
eprint(e.errorLong)
|
eprint(e.details)
|
||||||
eprint(e.errorException)
|
eprint(e.org)
|
||||||
print("error='{0}'".format(e.errorShort))
|
print("error='{0}'".format(e.short))
|
||||||
else:
|
else:
|
||||||
eprint(e)
|
eprint(e)
|
||||||
print("error='{0}'".format(str(e)))
|
print("error='{0}'".format(str(e)))
|
||||||
|
@ -150,17 +144,17 @@ def apiGetHosts(session, shopurl):
|
||||||
try:
|
try:
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed HTTP request", url, e)
|
raise BlitzError("failed HTTP request", {'url': url}, e)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise BlitzError("failed HTTP code", response.status_code, )
|
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
|
||||||
|
|
||||||
# parse & validate data
|
# parse & validate data
|
||||||
try:
|
try:
|
||||||
jData = json.loads(response.content)
|
jData = json.loads(response.content)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed JSON parsing", response.content, e)
|
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
|
||||||
if not isinstance(jData, list):
|
if not isinstance(jData, list):
|
||||||
raise BlitzError("hosts not list", response.content)
|
raise BlitzError("hosts not list", {'content': response.content})
|
||||||
for idx, hostEntry in enumerate(jData):
|
for idx, hostEntry in enumerate(jData):
|
||||||
try:
|
try:
|
||||||
# ignore if not offering tor bridge
|
# ignore if not offering tor bridge
|
||||||
|
@ -188,7 +182,7 @@ def apiGetHosts(session, shopurl):
|
||||||
# shorten names to 20 chars max
|
# shorten names to 20 chars max
|
||||||
hostEntry['name'] = hostEntry['name'][:20]
|
hostEntry['name'] = hostEntry['name'][:20]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed host entry pasring", str(hostEntry), e)
|
raise BlitzError("failed host entry pasring", hostEntry, e)
|
||||||
|
|
||||||
hosts.append(hostEntry)
|
hosts.append(hostEntry)
|
||||||
|
|
||||||
|
@ -211,11 +205,11 @@ def apiPlaceOrderNew(session, shopurl, hostid, toraddressWithPort):
|
||||||
try:
|
try:
|
||||||
response = session.post(url, data=postData)
|
response = session.post(url, data=postData)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed HTTP request", url, e)
|
raise BlitzError("failed HTTP request", {'url': url}, e)
|
||||||
if response.status_code == 420:
|
if response.status_code == 420:
|
||||||
raise BlitzError("forwarding this address was rejected", response.status_code)
|
raise BlitzError("forwarding this address was rejected", {'status_code': response.status_code})
|
||||||
if response.status_code != 201:
|
if response.status_code != 201:
|
||||||
raise BlitzError("failed HTTP code", response.status_code)
|
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
|
||||||
|
|
||||||
# parse & validate data
|
# parse & validate data
|
||||||
try:
|
try:
|
||||||
|
@ -224,7 +218,7 @@ def apiPlaceOrderNew(session, shopurl, hostid, toraddressWithPort):
|
||||||
print("error='MISSING ID'")
|
print("error='MISSING ID'")
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed JSON parsing", response.status_code, e)
|
raise BlitzError("failed JSON parsing", {'status_code': response.status_code}, e)
|
||||||
|
|
||||||
return jData['id']
|
return jData['id']
|
||||||
|
|
||||||
|
@ -236,11 +230,11 @@ def apiPlaceOrderExtension(session, shopurl, bridgeid):
|
||||||
try:
|
try:
|
||||||
response = session.post(url)
|
response = session.post(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed HTTP request", url, e)
|
raise BlitzError("failed HTTP request", {'url': url}, e)
|
||||||
if response.status_code == 420:
|
if response.status_code == 420:
|
||||||
raise BlitzError("forwarding this address was rejected", response.status_code)
|
raise BlitzError("forwarding this address was rejected", {'status_code': response.status_code})
|
||||||
if response.status_code != 200 and response.status_code != 201:
|
if response.status_code != 200 and response.status_code != 201:
|
||||||
raise BlitzError("failed HTTP code", response.status_code)
|
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
|
||||||
|
|
||||||
# parse & validate data
|
# parse & validate data
|
||||||
print("# parse")
|
print("# parse")
|
||||||
|
@ -250,12 +244,12 @@ def apiPlaceOrderExtension(session, shopurl, bridgeid):
|
||||||
print("error='MISSING ID'")
|
print("error='MISSING ID'")
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed JSON parsing", response.content, e)
|
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
|
||||||
|
|
||||||
return jData['po_id']
|
return jData['po_id']
|
||||||
|
|
||||||
|
|
||||||
def apiGetOrder(session, shopurl, orderid):
|
def apiGetOrder(session, shopurl, orderid) -> dict:
|
||||||
print("# apiGetOrder")
|
print("# apiGetOrder")
|
||||||
|
|
||||||
# make HTTP request
|
# make HTTP request
|
||||||
|
@ -263,19 +257,19 @@ def apiGetOrder(session, shopurl, orderid):
|
||||||
try:
|
try:
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed HTTP request", url, e)
|
raise BlitzError("failed HTTP request", {'url': url}, e)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise BlitzError("failed HTTP code", response.status_code)
|
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
|
||||||
|
|
||||||
# parse & validate data
|
# parse & validate data
|
||||||
try:
|
try:
|
||||||
jData = json.loads(response.content)
|
jData = json.loads(response.content)
|
||||||
if len(jData['item_details']) == 0:
|
if len(jData['item_details']) == 0:
|
||||||
raise BlitzError("missing item", response.content)
|
raise BlitzError("missing item", {'content': response.content})
|
||||||
if len(jData['ln_invoices']) > 1:
|
if len(jData['ln_invoices']) > 1:
|
||||||
raise BlitzError("more than one invoice", response.content)
|
raise BlitzError("more than one invoice", {'content': response.content})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed JSON parsing", response.content, e)
|
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
|
||||||
|
|
||||||
return jData
|
return jData
|
||||||
|
|
||||||
|
@ -288,16 +282,16 @@ def apiGetBridgeStatus(session, shopurl, bridgeid):
|
||||||
try:
|
try:
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed HTTP request", url, e)
|
raise BlitzError("failed HTTP request", {'url': url}, e)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise BlitzError("failed HTTP code", response.status_code)
|
raise BlitzError("failed HTTP code", {'status_code': response.status_code})
|
||||||
# parse & validate data
|
# parse & validate data
|
||||||
try:
|
try:
|
||||||
jData = json.loads(response.content)
|
jData = json.loads(response.content)
|
||||||
if len(jData['id']) == 0:
|
if len(jData['id']) == 0:
|
||||||
raise BlitzError("missing id", response.content)
|
raise BlitzError("missing id", {'content': response.content})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed JSON parsing", response.content, e)
|
raise BlitzError("failed JSON parsing", {'content': response.content}, e)
|
||||||
|
|
||||||
return jData
|
return jData
|
||||||
|
|
||||||
|
@ -322,10 +316,10 @@ def lndDecodeInvoice(lnInvoiceString):
|
||||||
|
|
||||||
# validate results
|
# validate results
|
||||||
if response.num_msat <= 0:
|
if response.num_msat <= 0:
|
||||||
raise BlitzError("zero invoice not allowed", lnInvoiceString)
|
raise BlitzError("zero invoice not allowed", {'invoice': lnInvoiceString})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("failed LND invoice decoding", lnInvoiceString, e)
|
raise BlitzError("failed LND invoice decoding", {'invoice': lnInvoiceString}, e)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -346,10 +340,10 @@ def lndPayInvoice(lnInvoiceString):
|
||||||
|
|
||||||
# validate results
|
# validate results
|
||||||
if len(response.payment_error) > 0:
|
if len(response.payment_error) > 0:
|
||||||
raise BlitzError(response.payment_error, lnInvoiceString)
|
raise BlitzError(response.payment_error, {'invoice': lnInvoiceString})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BlitzError("payment failed", lnInvoiceString, e)
|
raise BlitzError("payment failed", {'invoice': lnInvoiceString}, e)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -480,7 +474,7 @@ def shopOrder(shopUrl, hostid, servicename, torTarget, duration, msatsFirst, msa
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
eprint(e)
|
eprint(e)
|
||||||
raise BlitzError("fail on subscription storage", str(subscription), e)
|
raise BlitzError("fail on subscription storage", subscription, e)
|
||||||
|
|
||||||
print("# OK - BRIDGE READY: {0}:{1} -> {2}".format(bridge_ip, bridge_port, torTarget))
|
print("# OK - BRIDGE READY: {0}:{1} -> {2}".format(bridge_ip, bridge_port, torTarget))
|
||||||
return subscription
|
return subscription
|
||||||
|
@ -578,7 +572,7 @@ def subscriptionExtend(shopUrl, bridgeid, durationAdvertised, msatsNext, bridge_
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
eprint(e)
|
eprint(e)
|
||||||
raise BlitzError("fail on subscription storage", "", e)
|
raise BlitzError("fail on subscription storage", org=e)
|
||||||
|
|
||||||
print("# BRIDGE GOT EXTENDED: {0} -> {1}".format(bridge_suspendafter, bridge['suspend_after']))
|
print("# BRIDGE GOT EXTENDED: {0} -> {1}".format(bridge_suspendafter, bridge['suspend_after']))
|
||||||
|
|
||||||
|
@ -664,7 +658,8 @@ Try again later, enter another address or cancel.
|
||||||
choices=choices, title="Available Subscriptions")
|
choices=choices, title="Available Subscriptions")
|
||||||
|
|
||||||
# if user cancels
|
# if user cancels
|
||||||
if code != d.OK: sys.exit(0)
|
if code != d.OK:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
# get data of selected
|
# get data of selected
|
||||||
seletedIndex = int(tag)
|
seletedIndex = int(tag)
|
||||||
|
@ -712,7 +707,8 @@ More information on the service you can find under:
|
||||||
height=30)
|
height=30)
|
||||||
|
|
||||||
# if user AGREED break loop and continue with selected host
|
# if user AGREED break loop and continue with selected host
|
||||||
if code == "extra": break
|
if code == "extra":
|
||||||
|
break
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# PHASE 3: Make Subscription
|
# PHASE 3: Make Subscription
|
||||||
|
@ -729,16 +725,15 @@ More information on the service you can find under:
|
||||||
|
|
||||||
exitcode = 0
|
exitcode = 0
|
||||||
|
|
||||||
order = ast.literal_eval(be.errorLong)
|
try:
|
||||||
try :
|
message = be.details['message']
|
||||||
message = order['message']
|
except KeyError:
|
||||||
except Exception as e:
|
message = ""
|
||||||
message = "n/a"
|
|
||||||
|
|
||||||
if (be.errorShort == "timeout on waiting for extending bridge" or
|
if (be.short == "timeout on waiting for extending bridge" or
|
||||||
be.errorShort == "fail on subscription storage" or
|
be.short == "fail on subscription storage" or
|
||||||
be.errorShort == "invalid port" or
|
be.short == "invalid port" or
|
||||||
be.errorShort == "timeout bridge not getting ready"):
|
be.short == "timeout bridge not getting ready"):
|
||||||
|
|
||||||
# error happened after payment
|
# error happened after payment
|
||||||
exitcode = Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
exitcode = Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
||||||
|
@ -748,7 +743,7 @@ Subscription will be ignored.
|
||||||
|
|
||||||
Error: {0}
|
Error: {0}
|
||||||
Message: {1}
|
Message: {1}
|
||||||
'''.format(be.errorShort, message), title="Error on Subscription", extra_button=True, extra_label="Details")
|
'''.format(be.short, message), title="Error on Subscription", extra_button=True, extra_label="Details")
|
||||||
else:
|
else:
|
||||||
|
|
||||||
# error happened before payment
|
# error happened before payment
|
||||||
|
@ -759,7 +754,7 @@ Subscription will be ignored.
|
||||||
|
|
||||||
Error: {0}
|
Error: {0}
|
||||||
Message: {1}
|
Message: {1}
|
||||||
'''.format(be.errorShort, message), title="Error on Subscription", extra_button=True, extra_label="Details")
|
'''.format(be.short, message), title="Error on Subscription", extra_button=True, extra_label="Details")
|
||||||
|
|
||||||
# show more details (when user used extra button)
|
# show more details (when user used extra button)
|
||||||
if exitcode == Dialog.EXTRA:
|
if exitcode == Dialog.EXTRA:
|
||||||
|
@ -767,13 +762,13 @@ Message: {1}
|
||||||
print('###### ERROR DETAIL FOR DEBUG #######')
|
print('###### ERROR DETAIL FOR DEBUG #######')
|
||||||
print("")
|
print("")
|
||||||
print("Error Short:")
|
print("Error Short:")
|
||||||
print(be.errorShort)
|
print(be.short)
|
||||||
print('Shop:')
|
print('Shop:')
|
||||||
print(shopurl)
|
print(shopurl)
|
||||||
print('Bridge:')
|
print('Bridge:')
|
||||||
print(str(host))
|
print(str(host))
|
||||||
print("Error Detail:")
|
print("Error Detail:")
|
||||||
print(be.errorLong)
|
print(be.details)
|
||||||
print("")
|
print("")
|
||||||
input("Press Enter to continue ...")
|
input("Press Enter to continue ...")
|
||||||
|
|
||||||
|
@ -796,7 +791,7 @@ Message: {1}
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# if LND REST or LND GRPC service ... add bridge IP to TLS
|
# if LND REST or LND GRPC service ... add bridge IP to TLS
|
||||||
if servicename == "LND-REST-API" or servicename == "LND-GRPC-API":
|
if blitzServiceName == SERVICE_LND_REST_API or blitzServiceName == SERVICE_LND_GRPC_API:
|
||||||
os.system("sudo /home/admin/config.scripts/lnd.tlscert.sh ip-add {0}".format(subscription['ip']))
|
os.system("sudo /home/admin/config.scripts/lnd.tlscert.sh ip-add {0}".format(subscription['ip']))
|
||||||
os.system("sudo /home/admin/config.scripts/lnd.credentials.sh reset tls")
|
os.system("sudo /home/admin/config.scripts/lnd.credentials.sh reset tls")
|
||||||
os.system("sudo /home/admin/config.scripts/lnd.credentials.sh sync")
|
os.system("sudo /home/admin/config.scripts/lnd.credentials.sh sync")
|
||||||
|
@ -811,7 +806,7 @@ You may want to consider to cancel the subscription later.
|
||||||
|
|
||||||
# decide if https:// address
|
# decide if https:// address
|
||||||
protocol = ""
|
protocol = ""
|
||||||
if blitzServiceName == "LNBITS":
|
if blitzServiceName == SERVICE_LNBITS:
|
||||||
protocol = "https://"
|
protocol = "https://"
|
||||||
|
|
||||||
# Give final result feedback to user
|
# Give final result feedback to user
|
||||||
|
@ -847,13 +842,11 @@ MAIN MENU > Manage Subscriptions > My Subscriptions
|
||||||
# CREATE SSH DIALOG
|
# CREATE SSH DIALOG
|
||||||
# use for ssh shell menu
|
# use for ssh shell menu
|
||||||
###############
|
###############
|
||||||
|
def create_ssh_dialog():
|
||||||
if sys.argv[1] == "create-ssh-dialog":
|
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 4:
|
if len(sys.argv) <= 4:
|
||||||
raise BlitzError("incorrect parameters", "")
|
raise BlitzError("incorrect parameters")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
|
@ -865,17 +858,16 @@ if sys.argv[1] == "create-ssh-dialog":
|
||||||
|
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# SHOP LIST
|
# SHOP LIST
|
||||||
# call from web interface
|
# call from web interface
|
||||||
###############
|
###############
|
||||||
|
def shop_list():
|
||||||
if sys.argv[1] == "shop-list":
|
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 2:
|
if len(sys.argv) <= 2:
|
||||||
raise BlitzError("incorrect parameters", "")
|
raise BlitzError("incorrect parameters")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
|
@ -891,17 +883,16 @@ if sys.argv[1] == "shop-list":
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
# SHOP ORDER
|
# SHOP ORDER
|
||||||
# call from web interface
|
# call from web interface
|
||||||
##########################
|
##########################
|
||||||
|
def shop_order():
|
||||||
if sys.argv[1] == "shop-order":
|
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 8:
|
if len(sys.argv) <= 8:
|
||||||
raise BlitzError("incorrect parameters", "")
|
raise BlitzError("incorrect parameters")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
|
@ -926,13 +917,12 @@ if sys.argv[1] == "shop-order":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# SUBSCRIPTIONS LIST
|
# SUBSCRIPTIONS LIST
|
||||||
# call in intervals from background process
|
# call in intervals from background process
|
||||||
#######################
|
#######################
|
||||||
|
def subscriptions_list():
|
||||||
if sys.argv[1] == "subscriptions-list":
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if Path(SUBSCRIPTIONS_FILE).is_file():
|
if Path(SUBSCRIPTIONS_FILE).is_file():
|
||||||
|
@ -947,15 +937,12 @@ if sys.argv[1] == "subscriptions-list":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# SUBSCRIPTIONS RENEW
|
# SUBSCRIPTIONS RENEW
|
||||||
# call in intervals from background process
|
# call in intervals from background process
|
||||||
#######################
|
#######################
|
||||||
|
def subscriptions_renew():
|
||||||
if sys.argv[1] == "subscriptions-renew":
|
|
||||||
|
|
||||||
print("# RUNNING subscriptions-renew")
|
print("# RUNNING subscriptions-renew")
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
|
@ -1002,16 +989,16 @@ if sys.argv[1] == "subscriptions-renew":
|
||||||
subs = toml.load(SUBSCRIPTIONS_FILE)
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
||||||
for sub in subs['subscriptions_ip2tor']:
|
for sub in subs['subscriptions_ip2tor']:
|
||||||
if sub['id'] == subscription['id']:
|
if sub['id'] == subscription['id']:
|
||||||
sub['warning'] = "Exception on Renew: {0}".format(be.errorShort)
|
sub['warning'] = "Exception on Renew: {0}".format(be.short)
|
||||||
if be.errorShort == "invoice bigger amount than advertised":
|
if be.short == "invoice bigger amount than advertised":
|
||||||
sub['contract_breached'] = True
|
sub['contract_breached'] = True
|
||||||
sub['active'] = False
|
sub['active'] = False
|
||||||
with open(SUBSCRIPTIONS_FILE, 'w') as writer:
|
with open(SUBSCRIPTIONS_FILE, 'w') as writer:
|
||||||
writer.write(toml.dumps(subs))
|
writer.write(toml.dumps(subs))
|
||||||
writer.close()
|
writer.close()
|
||||||
break
|
break
|
||||||
print("# BLITZERROR on subscriptions-renew of subscription index {0}: {1}".format(idx, be.errorShort))
|
print("# BLITZERROR on subscriptions-renew of subscription index {0}: {1}".format(idx, be.short))
|
||||||
print("# {0}".format(be.errorShort))
|
print("# {0}".format(be.short))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("# EXCEPTION on subscriptions-renew of subscription index {0}".format(idx))
|
print("# EXCEPTION on subscriptions-renew of subscription index {0}".format(idx))
|
||||||
|
@ -1022,18 +1009,17 @@ if sys.argv[1] == "subscriptions-renew":
|
||||||
|
|
||||||
# output - not needed only for debug logs
|
# output - not needed only for debug logs
|
||||||
print("# DONE subscriptions-renew")
|
print("# DONE subscriptions-renew")
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# SUBSCRIPTION CANCEL
|
# SUBSCRIPTION CANCEL
|
||||||
# call in intervalls from background process
|
# call in intervals from background process
|
||||||
#######################
|
#######################
|
||||||
if sys.argv[1] == "subscription-cancel":
|
def subscription_cancel():
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 2:
|
if len(sys.argv) <= 2:
|
||||||
raise BlitzError("incorrect parameters", "")
|
raise BlitzError("incorrect parameters")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
|
@ -1058,30 +1044,28 @@ if sys.argv[1] == "subscription-cancel":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# GET ADDRESS BY SERVICENAME
|
# GET ADDRESS BY SERVICE NAME
|
||||||
# gets called by other scripts to check if service has a ip2tor bridge address
|
# gets called by other scripts to check if service has a ip2tor bridge address
|
||||||
# output is bash key/value style so that it can be imported with source
|
# output is bash key/value style so that it can be imported with source
|
||||||
#######################
|
#######################
|
||||||
if sys.argv[1] == "subscription-by-service":
|
def subscription_by_service():
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 2:
|
if len(sys.argv) <= 2:
|
||||||
raise BlitzError("incorrect parameters", "")
|
raise BlitzError("incorrect parameters")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
servicename = sys.argv[2]
|
service_name = sys.argv[2]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if os.path.isfile(SUBSCRIPTIONS_FILE):
|
if os.path.isfile(SUBSCRIPTIONS_FILE):
|
||||||
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
||||||
subs = toml.load(SUBSCRIPTIONS_FILE)
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
||||||
for idx, sub in enumerate(subs['subscriptions_ip2tor']):
|
for idx, sub in enumerate(subs['subscriptions_ip2tor']):
|
||||||
if sub['active'] and sub['name'] == servicename:
|
if sub['active'] and sub['name'] == service_name:
|
||||||
print("type='{0}'".format(sub['type']))
|
print("type='{0}'".format(sub['type']))
|
||||||
print("ip='{0}'".format(sub['ip']))
|
print("ip='{0}'".format(sub['ip']))
|
||||||
print("port='{0}'".format(sub['port']))
|
print("port='{0}'".format(sub['port']))
|
||||||
|
@ -1089,24 +1073,22 @@ if sys.argv[1] == "subscription-by-service":
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
print("error='not found'")
|
print("error='not found'")
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# GET IP BY ONIONADDRESS
|
# GET IP BY ONION ADDRESS
|
||||||
# gets called by other scripts to check if a onion address as a IP2TOR bridge
|
# gets called by other scripts to check if a onion address as a IP2TOR bridge
|
||||||
# output is bash key/value style so that it can be imported with source
|
# output is bash key/value style so that it can be imported with source
|
||||||
#######################
|
#######################
|
||||||
if sys.argv[1] == "ip-by-tor":
|
def ip_by_tor():
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 2:
|
if len(sys.argv) <= 2:
|
||||||
raise BlitzError("incorrect parameters", "")
|
raise BlitzError("incorrect parameters")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
|
@ -1126,12 +1108,41 @@ if sys.argv[1] == "ip-by-tor":
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
print("error='not found'")
|
print("error='not found'")
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# unknown command
|
def main():
|
||||||
print("# unknown command")
|
if sys.argv[1] == "create-ssh-dialog":
|
||||||
|
create_ssh_dialog()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "shop-list":
|
||||||
|
shop_list()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "shop-order":
|
||||||
|
shop_order()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscriptions-list":
|
||||||
|
subscriptions_list()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscriptions-renew":
|
||||||
|
subscriptions_renew()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscription-cancel":
|
||||||
|
subscription_cancel()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscription-by-service":
|
||||||
|
subscription_by_service()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "ip-by-tor":
|
||||||
|
ip_by_tor()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# unknown command
|
||||||
|
print("# unknown command")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
|
@ -10,7 +10,7 @@ from pathlib import Path
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import toml
|
import toml
|
||||||
from blitzpy import RaspiBlitzConfig
|
from blitzpy import RaspiBlitzConfig,BlitzError
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
# SCRIPT INFO
|
# SCRIPT INFO
|
||||||
|
@ -30,6 +30,12 @@ if len(sys.argv) <= 1 or sys.argv[1] == "-h" or sys.argv[1] == "help":
|
||||||
print("# blitz.subscriptions.ip2tor.py subscription-cancel <id>")
|
print("# blitz.subscriptions.ip2tor.py subscription-cancel <id>")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# constants for standard services
|
||||||
|
SERVICE_LND_REST_API = "LND-REST-API"
|
||||||
|
SERVICE_LND_GRPC_API = "LND-GRPC-API"
|
||||||
|
SERVICE_LNBITS = "LNBITS"
|
||||||
|
SERVICE_BTCPAY = "BTCPAY"
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
# BASIC SETTINGS
|
# BASIC SETTINGS
|
||||||
#####################
|
#####################
|
||||||
|
@ -49,6 +55,7 @@ if cfg.run_behind_tor:
|
||||||
# HELPER CLASSES
|
# HELPER CLASSES
|
||||||
#####################
|
#####################
|
||||||
|
|
||||||
|
# ToDo(frennkie) replace this with updated BlitzError from blitzpy
|
||||||
class BlitzError(Exception):
|
class BlitzError(Exception):
|
||||||
def __init__(self, errorShort, errorLong="", errorException=None):
|
def __init__(self, errorShort, errorLong="", errorException=None):
|
||||||
self.errorShort = str(errorShort)
|
self.errorShort = str(errorShort)
|
||||||
|
@ -75,19 +82,19 @@ def handleException(e):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def getsubdomain(fulldomainstring):
|
def get_subdomain(fulldomain_str):
|
||||||
return fulldomainstring.split('.')[0]
|
return fulldomain_str.split('.')[0]
|
||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# API Calls to DNS Servcies
|
# API Calls to DNS Services
|
||||||
############################
|
############################
|
||||||
|
|
||||||
def duckDNSupdate(domain, token, ip):
|
def duckdns_update(domain, token, ip):
|
||||||
print("# duckDNS update IP API call for {0}".format(domain))
|
print("# duckDNS update IP API call for {0}".format(domain))
|
||||||
|
|
||||||
# make HTTP request
|
# make HTTP request
|
||||||
url = "https://www.duckdns.org/update?domains={0}&token={1}&ip={2}".format(getsubdomain(domain), token, ip)
|
url = "https://www.duckdns.org/update?domains={0}&token={1}&ip={2}".format(get_subdomain(domain), token, ip)
|
||||||
try:
|
try:
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
|
@ -102,31 +109,33 @@ def duckDNSupdate(domain, token, ip):
|
||||||
# PROCESS FUNCTIONS
|
# PROCESS FUNCTIONS
|
||||||
#####################
|
#####################
|
||||||
|
|
||||||
def subscriptionsNew(ip, dnsservice, id, token, target):
|
def subscriptions_new(ip, dnsservice, id, token, target):
|
||||||
# id needs to the full domain name
|
# id needs to be the full domain name
|
||||||
if id.find(".") == -1:
|
if id.find(".") == -1:
|
||||||
raise BlitzError("not a fully qualified domainname", dnsservice_id)
|
# ToDo(frennkie) dnsservice_id doesn't exit
|
||||||
|
raise BlitzError("not a fully qualified domain name", dnsservice_id)
|
||||||
|
|
||||||
# check if id already exists
|
# check if id already exists
|
||||||
if len(getSubscription(id)) > 0:
|
if len(get_subscription(id)) > 0:
|
||||||
raise BlitzError("id already exists", id)
|
raise BlitzError("id already exists", id)
|
||||||
|
|
||||||
# make sure lets encrypt client is installed
|
# make sure lets encrypt client is installed
|
||||||
os.system("/home/admin/config.scripts/bonus.letsencrypt.sh on")
|
os.system("/home/admin/config.scripts/bonus.letsencrypt.sh on")
|
||||||
|
|
||||||
# dyndns
|
# dyndns
|
||||||
realip = ip
|
real_ip = ip
|
||||||
if ip == "dyndns":
|
if ip == "dyndns":
|
||||||
updateURL = ""
|
update_url = ""
|
||||||
if dnsservice == "duckdns":
|
if dnsservice == "duckdns":
|
||||||
updateURL = "https://www.duckdns.org/update?domains={0}&token={1}".format(getsubdomain(domain), token, ip)
|
# ToDo(frennkie) domain doesn't exit
|
||||||
subprocess.run(['/home/admin/config.scriprs/internet.dyndomain.sh', 'on', id, updateURL],
|
update_url = "https://www.duckdns.org/update?domains={0}&token={1}".format(get_subdomain(domain), token, ip)
|
||||||
|
subprocess.run(['/home/admin/config.scriprs/internet.dyndomain.sh', 'on', id, update_url],
|
||||||
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
||||||
realip = cfg.public_ip
|
real_ip = cfg.public_ip
|
||||||
|
|
||||||
# update DNS with actual IP
|
# update DNS with actual IP
|
||||||
if dnsservice == "duckdns":
|
if dnsservice == "duckdns":
|
||||||
duckDNSupdate(getsubdomain(id), token, realip)
|
duckdns_update(get_subdomain(id), token, real_ip)
|
||||||
|
|
||||||
# create subscription data for storage
|
# create subscription data for storage
|
||||||
subscription = dict()
|
subscription = dict()
|
||||||
|
@ -164,10 +173,10 @@ def subscriptionsNew(ip, dnsservice, id, token, target):
|
||||||
|
|
||||||
# run the ACME script
|
# run the ACME script
|
||||||
print("# Running letsencrypt ACME script ...")
|
print("# Running letsencrypt ACME script ...")
|
||||||
acmeResult = subprocess.Popen(
|
acme_result = subprocess.Popen(
|
||||||
["/home/admin/config.scripts/bonus.letsencrypt.sh", "issue-cert", dnsservice, id, token, target],
|
["/home/admin/config.scripts/bonus.letsencrypt.sh", "issue-cert", dnsservice, id, token, target],
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
|
||||||
out, err = acmeResult.communicate()
|
out, err = acme_result.communicate()
|
||||||
eprint(str(out))
|
eprint(str(out))
|
||||||
eprint(str(err))
|
eprint(str(err))
|
||||||
if out.find("error=") > -1:
|
if out.find("error=") > -1:
|
||||||
|
@ -178,26 +187,24 @@ def subscriptionsNew(ip, dnsservice, id, token, target):
|
||||||
return subscription
|
return subscription
|
||||||
|
|
||||||
|
|
||||||
def subscriptionsCancel(id):
|
def subscriptions_cancel(s_id):
|
||||||
# ToDo(frennkie) id is not used..
|
|
||||||
|
|
||||||
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
||||||
subs = toml.load(SUBSCRIPTIONS_FILE)
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
||||||
newList = []
|
new_list = []
|
||||||
removedCert = None
|
removed_cert = None
|
||||||
for idx, sub in enumerate(subs['subscriptions_letsencrypt']):
|
for idx, sub in enumerate(subs['subscriptions_letsencrypt']):
|
||||||
if sub['id'] != subscriptionID:
|
if sub['id'] != s_id:
|
||||||
newList.append(sub)
|
new_list.append(sub)
|
||||||
else:
|
else:
|
||||||
removedCert = sub
|
removed_cert = sub
|
||||||
subs['subscriptions_letsencrypt'] = newList
|
subs['subscriptions_letsencrypt'] = new_list
|
||||||
|
|
||||||
# run the ACME script to remove cert
|
# run the ACME script to remove cert
|
||||||
if removedCert:
|
if removed_cert:
|
||||||
acmeResult = subprocess.Popen(
|
acme_result = subprocess.Popen(
|
||||||
["/home/admin/config.scripts/bonus.letsencrypt.sh", "remove-cert", removedCert['id'],
|
["/home/admin/config.scripts/bonus.letsencrypt.sh", "remove-cert", removed_cert['id'],
|
||||||
removedCert['target']], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
|
removed_cert['target']], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8')
|
||||||
out, err = acmeResult.communicate()
|
out, err = acme_result.communicate()
|
||||||
if out.find("error=") > -1:
|
if out.find("error=") > -1:
|
||||||
time.sleep(6)
|
time.sleep(6)
|
||||||
raise BlitzError("letsencrypt acme failed", out)
|
raise BlitzError("letsencrypt acme failed", out)
|
||||||
|
@ -212,7 +219,7 @@ def subscriptionsCancel(id):
|
||||||
# todo: deinstall letsencrypt if this was last subscription
|
# todo: deinstall letsencrypt if this was last subscription
|
||||||
|
|
||||||
|
|
||||||
def getSubscription(subscriptionID):
|
def get_subscription(subscription_id):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if Path(SUBSCRIPTIONS_FILE).is_file():
|
if Path(SUBSCRIPTIONS_FILE).is_file():
|
||||||
|
@ -223,7 +230,7 @@ def getSubscription(subscriptionID):
|
||||||
if "subscriptions_letsencrypt" not in subs:
|
if "subscriptions_letsencrypt" not in subs:
|
||||||
return []
|
return []
|
||||||
for idx, sub in enumerate(subs['subscriptions_letsencrypt']):
|
for idx, sub in enumerate(subs['subscriptions_letsencrypt']):
|
||||||
if sub['id'] == subscriptionID:
|
if sub['id'] == subscription_id:
|
||||||
return sub
|
return sub
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -231,7 +238,7 @@ def getSubscription(subscriptionID):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def getDomainByIP(ip):
|
def get_domain_by_ip(ip):
|
||||||
# does subscriptin file exists
|
# does subscriptin file exists
|
||||||
if Path(SUBSCRIPTIONS_FILE).is_file():
|
if Path(SUBSCRIPTIONS_FILE).is_file():
|
||||||
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
||||||
|
@ -253,7 +260,7 @@ def getDomainByIP(ip):
|
||||||
raise BlitzError("no match")
|
raise BlitzError("no match")
|
||||||
|
|
||||||
|
|
||||||
def menuMakeSubscription():
|
def menu_make_subscription():
|
||||||
# late imports - so that rest of script can run also if dependency is not available
|
# late imports - so that rest of script can run also if dependency is not available
|
||||||
from dialog import Dialog
|
from dialog import Dialog
|
||||||
|
|
||||||
|
@ -299,7 +306,7 @@ If you havent already go to https://duckdns.org
|
||||||
title="DuckDNS Domain")
|
title="DuckDNS Domain")
|
||||||
subdomain = text.strip()
|
subdomain = text.strip()
|
||||||
subdomain = subdomain.split(' ')[0]
|
subdomain = subdomain.split(' ')[0]
|
||||||
subdomain = getsubdomain(subdomain)
|
subdomain = get_subdomain(subdomain)
|
||||||
domain = "{0}.duckdns.org".format(subdomain)
|
domain = "{0}.duckdns.org".format(subdomain)
|
||||||
os.system("clear")
|
os.system("clear")
|
||||||
|
|
||||||
|
@ -326,7 +333,7 @@ This looks not like a valid subdomain.
|
||||||
if len(token) < 20:
|
if len(token) < 20:
|
||||||
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
||||||
This looks not like a valid token.
|
This looks not like a valid token.
|
||||||
''', title="Unvalid Input")
|
''', title="Invalid Input")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -350,7 +357,7 @@ This looks not like a valid token.
|
||||||
"\nChoose the kind of IP you want to use:",
|
"\nChoose the kind of IP you want to use:",
|
||||||
choices=choices, width=60, height=10, title="Select Service")
|
choices=choices, width=60, height=10, title="Select Service")
|
||||||
|
|
||||||
# if user chosses CANCEL
|
# if user chooses CANCEL
|
||||||
os.system("clear")
|
os.system("clear")
|
||||||
if code != d.OK:
|
if code != d.OK:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -362,16 +369,16 @@ This looks not like a valid token.
|
||||||
if tag == "IP2TOR":
|
if tag == "IP2TOR":
|
||||||
|
|
||||||
# get all active IP2TOR subscriptions (just in case)
|
# get all active IP2TOR subscriptions (just in case)
|
||||||
ip2torSubs = []
|
ip2tor_subs = []
|
||||||
if Path(SUBSCRIPTIONS_FILE).is_file():
|
if Path(SUBSCRIPTIONS_FILE).is_file():
|
||||||
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
||||||
subs = toml.load(SUBSCRIPTIONS_FILE)
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
||||||
for idx, sub in enumerate(subs['subscriptions_ip2tor']):
|
for idx, sub in enumerate(subs['subscriptions_ip2tor']):
|
||||||
if sub['active']:
|
if sub['active']:
|
||||||
ip2torSubs.append(sub)
|
ip2tor_subs.append(sub)
|
||||||
|
|
||||||
# when user has no IP2TOR subs yet
|
# when user has no IP2TOR subs yet
|
||||||
if len(ip2torSubs) == 0:
|
if len(ip2tor_subs) == 0:
|
||||||
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
||||||
You have no active IP2TOR subscriptions.
|
You have no active IP2TOR subscriptions.
|
||||||
Create one first and try again.
|
Create one first and try again.
|
||||||
|
@ -380,7 +387,7 @@ Create one first and try again.
|
||||||
|
|
||||||
# let user select a IP2TOR subscription
|
# let user select a IP2TOR subscription
|
||||||
choices = []
|
choices = []
|
||||||
for idx, sub in enumerate(ip2torSubs):
|
for idx, sub in enumerate(ip2tor_subs):
|
||||||
choices.append(("{0}".format(idx), "IP2TOR {0} {1}:{2}".format(sub['name'], sub['ip'], sub['port'])))
|
choices.append(("{0}".format(idx), "IP2TOR {0} {1}:{2}".format(sub['name'], sub['ip'], sub['port'])))
|
||||||
|
|
||||||
d = Dialog(dialog="dialog", autowidgetsize=True)
|
d = Dialog(dialog="dialog", autowidgetsize=True)
|
||||||
|
@ -394,8 +401,8 @@ Create one first and try again.
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# get the slected IP2TOR bridge
|
# get the slected IP2TOR bridge
|
||||||
ip2torSelect = ip2torSubs[int(tag)]
|
ip2tor_select = ip2tor_subs[int(tag)]
|
||||||
ip = ip2torSelect["ip"]
|
ip = ip2tor_select["ip"]
|
||||||
target = "tor"
|
target = "tor"
|
||||||
|
|
||||||
elif tag == "DYNDNS":
|
elif tag == "DYNDNS":
|
||||||
|
@ -421,13 +428,13 @@ Create one first and try again.
|
||||||
if len(ip) == 0:
|
if len(ip) == 0:
|
||||||
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
||||||
This looks not like a valid IP.
|
This looks not like a valid IP.
|
||||||
''', title="Unvalid Input")
|
''', title="Invalid Input")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# create the letsencrypt subscription
|
# create the letsencrypt subscription
|
||||||
try:
|
try:
|
||||||
os.system("clear")
|
os.system("clear")
|
||||||
subscription = subscriptionsNew(ip, dnsservice, domain, token, target)
|
subscription = subscriptions_new(ip, dnsservice, domain, token, target)
|
||||||
|
|
||||||
# success dialog
|
# success dialog
|
||||||
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
||||||
|
@ -455,19 +462,15 @@ Unknown Error happened - please report to developers:
|
||||||
# CREATE SSH DIALOG
|
# CREATE SSH DIALOG
|
||||||
# use for ssh shell menu
|
# use for ssh shell menu
|
||||||
###############
|
###############
|
||||||
|
def create_ssh_dialog():
|
||||||
|
menu_make_subscription()
|
||||||
|
|
||||||
if sys.argv[1] == "create-ssh-dialog":
|
|
||||||
menuMakeSubscription()
|
|
||||||
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
# SUBSCRIPTIONS NEW
|
# SUBSCRIPTIONS NEW
|
||||||
# call from web interface
|
# call from web interface
|
||||||
##########################
|
##########################
|
||||||
|
def subscription_new():
|
||||||
if sys.argv[1] == "subscription-new":
|
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 5:
|
if len(sys.argv) <= 5:
|
||||||
|
@ -486,7 +489,7 @@ if sys.argv[1] == "subscription-new":
|
||||||
|
|
||||||
# create the subscription
|
# create the subscription
|
||||||
try:
|
try:
|
||||||
subscription = subscriptionsNew(ip, dnsservice_type, dnsservice_id, dnsservice_token, target)
|
subscription = subscriptions_new(ip, dnsservice_type, dnsservice_id, dnsservice_token, target)
|
||||||
|
|
||||||
# output json ordered bridge
|
# output json ordered bridge
|
||||||
print(json.dumps(subscription, indent=2))
|
print(json.dumps(subscription, indent=2))
|
||||||
|
@ -495,12 +498,11 @@ if sys.argv[1] == "subscription-new":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# SUBSCRIPTIONS LIST
|
# SUBSCRIPTIONS LIST
|
||||||
#######################
|
#######################
|
||||||
|
def subscriptions_list():
|
||||||
if sys.argv[1] == "subscriptions-list":
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if Path(SUBSCRIPTIONS_FILE).is_file():
|
if Path(SUBSCRIPTIONS_FILE).is_file():
|
||||||
|
@ -515,13 +517,11 @@ if sys.argv[1] == "subscriptions-list":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# SUBSCRIPTION DETAIL
|
# SUBSCRIPTION DETAIL
|
||||||
#######################
|
#######################
|
||||||
if sys.argv[1] == "subscription-detail":
|
def subscription_detail():
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 2:
|
if len(sys.argv) <= 2:
|
||||||
|
@ -529,22 +529,20 @@ if sys.argv[1] == "subscription-detail":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
subscriptionID = sys.argv[2]
|
subscription_id = sys.argv[2]
|
||||||
try:
|
try:
|
||||||
sub = getSubscription(subscriptionID)
|
sub = get_subscription(subscription_id)
|
||||||
print(json.dumps(sub, indent=2))
|
print(json.dumps(sub, indent=2))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# DOMAIN BY IP
|
# DOMAIN BY IP
|
||||||
# to check if an ip has a domain mapping
|
# to check if an ip has a domain mapping
|
||||||
#######################
|
#######################
|
||||||
if sys.argv[1] == "domain-by-ip":
|
def domain_by_ip():
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 2:
|
if len(sys.argv) <= 2:
|
||||||
|
@ -556,19 +554,17 @@ if sys.argv[1] == "domain-by-ip":
|
||||||
ip = sys.argv[2]
|
ip = sys.argv[2]
|
||||||
try:
|
try:
|
||||||
|
|
||||||
domain = getDomainByIP(ip)
|
domain = get_domain_by_ip(ip)
|
||||||
print("domain='{0}'".format(domain))
|
print("domain='{0}'".format(domain))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# SUBSCRIPTION CANCEL
|
# SUBSCRIPTION CANCEL
|
||||||
#######################
|
#######################
|
||||||
if sys.argv[1] == "subscription-cancel":
|
def subscription_cancel():
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
try:
|
try:
|
||||||
if len(sys.argv) <= 2:
|
if len(sys.argv) <= 2:
|
||||||
|
@ -576,13 +572,36 @@ if sys.argv[1] == "subscription-cancel":
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
subscriptionID = sys.argv[2]
|
subscription_id = sys.argv[2]
|
||||||
try:
|
try:
|
||||||
subscriptionsCancel(subscriptionID)
|
subscriptions_cancel(subscription_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
handleException(e)
|
handleException(e)
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# unknown command
|
def main():
|
||||||
print("# unknown command")
|
if sys.argv[1] == "create-ssh-dialog":
|
||||||
|
create_ssh_dialog()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "domain-by-ip":
|
||||||
|
domain_by_ip()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscriptions-list":
|
||||||
|
subscriptions_list()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscription-cancel":
|
||||||
|
subscription_cancel()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscription-detail":
|
||||||
|
subscription_detail()
|
||||||
|
|
||||||
|
elif sys.argv[1] == "subscription-new":
|
||||||
|
subscription_new()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# unknown command
|
||||||
|
print("# unknown command")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
|
@ -15,10 +15,10 @@ from blitzpy import RaspiBlitzConfig
|
||||||
from dialog import Dialog
|
from dialog import Dialog
|
||||||
|
|
||||||
# constants for standard services
|
# constants for standard services
|
||||||
LND_REST_API = "LND-REST-API"
|
SERVICE_LND_REST_API = "LND-REST-API"
|
||||||
LND_GRPC_API = "LND-GRPC-API"
|
SERVICE_LND_GRPC_API = "LND-GRPC-API"
|
||||||
LNBITS = "LNBITS"
|
SERVICE_LNBITS = "LNBITS"
|
||||||
BTCPAY = "BTCPAY"
|
SERVICE_BTCPAY = "BTCPAY"
|
||||||
|
|
||||||
# load config
|
# load config
|
||||||
cfg = RaspiBlitzConfig()
|
cfg = RaspiBlitzConfig()
|
||||||
|
@ -32,35 +32,38 @@ SUBSCRIPTIONS_FILE = "/mnt/hdd/app-data/subscriptions/subscriptions.toml"
|
||||||
# HELPER FUNCTIONS
|
# HELPER FUNCTIONS
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
|
# ToDo(frennkie) these are not being used!
|
||||||
|
|
||||||
def eprint(*args, **kwargs):
|
def eprint(*args, **kwargs):
|
||||||
print(*args, file=sys.stderr, **kwargs)
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def parseDateIP2TORSERVER(datestr):
|
def parse_date_ip2tor(date_str):
|
||||||
return datetime.strptime(datestr, "%Y-%m-%dT%H:%M:%S.%fZ")
|
return datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%S.%fZ")
|
||||||
|
|
||||||
|
|
||||||
def secondsLeft(dateObj):
|
def seconds_left(date_obj):
|
||||||
return round((dateObj - datetime.utcnow()).total_seconds())
|
return round((date_obj - datetime.utcnow()).total_seconds())
|
||||||
|
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# SSH MENU FUNCTIONS
|
# SSH MENU FUNCTIONS
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
def mySubscriptions():
|
def my_subscriptions():
|
||||||
# check if any subscriptions are available
|
# check if any subscriptions are available
|
||||||
countSubscriptions = 0
|
count_subscriptions = 0
|
||||||
try:
|
try:
|
||||||
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
||||||
subs = toml.load(SUBSCRIPTIONS_FILE)
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
||||||
if 'subscriptions_ip2tor' in subs:
|
if 'subscriptions_ip2tor' in subs:
|
||||||
countSubscriptions += len(subs['subscriptions_ip2tor'])
|
count_subscriptions += len(subs['subscriptions_ip2tor'])
|
||||||
if 'subscriptions_letsencrypt' in subs:
|
if 'subscriptions_letsencrypt' in subs:
|
||||||
countSubscriptions += len(subs['subscriptions_letsencrypt'])
|
count_subscriptions += len(subs['subscriptions_letsencrypt'])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
print(f"warning: {e}")
|
||||||
if countSubscriptions == 0:
|
|
||||||
|
if count_subscriptions == 0:
|
||||||
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
||||||
You have no active or inactive subscriptions.
|
You have no active or inactive subscriptions.
|
||||||
''', title="Info")
|
''', title="Info")
|
||||||
|
@ -69,36 +72,36 @@ You have no active or inactive subscriptions.
|
||||||
# load subscriptions and make dialog choices out of it
|
# load subscriptions and make dialog choices out of it
|
||||||
choices = []
|
choices = []
|
||||||
lookup = {}
|
lookup = {}
|
||||||
lookupIndex = 0
|
lookup_index = 0
|
||||||
subs = toml.load(SUBSCRIPTIONS_FILE)
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
||||||
|
|
||||||
# list ip2tor subscriptions
|
# list ip2tor subscriptions
|
||||||
if 'subscriptions_ip2tor' in subs:
|
if 'subscriptions_ip2tor' in subs:
|
||||||
for sub in subs['subscriptions_ip2tor']:
|
for sub in subs['subscriptions_ip2tor']:
|
||||||
# remember subscription under lookupindex
|
# remember subscription under lookupindex
|
||||||
lookupIndex += 1
|
lookup_index += 1
|
||||||
lookup[str(lookupIndex)] = sub
|
lookup[str(lookup_index)] = sub
|
||||||
# add to dialog choices
|
# add to dialog choices
|
||||||
if sub['active']:
|
if sub['active']:
|
||||||
activeState = "active"
|
active_state = "active"
|
||||||
else:
|
else:
|
||||||
activeState = "in-active"
|
active_state = "in-active"
|
||||||
name = "IP2TOR Bridge (P:{1}) for {0}".format(sub['name'], sub['port'])
|
name = "IP2TOR Bridge (P:{1}) for {0}".format(sub['name'], sub['port'])
|
||||||
choices.append(("{0}".format(lookupIndex), "{0} ({1})".format(name.ljust(30), activeState)))
|
choices.append(("{0}".format(lookup_index), "{0} ({1})".format(name.ljust(30), active_state)))
|
||||||
|
|
||||||
# list letsencrypt subscriptions
|
# list letsencrypt subscriptions
|
||||||
if 'subscriptions_letsencrypt' in subs:
|
if 'subscriptions_letsencrypt' in subs:
|
||||||
for sub in subs['subscriptions_letsencrypt']:
|
for sub in subs['subscriptions_letsencrypt']:
|
||||||
# remember subscription under lookupindex
|
# remember subscription under lookupindex
|
||||||
lookupIndex += 1
|
lookup_index += 1
|
||||||
lookup[str(lookupIndex)] = sub
|
lookup[str(lookup_index)] = sub
|
||||||
# add to dialog choices
|
# add to dialog choices
|
||||||
if sub['active']:
|
if sub['active']:
|
||||||
activeState = "active"
|
active_state = "active"
|
||||||
else:
|
else:
|
||||||
activeState = "in-active"
|
active_state = "in-active"
|
||||||
name = "LETSENCRYPT {0}".format(sub['id'])
|
name = "LETSENCRYPT {0}".format(sub['id'])
|
||||||
choices.append(("{0}".format(lookupIndex), "{0} ({1})".format(name.ljust(30), activeState)))
|
choices.append(("{0}".format(lookup_index), "{0} ({1})".format(name.ljust(30), active_state)))
|
||||||
|
|
||||||
# show menu with options
|
# show menu with options
|
||||||
d = Dialog(dialog="dialog", autowidgetsize=True)
|
d = Dialog(dialog="dialog", autowidgetsize=True)
|
||||||
|
@ -111,15 +114,15 @@ You have no active or inactive subscriptions.
|
||||||
if code != d.OK:
|
if code != d.OK:
|
||||||
return
|
return
|
||||||
|
|
||||||
# get data of selected subscrption
|
# get data of selected subscription
|
||||||
selectedSub = lookup[str(tag)]
|
selected_sub = lookup[str(tag)]
|
||||||
|
|
||||||
# show details of selected
|
# show details of selected
|
||||||
d = Dialog(dialog="dialog", autowidgetsize=True)
|
d = Dialog(dialog="dialog", autowidgetsize=True)
|
||||||
d.set_background_title("My Subscriptions")
|
d.set_background_title("My Subscriptions")
|
||||||
if selectedSub['type'] == "letsencrypt-v1":
|
if selected_sub['type'] == "letsencrypt-v1":
|
||||||
if len(selectedSub['warning']) > 0:
|
if len(selected_sub['warning']) > 0:
|
||||||
selectedSub['warning'] = "\n{0}".format(selectedSub['warning'])
|
selected_sub['warning'] = "\n{0}".format(selected_sub['warning'])
|
||||||
text = '''
|
text = '''
|
||||||
This is a LetsEncrypt subscription using the free DNS service
|
This is a LetsEncrypt subscription using the free DNS service
|
||||||
{dnsservice}
|
{dnsservice}
|
||||||
|
@ -135,17 +138,17 @@ The state of the subscription is: {active} {warning}
|
||||||
The following additional information is available:
|
The following additional information is available:
|
||||||
{description}
|
{description}
|
||||||
|
|
||||||
'''.format(dnsservice=selectedSub['dnsservice_type'],
|
'''.format(dnsservice=selected_sub['dnsservice_type'],
|
||||||
domain=selectedSub['id'],
|
domain=selected_sub['id'],
|
||||||
ip=selectedSub['ip'],
|
ip=selected_sub['ip'],
|
||||||
active="ACTIVE" if selectedSub['active'] else "NOT ACTIVE",
|
active="ACTIVE" if selected_sub['active'] else "NOT ACTIVE",
|
||||||
warning=selectedSub['warning'],
|
warning=selected_sub['warning'],
|
||||||
description=selectedSub['description']
|
description=selected_sub['description']
|
||||||
)
|
)
|
||||||
|
|
||||||
elif selectedSub['type'] == "ip2tor-v1":
|
elif selected_sub['type'] == "ip2tor-v1":
|
||||||
if len(selectedSub['warning']) > 0:
|
if len(selected_sub['warning']) > 0:
|
||||||
selectedSub['warning'] = "\n{0}".format(selectedSub['warning'])
|
selected_sub['warning'] = "\n{0}".format(selected_sub['warning'])
|
||||||
text = '''
|
text = '''
|
||||||
This is a IP2TOR subscription bought on {initdate} at
|
This is a IP2TOR subscription bought on {initdate} at
|
||||||
{shop}
|
{shop}
|
||||||
|
@ -161,26 +164,26 @@ The state of the subscription is: {active} {warning}
|
||||||
|
|
||||||
The following additional information is available:
|
The following additional information is available:
|
||||||
{description}
|
{description}
|
||||||
'''.format(initdate=selectedSub['time_created'],
|
'''.format(initdate=selected_sub['time_created'],
|
||||||
shop=selectedSub['shop'],
|
shop=selected_sub['shop'],
|
||||||
publicaddress="{0}:{1}".format(selectedSub['ip'], selectedSub['port']),
|
publicaddress="{0}:{1}".format(selected_sub['ip'], selected_sub['port']),
|
||||||
toraddress=selectedSub['tor'],
|
toraddress=selected_sub['tor'],
|
||||||
renewhours=(round(int(selectedSub['duration']) / 3600)),
|
renewhours=(round(int(selected_sub['duration']) / 3600)),
|
||||||
renewsats=(round(int(selectedSub['price_extension']) / 1000)),
|
renewsats=(round(int(selected_sub['price_extension']) / 1000)),
|
||||||
totalsats=(round(int(selectedSub['price_total']) / 1000)),
|
totalsats=(round(int(selected_sub['price_total']) / 1000)),
|
||||||
active="ACTIVE" if selectedSub['active'] else "NOT ACTIVE",
|
active="ACTIVE" if selected_sub['active'] else "NOT ACTIVE",
|
||||||
warning=selectedSub['warning'],
|
warning=selected_sub['warning'],
|
||||||
description=selectedSub['description'],
|
description=selected_sub['description'],
|
||||||
service=selectedSub['name']
|
service=selected_sub['name']
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
text = "no text?! FIXME"
|
text = "no text?! FIXME"
|
||||||
|
|
||||||
if selectedSub['active']:
|
if selected_sub['active']:
|
||||||
extraLable = "CANCEL SUBSCRIPTION"
|
extra_label = "CANCEL SUBSCRIPTION"
|
||||||
else:
|
else:
|
||||||
extraLable = "DELETE SUBSCRIPTION"
|
extra_label = "DELETE SUBSCRIPTION"
|
||||||
code = d.msgbox(text, title="Subscription Detail", ok_label="Back", extra_button=True, extra_label=extraLable,
|
code = d.msgbox(text, title="Subscription Detail", ok_label="Back", extra_button=True, extra_label=extra_label,
|
||||||
width=75, height=30)
|
width=75, height=30)
|
||||||
|
|
||||||
# user wants to delete this subscription
|
# user wants to delete this subscription
|
||||||
|
@ -188,15 +191,15 @@ The following additional information is available:
|
||||||
# api calls when canceling
|
# api calls when canceling
|
||||||
if code == "extra":
|
if code == "extra":
|
||||||
os.system("clear")
|
os.system("clear")
|
||||||
if selectedSub['type'] == "letsencrypt-v1":
|
if selected_sub['type'] == "letsencrypt-v1":
|
||||||
cmd = "python /home/admin/config.scripts/blitz.subscriptions.letsencrypt.py subscription-cancel {0}".format(
|
cmd = "python /home/admin/config.scripts/blitz.subscriptions.letsencrypt.py subscription-cancel {0}".format(
|
||||||
selectedSub['id'])
|
selected_sub['id'])
|
||||||
print("# running: {0}".format(cmd))
|
print("# running: {0}".format(cmd))
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
elif selectedSub['type'] == "ip2tor-v1":
|
elif selected_sub['type'] == "ip2tor-v1":
|
||||||
cmd = "python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py subscription-cancel {0}".format(
|
cmd = "python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py subscription-cancel {0}".format(
|
||||||
selectedSub['id'])
|
selected_sub['id'])
|
||||||
print("# running: {0}".format(cmd))
|
print("# running: {0}".format(cmd))
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
@ -205,183 +208,188 @@ The following additional information is available:
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
# loop until no more subscriptions or user chooses CANCEL on subscription list
|
# loop until no more subscriptions or user chooses CANCEL on subscription list
|
||||||
mySubscriptions()
|
my_subscriptions()
|
||||||
|
|
||||||
|
|
||||||
#######################
|
def main():
|
||||||
# SSH MENU
|
#######################
|
||||||
#######################
|
# SSH MENU
|
||||||
|
#######################
|
||||||
|
|
||||||
choices = list()
|
|
||||||
choices.append(("LIST", "My Subscriptions"))
|
|
||||||
choices.append(("NEW1", "+ IP2TOR Bridge (paid)"))
|
|
||||||
choices.append(("NEW2", "+ LetsEncrypt HTTPS Domain (free)"))
|
|
||||||
|
|
||||||
d = Dialog(dialog="dialog", autowidgetsize=True)
|
|
||||||
d.set_background_title("RaspiBlitz Subscriptions")
|
|
||||||
code, tag = d.menu(
|
|
||||||
"\nCheck existing subscriptions or create new:",
|
|
||||||
choices=choices, width=50, height=10, title="Subscription Management")
|
|
||||||
|
|
||||||
# if user chosses CANCEL
|
|
||||||
if code != d.OK:
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
#######################
|
|
||||||
# MANAGE SUBSCRIPTIONS
|
|
||||||
#######################
|
|
||||||
|
|
||||||
if tag == "LIST":
|
|
||||||
mySubscriptions()
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
###############################
|
|
||||||
# NEW LETSENCRYPT HTTPS DOMAIN
|
|
||||||
###############################
|
|
||||||
|
|
||||||
if tag == "NEW2":
|
|
||||||
# run creating a new IP2TOR subscription
|
|
||||||
os.system("clear")
|
|
||||||
cmd = "python /home/admin/config.scripts/blitz.subscriptions.letsencrypt.py create-ssh-dialog"
|
|
||||||
print("# running: {0}".format(cmd))
|
|
||||||
os.system(cmd)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
###############################
|
|
||||||
# NEW IP2TOR BRIDGE
|
|
||||||
###############################
|
|
||||||
|
|
||||||
if tag == "NEW1":
|
|
||||||
|
|
||||||
# check if Blitz is running behind TOR
|
|
||||||
cfg.reload()
|
|
||||||
if not cfg.run_behind_tor.value:
|
|
||||||
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
|
||||||
The IP2TOR service just makes sense if you run
|
|
||||||
your RaspiBlitz behind TOR.
|
|
||||||
''', title="Info")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
os.system("clear")
|
|
||||||
print("please wait ..")
|
|
||||||
|
|
||||||
# check for which standard services already a active bridge exists
|
|
||||||
lnd_rest_api = False
|
|
||||||
lnd_grpc_api = False
|
|
||||||
lnbits = False
|
|
||||||
btcpay = False
|
|
||||||
try:
|
|
||||||
if os.path.isfile(SUBSCRIPTIONS_FILE):
|
|
||||||
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
|
||||||
subs = toml.load(SUBSCRIPTIONS_FILE)
|
|
||||||
for sub in subs['subscriptions_ip2tor']:
|
|
||||||
if not sub['active']:
|
|
||||||
continue
|
|
||||||
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
|
|
||||||
if sub['active'] and sub['name'] == LNBITS:
|
|
||||||
lnbits = True
|
|
||||||
if sub['active'] and sub['name'] == BTCPAY:
|
|
||||||
btcpay = True
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
# check if BTCPayserver is installed
|
|
||||||
btcPayServer = False
|
|
||||||
statusData = subprocess.run(['/home/admin/config.scripts/bonus.btcpayserver.sh', 'status'],
|
|
||||||
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
|
||||||
if statusData.find("installed=1") > -1:
|
|
||||||
btcPayServer = True
|
|
||||||
|
|
||||||
# ask user for which RaspiBlitz service the bridge should be used
|
|
||||||
choices = list()
|
choices = list()
|
||||||
choices.append(("REST", "LND REST API {0}".format("--> ALREADY BRIDGED" if lnd_rest_api else "")))
|
choices.append(("LIST", "My Subscriptions"))
|
||||||
choices.append(("GRPC", "LND gRPC API {0}".format("--> ALREADY BRIDGED" if lnd_grpc_api else "")))
|
choices.append(("NEW1", "+ IP2TOR Bridge (paid)"))
|
||||||
if cfg.lnbits:
|
choices.append(("NEW2", "+ LetsEncrypt HTTPS Domain (free)"))
|
||||||
choices.append(("LNBITS", "LNbits Webinterface {0}".format("--> ALREADY BRIDGED" if lnd_grpc_api else "")))
|
|
||||||
if btcPayServer:
|
|
||||||
choices.append(("BTCPAY", "BTCPay Server Webinterface {0}".format("--> ALREADY BRIDGED" if btcpay else "")))
|
|
||||||
choices.append(("SELF", "Create a custom IP2TOR Bridge"))
|
|
||||||
|
|
||||||
d = Dialog(dialog="dialog", autowidgetsize=True)
|
d = Dialog(dialog="dialog", autowidgetsize=True)
|
||||||
d.set_background_title("RaspiBlitz Subscriptions")
|
d.set_background_title("RaspiBlitz Subscriptions")
|
||||||
code, tag = d.menu(
|
code, tag = d.menu(
|
||||||
"\nChoose RaspiBlitz Service to create Bridge for:",
|
"\nCheck existing subscriptions or create new:",
|
||||||
choices=choices, width=60, height=10, title="Select Service")
|
choices=choices, width=50, height=10, title="Subscription Management")
|
||||||
|
|
||||||
# if user chosses CANCEL
|
# if user chosses CANCEL
|
||||||
if code != d.OK:
|
if code != d.OK:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
servicename = None
|
#######################
|
||||||
torAddress = None
|
# MANAGE SUBSCRIPTIONS
|
||||||
torPort = None
|
#######################
|
||||||
if tag == "REST":
|
|
||||||
# get TOR address for REST
|
if tag == "LIST":
|
||||||
servicename = LND_REST_API
|
my_subscriptions()
|
||||||
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrest8080/hostname'],
|
sys.exit(0)
|
||||||
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
|
||||||
torPort = 8080
|
###############################
|
||||||
if tag == "GRPC":
|
# NEW LETSENCRYPT HTTPS DOMAIN
|
||||||
# get TOR address for GRPC
|
###############################
|
||||||
servicename = LND_GRPC_API
|
|
||||||
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrpc10009/hostname'],
|
if tag == "NEW2":
|
||||||
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
# run creating a new IP2TOR subscription
|
||||||
torPort = 10009
|
os.system("clear")
|
||||||
if tag == "LNBITS":
|
cmd = "python /home/admin/config.scripts/blitz.subscriptions.letsencrypt.py create-ssh-dialog"
|
||||||
# get TOR address for LNBits
|
print("# running: {0}".format(cmd))
|
||||||
servicename = LNBITS
|
os.system(cmd)
|
||||||
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lnbits/hostname'],
|
sys.exit(0)
|
||||||
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
|
||||||
torPort = 443
|
###############################
|
||||||
if tag == "BTCPAY":
|
# NEW IP2TOR BRIDGE
|
||||||
# get TOR address for BTCPAY
|
###############################
|
||||||
servicename = BTCPAY
|
|
||||||
torAddress = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/btcpay/hostname'],
|
if tag == "NEW1":
|
||||||
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
|
||||||
torPort = 443
|
# check if Blitz is running behind TOR
|
||||||
if tag == "SELF":
|
cfg.reload()
|
||||||
servicename = "CUSTOM"
|
if not cfg.run_behind_tor.value:
|
||||||
try:
|
Dialog(dialog="dialog", autowidgetsize=True).msgbox('''
|
||||||
# get custom TOR address
|
The IP2TOR service just makes sense if you run
|
||||||
code, text = d.inputbox(
|
your RaspiBlitz behind TOR.
|
||||||
"Enter TOR Onion-Address:",
|
''', title="Info")
|
||||||
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)
|
sys.exit(1)
|
||||||
|
|
||||||
# run creating a new IP2TOR subscription
|
os.system("clear")
|
||||||
os.system("clear")
|
print("please wait ..")
|
||||||
cmd = "python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py create-ssh-dialog {0} {1} {2}".format(
|
|
||||||
servicename, torAddress, torPort)
|
# check for which standard services already a active bridge exists
|
||||||
print("# running: {0}".format(cmd))
|
lnd_rest_api = False
|
||||||
os.system(cmd)
|
lnd_grpc_api = False
|
||||||
sys.exit(0)
|
lnbits = False
|
||||||
|
btcpay = False
|
||||||
|
try:
|
||||||
|
if os.path.isfile(SUBSCRIPTIONS_FILE):
|
||||||
|
os.system("sudo chown admin:admin {0}".format(SUBSCRIPTIONS_FILE))
|
||||||
|
subs = toml.load(SUBSCRIPTIONS_FILE)
|
||||||
|
for sub in subs['subscriptions_ip2tor']:
|
||||||
|
if not sub['active']:
|
||||||
|
continue
|
||||||
|
if sub['active'] and sub['name'] == SERVICE_LND_REST_API:
|
||||||
|
lnd_rest_api = True
|
||||||
|
if sub['active'] and sub['name'] == SERVICE_LND_GRPC_API:
|
||||||
|
lnd_grpc_api = True
|
||||||
|
if sub['active'] and sub['name'] == SERVICE_LNBITS:
|
||||||
|
lnbits = True
|
||||||
|
if sub['active'] and sub['name'] == SERVICE_BTCPAY:
|
||||||
|
btcpay = True
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
# check if BTCPayServer is installed
|
||||||
|
btc_pay_server = False
|
||||||
|
status_data = subprocess.run(['/home/admin/config.scripts/bonus.btcpayserver.sh', 'status'],
|
||||||
|
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
||||||
|
if status_data.find("installed=1") > -1:
|
||||||
|
btc_pay_server = True
|
||||||
|
|
||||||
|
# ask user for which RaspiBlitz service the bridge should be used
|
||||||
|
choices = list()
|
||||||
|
choices.append(("REST", "LND REST API {0}".format("--> ALREADY BRIDGED" if lnd_rest_api else "")))
|
||||||
|
choices.append(("GRPC", "LND gRPC API {0}".format("--> ALREADY BRIDGED" if lnd_grpc_api else "")))
|
||||||
|
if cfg.lnbits:
|
||||||
|
choices.append(("LNBITS", "LNbits Webinterface {0}".format("--> ALREADY BRIDGED" if lnbits else "")))
|
||||||
|
if btc_pay_server:
|
||||||
|
choices.append(("BTCPAY", "BTCPay Server Webinterface {0}".format("--> ALREADY BRIDGED" if btcpay else "")))
|
||||||
|
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:",
|
||||||
|
choices=choices, width=60, height=10, title="Select Service")
|
||||||
|
|
||||||
|
# if user chosses CANCEL
|
||||||
|
if code != d.OK:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
service_name = None
|
||||||
|
tor_address = None
|
||||||
|
tor_port = None
|
||||||
|
if tag == "REST":
|
||||||
|
# get TOR address for REST
|
||||||
|
service_name = SERVICE_LND_REST_API
|
||||||
|
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrest8080/hostname'],
|
||||||
|
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
||||||
|
tor_port = 8080
|
||||||
|
if tag == "GRPC":
|
||||||
|
# get TOR address for GRPC
|
||||||
|
service_name = SERVICE_LND_GRPC_API
|
||||||
|
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lndrpc10009/hostname'],
|
||||||
|
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
||||||
|
tor_port = 10009
|
||||||
|
if tag == "LNBITS":
|
||||||
|
# get TOR address for LNBits
|
||||||
|
service_name = SERVICE_LNBITS
|
||||||
|
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/lnbits/hostname'],
|
||||||
|
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
||||||
|
tor_port = 443
|
||||||
|
if tag == "BTCPAY":
|
||||||
|
# get TOR address for BTCPAY
|
||||||
|
service_name = SERVICE_BTCPAY
|
||||||
|
tor_address = subprocess.run(['sudo', 'cat', '/mnt/hdd/tor/btcpay/hostname'],
|
||||||
|
stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
|
||||||
|
tor_port = 443
|
||||||
|
if tag == "SELF":
|
||||||
|
service_name = "CUSTOM"
|
||||||
|
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)
|
||||||
|
tor_address = 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)
|
||||||
|
tor_port = int(text)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
time.sleep(3)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# run creating a new IP2TOR subscription
|
||||||
|
os.system("clear")
|
||||||
|
cmd = "python /home/admin/config.scripts/blitz.subscriptions.ip2tor.py create-ssh-dialog {0} {1} {2}".format(
|
||||||
|
service_name, tor_address, tor_port)
|
||||||
|
print("# running: {0}".format(cmd))
|
||||||
|
os.system(cmd)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue