7 Commits

Author SHA1 Message Date
afc227b5b4 fix: Remove some unnecessary logs
All checks were successful
Build Docker / Build Image (push) Successful in 43s
2025-02-05 14:53:33 +11:00
ab7749ef93 fix: Allow desciption to have HTML in plugin output 2025-02-05 14:39:52 +11:00
a568abeb49 fix: Don't import gunicorn unless specified by args
All checks were successful
Build Docker / Build Image (push) Successful in 45s
2025-02-05 13:51:01 +11:00
4652af3a2d feat: Add new server backend to add windows support
All checks were successful
Build Docker / Build Image (push) Successful in 1m18s
2025-02-05 13:20:09 +11:00
9aa061691d fix: Update update to make it clearer
All checks were successful
Build Docker / Build Image (push) Successful in 51s
2025-02-04 18:25:27 +11:00
ce8c773db3 fix: Allow reloading modules without a restart
All checks were successful
Build Docker / Build Image (push) Successful in 53s
2025-02-04 16:59:47 +11:00
12884fe696 feat: Default to debug mode off to stop reloads
All checks were successful
Build Docker / Build Image (push) Successful in 47s
2025-02-04 15:33:56 +11:00
9 changed files with 69 additions and 47 deletions

4
.gitignore vendored
View File

@@ -13,4 +13,6 @@ plugins/signatures.json
user_data/ user_data/
customPlugins/ customPlugins/
cache/ cache/
build/
dist/

Binary file not shown.

View File

