|
|
@@ -1,121 +1,134 @@
|
|
|
# CLAUDE.md
|
|
|
+
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
|
|
## Project Overview
|
|
|
|
|
|
-VMess domain rotator - automated pipeline that fetches preferred domains from an API, selects the best candidate, and exports runtime files for Sub-Store and V2Ray integration.
|
|
|
+VMess domain rotator: fetch candidate domains from an API, select a preferred domain, write runtime artifacts, and optionally auto-commit runtime changes to a dedicated branch.
|
|
|
|
|
|
-## Key Commands
|
|
|
+## Common Commands
|
|
|
|
|
|
-### Development
|
|
|
+### Validate scripts
|
|
|
```bash
|
|
|
-# Syntax check Python scripts
|
|
|
python3 -m py_compile scripts/domain_updater.py
|
|
|
python3 -m py_compile scripts/update_vmess_links.py
|
|
|
+```
|
|
|
|
|
|
-# Manual run (single update)
|
|
|
+### Run domain selection once
|
|
|
+```bash
|
|
|
python3 scripts/domain_updater.py --config config.json
|
|
|
+```
|
|
|
|
|
|
-# Manual run with conditional git commit (commits only if domain changed)
|
|
|
+### Run scheduler entrypoint with conditional git commit
|
|
|
+```bash
|
|
|
bash scripts/run_update_and_commit.sh config.json
|
|
|
+```
|
|
|
|
|
|
-# Update VMess base64 links with selected domain
|
|
|
-python3 scripts/update_vmess_links.py --input ./nodes.txt --output ./nodes.updated.txt --domain-file ./runtime/current_domain.txt
|
|
|
+### Update VMess links from selected domain
|
|
|
+```bash
|
|
|
+python3 scripts/update_vmess_links.py \
|
|
|
+ --input ./nodes.txt \
|
|
|
+ --output ./nodes.updated.txt \
|
|
|
+ --domain-file ./runtime/current_domain.txt
|
|
|
+```
|
|
|
|
|
|
-# Update specific nodes by regex
|
|
|
-python3 scripts/update_vmess_links.py --input ./nodes.txt --output ./nodes.updated.txt --domain-file ./runtime/current_domain.txt --name-regex "(argo|cf|vm)"
|
|
|
+### Update only matching node names
|
|
|
+```bash
|
|
|
+python3 scripts/update_vmess_links.py \
|
|
|
+ --input ./nodes.txt \
|
|
|
+ --output ./nodes.updated.txt \
|
|
|
+ --domain-file ./runtime/current_domain.txt \
|
|
|
+ --name-regex "(argo|cf|vm)"
|
|
|
+```
|
|
|
|
|
|
-# Local smoke test HTTP endpoint for runtime outputs
|
|
|
+### Local runtime smoke test
|
|
|
+```bash
|
|
|
python3 -m http.server 8080 --directory runtime
|
|
|
+curl http://127.0.0.1:8080/current_domain.json
|
|
|
```
|
|
|
|
|
|
-### Deployment (Debian)
|
|
|
+### Debian systemd install/uninstall
|
|
|
```bash
|
|
|
-# Install systemd service+timer (uses current git repo directory)
|
|
|
sudo bash scripts/install_debian.sh
|
|
|
-
|
|
|
-# Install with custom timer interval
|
|
|
sudo bash scripts/install_debian.sh --interval 5min
|
|
|
-
|
|
|
-# Uninstall (keeps git repository and files)
|
|
|
+sudo bash scripts/install_debian.sh --git-push 0
|
|
|
+sudo bash scripts/install_debian.sh --git-http-username aurora --git-http-token-file /root/.config/vmess-token --git-use-credential-store 1
|
|
|
sudo bash scripts/uninstall_debian.sh
|
|
|
+sudo bash scripts/uninstall_debian.sh --keep-auth-files
|
|
|
```
|
|
|
|
|
|
-## Architecture
|
|
|
-
|
|
|
-### Core Flow
|
|
|
-1. `scripts/domain_updater.py` - Main entrypoint that:
|
|
|
- - Fetches domain candidates from API (configured in `config.json`)
|
|
|
- - Parses response using JSON path or regex
|
|
|
- - Optionally scores candidates based on API fields
|
|
|
- - Optionally healthchecks domains (TLS handshake)
|
|
|
- - Selects best domain and writes runtime outputs
|
|
|
- - Falls back to `last_good_domain` from state.json if all checks fail
|
|
|
-
|
|
|
-2. `scripts/run_update_and_commit.sh` - Scheduler entrypoint that:
|
|
|
- - Runs domain_updater.py
|
|
|
- - Compares before/after domain
|
|
|
- - Commits to `runtime-state` branch if domain changed
|
|
|
- - Pushes to remote if configured
|
|
|
-
|
|
|
-3. `scripts/update_vmess_links.py` - Post-processor for VMess subscription links:
|
|
|
- - Decodes vmess:// base64 payloads
|
|
|
- - Updates `add` field with selected domain
|
|
|
- - Supports node name filtering by regex
|
|
|
-
|
|
|
-### Configuration Structure
|
|
|
-- `config.json` - Single runtime config file containing:
|
|
|
- - `api`: endpoint URL, method, headers, timeout
|
|
|
- - `parser`: JSON paths (`field_paths`) or regex for extracting domains
|
|
|
- - `domain_filter`: include/exclude patterns (e.g., filter out IPv4 addresses)
|
|
|
- - `scoring`: ranking logic based on API fields or API order
|
|
|
- - `healthcheck`: TLS handshake verification settings
|
|
|
- - `selection`: top_n candidates to consider
|
|
|
- - `output`: runtime directory and file paths
|
|
|
- - `v2ray`: template file token replacement (optional)
|
|
|
-
|
|
|
-### Output Files
|
|
|
-All runtime outputs are written to `runtime/`:
|
|
|
-- `current_domain.txt` - Plain text domain
|
|
|
-- `current_domain.json` - JSON payload with domain, timestamp, status, source_count
|
|
|
-- `state.json` - Persistent state including `last_good_domain` for fallback
|
|
|
-- `substore_vars.json` - Variables for Sub-Store operator scripts
|
|
|
-
|
|
|
-### Sub-Store Integration
|
|
|
-`substore/operator_template.js` - Operator script that:
|
|
|
-- Fetches `current_domain.json` via HTTP using `$substore.http.get`
|
|
|
-- Caches domain with TTL (5 minutes by default)
|
|
|
-- Replaces VMess `server` field for nodes matching `NODE_NAME_REGEX`
|
|
|
-- Must be configured with actual DOMAIN_JSON_URL in production
|
|
|
-
|
|
|
-### Systemd Deployment
|
|
|
-- Service runs `run_update_and_commit.sh` oneshot
|
|
|
-- Timer triggers every 1h by default (configurable via install_debian.sh)
|
|
|
-- Uses current git repository directory (in-place mode only)
|
|
|
-- Uses the installing user (from SUDO_USER) as service user
|
|
|
-- Runtime state committed to `runtime-state` branch
|
|
|
-- No separate service user created - uses existing user's git credentials
|
|
|
-
|
|
|
-## Important Behaviors
|
|
|
-
|
|
|
-- **Fallback**: If all healthchecks fail, script uses `last_good_domain` from `runtime/state.json`
|
|
|
-- **Conditional commits**: `run_update_and_commit.sh` only commits when domain actually changes
|
|
|
-- **Branch separation**: Runtime state goes to `runtime-state` branch via git worktree
|
|
|
-- **API order mode**: For vps789 Top20, set `scoring.use_api_order=true` to trust API ranking
|
|
|
-- **Domain filtering**: Use `domain_filter.exclude_regex` to filter out IPv4 addresses when API returns mixed results
|
|
|
-- **Sub-Store caching**: Operator uses `scriptResourceCache` with TTL to avoid excessive HTTP requests
|
|
|
-
|
|
|
-## Configuration Notes
|
|
|
-
|
|
|
-For vps789 Top20 API specifically:
|
|
|
-- Use `parser.field_paths: ["data.good[].ip"]`
|
|
|
-- Enable `scoring.use_api_order: true` to respect API ranking
|
|
|
-- Set `healthcheck.enabled: false` if you want pure API-based selection
|
|
|
-- Add IPv4 exclude regex to `domain_filter.exclude_regex` to filter out IP addresses
|
|
|
-
|
|
|
-## Git Workflow
|
|
|
-
|
|
|
-- Main branch: `main` (source code)
|
|
|
-- Runtime branch: `runtime-state` (auto-committed domain updates)
|
|
|
-- Commits to runtime-state use generic git identity: `vmess-domain-rotator@localhost`
|
|
|
-- Script creates runtime-state branch automatically if missing
|
|
|
+## Testing and verification status
|
|
|
+
|
|
|
+- There is currently no dedicated `tests/` directory or unit test suite.
|
|
|
+- Primary verification is Python syntax check (`py_compile`) plus manual script runs.
|
|
|
+
|
|
|
+## Architecture (big picture)
|
|
|
+
|
|
|
+### 1) Domain selection pipeline
|
|
|
+`scripts/domain_updater.py` is the core pipeline:
|
|
|
+- Calls the configured API (`api` block in `config.json`).
|
|
|
+- Extracts candidates via `parser.field_paths`, `parser.json_paths`, or regex fallback.
|
|
|
+- Normalizes and de-duplicates domains/IPs.
|
|
|
+- Applies include/exclude filtering (`domain_filter`).
|
|
|
+- Optionally ranks records (`scoring`) using API fields/time windows or API order.
|
|
|
+- Optionally healthchecks candidates with TLS handshake (`healthcheck`).
|
|
|
+- Selects winner from scored/check results (`selection.top_n`).
|
|
|
+- Writes runtime artifacts under `runtime/`.
|
|
|
+- Falls back to `last_good_domain` from `runtime/state.json` when selection fails.
|
|
|
+
|
|
|
+### 2) Runtime-state git automation
|
|
|
+`scripts/run_update_and_commit.sh` wraps the updater and git workflow:
|
|
|
+- Resolves git top-level robustly and skips commit if service is not running inside a git repo.
|
|
|
+- Skips commit if domain unchanged or empty.
|
|
|
+- Commits only runtime outputs (`runtime/current_domain.txt`, `runtime/current_domain.json`, `runtime/state.json`, `runtime/substore_vars.json`).
|
|
|
+- Targets `runtime-state` branch (configurable via `GIT_RUNTIME_BRANCH`) and includes a branch safety check before staging.
|
|
|
+- Uses a temporary git worktree when current branch is not `runtime-state`.
|
|
|
+- Supports non-interactive push auth in two modes:
|
|
|
+ - credential helper mode (`GIT_CREDENTIAL_HELPER`, e.g. `store`)
|
|
|
+ - header mode (`GIT_HTTP_USERNAME` + `GIT_HTTP_TOKEN`/`GIT_HTTP_TOKEN_FILE`)
|
|
|
+- `GIT_PUSH_REQUIRED` defaults to `GIT_PUSH_ENABLED`; when enabled, push failure returns non-zero for systemd visibility.
|
|
|
+- Disables interactive git prompts via `GIT_TERMINAL_PROMPT=0` to avoid systemd hangs.
|
|
|
+
|
|
|
+
|
|
|
+### 3) VMess subscription post-processing
|
|
|
+`scripts/update_vmess_links.py`:
|
|
|
+- Reads subscription lines (plain text or full base64 subscription).
|
|
|
+- Decodes each `vmess://` payload JSON.
|
|
|
+- Replaces `add` field with selected domain.
|
|
|
+- Optionally filters by node name regex (`ps` field).
|
|
|
+- Re-encodes output and prints JSON summary stats.
|
|
|
+
|
|
|
+### 4) Sub-Store runtime consumer
|
|
|
+`substore/operator_template.js`:
|
|
|
+- Fetches `runtime/current_domain.json` over HTTP.
|
|
|
+- Caches domain in `scriptResourceCache` (default TTL 5 min).
|
|
|
+- Rewrites VMess `server` for matched node names.
|
|
|
+
|
|
|
+## Config model (`config.json`)
|
|
|
+
|
|
|
+Key top-level blocks:
|
|
|
+- `api`: endpoint/method/headers/body/timeout
|
|
|
+- `parser`: domain extraction paths/regex
|
|
|
+- `domain_filter`: include suffixes / exclude regex
|
|
|
+- `scoring`: record ranking fields and strategy
|
|
|
+- `healthcheck`: TLS probe settings
|
|
|
+- `selection`: candidate cut (`top_n`)
|
|
|
+- `output`: runtime file names/paths
|
|
|
+- `v2ray`: optional token replacement rendering
|
|
|
+- `notify`: optional post-run command (`AUTODOMAIN`, `AUTODOMAIN_STATUS` env vars)
|
|
|
+
|
|
|
+## Runtime artifacts
|
|
|
+
|
|
|
+Generated in `runtime/`:
|
|
|
+- `current_domain.txt`: selected domain (plain text)
|
|
|
+- `current_domain.json`: selected domain + status + metadata
|
|
|
+- `state.json`: persistent state, including `last_good_domain`
|
|
|
+- `substore_vars.json`: export-friendly variables
|
|
|
+
|
|
|
+## Operational behavior that matters
|
|
|
+
|
|
|
+- Fallback behavior is stateful: `last_good_domain` persistence is critical for resilience.
|
|
|
+- `runtime-state` branch is intended to isolate frequently changing runtime outputs from `main` source history.
|
|
|
+- Debian installer (`scripts/install_debian.sh`) writes `/etc/vmess-domain-rotator.env` (service env), configures oneshot service+timer, and can store HTTPS token in `/var/lib/vmess-domain-rotator/git_http_token`.
|
|
|
+- For non-interactive systemd runs, prefer SSH deploy key or installer-provided HTTPS token env configuration.
|
|
|
+- Uninstaller removes systemd units and, by default, removes service auth/env files unless `--keep-auth-files` is set.
|