[A] configGen
This commit is contained in:
84
CLAUDE.md
Normal file
84
CLAUDE.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Config-Man is a Python CLI tool for managing encrypted static configuration files stored in object storage with Cloudflare CDN distribution. It's primarily used for game application configuration management with support for multi-version management and update strategies.
|
||||||
|
|
||||||
|
## Code Architecture
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
- `src/config_man/core/` - Core business logic modules:
|
||||||
|
- `config_manager.py` - Handles storage and CDN configuration file operations
|
||||||
|
- `display_manager.py` - Manages configuration display and comparison
|
||||||
|
- `view_command.py` - Implements the view command functionality
|
||||||
|
- `suggest_update_command.py` - Implements the suggest-update command functionality
|
||||||
|
- `force_update_command.py` - Implements the force-update command functionality
|
||||||
|
|
||||||
|
### CLI Layer
|
||||||
|
- `src/config_man/cli/main.py` - Main CLI entry point using Click framework
|
||||||
|
- Commands: view, suggest-update, force-update, show-config, setup-cloudflare, set-config
|
||||||
|
|
||||||
|
### Utilities
|
||||||
|
- `src/config_man/utils/` - Utility modules for crypto, config management, and mock functionality
|
||||||
|
|
||||||
|
## Common Development Commands
|
||||||
|
|
||||||
|
### Installation and Setup
|
||||||
|
```bash
|
||||||
|
# Install dependencies
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Install in development mode
|
||||||
|
pip install -e .
|
||||||
|
|
||||||
|
# Install with development dependencies
|
||||||
|
pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running the CLI
|
||||||
|
```bash
|
||||||
|
# Run the CLI tool
|
||||||
|
python main.py --help
|
||||||
|
|
||||||
|
# Or if installed
|
||||||
|
config-man --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
```bash
|
||||||
|
# Run all tests
|
||||||
|
pytest
|
||||||
|
|
||||||
|
# Run tests with coverage
|
||||||
|
pytest --cov=src/config_man
|
||||||
|
|
||||||
|
# Run tests with coverage report
|
||||||
|
pytest --cov=src/config_man --cov-report=html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Quality
|
||||||
|
```bash
|
||||||
|
# Format code with black
|
||||||
|
black .
|
||||||
|
|
||||||
|
# Lint with flake8
|
||||||
|
flake8 .
|
||||||
|
|
||||||
|
# Type checking with mypy
|
||||||
|
mypy src/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
- Uses `config-man.json` for runtime configuration
|
||||||
|
- Supports environment variables for Cloudflare CDN settings
|
||||||
|
- Configuration can be modified with `config-man set-config` command
|
||||||
|
|
||||||
|
## Key Dependencies
|
||||||
|
- click>=8.0.0 - CLI framework
|
||||||
|
- pycryptodome>=3.19.0 - Encryption/decryption
|
||||||
|
- tabulate>=0.9.0 - Table formatting
|
||||||
|
- requests>=2.31.0 - HTTP requests
|
||||||
|
- rich>=13.0.0 - Rich text formatting
|
||||||
|
- rclone - Required for storage operations
|
||||||
162
configGen.py
Executable file
162
configGen.py
Executable file
@@ -0,0 +1,162 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Config Generator Tool
|
||||||
|
|
||||||
|
读取加密的 'androidconfig.json' 或 'iosconfig.json' 文件,
|
||||||
|
生成新的加密配置文件,支持添加建议更新版本号或强制更新版本号。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.syntax import Syntax
|
||||||
|
from rich import print as rprint
|
||||||
|
|
||||||
|
# Add the src directory to the path so we can import the crypto module
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent / "src"))
|
||||||
|
|
||||||
|
from config_man.utils.crypto import encrypt, decrypt
|
||||||
|
|
||||||
|
# Initialize rich console
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
|
||||||
|
def load_encrypted_config(file_path):
|
||||||
|
"""Load and decrypt a configuration file"""
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
encrypted_content = f.read().strip()
|
||||||
|
|
||||||
|
if not encrypted_content:
|
||||||
|
console.print(f"[red]错误: 文件 {file_path} 为空[/red]")
|
||||||
|
return None
|
||||||
|
|
||||||
|
decrypted_content = decrypt(encrypted_content)
|
||||||
|
config_data = json.loads(decrypted_content)
|
||||||
|
return config_data
|
||||||
|
except FileNotFoundError:
|
||||||
|
console.print(f"[red]错误: 文件 {file_path} 不存在[/red]")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
console.print(f"[red]错误: 无法读取或解密文件 {file_path}: {str(e)}[/red]")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def save_encrypted_config(config_data, file_path):
|
||||||
|
"""Encrypt and save a configuration file"""
|
||||||
|
try:
|
||||||
|
# Convert config data to JSON string
|
||||||
|
config_json = json.dumps(config_data, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
|
# Encrypt the content
|
||||||
|
encrypted_content = encrypt(config_json)
|
||||||
|
|
||||||
|
# Save to file
|
||||||
|
with open(file_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(encrypted_content)
|
||||||
|
|
||||||
|
console.print(f"[green]✅ 配置文件已保存到: {file_path}[/green]")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
console.print(f"[red]错误: 无法保存文件 {file_path}: {str(e)}[/red]")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def add_suggest_update(config_data, update_version):
|
||||||
|
"""Add suggest update version (Ver_New) to config"""
|
||||||
|
# Show before and after
|
||||||
|
console.print(Panel("更新前的配置", title="🔄 更新前", border_style="blue"))
|
||||||
|
console.print(Syntax(json.dumps(config_data, ensure_ascii=False, indent=2), "json", theme="monokai"))
|
||||||
|
|
||||||
|
# Get the Ver value from the update version config
|
||||||
|
# For now, we'll just add the version string as Ver_New
|
||||||
|
config_data["Ver_New"] = update_version
|
||||||
|
|
||||||
|
console.print(Panel("更新后的配置", title="✅ 更新后", border_style="green"))
|
||||||
|
console.print(Syntax(json.dumps(config_data, ensure_ascii=False, indent=2), "json", theme="monokai"))
|
||||||
|
|
||||||
|
console.print(f"✅ 已添加建议更新版本: {update_version}")
|
||||||
|
return config_data
|
||||||
|
|
||||||
|
|
||||||
|
def add_force_update(config_data, update_version):
|
||||||
|
"""Add force update version (Ver) to config"""
|
||||||
|
# Show before and after
|
||||||
|
console.print(Panel("更新前的配置", title="🔄 更新前", border_style="blue"))
|
||||||
|
console.print(Syntax(json.dumps(config_data, ensure_ascii=False, indent=2), "json", theme="monokai"))
|
||||||
|
|
||||||
|
# Update the Ver field
|
||||||
|
config_data["Ver"] = update_version
|
||||||
|
|
||||||
|
console.print(Panel("更新后的配置", title="✅ 更新后", border_style="green"))
|
||||||
|
console.print(Syntax(json.dumps(config_data, ensure_ascii=False, indent=2), "json", theme="monokai"))
|
||||||
|
|
||||||
|
console.print(f"✅ 已更新强制版本为: {update_version}")
|
||||||
|
return config_data
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
console.print(Panel("🔧 Config Generator Tool", expand=False, border_style="bold blue"))
|
||||||
|
|
||||||
|
# Get input file path
|
||||||
|
while True:
|
||||||
|
input_file = input("请输入要读取的加密配置文件路径 (如: androidconfig.json): ").strip()
|
||||||
|
if input_file and os.path.exists(input_file):
|
||||||
|
break
|
||||||
|
console.print("[red]❌ 文件不存在,请重新输入[/red]")
|
||||||
|
|
||||||
|
# Load and decrypt the config file
|
||||||
|
console.print(f"[blue]正在读取配置文件: {input_file}[/blue]")
|
||||||
|
config_data = load_encrypted_config(input_file)
|
||||||
|
if config_data is None:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
console.print("[green]✅ 配置文件读取成功[/green]")
|
||||||
|
console.print(f"[cyan]当前版本: {config_data.get('Ver', 'N/A')}[/cyan]")
|
||||||
|
|
||||||
|
# Get update type
|
||||||
|
while True:
|
||||||
|
update_type = input("\n请选择更新类型 (1: 建议更新, 2: 强制更新): ").strip()
|
||||||
|
if update_type in ['1', '2']:
|
||||||
|
break
|
||||||
|
console.print("[red]❌ 请输入 1 或 2[/red]")
|
||||||
|
|
||||||
|
# Get update version
|
||||||
|
update_version = input("请输入更新版本号 (如: 0.30): ").strip()
|
||||||
|
if not update_version:
|
||||||
|
console.print("[red]❌ 版本号不能为空[/red]")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Apply update
|
||||||
|
if update_type == '1':
|
||||||
|
config_data = add_suggest_update(config_data, update_version)
|
||||||
|
else:
|
||||||
|
config_data = add_force_update(config_data, update_version)
|
||||||
|
|
||||||
|
# Get output file path
|
||||||
|
default_output = f"new_{os.path.basename(input_file)}"
|
||||||
|
output_file = input(f"\n请输入输出文件路径 (默认: {default_output}): ").strip()
|
||||||
|
if not output_file:
|
||||||
|
output_file = default_output
|
||||||
|
|
||||||
|
# Save the new encrypted config
|
||||||
|
console.print(f"[blue]正在保存配置文件: {output_file}[/blue]")
|
||||||
|
if save_encrypted_config(config_data, output_file):
|
||||||
|
console.print(Panel("🎉 配置文件生成完成!", expand=False, border_style="bold green"))
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
sys.exit(main())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n\n👋 已取消操作")
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n❌ 程序执行出错: {str(e)}")
|
||||||
|
sys.exit(1)
|
||||||
Reference in New Issue
Block a user