mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-25 23:35:00 +03:00
bc1b750e00
Host rules applied per inbound only, so every client of an inbound got the same subscription endpoints (#6618). A client can now be bound to one or more host rules, and its raw, JSON and Clash subscriptions render only those hosts, in either subscription order; an unbound client is unchanged. A binding whose hosts are deleted, disabled or excluded from the format fails closed: the client gets no links there but stays in traffic accounting. Host edits keep row ids, so bindings survive them; nil leaves a stored binding alone and an empty list clears it.
78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package sub
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
|
)
|
|
|
|
type LinkProvider struct {
|
|
settingService service.SettingService
|
|
}
|
|
|
|
func NewLinkProvider() *LinkProvider {
|
|
return &LinkProvider{}
|
|
}
|
|
|
|
func (p *LinkProvider) build(host string) *SubService {
|
|
remarkTemplate, _ := p.settingService.GetRemarkTemplate()
|
|
svc := NewSubService(remarkTemplate)
|
|
svc.PrepareForRequest(host)
|
|
return svc
|
|
}
|
|
|
|
func (p *LinkProvider) SubLinksForSubId(host, subId string) ([]string, error) {
|
|
svc := p.build(host)
|
|
links, _, _, _, err := svc.GetSubs(subId, host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out := make([]string, 0, len(links))
|
|
for _, l := range links {
|
|
out = append(out, splitLinkLines(l)...)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (p *LinkProvider) LinksForClient(host string, inbound *model.Inbound, email string) []string {
|
|
svc := p.build(host)
|
|
svc.projectThroughFallbackMaster(inbound)
|
|
baseEps := svc.hostEndpoints(inbound, "raw")
|
|
if client, ok := svc.clientForLink(inbound, email); ok {
|
|
effectiveEps, bound := svc.clientHostEndpoints(inbound, client, "raw", baseEps)
|
|
if bound && len(effectiveEps) == 0 {
|
|
return nil
|
|
}
|
|
if len(effectiveEps) > 0 {
|
|
if link := svc.linkFromHosts(inbound, client, effectiveEps); link != "" {
|
|
return splitLinkLines(link)
|
|
}
|
|
}
|
|
}
|
|
return splitLinkLines(svc.GetLink(inbound, email))
|
|
}
|
|
|
|
func (p *LinkProvider) LinksForInbounds(host string, inbounds []*model.Inbound) []string {
|
|
svc := p.build(host)
|
|
var out []string
|
|
for _, inbound := range inbounds {
|
|
out = append(out, svc.inboundLinks(inbound)...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func splitLinkLines(raw string) []string {
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
parts := strings.Split(raw, "\n")
|
|
out := make([]string, 0, len(parts))
|
|
for _, p := range parts {
|
|
if p = strings.TrimSpace(p); p != "" {
|
|
out = append(out, p)
|
|
}
|
|
}
|
|
return out
|
|
}
|