From f369e2fdaccfb7f071829e26c8a060a555abe756 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 10:57:29 +0200 Subject: [PATCH] Revert "chore: code format" This reverts commit 619e0f05e25ae46487a06db82ab9d0cec7ba0f20. --- README.md | 2 ++ __init__.py | 3 +- crud.py | 1 - models.py | 3 +- nostr/bech32.py | 33 +++++++-------------- nostr/client/cbc.py | 10 +++---- nostr/client/client.py | 20 +++++++------ nostr/delegation.py | 8 +++--- nostr/event.py | 5 ++-- nostr/key.py | 9 +++--- nostr/message_pool.py | 3 +- nostr/message_type.py | 9 ++---- nostr/pow.py | 11 ++----- nostr/relay.py | 2 -- nostr/subscription.py | 8 ++++-- services.py | 4 +-- tasks.py | 6 ++-- templates/nostrclient/index.html | 49 +++++++++++--------------------- views.py | 3 +- views_api.py | 5 ++-- 20 files changed, 77 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 5f9bfbc..e609b6c 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,6 @@ `nostrclient` is an always-on extension that can open multiple connections to nostr relays and act as a multiplexer for other clients: You open a single websocket to `nostrclient` which then sends the data to multiple relays. The responses from these relays are then sent back to the client. + + ![2023-03-08 18 11 07](https://user-images.githubusercontent.com/93376500/225265727-369f0f8a-196e-41df-a0d1-98b50a0228be.jpg) diff --git a/__init__.py b/__init__.py index 60d8e23..90da4ec 100644 --- a/__init__.py +++ b/__init__.py @@ -1,9 +1,8 @@ from fastapi import APIRouter -from starlette.staticfiles import StaticFiles - from lnbits.db import Database from lnbits.helpers import template_renderer from lnbits.tasks import catch_everything_and_restart +from starlette.staticfiles import StaticFiles db = Database("ext_nostrclient") diff --git a/crud.py b/crud.py index 780642d..497fcd7 100644 --- a/crud.py +++ b/crud.py @@ -1,7 +1,6 @@ from typing import List, Optional, Union import shortuuid - from lnbits.helpers import urlsafe_short_hash from . import db diff --git a/models.py b/models.py index 4ed1e30..75a086d 100644 --- a/models.py +++ b/models.py @@ -3,9 +3,8 @@ from typing import Dict, List, Optional from fastapi import Request from fastapi.param_functions import Query -from pydantic import BaseModel, Field - from lnbits.helpers import urlsafe_short_hash +from pydantic import BaseModel, Field class Relay(BaseModel): diff --git a/nostr/bech32.py b/nostr/bech32.py index 0ae6c80..b068de7 100644 --- a/nostr/bech32.py +++ b/nostr/bech32.py @@ -23,25 +23,21 @@ from enum import Enum - class Encoding(Enum): """Enumeration type to list the various supported encodings.""" - BECH32 = 1 BECH32M = 2 - CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" -BECH32M_CONST = 0x2BC830A3 - +BECH32M_CONST = 0x2bc830a3 def bech32_polymod(values): """Internal function that computes the Bech32 checksum.""" - generator = [0x3B6A57B2, 0x26508E6D, 0x1EA119FA, 0x3D4233DD, 0x2A1462B3] + generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] chk = 1 for value in values: top = chk >> 25 - chk = (chk & 0x1FFFFFF) << 5 ^ value + chk = (chk & 0x1ffffff) << 5 ^ value for i in range(5): chk ^= generator[i] if ((top >> i) & 1) else 0 return chk @@ -61,7 +57,6 @@ def bech32_verify_checksum(hrp, data): return Encoding.BECH32M return None - def bech32_create_checksum(hrp, data, spec): """Compute the checksum values given HRP and data.""" values = bech32_hrp_expand(hrp) + data @@ -73,29 +68,26 @@ def bech32_create_checksum(hrp, data, spec): def bech32_encode(hrp, data, spec): """Compute a Bech32 string given HRP and data values.""" combined = data + bech32_create_checksum(hrp, data, spec) - return hrp + "1" + "".join([CHARSET[d] for d in combined]) - + return hrp + '1' + ''.join([CHARSET[d] for d in combined]) def bech32_decode(bech): """Validate a Bech32/Bech32m string, and determine HRP and data.""" - if (any(ord(x) < 33 or ord(x) > 126 for x in bech)) or ( - bech.lower() != bech and bech.upper() != bech - ): + if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or + (bech.lower() != bech and bech.upper() != bech)): return (None, None, None) bech = bech.lower() - pos = bech.rfind("1") + pos = bech.rfind('1') if pos < 1 or pos + 7 > len(bech) or len(bech) > 90: return (None, None, None) - if not all(x in CHARSET for x in bech[pos + 1 :]): + if not all(x in CHARSET for x in bech[pos+1:]): return (None, None, None) hrp = bech[:pos] - data = [CHARSET.find(x) for x in bech[pos + 1 :]] + data = [CHARSET.find(x) for x in bech[pos+1:]] spec = bech32_verify_checksum(hrp, data) if spec is None: return (None, None, None) return (hrp, data[:-6], spec) - def convertbits(data, frombits, tobits, pad=True): """General power-of-2 base conversion.""" acc = 0 @@ -131,12 +123,7 @@ def decode(hrp, addr): return (None, None) if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32: return (None, None) - if ( - data[0] == 0 - and spec != Encoding.BECH32 - or data[0] != 0 - and spec != Encoding.BECH32M - ): + if data[0] == 0 and spec != Encoding.BECH32 or data[0] != 0 and spec != Encoding.BECH32M: return (None, None) return (data[0], decoded) diff --git a/nostr/client/cbc.py b/nostr/client/cbc.py index e69e8b5..a41dbc0 100644 --- a/nostr/client/cbc.py +++ b/nostr/client/cbc.py @@ -1,3 +1,4 @@ + from Cryptodome import Random from Cryptodome.Cipher import AES @@ -10,10 +11,10 @@ key = bytes.fromhex("3aa925cb69eb613e2928f8a18279c78b1dca04541dfd064df2eda66b598 BLOCK_SIZE = 16 - class AESCipher(object): - """This class is compatible with crypto.createCipheriv('aes-256-cbc')""" + """This class is compatible with crypto.createCipheriv('aes-256-cbc') + """ def __init__(self, key=None): self.key = key @@ -32,10 +33,9 @@ class AESCipher(object): def decrypt(self, iv, enc_text): cipher = AES.new(self.key, AES.MODE_CBC, iv=iv) return self.unpad(cipher.decrypt(enc_text).decode("UTF-8")) - - + if __name__ == "__main__": aes = AESCipher(key=key) iv, enc_text = aes.encrypt(plain_text) dec_text = aes.decrypt(iv, enc_text) - print(dec_text) + print(dec_text) \ No newline at end of file diff --git a/nostr/client/client.py b/nostr/client/client.py index bf91050..6fb885f 100644 --- a/nostr/client/client.py +++ b/nostr/client/client.py @@ -1,15 +1,19 @@ -import base64 -import json -import os +from typing import * import ssl import time -from typing import * +import json +import os +import base64 -from ..event import EncryptedDirectMessage, Event, EventKind -from ..filter import Filter, Filters -from ..key import PrivateKey, PublicKey -from ..message_type import ClientMessageType +from ..event import Event from ..relay_manager import RelayManager +from ..message_type import ClientMessageType +from ..key import PrivateKey, PublicKey + +from ..filter import Filter, Filters +from ..event import Event, EventKind, EncryptedDirectMessage +from ..relay_manager import RelayManager +from ..message_type import ClientMessageType # from aes import AESCipher from . import cbc diff --git a/nostr/delegation.py b/nostr/delegation.py index 8b1c311..94801f5 100644 --- a/nostr/delegation.py +++ b/nostr/delegation.py @@ -7,23 +7,23 @@ class Delegation: delegator_pubkey: str delegatee_pubkey: str event_kind: int - duration_secs: int = 30 * 24 * 60 # default to 30 days + duration_secs: int = 30*24*60 # default to 30 days signature: str = None # set in PrivateKey.sign_delegation @property def expires(self) -> int: return int(time.time()) + self.duration_secs - + @property def conditions(self) -> str: return f"kind={self.event_kind}&created_at<{self.expires}" - + @property def delegation_token(self) -> str: return f"nostr:delegation:{self.delegatee_pubkey}:{self.conditions}" def get_tag(self) -> list[str]: - """Called by Event""" + """ Called by Event """ return [ "delegation", self.delegator_pubkey, diff --git a/nostr/event.py b/nostr/event.py index 65b187d..b903e0e 100644 --- a/nostr/event.py +++ b/nostr/event.py @@ -1,11 +1,10 @@ -import json import time +import json from dataclasses import dataclass, field from enum import IntEnum -from hashlib import sha256 from typing import List - from secp256k1 import PublicKey +from hashlib import sha256 from .message_type import ClientMessageType diff --git a/nostr/key.py b/nostr/key.py index 8089e11..d34697f 100644 --- a/nostr/key.py +++ b/nostr/key.py @@ -1,15 +1,14 @@ -import base64 import secrets -from hashlib import sha256 - +import base64 import secp256k1 from cffi import FFI -from cryptography.hazmat.primitives import padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives import padding +from hashlib import sha256 -from . import bech32 from .delegation import Delegation from .event import EncryptedDirectMessage, Event, EventKind +from . import bech32 class PublicKey: diff --git a/nostr/message_pool.py b/nostr/message_pool.py index 373d9fc..d364cf2 100644 --- a/nostr/message_pool.py +++ b/nostr/message_pool.py @@ -1,9 +1,8 @@ import json from queue import Queue from threading import Lock - -from .event import Event from .message_type import RelayMessageType +from .event import Event class EventMessage: diff --git a/nostr/message_type.py b/nostr/message_type.py index 9f3be78..3f5206b 100644 --- a/nostr/message_type.py +++ b/nostr/message_type.py @@ -3,7 +3,6 @@ class ClientMessageType: REQUEST = "REQ" CLOSE = "CLOSE" - class RelayMessageType: EVENT = "EVENT" NOTICE = "NOTICE" @@ -11,10 +10,6 @@ class RelayMessageType: @staticmethod def is_valid(type: str) -> bool: - if ( - type == RelayMessageType.EVENT - or type == RelayMessageType.NOTICE - or type == RelayMessageType.END_OF_STORED_EVENTS - ): + if type == RelayMessageType.EVENT or type == RelayMessageType.NOTICE or type == RelayMessageType.END_OF_STORED_EVENTS: return True - return False + return False \ No newline at end of file diff --git a/nostr/pow.py b/nostr/pow.py index 034ad9a..e006288 100644 --- a/nostr/pow.py +++ b/nostr/pow.py @@ -1,9 +1,7 @@ import time - from .event import Event from .key import PrivateKey - def zero_bits(b: int) -> int: n = 0 @@ -16,11 +14,10 @@ def zero_bits(b: int) -> int: return 7 - n - def count_leading_zero_bits(hex_str: str) -> int: total = 0 for i in range(0, len(hex_str) - 2, 2): - bits = zero_bits(int(hex_str[i : i + 2], 16)) + bits = zero_bits(int(hex_str[i:i+2], 16)) total += bits if bits != 8: @@ -28,10 +25,7 @@ def count_leading_zero_bits(hex_str: str) -> int: return total - -def mine_event( - content: str, difficulty: int, public_key: str, kind: int, tags: list = [] -) -> Event: +def mine_event(content: str, difficulty: int, public_key: str, kind: int, tags: list=[]) -> Event: all_tags = [["nonce", "1", str(difficulty)]] all_tags.extend(tags) @@ -49,7 +43,6 @@ def mine_event( return Event(public_key, content, created_at, kind, all_tags, event_id) - def mine_key(difficulty: int) -> PrivateKey: sk = PrivateKey() num_leading_zero_bits = count_leading_zero_bits(sk.public_key.hex()) diff --git a/nostr/relay.py b/nostr/relay.py index 0851c02..ee78baa 100644 --- a/nostr/relay.py +++ b/nostr/relay.py @@ -2,9 +2,7 @@ import json import time from queue import Queue from threading import Lock - from websocket import WebSocketApp - from .event import Event from .filter import Filters from .message_pool import MessagePool diff --git a/nostr/subscription.py b/nostr/subscription.py index 10b5363..7afba20 100644 --- a/nostr/subscription.py +++ b/nostr/subscription.py @@ -1,10 +1,12 @@ from .filter import Filters - class Subscription: - def __init__(self, id: str, filters: Filters = None) -> None: + def __init__(self, id: str, filters: Filters=None) -> None: self.id = id self.filters = filters def to_json_object(self): - return {"id": self.id, "filters": self.filters.to_json_array()} + return { + "id": self.id, + "filters": self.filters.to_json_array() + } diff --git a/services.py b/services.py index ab65dae..09e9235 100644 --- a/services.py +++ b/services.py @@ -3,16 +3,16 @@ import json from typing import List, Union from fastapi import WebSocket, WebSocketDisconnect - from lnbits.helpers import urlsafe_short_hash +from .nostr.client.client import NostrClient as NostrClientLib from .models import Event, Filter, Filters, Relay, RelayList -from .nostr.client.client import NostrClient as NostrClientLib from .nostr.event import Event as NostrEvent from .nostr.filter import Filter as NostrFilter from .nostr.filter import Filters as NostrFilters from .nostr.message_pool import EndOfStoredEventsMessage, EventMessage, NoticeMessage + received_subscription_events: dict[str, list[Event]] = {} received_subscription_notices: dict[str, list[NoticeMessage]] = {} received_subscription_eosenotices: dict[str, EndOfStoredEventsMessage] = {} diff --git a/tasks.py b/tasks.py index 1566f65..7894e40 100644 --- a/tasks.py +++ b/tasks.py @@ -2,18 +2,20 @@ import asyncio import ssl import threading -from .crud import get_relays from .nostr.event import Event from .nostr.key import PublicKey from .nostr.message_pool import EndOfStoredEventsMessage, EventMessage, NoticeMessage from .nostr.relay_manager import RelayManager from .services import ( nostr, - received_subscription_eosenotices, received_subscription_events, + received_subscription_eosenotices, ) +from .crud import get_relays + + async def init_relays(): # reinitialize the entire client nostr.__init__() diff --git a/templates/nostrclient/index.html b/templates/nostrclient/index.html index b3d58c8..2a6cf60 100644 --- a/templates/nostrclient/index.html +++ b/templates/nostrclient/index.html @@ -75,17 +75,12 @@ + -
- Your endpoint: - -
+
Your endpoint: + +
@@ -93,13 +88,7 @@
- +
Add relay @@ -115,21 +104,17 @@
Nostrclient Extension

This extension is a always-on nostr client that other extensions can - use to send and receive events on nostr. Add multiple nostr relays to - connect to. The extension then opens a websocket for you to use at -

+ use to send and receive events on nostr. -

- - + Add multiple nostr relays to connect to. The extension then opens a websocket for you to use + at +

+ + +

+ Only Admin users can manage + this extension.

- Only Admin users can manage this extension. - @@ -232,7 +217,7 @@ message: `Invalid relay URL.`, caption: "Should start with 'wss://'' or 'ws://'" }) - return false + return false; } console.log('ADD RELAY ' + this.relayToAdd) let that = this @@ -244,7 +229,7 @@ {url: this.relayToAdd} ) .then(function (response) { - console.log('response:', response) + console.log("response:", response) if (response.data) { response.data.map(maplrelays) that.nostrrelayLinks = response.data @@ -254,7 +239,7 @@ .catch(function (error) { LNbits.utils.notifyApiError(error) }) - return false + return false; }, deleteRelay(url) { console.log('DELETE RELAY ' + url) diff --git a/views.py b/views.py index a05f956..ce30b3b 100644 --- a/views.py +++ b/views.py @@ -6,12 +6,11 @@ from fastapi import Request from fastapi.param_functions import Query from fastapi.params import Depends from fastapi.templating import Jinja2Templates -from starlette.responses import HTMLResponse - from lnbits.core.crud import update_payment_status from lnbits.core.models import User from lnbits.core.views.api import api_payment from lnbits.decorators import check_admin, check_user_exists +from starlette.responses import HTMLResponse from . import nostr_renderer, nostrclient_ext diff --git a/views_api.py b/views_api.py index 15cc3ab..c3da200 100644 --- a/views_api.py +++ b/views_api.py @@ -3,11 +3,10 @@ from http import HTTPStatus from typing import Optional from fastapi import Depends, WebSocket -from loguru import logger -from starlette.exceptions import HTTPException - from lnbits.decorators import check_admin from lnbits.helpers import urlsafe_short_hash +from loguru import logger +from starlette.exceptions import HTTPException from . import nostrclient_ext from .crud import add_relay, delete_relay, get_relays