refactor: extract NostrRelay

This commit is contained in:
Vlad Stan 2023-02-17 14:23:58 +02:00
parent 2ebc83a286
commit 855812cb8f
8 changed files with 143 additions and 141 deletions

View file

@ -2,9 +2,10 @@ import json
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from . import db from . import db
from .models import NostrAccount, NostrRelay, RelayPublicSpec, RelaySpec from .models import NostrAccount
from .relay.event import NostrEvent from .relay.event import NostrEvent
from .relay.filter import NostrFilter from .relay.filter import NostrFilter
from .relay.relay import NostrRelay, RelayPublicSpec, RelaySpec
########################## RELAYS #################### ########################## RELAYS ####################

131
models.py
View file

@ -1,134 +1,7 @@
import json
from sqlite3 import Row from sqlite3 import Row
from typing import Any, List, Optional, Tuple from typing import Optional
from pydantic import BaseModel, Field
from .relay.event import NostrEvent
class Spec(BaseModel):
class Config:
allow_population_by_field_name = True
class FilterSpec(Spec):
max_client_filters = Field(0, alias="maxClientFilters")
limit_per_filter = Field(1000, alias="limitPerFilter")
class EventSpec(Spec):
max_events_per_hour = Field(0, alias="maxEventsPerHour")
created_at_days_past = Field(0, alias="createdAtDaysPast")
created_at_hours_past = Field(0, alias="createdAtHoursPast")
created_at_minutes_past = Field(0, alias="createdAtMinutesPast")
created_at_seconds_past = Field(0, alias="createdAtSecondsPast")
created_at_days_future = Field(0, alias="createdAtDaysFuture")
created_at_hours_future = Field(0, alias="createdAtHoursFuture")
created_at_minutes_future = Field(0, alias="createdAtMinutesFuture")
created_at_seconds_future = Field(0, alias="createdAtSecondsFuture")
@property
def created_at_in_past(self) -> int:
return (
self.created_at_days_past * 86400
+ self.created_at_hours_past * 3600
+ self.created_at_minutes_past * 60
+ self.created_at_seconds_past
)
@property
def created_at_in_future(self) -> int:
return (
self.created_at_days_future * 86400
+ self.created_at_hours_future * 3600
+ self.created_at_minutes_future * 60
+ self.created_at_seconds_future
)
class StorageSpec(Spec):
free_storage_value = Field(1, alias="freeStorageValue")
free_storage_unit = Field("MB", alias="freeStorageUnit")
full_storage_action = Field("prune", alias="fullStorageAction")
@property
def free_storage_bytes_value(self):
value = self.free_storage_value * 1024
if self.free_storage_unit == "MB":
value *= 1024
return value
class AuthSpec(BaseModel):
require_auth_events = Field(False, alias="requireAuthEvents")
skiped_auth_events = Field([], alias="skipedAuthEvents")
forced_auth_events = Field([], alias="forcedAuthEvents")
require_auth_filter = Field(False, alias="requireAuthFilter")
def event_requires_auth(self, kind: int) -> bool:
if self.require_auth_events:
return kind not in self.skiped_auth_events
return kind in self.forced_auth_events
class PaymentSpec(BaseModel):
is_paid_relay = Field(False, alias="isPaidRelay")
cost_to_join = Field(0, alias="costToJoin")
storage_cost_value = Field(0, alias="storageCostValue")
storage_cost_unit = Field("MB", alias="storageCostUnit")
class WalletSpec(Spec):
wallet = Field("")
class RelayPublicSpec(FilterSpec, EventSpec, StorageSpec, PaymentSpec):
domain: str = ""
@property
def is_read_only_relay(self):
self.free_storage_value == 0 and not self.is_paid_relay
class RelaySpec(RelayPublicSpec, WalletSpec, AuthSpec):
pass
class NostrRelay(BaseModel):
id: str
name: str
description: Optional[str]
pubkey: Optional[str]
contact: Optional[str]
active: bool = False
config: "RelaySpec" = RelaySpec()
@property
def is_free_to_join(self):
return not self.config.is_paid_relay or self.config.cost_to_join == 0
@classmethod
def from_row(cls, row: Row) -> "NostrRelay":
relay = cls(**dict(row))
relay.config = RelaySpec(**json.loads(row["meta"]))
return relay
@classmethod
def info(
cls,
) -> dict:
return {
"contact": "https://t.me/lnbits",
"supported_nips": [1, 9, 11, 15, 20, 22, 42],
"software": "LNbits",
"version": "",
}
from pydantic import BaseModel
class BuyOrder(BaseModel): class BuyOrder(BaseModel):

View file

@ -14,7 +14,7 @@ from ..crud import (
get_events, get_events,
mark_events_deleted, mark_events_deleted,
) )
from ..models import RelaySpec from .relay import RelaySpec
from .event import NostrEvent, NostrEventType from .event import NostrEvent, NostrEventType
from .event_validator import EventValidator from .event_validator import EventValidator
from .filter import NostrFilter from .filter import NostrFilter

View file

@ -1,7 +1,7 @@
from typing import List from typing import List
from ..crud import get_config_for_all_active_relays from ..crud import get_config_for_all_active_relays
from ..models import RelaySpec from .relay import RelaySpec
from .client_connection import NostrClientConnection from .client_connection import NostrClientConnection
from .event import NostrEvent from .event import NostrEvent

View file

