Files
nosys_libs/p2private/networks.py
2026-01-25 13:55:46 +10:00

158 lines
7.0 KiB
Python

from typing import Dict, List, Optional, Any
from libs.fspn.utils.sha256_util import hash_string
from libs.app.common.store import DataStore
from libs.app.common.logging import get_logger
from libs.noSys.noSysModule import NoSysModule
from libs.noSys.peers import Peer
from .networksApiBlueprint import Blueprint
logger = get_logger("networks")
class Networks(NoSysModule):
def __init__(self, nosys_core):
super().__init__(nosys_core)
self.store = DataStore(path="p2private/networkData.json", default_data={"networks":[], "messages":[]})
self.network_states = {}
def setup(self):
self.nosys_core.modules.api.register_blueprint(Blueprint(self).blueprint)
from .p2private import P2private
self.p2private_module:P2private = self.nosys_core.modules.get("p2private", "p2private")
from libs.p2post.p2post import P2post
self.p2post_module:P2post = self.nosys_core.modules.get("p2post", "p2post")
def on_nosys_ready(self, event):
for network in self.networks:
if not self.get_network(network["id"]):
self.add_network(network["id"])
def on_module_message(self, event):
handler_action = getattr(self, 'on_'+event.data.get("action"))
handler_action(event)
def post_network_message(self, message, networks=[]):
for network_id in networks:
if not self.get_message(message["hash"]):
self.add_message(message["hash"], message["from"], message["to"], message["content"], message["timestamp"], message["signature"])
self.add_message_to_network(network_id, message["hash"])
state = self.network_states.get(network_id, [])
for peer in state.get("peers", []):
self.send_network_message(network_id, message["hash"], peer)
def on_network_connection(self, event):
network_id = event.network_id
peer_id = event.peer.id
if network_id not in self.network_states:
self.network_states[network_id] = {"peers":[], "status":0} # TODO ENUM status
self.network_states[network_id]["peers"].append(peer_id)
self.send_network_hash(network_id, peer_id)
def send_network_hash(self, network_id:str, peer_id:str):
hash = self.get_network_hash(network_id)
self.nosys_core.dispatcher.send_message({'action':'network_hash','network':network_id, "hash":hash}, peer_id, self.id)
def on_network_hash(self, event):
peer: Peer = event.peer
data = event.data
network_id = data["network"]
if data["hash"] != self.get_network_hash(network_id):
self.send_network_messages(network_id, peer.id)
def send_network_messages(self, network_id, peer_id):
messages = self.get_network(network_id)["messages"]
self.nosys_core.dispatcher.send_message({'action':'network_messages','network':network_id, "messages":messages}, peer_id, self.id)
def on_network_messages(self, event):
peer: Peer = event.peer
data = event.data
network_id = data["network"]
messages = data["messages"]
for hash in messages:
if not self.get_message(hash):
self.send_get_network_message(network_id, hash, peer.id)
def send_get_network_message(self, network_id, message_id, peer_id):
self.nosys_core.dispatcher.send_message({'action':'get_network_message', "network":network_id, "message":message_id}, peer_id, self.id)
def on_get_network_message(self, event):
peer: Peer = event.peer
data = event.data
self.send_network_message(data["network"], data["message"], peer.id)
def send_network_message(self, network_id, message_id, peer_id):
message = self.get_message(message_id)
self.nosys_core.dispatcher.send_message({'action':'network_message', "network":network_id, "message":message}, peer_id, self.id)
def on_network_message(self, event):
data = event.data
network_id = data["network"]
message = data["message"]
if not self.get_message(message["hash"]):
self.add_message(message["hash"], message["from"], message["to"], message["content"], message["timestamp"], message["signature"])
# TODO Check if not in network messages
self.add_message_to_network(network_id, message["hash"])
self.post_network_message(message, [network_id])
self.check_message_to_me(message)
def check_message_to_me(self, message):
if self.p2post_module.data.get_user(message["to"]):
self.p2private_module.data.add_message(message)
# TODO SEND RECEIVED SIGNATURE TO THE NETWORKS IF USER LOGGED
def get_network_hash(self, network_id: str) -> str:
network = self.get_network(network_id)
if not network:
return ""
combined = ''.join(sorted(network["messages"]))
return hash_string(combined)
# ------------------- MESSAGE CRUD -------------------
def add_message(self, hash: str, from_id:str, to_id:str, content:str, timestamp, signature:str):
if self.get_message(hash):
raise ValueError(f"Message {hash} already exists")
message = {"hash": hash, "from": from_id, "to":to_id, "content":content, "timestamp":timestamp, "signature":signature}
self.store.add_item("messages", message, unique=True, id_field="hash", id=hash)
return message
def get_message(self, hash: str):
return self.store.get_item("messages", "hash", hash)
def delete_message(self, hash: str) -> bool:
return self.store.remove_item("messages", "hash", hash)
def list_messages(self):
return self.store.list_items("messages")
def update_message(self, hash: str, updates: Dict[str, Any]) -> bool:
return self.store.update_item("messages", "hash", hash, updates)
# ------------------- NETWORK CRUD -------------------
def add_network(self, network_id: str):
if self.get_network(network_id):
raise ValueError(f"Network {network_id} already exists")
network = {"id": network_id, "messages": []}
self.store.add_item("networks", network, unique=True, id_field="id", id=network_id)
return network
def get_network(self, network_id: str):
return self.store.get_item("networks", "id", network_id)
def delete_network(self, network_id: str) -> bool:
return self.store.remove_item("networks", "id", network_id)
def list_networks(self):
return self.store.list_items("networks")
def update_network(self, network_id: str, updates: Dict[str, Any]) -> bool:
return self.store.update_item("networks", "id", network_id, updates)
def add_message_to_network(self, network_id:str, message_id:str):
network = self.get_network(network_id)
if network and message_id not in network["messages"]:
network["messages"].append(message_id)
self.update_network(network_id, network)
return True
return False