collect announces in database
This commit is contained in:
17
database.py
17
database.py
@@ -23,6 +23,23 @@ class Config(BaseModel):
|
|||||||
table_name = "config"
|
table_name = "config"
|
||||||
|
|
||||||
|
|
||||||
|
class Announce(BaseModel):
|
||||||
|
|
||||||
|
id = BigAutoField()
|
||||||
|
destination_hash = CharField(unique=True) # unique destination hash that was announced
|
||||||
|
aspect = TextField(index=True) # aspect is not included in announce, but we want to filter saved announces by aspect
|
||||||
|
identity_hash = CharField(index=True) # identity hash that announced the destination
|
||||||
|
identity_public_key = CharField() # base64 encoded public key, incase we want to recreate the identity manually
|
||||||
|
app_data = TextField(null=True) # base64 encoded app data bytes
|
||||||
|
|
||||||
|
created_at = DateTimeField(default=datetime.now)
|
||||||
|
updated_at = DateTimeField(default=datetime.now)
|
||||||
|
|
||||||
|
# define table name
|
||||||
|
class Meta:
|
||||||
|
table_name = "announces"
|
||||||
|
|
||||||
|
|
||||||
class LxmfMessage(BaseModel):
|
class LxmfMessage(BaseModel):
|
||||||
|
|
||||||
id = BigAutoField()
|
id = BigAutoField()
|
||||||
|
|||||||
57
web.py
57
web.py
@@ -49,6 +49,7 @@ class ReticulumWebChat:
|
|||||||
self.db.connect()
|
self.db.connect()
|
||||||
self.db.create_tables([
|
self.db.create_tables([
|
||||||
database.Config,
|
database.Config,
|
||||||
|
database.Announce,
|
||||||
database.LxmfMessage,
|
database.LxmfMessage,
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ class ReticulumWebChat:
|
|||||||
|
|
||||||
# set a callback for when an lxmf announce is received
|
# set a callback for when an lxmf announce is received
|
||||||
RNS.Transport.register_announce_handler(LXMFAnnounceHandler(self.on_lxmf_announce_received))
|
RNS.Transport.register_announce_handler(LXMFAnnounceHandler(self.on_lxmf_announce_received))
|
||||||
|
RNS.Transport.register_announce_handler(NomadnetworkNodeAnnounceHandler(self.on_nomadnet_node_announce_received))
|
||||||
|
|
||||||
# remember websocket clients
|
# remember websocket clients
|
||||||
self.websocket_clients: List[web.WebSocketResponse] = []
|
self.websocket_clients: List[web.WebSocketResponse] = []
|
||||||
@@ -600,6 +602,29 @@ class ReticulumWebChat:
|
|||||||
query = query.on_conflict(conflict_target=[database.LxmfMessage.hash], update=data)
|
query = query.on_conflict(conflict_target=[database.LxmfMessage.hash], update=data)
|
||||||
query.execute()
|
query.execute()
|
||||||
|
|
||||||
|
# upserts the provided announce to the database
|
||||||
|
def db_upsert_announce(self, identity: RNS.Identity, destination_hash: bytes, aspect: str, app_data: bytes):
|
||||||
|
|
||||||
|
# parse app data
|
||||||
|
parsed_app_data = None
|
||||||
|
if app_data is not None:
|
||||||
|
parsed_app_data = base64.b64encode(app_data).decode("utf-8")
|
||||||
|
|
||||||
|
# prepare data to insert or update
|
||||||
|
data = {
|
||||||
|
"destination_hash": destination_hash.hex(),
|
||||||
|
"aspect": aspect,
|
||||||
|
"identity_hash": identity.hash.hex(),
|
||||||
|
"identity_public_key": base64.b64encode(identity.get_public_key()).decode("utf-8"),
|
||||||
|
"app_data": parsed_app_data,
|
||||||
|
"updated_at": datetime.now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
# upsert to database
|
||||||
|
query = database.Announce.insert(data)
|
||||||
|
query = query.on_conflict(conflict_target=[database.Announce.destination_hash], update=data)
|
||||||
|
query.execute()
|
||||||
|
|
||||||
# handle sending an lxmf message to reticulum
|
# handle sending an lxmf message to reticulum
|
||||||
async def send_message(self, destination_hash, content: str,
|
async def send_message(self, destination_hash, content: str,
|
||||||
image_field: LxmfImageField = None,
|
image_field: LxmfImageField = None,
|
||||||
@@ -689,7 +714,10 @@ class ReticulumWebChat:
|
|||||||
def on_lxmf_announce_received(self, destination_hash, announced_identity, app_data):
|
def on_lxmf_announce_received(self, destination_hash, announced_identity, app_data):
|
||||||
|
|
||||||
# log received announce
|
# log received announce
|
||||||
RNS.log("Received an announce from " + RNS.prettyhexrep(destination_hash))
|
print("Received an announce from " + RNS.prettyhexrep(destination_hash) + " for [lxmf.delivery]")
|
||||||
|
|
||||||
|
# upsert announce to database
|
||||||
|
self.db_upsert_announce(announced_identity, destination_hash, "lxmf.delivery", app_data)
|
||||||
|
|
||||||
# parse app data
|
# parse app data
|
||||||
parsed_app_data = None
|
parsed_app_data = None
|
||||||
@@ -706,6 +734,16 @@ class ReticulumWebChat:
|
|||||||
},
|
},
|
||||||
})))
|
})))
|
||||||
|
|
||||||
|
# handle an announce received from reticulum, for a nomadnet node
|
||||||
|
# NOTE: cant be async, as Reticulum doesn't await it
|
||||||
|
def on_nomadnet_node_announce_received(self, destination_hash, announced_identity, app_data):
|
||||||
|
|
||||||
|
# log received announce
|
||||||
|
print("Received an announce from " + RNS.prettyhexrep(destination_hash) + " for [nomadnetwork.node]")
|
||||||
|
|
||||||
|
# upsert announce to database
|
||||||
|
self.db_upsert_announce(announced_identity, destination_hash, "nomadnetwork.node", app_data)
|
||||||
|
|
||||||
|
|
||||||
# class to manage config stored in database
|
# class to manage config stored in database
|
||||||
class Config:
|
class Config:
|
||||||
@@ -773,6 +811,23 @@ class LXMFAnnounceHandler:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# an announce handler for nomadnetwork.node aspect that just forwards to a provided callback
|
||||||
|
class NomadnetworkNodeAnnounceHandler:
|
||||||
|
|
||||||
|
def __init__(self, received_announce_callback):
|
||||||
|
self.aspect_filter = "nomadnetwork.node"
|
||||||
|
self.received_announce_callback = received_announce_callback
|
||||||
|
|
||||||
|
# we will just pass the received announce back to the provided callback
|
||||||
|
def received_announce(self, destination_hash, announced_identity, app_data):
|
||||||
|
try:
|
||||||
|
# handle received announce
|
||||||
|
self.received_announce_callback(destination_hash, announced_identity, app_data)
|
||||||
|
except:
|
||||||
|
# ignore failure to handle received announce
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NomadnetDownloader:
|
class NomadnetDownloader:
|
||||||
|
|
||||||
def __init__(self, destination_hash: bytes, path: str, on_download_success: Callable[[bytes], None], on_download_failure: Callable[[str], None], on_progress_update: Callable[[float], None], timeout: int|None = None, auto_download=True):
|
def __init__(self, destination_hash: bytes, path: str, on_download_success: Callable[[bytes], None], on_download_failure: Callable[[str], None], on_progress_update: Callable[[float], None], timeout: int|None = None, auto_download=True):
|
||||||
|
|||||||
Reference in New Issue
Block a user