refactor: extract NostrRelay
This commit is contained in:
parent
2ebc83a286
commit
855812cb8f
8 changed files with 143 additions and 141 deletions
3
crud.py
3
crud.py
|
|
@ -2,9 +2,10 @@ import json
|
|||
from typing import List, Optional, Tuple
|
||||
|
||||
from . import db
|
||||
from .models import NostrAccount, NostrRelay, RelayPublicSpec, RelaySpec
|
||||
from .models import NostrAccount
|
||||
from .relay.event import NostrEvent
|
||||
from .relay.filter import NostrFilter
|
||||
from .relay.relay import NostrRelay, RelayPublicSpec, RelaySpec
|
||||
|
||||
########################## RELAYS ####################
|
||||
|
||||
|
|
|
|||
131
models.py
131
models.py
|
|
@ -1,134 +1,7 @@
|
|||
import json
|
||||
from sqlite3 import Row
|
||||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
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 typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class BuyOrder(BaseModel):
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from ..crud import (
|
|||
get_events,
|
||||
mark_events_deleted,
|
||||
)
|
||||
from ..models import RelaySpec
|
||||
from .relay import RelaySpec
|
||||
from .event import NostrEvent, NostrEventType
|
||||
from .event_validator import EventValidator
|
||||
from .filter import NostrFilter
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from typing import List
|
||||
|
||||
from ..crud import get_config_for_all_active_relays
|
||||
from ..models import RelaySpec
|
||||
from .relay import RelaySpec
|
||||
from .client_connection import NostrClientConnection
|
||||
from .event import NostrEvent
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ from typing import Callable, Optional, Tuple
|
|||
|
||||
from ..crud import get_account, get_storage_for_public_key, prune_old_events
|
||||
from ..helpers import extract_domain
|
||||
from ..models import NostrAccount, RelaySpec
|
||||
from ..models import NostrAccount
|
||||
from .event import NostrEvent
|
||||
from .relay import RelaySpec
|
||||
|
||||
|
||||
class EventValidator:
|
||||
|
|
|
|||
130
relay/relay.py
Normal file
130
relay/relay.py
Normal 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": "",
|
||||
}
|
||||
|
||||
|
|
@ -6,13 +6,9 @@ import pytest
|
|||
from fastapi import WebSocket
|
||||
from loguru import logger
|
||||
|
||||
from lnbits.extensions.nostrrelay.models import RelaySpec # type: ignore
|
||||
from lnbits.extensions.nostrrelay.relay.client_connection import (
|
||||
NostrClientConnection, # type: ignore
|
||||
)
|
||||
from lnbits.extensions.nostrrelay.relay.client_manager import (
|
||||
NostrClientManager, # type: ignore
|
||||
)
|
||||
from lnbits.extensions.nostrrelay.relay.relay import RelaySpec # type: ignore
|
||||
from lnbits.extensions.nostrrelay.relay.client_connection import NostrClientConnection # type: ignore
|
||||
from lnbits.extensions.nostrrelay.relay.client_manager import NostrClientManager # type: ignore
|
||||
|
||||
from .helpers import get_fixtures
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@ from .crud import (
|
|||
update_relay,
|
||||
)
|
||||
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.relay import NostrRelay
|
||||
|
||||
client_manager = NostrClientManager()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue