feat(sub): per-client external links and remote subscriptions

Add a Links tab to the client form for attaching third-party share
links and remote subscription URLs per client. They are merged into
the client's raw/JSON/Clash subscription output: links are emitted
verbatim and parsed for JSON/Clash; subscription URLs are fetched
(cached, with a short timeout) and their configs merged in.

i18n keys added across all 13 locales.
This commit is contained in:
MHSanaei
2026-06-14 20:57:14 +02:00
parent 7c2598fae9
commit dcb923b4a1
33 changed files with 1204 additions and 28 deletions
+17 -1
View File
@@ -147,8 +147,12 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, []string, int
if err != nil {
return nil, nil, 0, traffic, err
}
externalLinks, err := s.getClientExternalLinksBySubId(subId)
if err != nil {
return nil, nil, 0, traffic, err
}
if len(inbounds) == 0 {
if len(inbounds) == 0 && len(externalLinks) == 0 {
return nil, nil, 0, traffic, nil
}
@@ -178,6 +182,18 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, []string, int
seenEmails[client.Email] = struct{}{}
}
}
for _, ext := range externalLinks {
if ext.Enable {
hasEnabledClient = true
}
for _, el := range expandEntry(ext) {
if link := applyRemarkToLink(el.Link, el.Name); link != "" {
result = append(result, link)
emails = append(emails, ext.Email)
seenEmails[ext.Email] = struct{}{}
}
}
}
uniqueEmails := make([]string, 0, len(seenEmails))
for e := range seenEmails {