@ -3,8 +3,9 @@ from typing import Callable, Optional, Tuple
from ..crud import get_account, get_storage_for_public_key, prune_old_events from ..crud import get_account, get_storage_for_public_key, prune_old_events
from ..helpers import extract_domain from ..helpers import extract_domain
from ..models import NostrAccount, RelaySpec from ..models import NostrAccount
from .event import NostrEvent from .event import NostrEvent
from .relay import RelaySpec
class EventValidator: class EventValidator:

130
relay/relay.py Normal file
View file

@ -0,0 +1,130 @@
import json
from sqlite3 import Row
from typing import Optional
from pydantic import BaseModel, Field
class Spec(BaseModel):
class Config:
allow_population_by_field_name = True
class FilterSpec(Spec):
max_client_filters = Field(0, alias="maxClientFilters")
limit_per_filter = Field(1000, alias="limitPerFilter")
class EventSpec(Spec):
max_events_per_hour = Field(0, alias="maxEventsPerHour")
created_at_days_past = Field(0, alias="createdAtDaysPast")
created_at_hours_past = Field(0, alias="createdAtHoursPast")
created_at_minutes_past = Field(0, alias="createdAtMinutesPast")
created_at_seconds_past = Field(0, alias="createdAtSecondsPast")
created_at_days_future = Field(0, alias="createdAtDaysFuture")
created_at_hours_future = Field(0, alias="createdAtHoursFuture")
created_at_minutes_future = Field(0, alias="createdAtMinutesFuture")
created_at_seconds_future = Field(0, alias="createdAtSecondsFuture")
@property
def created_at_in_past(self) -> int:
return (
self.created_at_days_past * 86400
+ self.created_at_hours_past * 3600
+ self.created_at_minutes_past * 60
+ self.created_at_seconds_past
)
@property
def created_at_in_future(self) -> int:
return (
self.created_at_days_future * 86400
+ self.created_at_hours_future * 3600
+ self.created_at_minutes_future * 60
+ self.created_at_seconds_future
)
class StorageSpec(Spec):
free_storage_value = Field(1, alias="freeStorageValue")
free_storage_unit = Field("MB", alias="freeStorageUnit")
full_storage_action = Field("prune", alias="fullStorageAction")
@property
def free_storage_bytes_value(self):
value = self.free_storage_value * 1024
if self.free_storage_unit == "MB":
value *= 1024
return value
class AuthSpec(BaseModel):
require_auth_events = Field(False, alias="requireAuthEvents")
skiped_auth_events = Field([], alias="skipedAuthEvents")
forced_auth_events = Field([], alias="forcedAuthEvents")
require_auth_filter = Field(False, alias="requireAuthFilter")
def event_requires_auth(self, kind: int) -> bool:
if self.require_auth_events:
return kind not in self.skiped_auth_events
return kind in self.forced_auth_events
class PaymentSpec(BaseModel):
is_paid_relay = Field(False, alias="isPaidRelay")
cost_to_join = Field(0, alias="costToJoin")
storage_cost_value = Field(0, alias="storageCostValue")
storage_cost_unit = Field("MB", alias="storageCostUnit")
class WalletSpec(Spec):
wallet = Field("")
class RelayPublicSpec(FilterSpec, EventSpec, StorageSpec, PaymentSpec):
domain: str = ""
@property
def is_read_only_relay(self):
self.free_storage_value == 0 and not self.is_paid_relay
class RelaySpec(RelayPublicSpec, WalletSpec, AuthSpec):
pass
class NostrRelay(BaseModel):
id: str
name: str
description: Optional[str]
pubkey: Optional[str]
contact: Optional[str]
active: bool = False
config: "RelaySpec" = RelaySpec()
@property
def is_free_to_join(self):
return not self.config.is_paid_relay or self.config.cost_to_join == 0
@classmethod
def from_row(cls, row: Row) -> "NostrRelay":
relay = cls(**dict(row))
relay.config = RelaySpec(**json.loads(row["meta"]))
return relay
@classmethod
def info(
cls,
) -> dict:
return {
"contact": "https://t.me/lnbits",
"supported_nips": [1, 9, 11, 15, 20, 22, 42],
"software": "LNbits",
"version": "",
}

View file

@ -6,13 +6,9 @@ import pytest
from fastapi import WebSocket from fastapi import WebSocket
from loguru import logger from loguru import logger
from lnbits.extensions.nostrrelay.models import RelaySpec # type: ignore from lnbits.extensions.nostrrelay.relay.relay import RelaySpec # type: ignore
from lnbits.extensions.nostrrelay.relay.client_connection import ( from lnbits.extensions.nostrrelay.relay.client_connection import NostrClientConnection # type: ignore
NostrClientConnection, # type: ignore from lnbits.extensions.nostrrelay.relay.client_manager import NostrClientManager # type: ignore
)
from lnbits.extensions.nostrrelay.relay.client_manager import (
NostrClientManager, # type: ignore
)
from .helpers import get_fixtures from .helpers import get_fixtures

View file

@ -30,8 +30,9 @@ from .crud import (
update_relay, update_relay,
) )
from .helpers import extract_domain, normalize_public_key from .helpers import extract_domain, normalize_public_key
from .models import BuyOrder, NostrAccount, NostrPartialAccount, NostrRelay from .models import BuyOrder, NostrAccount, NostrPartialAccount
from .relay.client_manager import NostrClientConnection, NostrClientManager from .relay.client_manager import NostrClientConnection, NostrClientManager
from .relay.relay import NostrRelay
client_manager = NostrClientManager() client_manager = NostrClientManager()