import ipfsClient from dotenv import load_dotenv import datetime import asyncio import uvicorn load_dotenv() import os import subprocess # import socketio import requests from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware import time # from explict import parallel from pydantic import BaseModel import urllib.parse # import rich class Item(BaseModel): filename: str directory: str username: str fileURI: str class DeleteItem(BaseModel): CID: str def get_folder_size(folder_path): total_size = 0 for dirpath, dirnames, filenames in os.walk(folder_path): for filename in filenames: filepath = os.path.join(dirpath, filename) total_size += os.path.getsize(filepath) return total_size def info(message: str): print(f"[INFO] <{datetime.datetime.now()}> - {message}") def network(message: str): print(f"[NET] <{datetime.datetime.now()}> - {message}") NODE_ID = os.getenv("NODE_ID") URL = os.getenv("MASTER_URL") # @parallel def startup(): info("Spinning up...") #TODO: Query the database from nodejs server instead because I cannot get the db here fuck safe_node_id = urllib.parse.quote(NODE_ID, safe='') info(safe_node_id) req = requests.get(URL + f"/bee3hive/internal/files/{safe_node_id}") if req.status_code != 200: info("Failed to get file from node") return data = req.json() # print(data) #! debug only for file in data: info(f"Caching file -- {file["CID"]}") network(ipfsClient.add_pin(file["CID"])["Pins"]) info("Finished") app = FastAPI() origins = [ "https://quanvndzai-bee3hiveapi.hf.space", "http://localhost", ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/") async def root(): return {"message": "Hello World"} @app.get("/healthcheck") async def health(): return {"message": "Ok!"} @app.post("/delete") async def fetch(data: DeleteItem): network("Reciving file deletion") return ipfsClient.unpin(data.CID) @app.get("/id") async def id(): return subprocess.check_output(['ipfs', 'id']) @app.post("/fetch") async def fetch(data: Item): network("Reciving file assignment") # File is an json object containing the filename and part of the file print(data) network(f"Fetching file {data.filename}") url = URL + "/upload_queue/" + data.fileURI print(url) r = requests.get(url=url, stream=True) total_length = r.headers.get('content-length') if r.status_code != 200: return {"message": "Failed to fetch file"} if not os.path.exists(".ipfs/upload_queue"): info("Create folder") os.chdir(".ipfs") os.mkdir("upload_queue") os.chdir("..") info("Writing temp file to disk") relative_path = f".ipfs/upload_queue/{data.fileURI}" with open(relative_path, "wb") as f: dl = 0 total_length = int(total_length) for d in r.iter_content(chunk_size=4096): dl += len(d) f.write(d) done = int(100 * dl / total_length) # info(f"Downloaded {done}%") # f.write(r.content) info("Uploading file to ipfs") ipfs = ipfsClient.add(relative_path, data.filename, data.directory) # double check this pined = ipfsClient.add_pin(ipfs[0]["Hash"]) print(pined) info("Done!") return ipfs # This is a json @app.get("/availible") async def availible(): print(os.getcwd()) print(f"Checking availibility... {get_folder_size("../.ipfs")}bytes") if get_folder_size("../.ipfs") >= 40 * 1024 * 1024 * 1024: return "Unavailible" else: return "Ok!" # @parallel # def run_web_app(): # uvicorn.run(app, host="0.0.0.0", port=7861) if __name__ == "__main__": # startup() uvicorn.run(app, host="0.0.0.0", port=7860)