diff --git a/lnbits/extensions/gerty/__init__.py b/lnbits/extensions/gerty/__init__.py index bd353c78e..5b24718ac 100644 --- a/lnbits/extensions/gerty/__init__.py +++ b/lnbits/extensions/gerty/__init__.py @@ -5,11 +5,9 @@ from fastapi.staticfiles import StaticFiles from lnbits.db import Database from lnbits.helpers import template_renderer -from lnbits.tasks import catch_everything_and_restart db = Database("ext_gerty") - gerty_static_files = [ { "path": "/gerty/static", diff --git a/lnbits/extensions/gerty/crud.py b/lnbits/extensions/gerty/crud.py index 2fc0a7c18..5475139cd 100644 --- a/lnbits/extensions/gerty/crud.py +++ b/lnbits/extensions/gerty/crud.py @@ -50,11 +50,12 @@ async def create_gerty(wallet_id: str, data: Gerty) -> Gerty: return gerty -async def update_gerty(gerty_id: str, **kwargs) -> Gerty: +async def update_gerty(gerty_id: str, **kwargs) -> Optional[Gerty]: q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( f"UPDATE gerty.gertys SET {q} WHERE id = ?", (*kwargs.values(), gerty_id) ) + return await get_gerty(gerty_id) @@ -82,7 +83,7 @@ async def delete_gerty(gerty_id: str) -> None: #############MEMPOOL########### -async def get_mempool_info(endPoint: str, gerty) -> Optional[Mempool]: +async def get_mempool_info(endPoint: str, gerty) -> dict: logger.debug(endPoint) endpoints = MempoolEndpoint() url = "" diff --git a/lnbits/extensions/gerty/helpers.py b/lnbits/extensions/gerty/helpers.py index 65c690730..3e48c5763 100644 --- a/lnbits/extensions/gerty/helpers.py +++ b/lnbits/extensions/gerty/helpers.py @@ -3,15 +3,16 @@ import os import random import textwrap from datetime import datetime, timedelta +from typing import List import httpx from loguru import logger -from lnbits.core.crud import get_user, get_wallet_for_key +from lnbits.core.crud import get_wallet_for_key from lnbits.settings import settings from lnbits.utils.exchange_rates import satoshis_amount_as_fiat -from .crud import get_gerty, get_mempool_info +from .crud import get_mempool_info from .number_prefixer import * @@ -24,8 +25,8 @@ def get_percent_difference(current, previous, precision=3): def get_text_item_dict( text: str, font_size: int, - x_pos: int = None, - y_pos: int = None, + x_pos: int = -1, + y_pos: int = -1, gerty_type: str = "Gerty", ): # Get line size by font size @@ -63,13 +64,41 @@ def get_text_item_dict( # logger.debug('multilineText') # logger.debug(multilineText) - text = {"value": multilineText, "size": font_size} - if x_pos is None and y_pos is None: - text["position"] = "center" + data_text = {"value": multilineText, "size": font_size} + if x_pos == -1 and y_pos == -1: + data_text["position"] = "center" else: - text["x"] = x_pos - text["y"] = y_pos - return text + data_text["x"] = x_pos if x_pos > 0 else 0 + data_text["y"] = y_pos if x_pos > 0 else 0 + return data_text + + +def get_date_suffix(dayNumber): + if 4 <= dayNumber <= 20 or 24 <= dayNumber <= 30: + return "th" + else: + return ["st", "nd", "rd"][dayNumber % 10 - 1] + + +def get_time_remaining(seconds, granularity=2): + intervals = ( + # ('weeks', 604800), # 60 * 60 * 24 * 7 + ("days", 86400), # 60 * 60 * 24 + ("hours", 3600), # 60 * 60 + ("minutes", 60), + ("seconds", 1), + ) + + result = [] + + for name, count in intervals: + value = seconds // count + if value: + seconds -= value * count + if value == 1: + name = name.rstrip("s") + result.append("{} {}".format(round(value), name)) + return ", ".join(result[:granularity]) # format a number for nice display output @@ -293,8 +322,7 @@ def get_next_update_time(sleep_time_seconds: int = 0, utc_offset: int = 0): def gerty_should_sleep(utc_offset: int = 0): utc_now = datetime.utcnow() local_time = utc_now + timedelta(hours=utc_offset) - hours = local_time.strftime("%H") - hours = int(hours) + hours = int(local_time.strftime("%H")) if hours >= 22 and hours <= 23: return True else: @@ -352,23 +380,17 @@ async def get_mining_stat(stat_slug: str, gerty): async def api_get_mining_stat(stat_slug: str, gerty): - stat = "" + stat = {} if stat_slug == "mining_current_hash_rate": - async with httpx.AsyncClient() as client: - r = await get_mempool_info("hashrate_1m", gerty) - data = r - stat = {} - stat["current"] = data["currentHashrate"] - stat["1w"] = data["hashrates"][len(data["hashrates"]) - 7]["avgHashrate"] + r = await get_mempool_info("hashrate_1m", gerty) + data = r + stat["current"] = data["currentHashrate"] + stat["1w"] = data["hashrates"][len(data["hashrates"]) - 7]["avgHashrate"] elif stat_slug == "mining_current_difficulty": - async with httpx.AsyncClient() as client: - r = await get_mempool_info("hashrate_1m", gerty) - data = r - stat = {} - stat["current"] = data["currentDifficulty"] - stat["previous"] = data["difficulty"][len(data["difficulty"]) - 2][ - "difficulty" - ] + r = await get_mempool_info("hashrate_1m", gerty) + data = r + stat["current"] = data["currentDifficulty"] + stat["previous"] = data["difficulty"][len(data["difficulty"]) - 2]["difficulty"] return stat @@ -384,7 +406,7 @@ async def get_satoshi(): quote = satoshiQuotes[random.randint(0, len(satoshiQuotes) - 1)] # logger.debug(quote.text) if len(quote["text"]) > maxQuoteLength: - logger.debug("Quote is too long, getting another") + logger.trace("Quote is too long, getting another") return await get_satoshi() else: return quote @@ -399,15 +421,16 @@ def get_screen_slug_by_index(index: int, screens_list): # Get a list of text items for the screen number -async def get_screen_data(screen_num: int, screens_list: dict, gerty): +async def get_screen_data(screen_num: int, screens_list: list, gerty): screen_slug = get_screen_slug_by_index(screen_num, screens_list) # first get the relevant slug from the display_preferences - areas = [] + areas: List = [] title = "" if screen_slug == "dashboard": title = gerty.name areas = await get_dashboard(gerty) + if screen_slug == "lnbits_wallets_balance": wallets = await get_lnbits_wallet_balances(gerty) @@ -505,10 +528,10 @@ async def get_screen_data(screen_num: int, screens_list: dict, gerty): title = "Lightning Network" areas = await get_lightning_stats(gerty) - data = {} - data["title"] = title - data["areas"] = areas - + data = { + "title": title, + "areas": areas, + } return data @@ -570,7 +593,7 @@ async def get_dashboard(gerty): text = [] text.append( get_text_item_dict( - text=await get_time_remaining_next_difficulty_adjustment(gerty), + text=await get_time_remaining_next_difficulty_adjustment(gerty) or "0", font_size=15, gerty_type=gerty.type, ) @@ -602,7 +625,7 @@ async def get_lnbits_wallet_balances(gerty): return wallets -async def get_placeholder_text(): +async def get_placeholder_text(gerty): return [ get_text_item_dict( text="Some placeholder text", @@ -810,14 +833,14 @@ async def get_time_remaining_next_difficulty_adjustment(gerty): r = await get_mempool_info("difficulty_adjustment", gerty) stat = r["remainingTime"] time = get_time_remaining(stat / 1000, 3) - return time + return time async def get_mempool_stat(stat_slug: str, gerty): text = [] if isinstance(gerty.mempool_endpoint, str): if stat_slug == "mempool_tx_count": - r = get_mempool_info("mempool", gerty) + r = await get_mempool_info("mempool", gerty) if stat_slug == "mempool_tx_count": stat = round(r["count"]) text.append( @@ -921,31 +944,3 @@ async def get_mempool_stat(stat_slug: str, gerty): ) ) return text - - -def get_date_suffix(dayNumber): - if 4 <= dayNumber <= 20 or 24 <= dayNumber <= 30: - return "th" - else: - return ["st", "nd", "rd"][dayNumber % 10 - 1] - - -def get_time_remaining(seconds, granularity=2): - intervals = ( - # ('weeks', 604800), # 60 * 60 * 24 * 7 - ("days", 86400), # 60 * 60 * 24 - ("hours", 3600), # 60 * 60 - ("minutes", 60), - ("seconds", 1), - ) - - result = [] - - for name, count in intervals: - value = seconds // count - if value: - seconds -= value * count - if value == 1: - name = name.rstrip("s") - result.append("{} {}".format(round(value), name)) - return ", ".join(result[:granularity]) diff --git a/lnbits/extensions/gerty/models.py b/lnbits/extensions/gerty/models.py index 9ff29bda3..cb19c2bcb 100644 --- a/lnbits/extensions/gerty/models.py +++ b/lnbits/extensions/gerty/models.py @@ -1,5 +1,4 @@ from sqlite3 import Row -from typing import Optional from fastapi import Query from pydantic import BaseModel diff --git a/lnbits/extensions/gerty/templates/gerty/gerty.html b/lnbits/extensions/gerty/templates/gerty/gerty.html index d45484a41..06a29e225 100644 --- a/lnbits/extensions/gerty/templates/gerty/gerty.html +++ b/lnbits/extensions/gerty/templates/gerty/gerty.html @@ -32,7 +32,10 @@ gertyname }}{% endraw %}{% endblock %}{% block page %} {% raw %} -
+
- +
Mining
@@ -78,7 +81,12 @@ gertyname }}{% endraw %}{% endblock %}{% block page %} {% raw %}
- +
Lightning (Last 7 days)
@@ -88,7 +96,6 @@ gertyname }}{% endraw %}{% endblock %}{% block page %} {% raw %}