@@ -436,7 +436,6 @@ def send(account,address,amount):
def isOwnDomain(account,name: str): def isOwnDomain(account,name: str):
domains = getDomains(account) domains = getDomains(account)
for domain in domains: for domain in domains:
print(domain)
if domain['name'] == name: if domain['name'] == name:
return True return True
return False return False
@@ -1139,7 +1138,6 @@ def getxPub(account):
try: try:
print(account_name)
response = hsw.getAccountInfo(account_name,"default") response = hsw.getAccountInfo(account_name,"default")
if 'error' in response: if 'error' in response:
return { return {

18
main.py
View File

@@ -1,6 +1,7 @@
import io import io
import json import json
import random import random
import sys
from flask import Flask, make_response, redirect, request, jsonify, render_template, send_from_directory,send_file from flask import Flask, make_response, redirect, request, jsonify, render_template, send_from_directory,send_file
import os import os
import dotenv import dotenv
@@ -55,7 +56,7 @@ def index():
commit = info['commit'] commit = info['commit']
if commit != latestVersion(branch): if commit != latestVersion(branch):
print("New version available",flush=True) print("New version available",flush=True)
plugins += render_template('components/dashboard-plugin.html', name='Update', output='New version available') plugins += render_template('components/dashboard-alert.html', name='Update', output='A new version of FireWallet is available')
return render_template("index.html", account=account, plugins=plugins) return render_template("index.html", account=account, plugins=plugins)
@@ -550,7 +551,6 @@ def finalize(domain: str):
return redirect("/logout") return redirect("/logout")
domain = domain.lower() domain = domain.lower()
print(domain)
response = account_module.finalize(request.cookies.get("account"),domain) response = account_module.finalize(request.cookies.get("account"),domain)
if response['error'] != None: if response['error'] != None:
print(response) print(response)
@@ -569,7 +569,6 @@ def cancelTransfer(domain: str):
return redirect("/logout") return redirect("/logout")
domain = domain.lower() domain = domain.lower()
print(domain)
response = account_module.cancelTransfer(request.cookies.get("account"),domain) response = account_module.cancelTransfer(request.cookies.get("account"),domain)
if 'error' in response: if 'error' in response:
if response['error'] != None: if response['error'] != None:
@@ -884,7 +883,6 @@ def auction(domain):
# Get TX # Get TX
revealInfo = account_module.getRevealTX(reveal) revealInfo = account_module.getRevealTX(reveal)
reveal['bid'] = revealInfo reveal['bid'] = revealInfo
print(revealInfo)
bids = render.bids(bids,reveals) bids = render.bids(bids,reveals)
@@ -946,7 +944,6 @@ def rescan_auction(domain):
domain = domain.lower() domain = domain.lower()
response = account_module.rescan_auction(account,domain) response = account_module.rescan_auction(account,domain)
print(response)
return redirect("/auction/" + domain) return redirect("/auction/" + domain)
@app.route('/auction/<domain>/bid') @app.route('/auction/<domain>/bid')
@@ -1022,7 +1019,7 @@ def bid_confirm(domain):
response = account_module.bid(request.cookies.get("account"),domain, response = account_module.bid(request.cookies.get("account"),domain,
float(bid), float(bid),
float(blind)) float(blind))
print(response)
if 'error' in response: if 'error' in response:
return redirect("/auction/" + domain + "?error=" + response['error']['message']) return redirect("/auction/" + domain + "?error=" + response['error']['message'])
@@ -1044,7 +1041,7 @@ def open_auction(domain):
if 'error' in response: if 'error' in response:
if response['error'] != None: if response['error'] != None:
return redirect("/auction/" + domain + "?error=" + response['error']['message']) return redirect("/auction/" + domain + "?error=" + response['error']['message'])
print(response)
return redirect("/success?tx=" + response['hash']) return redirect("/success?tx=" + response['hash'])
@app.route('/auction/<domain>/reveal') @app.route('/auction/<domain>/reveal')
@@ -1474,7 +1471,6 @@ def plugin_function(ptype,plugin,function):
return render_template("plugin-output.html", account=account,name=data['name'], return render_template("plugin-output.html", account=account,name=data['name'],
description=data['description'],output=response) description=data['description'],output=response)
else: else:
return jsonify({"error": "Function not found"}) return jsonify({"error": "Function not found"})
@@ -1609,4 +1605,8 @@ def page_not_found(e):
#endregion #endregion
if __name__ == '__main__': if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0') # Check to see if --debug is in the command line arguments
if "--debug" in sys.argv:
app.run(debug=True,host='0.0.0.0')
else:
app.run(host='0.0.0.0')

View File

@@ -6,12 +6,19 @@ import hashlib
import subprocess import subprocess
def import_module(module_name):
if module_name in sys.modules:
return importlib.reload(sys.modules[module_name])
else:
return importlib.import_module(module_name)
def listPlugins(update=False): def listPlugins(update=False):
plugins = [] plugins = []
for file in os.listdir("plugins"): for file in os.listdir("plugins"):
if file.endswith(".py"): if file.endswith(".py"):
if file != "main.py": if file != "main.py":
plugin = importlib.import_module("plugins."+file[:-3]) plugin = import_module("plugins."+file[:-3])
if "info" not in dir(plugin): if "info" not in dir(plugin):
continue continue
details = plugin.info details = plugin.info
@@ -42,7 +49,7 @@ def listPlugins(update=False):
for file in os.listdir(f"customPlugins/{importPath}"): for file in os.listdir(f"customPlugins/{importPath}"):
if file.endswith(".py"): if file.endswith(".py"):
if file != "main.py": if file != "main.py":
plugin = importlib.import_module(f"customPlugins.{importPath}."+file[:-3]) plugin = import_module(f"customPlugins.{importPath}."+file[:-3])
if "info" not in dir(plugin): if "info" not in dir(plugin):
continue continue
details = plugin.info details = plugin.info
@@ -106,7 +113,7 @@ def hashPlugin(plugin: str):
def getPluginData(pluginStr: str): def getPluginData(pluginStr: str):
plugin = importlib.import_module(pluginStr.replace("/",".")) plugin = import_module(pluginStr.replace("/","."))
# Check if the plugin is verified # Check if the plugin is verified
signatures = [] signatures = []
@@ -141,12 +148,12 @@ def getPluginData(pluginStr: str):
def getPluginFunctions(plugin: str): def getPluginFunctions(plugin: str):
plugin = importlib.import_module(plugin.replace("/",".")) plugin = import_module(plugin.replace("/","."))
return plugin.functions return plugin.functions
def runPluginFunction(plugin: str, function: str, params: dict, authentication: str): def runPluginFunction(plugin: str, function: str, params: dict, authentication: str):
plugin_module = importlib.import_module(plugin.replace("/",".")) plugin_module = import_module(plugin.replace("/","."))
if function not in plugin_module.functions: if function not in plugin_module.functions:
return {"error": "Function not found"} return {"error": "Function not found"}
@@ -182,12 +189,12 @@ def runPluginFunction(plugin: str, function: str, params: dict, authentication:
def getPluginFunctionInputs(plugin: str, function: str): def getPluginFunctionInputs(plugin: str, function: str):
plugin = importlib.import_module(plugin.replace("/",".")) plugin = import_module(plugin.replace("/","."))
return plugin.functions[function]["params"] return plugin.functions[function]["params"]
def getPluginFunctionReturns(plugin: str, function: str): def getPluginFunctionReturns(plugin: str, function: str):
plugin = importlib.import_module(plugin.replace("/",".")) plugin = import_module(plugin.replace("/","."))
return plugin.functions[function]["returns"] return plugin.functions[function]["returns"]

View File

@@ -8,4 +8,5 @@ cryptography
requests-doh requests-doh
Flask-QRcode Flask-QRcode
PySocks PySocks
python-git-info python-git-info
waitress

View File

@@ -1,38 +1,44 @@
from flask import Flask
from main import app
import main
from gunicorn.app.base import BaseApplication
import os import os
import sys
import platform
from main import app
from waitress import serve
class GunicornApp(BaseApplication): threads = 4
def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super().__init__()
def load_config(self): def gunicornServer():
for key, value in self.options.items(): from gunicorn.app.base import BaseApplication
if key in self.cfg.settings and value is not None: class GunicornApp(BaseApplication):
self.cfg.set(key.lower(), value) def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super().__init__()
def load(self): def load_config(self):
return self.application for key, value in self.options.items():
if key in self.cfg.settings and value is not None:
self.cfg.set(key.lower(), value)
if __name__ == '__main__': def load(self):
workers = 1 return self.application
threads = 2
if workers is None:
workers = 1
if threads is None:
threads = 2
workers = int(workers)
threads = int(threads)
options = { options = {
'bind': '0.0.0.0:5000', 'bind': '0.0.0.0:5000',
'workers': workers, 'workers': 2,
'threads': threads, 'threads': threads,
} }
gunicorn_app = GunicornApp(app, options) gunicorn_app = GunicornApp(app, options)
print('Starting server with ' + str(workers) + ' workers and ' + str(threads) + ' threads', flush=True) print(f'Starting server with Gunicorn on {platform.system()} with {threads} threads...', flush=True)
gunicorn_app.run() gunicorn_app.run()
if __name__ == '__main__':
# Check if --gunicorn is in the command line arguments
if "--gunicorn" in sys.argv:
gunicornServer()
sys.exit()
print(f'Starting server with Waitress on {platform.system()} with {threads} threads...', flush=True)
print(f'Press Ctrl+C to stop the server', flush=True)
print(f'Serving on http://0.0.0.0:5000/', flush=True)
serve(app, host="0.0.0.0", port=5000, threads=threads)

View File

@@ -0,0 +1,8 @@
<div class="col-md-6 col-xl-3 mb-4">
<div class="card shadow border-start-warning py-2">
<div class="card-body">
<div class="text-uppercase fw-bold text-xs mb-1"><span style="color: var(--bs-dark);">{{name}}</span></div>
<div class="text-dark fw-bold h5 mb-0"><span>{{output | safe}}</span></div>
</div>
</div>
</div>

View File

@@ -64,7 +64,7 @@
</nav> </nav>
<div class="container-fluid" style="margin-bottom: 20px;"> <div class="container-fluid" style="margin-bottom: 20px;">
<h3 class="text-dark mb-1">{{name}}</h3> <h3 class="text-dark mb-1">{{name}}</h3>
<h4 class="text-dark mb-1">{{description}}</h4>{{output|safe}} <h4 class="text-dark mb-1">{{description|safe}}</h4>{{output|safe}}
</div> </div>
</div> </div>
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);"> <footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">