nomadnet-file-fetcher/fetcher.py
2025-12-26 17:48:28 -07:00

301 lines
9.6 KiB
Python
Executable file

#!/bin/python
import os
import io
import shutil
import argparse
import time
import RNS
# from io import BufferedReader
# import io
# import LXMF
# class Fetcher:
# # DEFAULT_PATH = "/page/index.mu"
# DEFAULT_TIMEOUT = 10
# DEFAULT_CACHE_TIME = 12*60*60
# NO_PATH = 0x00
# PATH_REQUESTED = 0x01
# ESTABLISHING_LINK = 0x02
# LINK_TIMEOUT = 0x03
# LINK_ESTABLISHED = 0x04
# REQUESTING = 0x05
# REQUEST_SENT = 0x06
# REQUEST_FAILED = 0x07
# REQUEST_TIMEOUT = 0x08
# RECEIVING_RESPONSE = 0x09
# DISCONECTED = 0xFE
# DONE = 0xFF
# def retrieve_url(self, url, request_data = None):
# self.previous_destination_hash = self.destination_hash
# self.previous_path = self.path
# destination_hash = None
# path = None
# components = url.split(":")
# if len(components) == 1:
# if len(components[0]) == (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2:
# try:
# destination_hash = bytes.fromhex(components[0])
# except Exception as e:
# raise ValueError("Malformed URL")
# # path = Browser.DEFAULT_PATH
# else:
# raise ValueError("Malformed URL")
# elif len(components) == 2:
# if len(components[0]) == (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2:
# try:
# destination_hash = bytes.fromhex(components[0])
# except Exception as e:
# raise ValueError("Malformed URL")
# path = components[1]
# # if len(path) == 0:
# # path = Browser.DEFAULT_PATH
# else:
# if len(components[0]) == 0:
# if self.destination_hash != None:
# destination_hash = self.destination_hash
# path = components[1]
# if len(path) == 0:
# path = Browser.DEFAULT_PATH
# else:
# raise ValueError("Malformed URL")
# else:
# raise ValueError("Malformed URL")
# else:
# raise ValueError("Malformed URL")
# if destination_hash != None and path != None:
# if path.startswith("/file/"):
# if destination_hash != self.loopback:
# if destination_hash == self.destination_hash:
# self.download_file(destination_hash, path)
# else:
# RNS.log("Cannot request file download from a node that is not currently connected.", RNS.LOG_ERROR)
# RNS.log("The requested URL was: "+str(url), RNS.LOG_ERROR)
# else:
# self.download_local_file(path)
# else:
# self.set_destination_hash(destination_hash)
# self.set_path(path)
# self.set_request_data(request_data)
# self.load_page()
# def download_file(self, destination_hash, path):
# if self.link == None or self.link.destination.hash != self.destination_hash:
# if not RNS.Transport.has_path(self.destination_hash):
# self.status = Browser.NO_PATH
# self.update_display()
# RNS.Transport.request_path(self.destination_hash)
# self.status = Browser.PATH_REQUESTED
# self.update_display()
# pr_time = time.time()+RNS.Transport.first_hop_timeout(self.destination_hash)
# while not RNS.Transport.has_path(self.destination_hash):
# now = time.time()
# if now > pr_time+self.timeout:
# self.request_timeout()
# return
# time.sleep(0.25)
# self.status = Browser.ESTABLISHING_LINK
# self.update_display()
# identity = RNS.Identity.recall(self.destination_hash)
# destination = RNS.Destination(
# identity,
# RNS.Destination.OUT,
# RNS.Destination.SINGLE,
# self.app_name,
# self.aspects
# )
# self.link = RNS.Link(destination, established_callback = self.link_established, closed_callback = self.link_closed)
# while self.status == Browser.ESTABLISHING_LINK:
# time.sleep(0.1)
# if self.status != Browser.LINK_ESTABLISHED:
# return
# self.update_display()
# if self.link != None and self.link.destination.hash == self.destination_hash:
# # Send the request
# self.status = Browser.REQUESTING
# self.response_progress = 0
# self.response_speed = None
# self.progress_updated_at = None
# self.previous_progress = 0
# self.response_size = None
# self.response_transfer_size = None
# self.saved_file_name = None
# self.update_display()
# receipt = self.link.request(
# path,
# data = None,
# response_callback = self.file_received,
# failed_callback = self.request_failed,
# progress_callback = self.response_progressed
# )
# if receipt:
# self.last_request_receipt = receipt
# self.last_request_id = receipt.request_id
# self.status = Browser.REQUEST_SENT
# self.update_display()
# else:
# self.link.teardown()
# global server link
server_link = None
file = None
# outdir = None
def link_established(link):
global server_link
server_link = link
print("link established")
def link_closed():
print("link closed")
def file_received(request_receipt):
global file
file = True
global outdir
try:
if type(request_receipt.response) == io.BufferedReader:
if request_receipt.metadata != None:
file_name = os.path.basename(request_receipt.metadata["name"].decode("utf-8"))
file_handle = request_receipt.response
file_destination = outdir+"/"+file_name
counter = 0
while os.path.isfile(file_destination):
counter += 1
file_destination = outdir+"/"+file_name+"."+str(counter)
shutil.move(file_handle.name, file_destination)
else:
file_name = request_receipt.response[0]
file_data = request_receipt.response[1]
file_destination_name = os.path.basename(file_name)
file_destination = "."+"/"+file_destination_name
counter = 0
while os.path.isfile(file_destination):
counter += 1
file_destination = outdir+"/"+file_destination_name+"."+str(counter)
fh = open(file_destination, "wb")
fh.write(file_data)
fh.close()
# self.saved_file_name = file_destination.replace(self.app.downloads_path+"/", "", 1)
# self.status = Browser.DONE
# self.response_progress = 0
# self.response_speed = None
# self.progress_updated_at = None
# self.previous_progress = 0
# self.update_display()
except Exception as e:
RNS.log("An error occurred while handling file response. The contained exception was: "+str(e), RNS.LOG_ERROR)
print("file received")
def request_failed(req_receipt):
print("request failed")
# print(str(e))
def response_progressed(req_receipt):
# print("response progressed")
return
parser = argparse.ArgumentParser(description="request a resource from a target node")
parser.add_argument("URL", help="the LXMF URL of the resource to be fetched")
parser.add_argument("OUTDIR", help="the output directory to place the file")
args = parser.parse_args()
arglist = args.URL.split(":")
dest_hash = arglist[0]
resource_path = arglist[1]
print(dest_hash)
print(resource_path)
outdir = args.OUTDIR
r = RNS.Reticulum()
RNS.loglevel = RNS.LOG_DEBUG
# router = LXMF.LXMRouter(storagepath="./tmp2")
# router.register_delivery_callback(delivery_callback)
ident = RNS.Identity()
dest_hash = bytes.fromhex(dest_hash)
dest_ident = RNS.Identity.recall(dest_hash)
# need these to connect to a nomadnetwork node
app_name = "nomadnetwork"
aspects = "node"
destination = RNS.Destination(
dest_ident,
RNS.Destination.OUT,
RNS.Destination.SINGLE,
app_name,
aspects
)
# with open(args.GCODE_FILE, "rb") as f:
# contents = f.read()
# content_size = len(contents)
# Look up the path to the destination.
print("looking up path to destination...")
if not RNS.Transport.has_path(dest_hash):
RNS.Transport.request_path(dest_hash)
while not RNS.Transport.has_path(dest_hash):
time.sleep(0.1)
# establish link
link = RNS.Link(destination, established_callback = link_established, closed_callback = link_closed)
while not server_link:
time.sleep(0.1)
receipt = link.request(
resource_path,
data = None,
response_callback = file_received,
failed_callback = request_failed,
progress_callback = response_progressed
)
while not file:
time.sleep(0.1)
# if receipt:
# last_request_receipt = receipt
# last_request_id = receipt.request_id
# # status = Browser.REQUEST_SENT
# # update_display()
# else:
# link.teardown()
# print(ident)