telegram-analytics / update_hf.py
rottg's picture
Upload folder using huggingface_hub
4a21e7e
#!/usr/bin/env python3
"""
Automated sync + deploy to Hugging Face Spaces.
Usage:
python update_hf.py # sync + upload everything
python update_hf.py --db-only # just upload DB (skip sync)
python update_hf.py --full # upload all files + DB (first time or after code changes)
"""
import subprocess
import sys
import os
# === CONFIGURATION ===
REPO_ID = "rottg/telegram-analytics"
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
DB_PATH = os.path.join(PROJECT_DIR, "telegram.db")
# Files to upload (code + config)
CODE_FILES = [
"dashboard.py", "ai_search.py", "algorithms.py", "data_structures.py",
"indexer.py", "search.py", "semantic_search.py", "schema.sql",
"Dockerfile", "requirements.txt", "README.md",
]
FOLDERS = ["static", "templates"]
# Token is read from environment variable or .hf_token file
HF_TOKEN = os.environ.get("HF_TOKEN")
if not HF_TOKEN:
token_file = os.path.join(PROJECT_DIR, ".hf_token")
if os.path.exists(token_file):
with open(token_file) as f:
HF_TOKEN = f.read().strip()
else:
print("ERROR: Set HF_TOKEN env var or create .hf_token file with your token")
sys.exit(1)
def run_sync():
"""Run daily_sync.py"""
sync_script = os.path.join(PROJECT_DIR, "daily_sync.py")
print("\n=== Step 1: Running daily sync ===")
result = subprocess.run([sys.executable, sync_script], cwd=PROJECT_DIR)
if result.returncode != 0:
print("ERROR: Sync failed!")
sys.exit(1)
print("Sync complete.")
def upload_to_hf(full=False):
"""Upload files to HF Space using the API (no git needed)."""
from huggingface_hub import HfApi
api = HfApi(token=HF_TOKEN)
if full:
# Upload all code files + folders + DB
print("\n=== Uploading all files to HF ===")
# Collect all files to upload
upload_files = []
for f in CODE_FILES:
path = os.path.join(PROJECT_DIR, f)
if os.path.exists(path):
upload_files.append((path, f))
for folder in FOLDERS:
folder_path = os.path.join(PROJECT_DIR, folder)
if os.path.exists(folder_path):
for root, dirs, files in os.walk(folder_path):
for fname in files:
full_path = os.path.join(root, fname)
rel_path = os.path.relpath(full_path, PROJECT_DIR)
upload_files.append((full_path, rel_path.replace("\\", "/")))
# Add DB
upload_files.append((DB_PATH, "telegram.db"))
print(f"Uploading {len(upload_files)} files...")
for local_path, repo_path in upload_files:
size_mb = os.path.getsize(local_path) / (1024 * 1024)
if size_mb > 1:
print(f" {repo_path} ({size_mb:.0f} MB)...")
else:
print(f" {repo_path}")
api.upload_folder(
folder_path=PROJECT_DIR,
repo_id=REPO_ID,
repo_type="space",
allow_patterns=[f for _, f in upload_files],
)
else:
# DB only - delete old, upload new
print("\n=== Removing old DB from HF ===")
try:
api.delete_file("telegram.db", repo_id=REPO_ID, repo_type="space")
print("Old DB removed.")
except Exception as e:
print(f"No old DB to remove ({e})")
print("\n=== Uploading new DB to HF ===")
db_size_mb = os.path.getsize(DB_PATH) / (1024 * 1024)
print(f"Uploading {db_size_mb:.0f} MB...")
api.upload_file(
path_or_fileobj=DB_PATH,
path_in_repo="telegram.db",
repo_id=REPO_ID,
repo_type="space",
)
print("Upload complete!")
print(f"\nSite will rebuild at: https://rottg-telegram-analytics.hf.space")
def main():
db_only = "--db-only" in sys.argv
full = "--full" in sys.argv
if not db_only:
run_sync()
else:
print("Skipping sync (--db-only)")
upload_to_hf(full=full or not db_only and "--db-only" not in sys.argv)
print("\n=== Done! ===")
if __name__ == "__main__":
main()