extract link.ParseCollection

This commit is contained in:
jebbs 2022-10-15 16:24:21 +08:00
parent de46340e83
commit 05280d01b9
3 changed files with 52 additions and 66 deletions

View File

@ -1,7 +1,9 @@
package link
import (
"encoding/base64"
"net/url"
"strings"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
@ -34,3 +36,49 @@ func Parse(u *url.URL) (Link, error) {
}
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
}

View File

@ -1,7 +1,6 @@
package link
import (
"encoding/base64"
"fmt"
"net/url"
"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
}

View File

@ -2,12 +2,9 @@ package service
import (
"context"
"encoding/base64"
"io"
"net"
"net/http"
"net/url"
"strings"
"time"
"github.com/sagernet/sing-box/adapter"
@ -144,63 +141,19 @@ func (s *Subscription) fetchProvider(client *http.Client, provider option.Subscr
if err != nil {
return nil, err
}
// try undecoded
content := string(body)
links, err := linksFromContent(content)
links, err := link.ParseCollection(string(body))
if len(links) > 0 {
if err != nil {
s.logger.Warn("some links failed", err)
s.logger.Warn("links parsed with error:", err)
}
return links, nil
}
// try decoded
decoded, err := base64Decode(content)
links, err = linksFromContent(string(decoded))
if len(links) > 0 {
if err != nil {
s.logger.Warn("some links failed", err)
}
return links, nil
if err != nil {
return nil, err
}
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) {
var detour adapter.Outbound
if s.options.DownloadDetour != "" {