| import streamlit as st |
| import subprocess |
| import shutil |
| import os |
| import zipfile |
| import io |
|
|
| |
| def run_command(command): |
| try: |
| |
| result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True) |
| return True, result.stdout |
| except subprocess.CalledProcessError as e: |
| return False, e.stderr |
|
|
| |
| def create_zip_buffer(source_dir, flatten=False): |
| zip_buffer = io.BytesIO() |
| with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zipf: |
| for root, dirs, files in os.walk(source_dir): |
| if '.git' in root: |
| continue |
| for file in files: |
| file_path = os.path.join(root, file) |
| if flatten: |
| arcname = file |
| else: |
| arcname = os.path.relpath(file_path, source_dir) |
| zipf.write(file_path, arcname=arcname) |
| return zip_buffer.getvalue() |
|
|
| |
| st.set_page_config(page_title="Hugging Face Space Tools", page_icon="🛠️") |
|
|
| st.title("🛠️ ابزارهای مدیریت اسپیس هاگینگفیس") |
|
|
| |
| tab1, tab2 = st.tabs(["🔄 انتقال به گیتهاب", "📦 دانلود اسپیس (فایل ZIP)"]) |
|
|
| |
| |
| |
| with tab1: |
| st.info("منبع خود را برای انتقال به گیتهاب انتخاب کنید:") |
| |
| |
| source_type = st.radio("نوع منبع:", ["لینک اسپیس هاگینگفیس", "آپلود فایل ZIP"]) |
| |
| with st.form("transfer_form"): |
| hf_url = "" |
| uploaded_zip = None |
| |
| if source_type == "لینک اسپیس هاگینگفیس": |
| hf_url = st.text_input("لینک صفحه اسپیس هاگینگ فیس (منبع)", |
| placeholder="https://huggingface.co/spaces/user/space") |
| else: |
| uploaded_zip = st.file_uploader("آپلود فایل ZIP (منبع)", type=["zip"]) |
| |
| st.markdown("---") |
| gh_url = st.text_input("لینک کامل ریپازیتوری گیتهاب (مقصد)", |
| placeholder="https://github.com/Hamed744/Zirnavis.git") |
| |
| gh_token = st.text_input("توکن گیتهاب (Classic Token)", type="password") |
| |
| submitted = st.form_submit_button("شروع عملیات انتقال 🚀") |
|
|
| if submitted: |
| if not gh_url or not gh_token: |
| st.error("لطفاً لینک گیتهاب و توکن را وارد کنید.") |
| elif source_type == "لینک اسپیس هاگینگفیس" and not hf_url: |
| st.error("لطفاً لینک اسپیس را وارد کنید.") |
| elif source_type == "لینک اسپیس هاگینگفیس" and "hf.space" in hf_url: |
| st.error("❌ لینک اشتباه است! لطفاً لینک اصلی پروفایل را وارد کنید.") |
| elif source_type == "آپلود فایل ZIP" and not uploaded_zip: |
| st.error("لطفاً فایل ZIP را آپلود کنید.") |
| else: |
| status_area = st.empty() |
| temp_dir = "temp_repo_gh" |
| |
| if os.path.exists(temp_dir): |
| shutil.rmtree(temp_dir, ignore_errors=True) |
| |
| try: |
| auth_gh_url = gh_url.replace("https://", f"https://{gh_token}@") |
| |
| |
| if source_type == "لینک اسپیس هاگینگفیس": |
| status_area.info("📥 در حال دانلود از هاگینگ فیس...") |
| success, msg = run_command(f"git clone {hf_url} {temp_dir}") |
| if not success: |
| st.error(f"خطا در دانلود: {msg}") |
| st.stop() |
| else: |
| status_area.info("📥 در حال استخراج فایل ZIP...") |
| os.makedirs(temp_dir, exist_ok=True) |
| with zipfile.ZipFile(uploaded_zip, 'r') as zip_ref: |
| zip_ref.extractall(temp_dir) |
| |
| |
| |
| extracted_items = [item for item in os.listdir(temp_dir) if item != '__MACOSX'] |
| |
| |
| if len(extracted_items) == 1: |
| single_folder_path = os.path.join(temp_dir, extracted_items[0]) |
| if os.path.isdir(single_folder_path): |
| |
| for item in os.listdir(single_folder_path): |
| shutil.move(os.path.join(single_folder_path, item), temp_dir) |
| |
| os.rmdir(single_folder_path) |
| |
| |
| os.chdir(temp_dir) |
| status_area.info("⚙️ در حال تنظیمات گیت...") |
| |
| if os.path.exists(".git"): |
| shutil.rmtree(".git", ignore_errors=True) |
| |
| run_command("git init") |
| run_command("git add .") |
| run_command('git config user.email "bot@transfer.com"') |
| run_command('git config user.name "Transfer Bot"') |
| run_command('git commit -m "Moved to GitHub automatically"') |
| run_command("git branch -M main") |
| |
| status_area.info("📤 در حال آپلود به گیتهاب...") |
| push_success, push_msg = run_command(f"git push -f {auth_gh_url} main") |
| |
| if push_success: |
| st.success("✅ تمام شد! فایلها دقیقاً در روت ریپازیتوری منتقل شدند.") |
| st.balloons() |
| else: |
| clean_error = push_msg.replace(gh_token, "***") |
| st.error(f"خطا در آپلود: {clean_error}") |
| |
| os.chdir("..") |
| |
| except Exception as e: |
| st.error(f"خطای سیستمی: {e}") |
| finally: |
| try: |
| if os.getcwd().endswith(temp_dir): |
| os.chdir("..") |
| except: |
| pass |
| if os.path.exists(temp_dir): |
| shutil.rmtree(temp_dir, ignore_errors=True) |
|
|
| |
| |
| |
| with tab2: |
| st.info("با استفاده از این بخش میتوانید کل فایلهای یک اسپیس عمومی را به صورت ZIP دانلود کنید.") |
| |
| hf_url_zip = st.text_input("لینک صفحه اسپیس هاگینگ فیس", |
| placeholder="https://huggingface.co/spaces/elias207/zirnavis52", key="zip_url") |
| |
| zip_mode = st.radio("ساختار فایل ZIP خروجی را انتخاب کنید:", |
| ("حفظ ساختار پوشهها (فایلها در پوشههای اصلی خودشان)", |
| "همه فایلها در روت (حذف پوشهبندی و انتقال همه فایلها به روت زیپ)")) |
|
|
| if st.button("آمادهسازی فایل دانلود 🗜️"): |
| if not hf_url_zip: |
| st.error("لطفاً لینک اسپیس را وارد کنید.") |
| elif "hf.space" in hf_url_zip: |
| st.error("❌ لینک اشتباه است! لینک اصلی (huggingface.co/spaces/...) را وارد کنید.") |
| else: |
| status_zip = st.empty() |
| temp_dir_zip = "temp_repo_zip" |
| |
| if os.path.exists(temp_dir_zip): |
| shutil.rmtree(temp_dir_zip, ignore_errors=True) |
| |
| try: |
| status_zip.info("📥 در حال دریافت فایلها از هاگینگفیس...") |
| success, msg = run_command(f"git clone {hf_url_zip} {temp_dir_zip}") |
| |
| if not success: |
| st.error(f"خطا در دریافت فایلها: {msg}") |
| else: |
| status_zip.info("⚙️ در حال فشردهسازی فایلها...") |
| flatten_files = True if zip_mode == "همه فایلها در روت (حذف پوشهبندی و انتقال همه فایلها به روت زیپ)" else False |
| zip_data = create_zip_buffer(temp_dir_zip, flatten=flatten_files) |
| |
| status_zip.success("✅ فایل با موفقیت آماده شد!") |
| |
| repo_name = hf_url_zip.strip("/").split("/")[-1] |
| file_suffix = "flat" if flatten_files else "structured" |
| download_filename = f"{repo_name}_{file_suffix}.zip" |
| |
| st.download_button( |
| label="⬇️ دانلود فایل ZIP", |
| data=zip_data, |
| file_name=download_filename, |
| mime="application/zip", |
| type="primary" |
| ) |
| |
| except Exception as e: |
| st.error(f"خطای سیستمی: {e}") |
| finally: |
| if os.path.exists(temp_dir_zip): |
| shutil.rmtree(temp_dir_zip, ignore_errors=True) |
|
|