mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
extract link.ParseCollection
This commit is contained in:
parent
de46340e83
commit
05280d01b9
@ -1,7 +1,9 @@
|
|||||||
package link
|
package link
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
@ -34,3 +36,49 @@ func Parse(u *url.URL) (Link, error) {
|
|||||||
}
|
}
|
||||||
return nil, E.Errors(errs...)
|
return nil, E.Errors(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseCollection parses a links collection string to []Link
|
||||||
|
func ParseCollection(content string) ([]Link, error) {
|
||||||
|
content = doBase64DecodeOrNothing(content)
|
||||||
|
links := make([]Link, 0)
|
||||||
|
errs := make([]error, 0)
|
||||||
|
for _, line := range strings.Split(content, "\n") {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
u, err := url.Parse(line)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
link, err := Parse(u)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
links = append(links, link)
|
||||||
|
}
|
||||||
|
return links, E.Errors(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doBase64DecodeOrNothing(s string) string {
|
||||||
|
b, err := base64Decode(s)
|
||||||
|
if err != nil {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func base64Decode(b64 string) ([]byte, error) {
|
||||||
|
b64 = strings.TrimSpace(b64)
|
||||||
|
stdb64 := b64
|
||||||
|
if pad := len(b64) % 4; pad != 0 {
|
||||||
|
stdb64 += strings.Repeat("=", 4-pad)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := base64.StdEncoding.DecodeString(stdb64)
|
||||||
|
if err != nil {
|
||||||
|
return base64.URLEncoding.DecodeString(b64)
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package link
|
package link
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -87,17 +86,3 @@ func (l *SSLink) Options() *option.Outbound {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func base64Decode(b64 string) ([]byte, error) {
|
|
||||||
b64 = strings.TrimSpace(b64)
|
|
||||||
stdb64 := b64
|
|
||||||
if pad := len(b64) % 4; pad != 0 {
|
|
||||||
stdb64 += strings.Repeat("=", 4-pad)
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := base64.StdEncoding.DecodeString(stdb64)
|
|
||||||
if err != nil {
|
|
||||||
return base64.URLEncoding.DecodeString(b64)
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
@ -2,12 +2,9 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@ -144,63 +141,19 @@ func (s *Subscription) fetchProvider(client *http.Client, provider option.Subscr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// try undecoded
|
links, err := link.ParseCollection(string(body))
|
||||||
content := string(body)
|
|
||||||
links, err := linksFromContent(content)
|
|
||||||
if len(links) > 0 {
|
if len(links) > 0 {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Warn("some links failed", err)
|
s.logger.Warn("links parsed with error:", err)
|
||||||
}
|
}
|
||||||
return links, nil
|
return links, nil
|
||||||
}
|
}
|
||||||
// try decoded
|
if err != nil {
|
||||||
decoded, err := base64Decode(content)
|
return nil, err
|
||||||
links, err = linksFromContent(string(decoded))
|
|
||||||
if len(links) > 0 {
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Warn("some links failed", err)
|
|
||||||
}
|
|
||||||
return links, nil
|
|
||||||
}
|
}
|
||||||
return nil, E.New("no links found")
|
return nil, E.New("no links found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func linksFromContent(content string) ([]link.Link, error) {
|
|
||||||
links := make([]link.Link, 0)
|
|
||||||
errs := make([]error, 0)
|
|
||||||
for _, line := range strings.Split(content, "\n") {
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if line == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
u, err := url.Parse(line)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
link, err := link.Parse(u)
|
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
links = append(links, link)
|
|
||||||
}
|
|
||||||
return links, E.Errors(errs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func base64Decode(b64 string) ([]byte, error) {
|
|
||||||
b64 = strings.TrimSpace(b64)
|
|
||||||
stdb64 := b64
|
|
||||||
if pad := len(b64) % 4; pad != 0 {
|
|
||||||
stdb64 += strings.Repeat("=", 4-pad)
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := base64.StdEncoding.DecodeString(stdb64)
|
|
||||||
if err != nil {
|
|
||||||
return base64.URLEncoding.DecodeString(b64)
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Subscription) client() (*http.Client, error) {
|
func (s *Subscription) client() (*http.Client, error) {
|
||||||
var detour adapter.Outbound
|
var detour adapter.Outbound
|
||||||
if s.options.DownloadDetour != "" {
|
if s.options.DownloadDetour != "" {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user