197 lines
7.9 KiB
Python
197 lines
7.9 KiB
Python
import sys, os
|
|
import math
|
|
from enum import Enum, auto
|
|
from pathlib import Path
|
|
import time
|
|
import json
|
|
from datetime import datetime, timezone
|
|
|
|
from libs.noSys.noSysModule import NoSysModule
|
|
from libs.noSys.events import Events as NoSysEvents, DynamicEvents as NoSysDynamicEvents
|
|
from libs.noSys.networks import Networks
|
|
from libs.noSys.peers import Peer
|
|
from libs.app.common.logging import get_logger
|
|
from libs.app.common.paths import ROOT_DIR, FILES_DIR
|
|
from libs.fspn.utils.sha256_util import hash_file, hash_bytes
|
|
from libs.app.common.store import DataStore
|
|
from libs.p2post.p2postApiBlueprint import Blueprint
|
|
from libs.p2post.p2postSocketio import HandlerSocketio
|
|
from libs.fileTransfer.fileTransfer import FileTransfer, File, FileEvents
|
|
from .dataManager import DataManager
|
|
|
|
logger = get_logger()
|
|
|
|
class P2postEvents(Enum):
|
|
ON_RECEIVING_ = auto()
|
|
|
|
class P2post(NoSysModule):
|
|
def __init__(self, nosys_core):
|
|
super().__init__(nosys_core)
|
|
|
|
self.data = DataManager()
|
|
self.file_transfer:FileTransfer = None
|
|
|
|
self.requested_signatures = {}
|
|
|
|
def setup(self):
|
|
self.nosys_core.subscribe_event(NoSysEvents.USER_ADDED, self.on_user_added)
|
|
self.nosys_core.modules.api.register_blueprint(Blueprint(self).blueprint)
|
|
self.nosys_core.modules.api.register_socketio(HandlerSocketio(self))
|
|
self.networks_module:Networks = self.nosys_core.modules.get("noSys", "networks")
|
|
self.file_transfer = self.nosys_core.modules.get("fileTransfer", "fileTransfer")
|
|
self.file_transfer.subscribe_module_file_events(self.id, self.on_file_event)
|
|
|
|
def on_nosys_ready(self, event):
|
|
pass
|
|
|
|
def on_user_added(self, event):
|
|
user_id = event.user_id
|
|
if not self.data.get_user(user_id):
|
|
temp_nickname = user_id[:4] + "..." + user_id[-4:]
|
|
self.data.add_user(user_id, temp_nickname)
|
|
|
|
def on_file_event(self, event):
|
|
file:File = event.file
|
|
file.subscribe_event(FileEvents.ON_FILE_COMPLETED.name, self.on_file_done)
|
|
file.subscribe_event(FileEvents.ON_FILE_ERROR.name, self.on_file_done)
|
|
file.subscribe_event(FileEvents.ON_FILE_UPDATE.name, self.on_file_update)
|
|
logger.error(f"{file.status} {file.id}")
|
|
file.approve_transfer(True) # TODO Check configuration
|
|
|
|
def on_file_done(self, event):
|
|
logger.info(f"File Done {event.source.status} {event.source.hash}")
|
|
self.data.add_media(event.source.hash, event.final_path)
|
|
|
|
def on_file_update(self, event):
|
|
pass
|
|
|
|
def on_module_connection(self, event):
|
|
pass
|
|
# self.send_networks(event.connection.id)
|
|
|
|
def on_module_message(self, event):
|
|
action = event.data['action']
|
|
handler_action = getattr(self, 'on_'+action)
|
|
handler_action(event)
|
|
|
|
def on_network_connection(self, event):
|
|
network_id:str = event.network_id
|
|
peer:Peer = event.peer
|
|
|
|
self.send_network_post(network_id, peer.id)
|
|
|
|
def send_network_post(self, network_id, peer_id):
|
|
network = self.data.get_network(network_id)
|
|
if network:
|
|
body = {"action":"network_posts", "hash":network["hash"], "posts":network["posts"]}
|
|
self.nosys_core.dispatcher.send_message(body, peer_id, self.id)
|
|
|
|
def on_network_posts(self, event):
|
|
payload = event.data
|
|
network = self.data.get_network(payload["hash"])
|
|
if network:
|
|
for post in payload["posts"]:
|
|
if not self.data.get_post(post):
|
|
self.send_get_post(post, network, event.peer.id)
|
|
|
|
|
|
def send_get_post(self, hash, network, peer_id):
|
|
body = {"action":"get_post", "hash":hash, "network":network}
|
|
self.nosys_core.dispatcher.send_message(body, peer_id, self.id)
|
|
|
|
def on_get_post(self, event):
|
|
payload = event.data
|
|
self.send_post(payload["hash"], payload["network"], event.peer.id)
|
|
|
|
def send_post(self, hash, network, peer_id):
|
|
post = self.data.get_post(hash)
|
|
body = {"action":"post", "post":post, "network":network}
|
|
self.nosys_core.dispatcher.send_message(body, peer_id, self.id)
|
|
|
|
def on_post(self, event):
|
|
payload = event.data
|
|
post = payload["post"]
|
|
network = payload["network"]
|
|
# TODO VERIFY POST
|
|
if not self.data.get_post(post["hash"]):
|
|
self.data.add_post(post["hash"], post["timestamp"], post["author"], post["content"], post["signature"], post["medias"])
|
|
for media in post["medias"]:
|
|
if media["type"] == "local" and (not self.data.get_media(media["hash"])):
|
|
self.send_get_media(media["hash"], event.peer.id)
|
|
self.data.get_network(network)["posts"].append(post["hash"])
|
|
|
|
if not self.data.get_user(post["author"]):
|
|
author_key = post["author"]
|
|
temp_nickname = author_key[:4] + "..." + author_key[-4:]
|
|
self.data.add_user(author_key, temp_nickname)
|
|
|
|
self.data.store.save()
|
|
|
|
elif post["hash"] not in self.data.get_network(network)["posts"]:
|
|
self.data.get_network(network)["posts"].append(post["hash"])
|
|
self.data.store.save()
|
|
|
|
def send_get_media(self, hash, peer_id):
|
|
body = {"action":"get_media", "hash":hash}
|
|
self.nosys_core.dispatcher.send_message(body, peer_id, self.id)
|
|
|
|
def on_get_media(self, event):
|
|
payload = event.data
|
|
media = self.data.get_media(payload["hash"])
|
|
self.file_transfer.send_file(media["file_path"], event.peer.id, self.id)
|
|
|
|
def create_post(self, author, content, medias, networks:list[str]):
|
|
# TODO File server to respond frontend requests
|
|
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.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()
|
|
post = {
|
|
"timestamp": utc_timestamp,
|
|
"author": author,
|
|
"content": content,
|
|
"medias": medias_data
|
|
}
|
|
post_serialized = json.dumps(post, sort_keys=True, separators=(",", ":"))
|
|
|
|
post["hash"] = hash_bytes(post_serialized.encode('utf-8'))
|
|
request_id = self.nosys_core.modules.pmc.sign(post["hash"], author, self.signature_callback, f"New Post {post}")
|
|
self.requested_signatures[request_id] = (post, networks)
|
|
logger.debug(f"Post waiting signature {request_id}: {post}")
|
|
return post["hash"]
|
|
|
|
def signature_callback(self, request_id, signature):
|
|
post, networks = self.requested_signatures[request_id]
|
|
if signature:
|
|
self.data.add_post(post["hash"], post["timestamp"], post["author"], post["content"], signature, post["medias"])
|
|
for network in networks:
|
|
self.data.get_network(network)["posts"].append(post["hash"])
|
|
network_state = self.networks_module.network_states.get(network)
|
|
for peer in network_state["peers"]:
|
|
self.send_post(post["hash"], network, peer)
|
|
self.data.store.save()
|
|
|
|
def test(self):
|
|
file_path = r"C:\Workspace\libs\noSys\index.html"
|
|
file_url = "https://pbs.twimg.com/media/GwvwQamW4AAQYiD?format=jpg&name=small"
|
|
|
|
medias = []
|
|
medias.append({
|
|
"type":"local",
|
|
"file_path": file_path
|
|
})
|
|
medias.append({
|
|
"type":"external",
|
|
"url": file_url
|
|
})
|
|
self.create_post("A4DZSk+TlR+4w39MbiIAQbti+N0H1QlJEhRH2DI6Iubj", "ContentTest", medias, ["629985fd999a675072a2e3f22f74e60c62e8c5b8efb21478c9b04e7ff2fe9779",])
|
|
|
|
|