Added libs
This commit is contained in:
161
p2private/p2private.py
Normal file
161
p2private/p2private.py
Normal file
@@ -0,0 +1,161 @@
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
import time
|
||||
|
||||
from libs.fspn.utils.wrapper_util import threaded
|
||||
from libs.app.common.logging import get_logger
|
||||
from libs.fspn.utils.sha256_util import hash_file, hash_bytes, hash_string
|
||||
from libs.noSys.noSysModule import NoSysModule
|
||||
from libs.noSys.events import Events as nosys_events, DynamicEvents as nosys_dynamic_events
|
||||
from libs.noSys.peers import Peer
|
||||
from libs.p2post.p2post import P2post
|
||||
from .networks import Networks
|
||||
from .dataManager import DataManager
|
||||
from .p2privateApiBlueprint import Blueprint
|
||||
|
||||
logger = get_logger()
|
||||
|
||||
class P2private(NoSysModule):
|
||||
def __init__(self, noSys):
|
||||
super().__init__(noSys)
|
||||
self.nosys_core.subscribe_event(nosys_events.USER_ADDED, self.on_user_added)
|
||||
|
||||
self.data = DataManager()
|
||||
self.p2post:P2post = None
|
||||
self.networks_module:Networks = None
|
||||
self.requested_signatures = {}
|
||||
|
||||
self.friends_state = {}
|
||||
|
||||
def setup(self):
|
||||
self.p2post = self.nosys_core.modules.get("p2post", "p2post")
|
||||
self.networks_module = self.nosys_core.modules.get("p2private", "networks")
|
||||
self.nosys_core.modules.api.register_blueprint(Blueprint(self).blueprint)
|
||||
|
||||
def on_nosys_ready(self, event):
|
||||
pass
|
||||
|
||||
def add_friend(self, pubkey, relays):
|
||||
self.data.add_friend(pubkey, relays)
|
||||
self.set_friend_state(pubkey)
|
||||
|
||||
def on_user_added(self, event):
|
||||
user_id:str = event.user_id
|
||||
self.manage_friends(user_id)
|
||||
|
||||
@threaded
|
||||
def manage_friends(self, my_user):
|
||||
for friend in self.data.list_friends():
|
||||
self.set_friend_state(friend["pubkey"])
|
||||
while True:
|
||||
for friend in self.data.list_friends():
|
||||
self.manage_friend(friend)
|
||||
time.sleep(10)
|
||||
|
||||
def set_friend_state(self, friend_pubkey):
|
||||
# TODO Add friends inside users object data
|
||||
self.friends_state[friend_pubkey] = {
|
||||
"id": friend_pubkey,
|
||||
"status": "dis", # TODO Enum
|
||||
}
|
||||
|
||||
def manage_friend(self, user):
|
||||
friend_id = user["pubkey"]
|
||||
state = self.friends_state[friend_id]
|
||||
|
||||
if state["status"] == "dis":
|
||||
print("FRIEND IS DISCONNECTED")
|
||||
for relay in user["relays"]:
|
||||
if self.networks_module.network_states.get(relay):
|
||||
print(f"Connected to relay {relay}")
|
||||
# TODO Check if friend is on in the network and send message to connect to a rendezvous
|
||||
elif state["status"] == "con":
|
||||
print("FRIEND IS CONNECTED")
|
||||
|
||||
def on_module_message(self, event):
|
||||
handler_action = getattr(self, 'on_'+event.data.get("action"))
|
||||
handler_action(event)
|
||||
|
||||
def create_message(self, from_user, to_user, content, medias):
|
||||
medias_data = []
|
||||
for media in medias:
|
||||
if media["type"] == "local":
|
||||
file_hash = os.path.splitext(os.path.basename(media["file_path"]))[0]
|
||||
medias_data.append({"type":"local", "hash":file_hash})
|
||||
self.p2post.data.add_media(file_hash, media["file_path"])
|
||||
else:
|
||||
medias_data.append({"type":media["type"], "url":media["url"]})
|
||||
|
||||
current_utc_datetime = datetime.now(timezone.utc)
|
||||
utc_timestamp = current_utc_datetime.timestamp()
|
||||
message = {
|
||||
"timestamp": utc_timestamp,
|
||||
"from": from_user,
|
||||
"to": to_user,
|
||||
"content": content, #TODO Hash it
|
||||
"medias": medias_data
|
||||
}
|
||||
message_serialized = json.dumps(message, sort_keys=True, separators=(",", ":"))
|
||||
|
||||
message["hash"] = hash_bytes(message_serialized.encode('utf-8'))
|
||||
request_id = self.nosys_core.modules.pmc.sign(message["hash"], from_user, self.signature_callback, f"New Message {message}")
|
||||
self.requested_signatures[request_id] = message
|
||||
logger.debug(f"Message waiting signature {request_id}: {message}")
|
||||
return message["hash"]
|
||||
|
||||
def signature_callback(self, request_id, signature):
|
||||
message = self.requested_signatures.get(request_id)
|
||||
if signature and message:
|
||||
message["signature"] = signature
|
||||
self.send_message(message)
|
||||
|
||||
def send_message(self, message):
|
||||
self.data.add_message(message)
|
||||
direct_connections = self.nosys_core.peers.get_by_peer_user_id(message["to"])
|
||||
if direct_connections:
|
||||
logger.debug(f"Friend {message['to']} direct connected")
|
||||
for peer in direct_connections:
|
||||
# TODO Maybe check 'from user', peers can set to just receive message from the user in connection and networks
|
||||
self.send_private_message(message, peer.id)
|
||||
else:
|
||||
logger.debug(f"Friend {message['to']} not direct connected. Posting message to user relays.")
|
||||
to_user = message["to"]
|
||||
relay_networks = self.get_friend_relay_networks(to_user) # TODO get from store
|
||||
if not relay_networks:
|
||||
logger.error(f"Not found a network relay to friend {to_user}")
|
||||
# TODO Update message status
|
||||
else:
|
||||
self.networks_module.post_network_message(message, relay_networks)
|
||||
|
||||
def send_private_message(self, message, peer_id):
|
||||
payload = {'action':'private_message','message':message}
|
||||
self.nosys_core.dispatcher.send_message(payload, peer_id, self.id)
|
||||
|
||||
def on_private_message(self, event):
|
||||
data = event.data
|
||||
message = data["message"]
|
||||
if not self.data.get_message(message["hash"]):
|
||||
self.data.add_message(message)
|
||||
logger.debug(f"New message received {message}")
|
||||
else:
|
||||
logger.debug("Message already exists")
|
||||
|
||||
# Read receipts ???? Talk to friends about it
|
||||
|
||||
def get_friend_relay_networks(self, user_id):
|
||||
user = self.data.get_friend(user_id)
|
||||
if user:
|
||||
return user["relays"]
|
||||
return []
|
||||
|
||||
def on_module_connection(self, event):
|
||||
peer:Peer = event.peer
|
||||
peer_user = peer.connection.security.peer_user
|
||||
state = self.friends_state.get(peer_user)
|
||||
if state:
|
||||
state["status"] = "con"
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user