Factor Studios commited on
Commit
eca4b9a
Β·
verified Β·
1 Parent(s): 8cd48dc

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -0
app.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import requests
4
+ from urllib.parse import urlparse
5
+ from huggingface_hub import upload_file
6
+ from fastapi import FastAPI
7
+ from contextlib import asynccontextmanager
8
+ import asyncio
9
+ import logging
10
+
11
+ # === CONFIGURATION ===
12
+ HF_TOKEN = os.environ.get("HF_TOKEN")
13
+ REPO_ID = "Fred808/BG1"
14
+ DATA_PATH = "Huidini"
15
+ OUTPUT_DIR = "batch_downloads"
16
+ DOWNLOAD_URLS = [
17
+ "https://ww8.zeroupload.xyz/025984a8fb2726d8e39b334d23c79360/MDA_TheSymbioteCreature_DownloadPirate.com.rar?download_token=2912b71a4669baaec51b23d28a1665d6ebadedb5f7cf89706a8111302838ca15",
18
+ "https://ww8.zeroupload.xyz/4f2f3f75fde2434d5946170303d08196/MDA_MasteringHoudiniArtDesign_DownloadPirate.com.rar?download_token=f2e041102d5c54df37949603fa6a8fe84ffb1611587bcf8f5f9cfa801454f9ed",
19
+ ]
20
+ DELAY_BETWEEN_DOWNLOADS = 12 # seconds
21
+
22
+ # === Setup Logging ===
23
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
24
+
25
+ # === Prepare output folder ===
26
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
27
+
28
+ app = FastAPI()
29
+
30
+ # === DUMMY ROUTE TO KEEP SERVER HEALTHY ===
31
+ @app.get("/")
32
+ def keep_alive():
33
+ return {"status": "running"}
34
+
35
+ # === Upload Function ===
36
+ def upload_to_dataset(filepath):
37
+ try:
38
+ upload_file(
39
+ path_or_fileobj=filepath,
40
+ path_in_repo=f"{DATA_PATH}/{os.path.basename(filepath)}",
41
+ repo_id=REPO_ID,
42
+ repo_type="dataset",
43
+ token=HF_TOKEN
44
+ )
45
+ logging.info(f"[↑] Uploaded: {filepath}")
46
+ except Exception as e:
47
+ logging.error(f"[!] Upload failed: {filepath} β€” {e}")
48
+
49
+ # === Background Worker ===
50
+ async def downloader_worker():
51
+ for direct_download_link in DOWNLOAD_URLS:
52
+ logging.info("[*] Waiting before next download...")
53
+ await asyncio.sleep(DELAY_BETWEEN_DOWNLOADS)
54
+
55
+ try:
56
+ logging.info(f"[*] Downloading from: {direct_download_link}")
57
+ filename = os.path.basename(urlparse(direct_download_link).path)
58
+ if not filename or "." not in filename:
59
+ filename = "downloaded_file_" + str(int(time.time()))
60
+
61
+ local_path = os.path.join(OUTPUT_DIR, filename)
62
+ logging.info(f"[*] Saving to: {local_path}")
63
+
64
+ with requests.get(direct_download_link, stream=True) as r:
65
+ r.raise_for_status()
66
+ with open(local_path, "wb") as f:
67
+ for chunk in r.iter_content(chunk_size=8192):
68
+ f.write(chunk)
69
+
70
+ logging.info(f"[βœ“] Downloaded: {filename}")
71
+ upload_to_dataset(local_path)
72
+ os.remove(local_path)
73
+
74
+ except Exception as e:
75
+ logging.error(f"[!] Error with {direct_download_link}: {e}")
76
+
77
+ logging.info("βœ… All files processed.")
78
+
79
+ @app.get("/")
80
+ def stay_alive():
81
+ return {"msg": "Running"}
82
+
83
+ @app.get("/health")
84
+ def healthcheck():
85
+ return {"healthy": True}
86
+
87
+ # === FastAPI Lifespan ===
88
+ @asynccontextmanager
89
+ async def lifespan(app: FastAPI):
90
+ logging.info("πŸš€ Starting FastAPI download-uploader microservice...")
91
+ task = asyncio.create_task(downloader_worker())
92
+ yield
93
+ task.cancel()
94
+ logging.info("πŸ›‘ Shutting down microservice.")
95
+
96
+ # === FastAPI App ===
97
+ app = FastAPI(lifespan=lifespan)
98
+ # Re-assign app with lifespan logic
99
+ app.router.lifespan_context = lifespan