-
Servers to check
@@ -153,7 +160,13 @@ gertyname }}{% endraw %}{% endblock %}{% block page %} {% raw %} lnbits_wallets_balance: {}, dashboard_onchain: {}, fun_satoshi_quotes: {}, - fun_exchange_market_rate: {}, + fun_exchange_market_rate: { + unit: '' + }, + dashboard_mining: {}, + lightning_dashboard: {}, + url_checker: {}, + dashboard_mining: {}, gerty: [], gerty_id: `{{gerty}}`, gertyname: '', @@ -182,7 +195,6 @@ gertyname }}{% endraw %}{% endblock %}{% block page %} {% raw %} LNbits.utils.notifyApiError(error) } } - console.log(this.gerty) for (let i = 0; i < this.gerty.length; i++) { if (this.gerty[i].screen.group == 'lnbits_wallets_balance') { for (let q = 0; q < this.gerty[i].screen.areas.length; q++) { diff --git a/lnbits/extensions/gerty/views.py b/lnbits/extensions/gerty/views.py index 66194a50a..33e95d3e6 100644 --- a/lnbits/extensions/gerty/views.py +++ b/lnbits/extensions/gerty/views.py @@ -1,10 +1,7 @@ -import json from http import HTTPStatus -from fastapi import Request -from fastapi.params import Depends +from fastapi import Depends, Request from fastapi.templating import Jinja2Templates -from loguru import logger from starlette.exceptions import HTTPException from starlette.responses import HTMLResponse @@ -13,7 +10,6 @@ from lnbits.decorators import check_user_exists from . import gerty_ext, gerty_renderer from .crud import get_gerty -from .views_api import api_gerty_json templates = Jinja2Templates(directory="templates") diff --git a/lnbits/extensions/gerty/views_api.py b/lnbits/extensions/gerty/views_api.py index 7272fb7d0..c408504b6 100644 --- a/lnbits/extensions/gerty/views_api.py +++ b/lnbits/extensions/gerty/views_api.py @@ -1,24 +1,12 @@ import json -import math -import os -import random -import time -from datetime import datetime from http import HTTPStatus -import httpx -from fastapi import Query -from fastapi.params import Depends -from fastapi.templating import Jinja2Templates -from lnurl import decode as decode_lnurl +from fastapi import Depends, Query from loguru import logger from starlette.exceptions import HTTPException -from lnbits.core.crud import get_user, get_wallet_for_key -from lnbits.core.services import create_invoice -from lnbits.core.views.api import api_payment, api_wallet +from lnbits.core.crud import get_user from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key -from lnbits.utils.exchange_rates import satoshis_amount_as_fiat from . import gerty_ext from .crud import ( @@ -29,8 +17,14 @@ from .crud import ( get_mempool_info, update_gerty, ) -from .helpers import * -from .models import Gerty, MempoolEndpoint +from .helpers import ( + gerty_should_sleep, + get_next_update_time, + get_satoshi, + get_screen_data, + get_screen_slug_by_index, +) +from .models import Gerty @gerty_ext.get("/api/v1/gerty", status_code=HTTPStatus.OK) @@ -39,7 +33,8 @@ async def api_gertys( ): wallet_ids = [wallet.wallet.id] if all_wallets: - wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids + user = await get_user(wallet.wallet.user) + wallet_ids = user.wallet_ids if user else [] return [gerty.dict() for gerty in await get_gertys(wallet_ids)] @@ -51,7 +46,6 @@ async def api_link_create_or_update( wallet: WalletTypeInfo = Depends(get_key_type), gerty_id: str = Query(None), ): - logger.debug(data) if gerty_id: gerty = await get_gerty(gerty_id) if not gerty: @@ -67,6 +61,9 @@ async def api_link_create_or_update( data.wallet = wallet.wallet.id gerty = await update_gerty(gerty_id, **data.dict()) + assert gerty, HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail="Gerty does not exist" + ) else: gerty = await create_gerty(wallet_id=wallet.wallet.id, data=data) @@ -93,11 +90,11 @@ async def api_gerty_delete( @gerty_ext.get("/api/v1/gerty/satoshiquote", status_code=HTTPStatus.OK) async def api_gerty_satoshi(): - return await get_satoshi + return await get_satoshi() @gerty_ext.get("/api/v1/gerty/pages/{gerty_id}/{p}") -async def api_gerty_json(gerty_id: str, p: int = None): # page number +async def api_gerty_json(gerty_id: str, p: int = 0): # page number gerty = await get_gerty(gerty_id) if not gerty: @@ -117,7 +114,7 @@ async def api_gerty_json(gerty_id: str, p: int = None): # page number enabled_screen_count += 1 enabled_screens.append(screen_slug) - logger.debug("Screeens " + str(enabled_screens)) + logger.debug("Screens " + str(enabled_screens)) data = await get_screen_data(p, enabled_screens, gerty) next_screen_number = 0 if ((p + 1) >= enabled_screen_count) else p + 1 diff --git a/pyproject.toml b/pyproject.toml index 186e2123a..4915de075 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,7 +92,6 @@ exclude = """(?x)( ^lnbits/extensions/bleskomat. | ^lnbits/extensions/boltz. | ^lnbits/extensions/boltcards. - | ^lnbits/extensions/gerty. | ^lnbits/extensions/invoices. | ^lnbits/extensions/livestream. | ^lnbits/extensions/lnaddress.