Commit Graph
29 Commits
Author SHA1 Message Date
rogeeandmultica-agent 3b059b974c fix: sanitize subscription download errors
Build and Publish Docker Image / build-and-push (pull_request) Failing after 28m52s
Co-authored-by: multica-agent <github@multica.ai>
2026-08-26 14:00:34 +08:00
rogeeandmultica-agent e356b7cc2a fix: propagate subscription fetch failures
Build and Publish Docker Image / build-and-push (pull_request) Failing after 37m0s
Co-authored-by: multica-agent <github@multica.ai>
2026-08-26 11:07:30 +08:00
rogee c73c2b55cd refactor: rename reads cached egress geo, fallback name-only (no DNS)
RenameCollectionNodes now reads geo info from cached egress-probe fields (country, countryCode, city, flag) on each node instead of doing per-node DNS lookups via DetectGeoWithServer.

When no cached egress data is available (probe not yet run), it falls back to name-based regex only (DetectGeo, no DNS) so the UI is never blocked. The background egress probe (triggered on source create/update) populates the cache asynchronously.

Also: runEgressProbe now stores countryCode and flag emoji from ipwho.is response. egressCacheKey and addCachedEgressInfo updated to include the new fields.

Reverted previous name-first hack on DetectGeoWithServer and DNS cache on geoip.LookupHost — no longer needed since rename doesn't call them.

Collection preview with rename: 30s -> 52ms (with cache miss, name-based fallback).
2026-07-30 19:02:25 +08:00
rogee 8e449c8531 perf: name-first geo detection to avoid serial DNS in collection rename
DetectGeoWithServer was doing GeoIP-first (DNS lookup per node) then falling back to name regex. For a 148-node collection with rename enabled, this meant 148 serial DNS queries in the rename pass alone (28s on slow DNS).

Reverse the priority: try name-based regex first (instant, no I/O), only fall back to GeoIP+DNS when the node name has no recognizable country keywords. Most proxy names already contain country/city info.

Also add in-memory DNS cache in geoip.LookupHost so repeated lookups for the same hostname don't re-resolve.

Collection preview with rename: 30s -> 3s.
2026-07-30 18:40:18 +08:00
rogee eba9fa1be0 fix: egress cache TTL independent from fetcher cache (24h default)
Egress probe results (IP/country/region/city/isp) were cached using the
fetcher's cache_ttl (300s / 5min). After 5 minutes the cache expired and
the node list showed empty Egress IP/Country/Region fields again.

Add a dedicated egress_cache_ttl config (default 24h) so egress data
persists long enough to be useful when re-expanding the node list.
2026-07-29 17:54:15 +08:00
rogee cc38a6f0ba fix: egress cache key mismatch between source and collection preview
Add _sourceAlias and _previewId to the skip list in egressCacheKey so
that nodes from source preview (with _sourceAlias) and collection
preview (without _sourceAlias, after rename) produce the same cache
key. This ensures egress info cached during source-level probe is
visible when expanding collection cards.
2026-07-29 13:29:07 +08:00
rogee ca1f20b3f3 feat: sort collection nodes by name in final output 2026-07-29 11:49:16 +08:00
rogee 585164dca6 fix: drop nodes that fail geo detection in collection rename
Nodes whose country cannot be detected are now filtered out instead of
kept with their original name. This prevents unlabelled/unrenamed nodes
from appearing in collection output.
2026-07-29 11:19:19 +08:00
rogee 71f814d1ce fix: filter out nodes missing server/port before rendering
Nodes with port=0 or empty server cause client-side errors (e.g.
sing-box decode config failures). Filter them at the render dispatch
layer so all targets (sing-box, mihomo, surge, etc.) are protected.
2026-07-29 09:45:09 +08:00
rogee 89802cbaf8 fix: convert Clash network to sing-box transport for vless/vmess
vless outbound was passing Clash's network field (ws/grpc/h2) directly
to sing-box's network field (which only accepts tcp/udp). Extract
clashToSingBoxTransport() to convert ws/grpc/h2/quic/httpupgrade into
sing-box transport objects. Apply to both vless and vmess outbounds.
2026-07-29 07:58:56 +08:00
rogee fbe09f13de fix: egress probe mode direct→rule so traffic goes through proxy node 2026-07-28 23:16:05 +08:00
rogee 013efe967e add bridge proxy service 2026-07-28 22:49:28 +08:00
rogee 55ab656606 feat: add force refresh button to source/collection cards
- Backend: preview handlers accept forceRefresh in request body
- Frontend: Sources & Collections cards get a refresh button that
  bypasses cache and re-fetches from remote
2026-07-28 21:42:12 +08:00
rogee feafb19714 fix: mihomo proxy-group name conflict + error message 2026-07-28 19:30:38 +08:00
rogee 8d396e63d6 fix: replace sing-box with mihomo for egress probe (xhttp support)
mihomo (Clash Meta) natively supports xhttp and all Clash transports.
Build minimal mihomo YAML config directly from the proxy node instead
of converting to sing-box JSON format.
2026-07-28 19:15:11 +08:00
rogee 5f0edae6fe fix: use musl build of sing-box for Alpine 2026-07-28 18:42:03 +08:00
rogee da609e8036 fix: use %02d format for collection rename index 2026-07-28 18:24:25 +08:00
rogee 7b06156f7d fix: upgrade sing-box to v1.13.14 for xhttp transport support 2026-07-28 18:18:25 +08:00
rogee 040e3ebab1 fix: fetcher proxy support, Dockerfile sing-box, rename index format
1. sslinks 403: Cloudflare blocks server IP. Add fetcher.proxy_url config
   so subscription/flow requests can route through an HTTP proxy.

