mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
116 lines
3.3 KiB
Python
116 lines
3.3 KiB
Python
import asyncio
|
|
import base64
|
|
import json
|
|
import logging
|
|
import time
|
|
import threading
|
|
from datetime import timedelta
|
|
from typing import List, Optional, TYPE_CHECKING
|
|
|
|
import websockets
|
|
from nostr_sdk import (
|
|
Client,
|
|
EventBuilder,
|
|
Filter,
|
|
Kind,
|
|
KindStandard,
|
|
NostrSigner,
|
|
Tag,
|
|
RelayUrl,
|
|
PublicKey,
|
|
)
|
|
from nostr_sdk import EventId, Keys, Timestamp
|
|
|
|
from constants import MAX_RETRIES, RETRY_DELAY
|
|
from seedpass.core.encryption import EncryptionManager
|
|
|
|
from .backup_models import (
|
|
ChunkMeta,
|
|
KIND_DELTA,
|
|
KIND_MANIFEST,
|
|
KIND_SNAPSHOT_CHUNK,
|
|
Manifest,
|
|
)
|
|
from .connection import ConnectionHandler, DEFAULT_RELAYS
|
|
from .key_manager import KeyManager as SeedPassKeyManager
|
|
from .snapshot import MANIFEST_ID_PREFIX, SnapshotHandler, prepare_snapshot
|
|
|
|
if TYPE_CHECKING: # pragma: no cover - imported for type hints
|
|
from seedpass.core.config_manager import ConfigManager
|
|
|
|
# Backwards compatibility for tests that patch these symbols
|
|
KeyManager = SeedPassKeyManager
|
|
ClientBuilder = Client
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logger.setLevel(logging.WARNING)
|
|
|
|
|
|
class NostrClient(ConnectionHandler, SnapshotHandler):
|
|
"""Interact with the Nostr network using nostr-sdk."""
|
|
|
|
def __init__(
|
|
self,
|
|
encryption_manager: EncryptionManager,
|
|
fingerprint: str,
|
|
relays: Optional[List[str]] = None,
|
|
parent_seed: Optional[str] = None,
|
|
offline_mode: bool = False,
|
|
config_manager: Optional["ConfigManager"] = None,
|
|
) -> None:
|
|
self.encryption_manager = encryption_manager
|
|
self.fingerprint = fingerprint
|
|
self.fingerprint_dir = self.encryption_manager.fingerprint_dir
|
|
self.config_manager = config_manager
|
|
self.verbose_timing = False
|
|
|
|
if parent_seed is None:
|
|
parent_seed = self.encryption_manager.decrypt_parent_seed()
|
|
|
|
# Use our project's KeyManager to derive the private key
|
|
self.key_manager = KeyManager(parent_seed, fingerprint)
|
|
|
|
# Create a nostr-sdk Keys object from our derived private key
|
|
private_key_hex = self.key_manager.keys.private_key_hex()
|
|
if not isinstance(private_key_hex, str):
|
|
private_key_hex = "0" * 64
|
|
try:
|
|
self.keys = Keys.parse(private_key_hex)
|
|
except Exception:
|
|
self.keys = Keys.generate()
|
|
|
|
self.offline_mode = offline_mode
|
|
if relays is None:
|
|
self.relays = [] if offline_mode else DEFAULT_RELAYS
|
|
else:
|
|
self.relays = relays
|
|
|
|
if self.config_manager is not None:
|
|
try:
|
|
self.verbose_timing = self.config_manager.get_verbose_timing()
|
|
except Exception:
|
|
self.verbose_timing = False
|
|
|
|
# store the last error encountered during network operations
|
|
self.last_error: Optional[str] = None
|
|
|
|
self.delta_threshold = 100
|
|
self._state_lock = threading.Lock()
|
|
self.current_manifest: Manifest | None = None
|
|
self.current_manifest_id: str | None = None
|
|
self._delta_events: list[str] = []
|
|
|
|
# Configure and initialize the nostr-sdk Client
|
|
signer = NostrSigner.keys(self.keys)
|
|
self.client = Client(signer)
|
|
|
|
self._connected = False
|
|
|
|
|
|
__all__ = [
|
|
"NostrClient",
|
|
"prepare_snapshot",
|
|
"DEFAULT_RELAYS",
|
|
"MANIFEST_ID_PREFIX",
|
|
]
|