From e71f9608c36e7ea72c31310aa6d863dd6e6eba91 Mon Sep 17 00:00:00 2001 From: sindoring Date: Thu, 26 Mar 2026 07:40:13 +0400 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=B5=D0=BF=D0=BB=D0=BE=D0=B9=20=D0=BF?= =?UTF-8?q?=D0=B0=D1=82=D1=87=D0=B5=D0=B9=20=D0=BD=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 9 +++- .gitignore | 5 ++- run.ps1 | 14 +++++- upload_to_s3.py | 117 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 upload_to_s3.py diff --git a/.env.example b/.env.example index 07b52ea..96f07f9 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,8 @@ -WOW_HOME=C:\Games\World of Warcraft 3.3.5 \ No newline at end of file +WOW_HOME=C:\Games\World of Warcraft 3.3.5 + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION= +AWS_BUCKET= +AWS_ENDPOINT= +AWS_USE_PATH_STYLE_ENDPOINT= \ No newline at end of file diff --git a/.gitignore b/.gitignore index ac8ded1..f914e60 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .env __pycache__/ -manifest.json \ No newline at end of file +manifest.json +.claude +.vscode +dist \ No newline at end of file diff --git a/run.ps1 b/run.ps1 index baa45fe..58d72db 100644 --- a/run.ps1 +++ b/run.ps1 @@ -32,14 +32,17 @@ $WOW_HOME = $env:WOW_HOME Write-Host "WOW_HOME = $WOW_HOME" # --- Paths +$DIST_DIR = Join-Path $ROOT "dist" # --- patch-ruRU-4 $INPUT_DIR_4 = Join-Path $ROOT "patch-ruRU-4" $OUTPUT_MPQ_4 = Join-Path $WOW_HOME "Data\ruRU\patch-ruRU-4.MPQ" +$DIST_MPQ_4 = Join-Path $DIST_DIR "Data\ruRU\patch-ruRU-4.MPQ" # --- patch-ruRU-5 $INPUT_DIR_5 = Join-Path $ROOT "patch-ruRU-5" $OUTPUT_MPQ_5 = Join-Path $WOW_HOME "Data\ruRU\patch-ruRU-5.MPQ" +$DIST_MPQ_5 = Join-Path $DIST_DIR "Data\ruRU\patch-ruRU-5.MPQ" $TOOL = Join-Path $ROOT "tool\target\release\tool.exe" $RELOAD_SCRIPT = Join-Path $ROOT "reload_wow.bat" @@ -52,11 +55,15 @@ if (!(Test-Path $TOOL)) { Pop-Location } -# --- Ensure WoW directory exists +# --- Ensure directories exist $wowDataDir = Join-Path $WOW_HOME "Data\ruRU" if (!(Test-Path $wowDataDir)) { New-Item -ItemType Directory -Force -Path $wowDataDir | Out-Null } +$distDataDir = Join-Path $DIST_DIR "Data\ruRU" +if (!(Test-Path $distDataDir)) { + New-Item -ItemType Directory -Force -Path $distDataDir | Out-Null +} # --- Build MPQ Write-Host "Building MPQ..." @@ -69,6 +76,11 @@ if (!(Test-Path $OUTPUT_MPQ_5)) { exit 1 } +# --- Copy to dist +Write-Host "Copying to dist..." +Copy-Item -Force $OUTPUT_MPQ_4 $DIST_MPQ_4 +Copy-Item -Force $OUTPUT_MPQ_5 $DIST_MPQ_5 + Write-Host "MPQ created" # --- Run WoW reload script diff --git a/upload_to_s3.py b/upload_to_s3.py new file mode 100644 index 0000000..c2ef960 --- /dev/null +++ b/upload_to_s3.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import sys +from pathlib import Path + +import boto3 +from botocore.config import Config + +S3_PREFIX = "World of Warcraft" +MANIFEST_S3_KEY = "manifest.json" + + +def load_dotenv(env_path: Path) -> dict[str, str]: + values: dict[str, str] = {} + if not env_path.exists(): + return values + for raw_line in env_path.read_text(encoding="utf-8").splitlines(): + line = raw_line.strip() + if not line or line.startswith("#") or "=" not in line: + continue + key, value = line.split("=", 1) + key = key.strip() + value = value.strip() + if key.startswith("export "): + key = key.removeprefix("export ").strip() + if not key: + continue + if len(value) >= 2 and value[0] == value[-1] and value[0] in {"'", '"'}: + value = value[1:-1] + values[key] = value + return values + + +def get_env(dotenv: dict[str, str], key: str) -> str: + value = os.environ.get(key) or dotenv.get(key) + if not value: + print(f"ERROR: {key} is not set (env or .env)", file=sys.stderr) + sys.exit(1) + return value + + +def main() -> int: + project_root = Path(__file__).resolve().parent + dotenv = load_dotenv(project_root / ".env") + + bucket = get_env(dotenv, "AWS_BUCKET") + endpoint = get_env(dotenv, "AWS_ENDPOINT") + region = get_env(dotenv, "AWS_DEFAULT_REGION") + access_key = get_env(dotenv, "AWS_ACCESS_KEY_ID") + secret_key = get_env(dotenv, "AWS_SECRET_ACCESS_KEY") + use_path_style = get_env(dotenv, "AWS_USE_PATH_STYLE_ENDPOINT").lower() == "true" + + s3 = boto3.client( + "s3", + endpoint_url=endpoint, + region_name=region, + aws_access_key_id=access_key, + aws_secret_access_key=secret_key, + config=Config(s3={"addressing_style": "path"}) if use_path_style else None, + ) + + dist_dir = project_root / "dist" + if not dist_dir.exists(): + print(f"ERROR: dist/ directory not found. Run build first.", file=sys.stderr) + return 1 + + errors = False + + # Загрузка всех файлов из dist/ с сохранением относительных путей + files = sorted(f for f in dist_dir.rglob("*") if f.is_file()) + if not files: + print("ERROR: dist/ is empty, nothing to upload.", file=sys.stderr) + return 1 + + for local_path in files: + rel_path = local_path.relative_to(dist_dir).as_posix() + s3_key = f"{S3_PREFIX}/{rel_path}" + size_mb = local_path.stat().st_size / (1024 * 1024) + print(f"Uploading {rel_path} ({size_mb:.1f} MB) -> s3://{bucket}/{s3_key}") + try: + s3.upload_file(str(local_path), bucket, s3_key) + print(f" OK") + except Exception as e: + print(f" ERROR: {e}", file=sys.stderr) + errors = True + + # Загрузка манифеста + manifest_path = project_root / "manifest.json" + if not manifest_path.exists(): + print(f"ERROR: manifest.json not found", file=sys.stderr) + return 1 + + print(f"Uploading manifest.json -> s3://{bucket}/{MANIFEST_S3_KEY}") + try: + s3.upload_file( + str(manifest_path), + bucket, + MANIFEST_S3_KEY, + ExtraArgs={"ContentType": "application/json"}, + ) + print(f" OK") + except Exception as e: + print(f" ERROR: {e}", file=sys.stderr) + errors = True + + if errors: + print("\nFinished with errors.") + return 1 + + print("\nAll uploads completed successfully.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())