2. Egress probe: Docker image lacked sing-box. Install sing-box v1.11.4
   in the Alpine runtime stage.

3. Collection rename: group by display baseName instead of internal
   groupKey, format index as -N instead of %02d. Fixes double-suffix
   issue where EnsureUniqueProxyNames appended -2/-3 onto existing  02.
2026-07-28 17:38:57 +08:00
rogee edae8235a6 feat: add docker-compose.yaml using ghcr image 2026-07-28 15:09:51 +08:00
rogee 3671c39b7c feat: single Docker image with frontend served from backend
- Dockerfile: 3-stage build (frontend npm build → backend go build → alpine runtime)
- Frontend dist files served from disk at /app/frontend/dist
- server.go: catch-all GET handler serves static files with SPA fallback to index.html
- config.go: new server.frontend_dir option (env: SUB_STORE_SERVER_FRONTEND_DIR)
- API routes (/api/*), download routes, and /health take priority over static serving
2026-07-28 14:52:53 +08:00
rogee de9ac92ede feat: GeoIP-based geo detection + configurable rename template
- Add MaxMind GeoLite2-City mmdb auto-download and IP-based geo lookup
  (covers all 249 countries globally, replacing limited 8-country regex)
- Add RenameOptions with 5 toggleable fields (flag/alias/country/city/index)
  stored as rename_options_json on collections
- Collection rename pipeline uses DetectGeoWithServer(name, server) which
  tries GeoIP lookup first, falls back to name-based regex matching
- Chinese country/city names + emoji flag prefix
- Country-city dedup: skip city when it equals country (e.g. 香港/香港)
- URI fragment encoding: url.QueryEscape -> url.PathEscape (%20 not +)
- Egress cache key excludes name field so renamed nodes still match cache
- Frontend: 5 toggle buttons in collection edit form, default all on
- Migrations: 0004 (source alias + collection rename_enabled),
  0005 (collection rename_options_json)
2026-07-28 14:44:54 +08:00
rogee 389c0d172a update 2026-07-28 10:32:21 +08:00
rogee fc8c23beee refactor: simplify auth and subscription links 2026-07-28 10:32:21 +08:00
rogee b7a7cd9c71 chore: add pnpm workspace with dev:frontend / dev:backend scripts
- Root package.json with dev:frontend, dev:backend, dev (parallel), build scripts
- pnpm-workspace.yaml linking frontend/ subpackage
- pnpm-lock.yaml for reproducible installs
- .gitignore: exclude root node_modules/
2026-07-27 22:55:53 +08:00
rogee 9ec8c956c1 feat: sing-box Clash template support + Docker CI + frontend scaffold
- Clash→sing-box template conversion engine (singbox_template.go)
- Auto-map 40+ Clash rule-providers to sing-box .srs binary rule-sets
- Fix sing-box 1.11+/1.12+ migrations (sniff/block/WireGuard/DNS/rule_set)
- Fix WireGuard URI '+' parsing bug (rawParamGet)
- Add REJECT block outbound for selector group references
- Skip rules referencing rule-sets with no sing-box equivalent
- Verified: sing-box run succeeds with ACL4SSR template (16 rule-sets loaded)
- Add Dockerfile (multi-stage Go build)
- Add GitHub Actions workflow (multi-arch: amd64+arm64, push to ghcr.io)
- Add frontend scaffold (Vue3 + Vite + Tailwind)
2026-07-27 21:56:19 +08:00
rogee cec95ff4e8 test: add comprehensive unit tests — coverage 20.2% → 91.8%
Add 12 test files covering all internal packages:

- internal/util/util_test.go (97.2%)
- internal/model/model_test.go (100.0%)
- internal/config/config_test.go (88.1%)
- internal/template/builtin_test.go (98.8%)
- internal/middleware/middleware_test.go (98.7%)
- internal/database/repo_extra_test.go (85.5%)
- internal/rules/converter_test.go (99.1%)
- internal/service/subscription_test.go (75.7%)
- internal/handler/handler_test.go (90.6%)
- internal/filter/filter_extra_test.go (91.9%)
- internal/proxy/client_parser_test.go (96.1%)
- internal/render/render_extra_test.go (99.2%)

Overall: 91.8% (4033/4400 statements) — exceeds 85% acceptance threshold.
All tests pass, go vet clean, go build clean.
2026-07-27 16:12:28 +08:00
rogee 264b84a738 refactor: remove standalone migrate command, auto-migrate on startup
Migrations already run idempotently during RunServer startup via goose
(which tracks applied versions in goose_db_version). The separate
 command is redundant — removed it and consolidated
serveCmd/configFile/init into server.go.
2026-07-27 14:43:22 +08:00
rogee 90e53aa754 chore: sub-store Go 重写项目初始化 2026-07-27 14:38:13 +08:00