Skip to content

feat: proxy-providers import mode for URL sources#56

Open
sodiseng wants to merge 1 commit into
SubBoost:mainfrom
sodiseng:feat/proxy-providers
Open

feat: proxy-providers import mode for URL sources#56
sodiseng wants to merge 1 commit into
SubBoost:mainfrom
sodiseng:feat/proxy-providers

Conversation

@sodiseng

Copy link
Copy Markdown

What

Adds an optional proxy-providers import mode for URL subscription sources: instead of fetching and inlining nodes, a source can be emitted as a mihomo proxy-providers entry, letting mihomo itself fetch and refresh the subscription.

为 URL 订阅源增加可选的 proxy-providers 导入模式:不再拉取节点内联,而是把订阅输出为 mihomo proxy-providers 条目,由 mihomo 自行拉取与更新。

Features / 功能

  • Per-source provider settings (URL sources only): custom provider key, attach mode, emoji group name, node filter regex. All fields persist end-to-end (store / auth handoff / subscription save & load / server-side saved-sources normalization). Existing saved data without these fields keeps the previous behavior.
  • Three attach modes / 三种接入模式:
    • grouped(分组,默认): generates an "airport group" {name, type: select, use: [key]}. The group joins all manual-select policy groups and custom groups as a regular member — it can be excluded, reordered, and manually attached to any group in the advanced group editor.
    • inline(内嵌): provider key is injected via use: into all policy groups (legacy behavior; default for old saved data).
    • bare(仅生成): only writes proxy-providers, attaches nothing.
  • Provider defaults: interval: 43200, health-check interval: 300 / timeout: 5000 / lazy: true; path follows the provider key (sanitized, deduped); default node filter regex excludes info nodes (customizable per source, empty string = no filter).
  • UI: inline status bar on URL source editors (quick & advanced mode) with mode selector and key/group-name fields; provider settings section in the advanced edit dialog (incl. filter); read-only airport group card in the core groups list; provider member chips in the group advanced editor; airport groups in the visual preview (sortable).

mihomo reference

proxy-providers fields and use: semantics per https://wiki.metacubex.one/config/proxy-providers/ and config/proxy-groups/.

Tests

  • 1121 unit tests pass (vitest), tsc clean, eslint --max-warnings=0 clean.
  • New tests cover plan building (key/path/filter tri-state), attach modes, airport-group member resolution (exclude/reorder/orphan fallback), and server-side persistence round-trip.

- Per-source provider settings: custom key, attach mode (grouped/inline/bare),
  emoji group name, node filter regex; persisted end-to-end (store, handoff,
  subscription save/load, server-side saved-sources normalization)
- Grouped mode generates an airport group (select + use) that joins all
  manual-select groups as a regular member: excludable, sortable, and
  manually attachable to any group via new provider member refs
- Fixed provider defaults (interval, health-check), provider path follows key
- UI: inline status bar on URL source editors, provider settings in advanced
  dialog, read-only airport group card, provider members in group editor,
  airport groups in visual preview

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73830ab590

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +267 to +271
const autoIndex = autoTarget ? proxies.indexOf(autoTarget) : -1;
const selectIndex = selectTarget ? proxies.indexOf(selectTarget) : -1;
const anchorIndex = autoIndex >= 0 ? autoIndex : selectIndex;
const insertAt = anchorIndex >= 0 ? anchorIndex + 1 : 0;
return [...proxies.slice(0, insertAt), ...missing, ...proxies.slice(insertAt)];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Put provider groups before empty auto groups

When the config has only URL sources in grouped proxy-provider mode (the UI now sets this mode by default when enabling providers), there are no parsed nodes and ⚡ 自动选择 is generated with no proxies/use because grouped providers are excluded from the inline provider list. Inserting the airport group after autoTarget leaves 🚀 节点选择 defaulting to that empty auto group, so provider-only subscriptions start on a dead/invalid policy until the user manually switches to the airport group.

Useful? React with 👍 / 👎.

Comment on lines +362 to +364
const groupedAttachments = groupedProviderKeys
.map((key) => attachmentByKey.get(key))
.filter((attachment): attachment is ProxyProviderAttachment => Boolean(attachment));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve attachment order when naming provider groups

When two grouped sources use the same providerGroupName and their provider keys sort differently from source order, this sorted provider-key list changes which key receives the unsuffixed/suffixed airport-group name compared with the UI/provider preview, which builds from source order. Since the advanced editor stores exclusions and ordering as provider-group keys, excluding the UI's “Air” can remove “Air 2” in the generated YAML.

Useful? React with 👍 / 👎.

type="button"
role="radio"
aria-checked={mode === option.value}
onClick={() => onUpdateMeta(source.id, { providerMode: option.value })}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Regenerate YAML after provider settings change

Changing this radio only calls onUpdateMeta with providerMode; in the controller that flows through setSources, which does not recompute generatedYaml when no source is removed, and these new provider fields are not part of the reimport snapshot. For an already-imported provider source, switching grouped/inline/bare (or editing key/filter/group name) leaves preview/download using the previous proxy-provider wiring until some unrelated generation-triggering action runs.

Useful? React with 👍 / 👎.

Comment on lines +266 to +267
const key = source.providerKey?.trim() || `url_${source.id}`;
out.push({ ref: { kind: "provider-inline", key }, label: `内联 ${key}` });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Sanitize default provider keys in provider chips

When a saved/imported source id contains characters that the provider builder sanitizes (for example bad/url becomes url_bad_url), this chip stores provider-inline:url_bad/url instead of the actual provider key. The generator only accepts keys present in the provider plan, so clicking the chip appears to add that bare/grouped provider to a policy group but no use: entry is emitted.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants