mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-09 02:41:22 +08:00
chore: change subscription-userinfo retrieval
This commit is contained in:
parent
ca3f1ebae6
commit
95af5f7325
@ -1,11 +1,9 @@
|
|||||||
package provider
|
package provider
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -14,7 +12,7 @@ import (
|
|||||||
"github.com/metacubex/mihomo/adapter"
|
"github.com/metacubex/mihomo/adapter"
|
||||||
"github.com/metacubex/mihomo/common/convert"
|
"github.com/metacubex/mihomo/common/convert"
|
||||||
"github.com/metacubex/mihomo/common/utils"
|
"github.com/metacubex/mihomo/common/utils"
|
||||||
mihomoHttp "github.com/metacubex/mihomo/component/http"
|
"github.com/metacubex/mihomo/component/profile/cachefile"
|
||||||
"github.com/metacubex/mihomo/component/resource"
|
"github.com/metacubex/mihomo/component/resource"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
types "github.com/metacubex/mihomo/constant/provider"
|
types "github.com/metacubex/mihomo/constant/provider"
|
||||||
@ -80,7 +78,9 @@ func (pp *proxySetProvider) Initial() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pp.getSubscriptionInfo()
|
if subscriptionInfo := cachefile.Cache().GetSubscriptionInfo(pp.Name()); subscriptionInfo != "" {
|
||||||
|
pp.SetSubscriptionInfo(subscriptionInfo)
|
||||||
|
}
|
||||||
pp.closeAllConnections()
|
pp.closeAllConnections()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -117,35 +117,14 @@ func (pp *proxySetProvider) setProxies(proxies []C.Proxy) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pp *proxySetProvider) getSubscriptionInfo() {
|
func (pp *proxySetProvider) SetSubscriptionInfo(userInfo string) {
|
||||||
if pp.VehicleType() != types.HTTP {
|
pp.subscriptionInfo = NewSubscriptionInfo(userInfo)
|
||||||
return
|
}
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*90)
|
|
||||||
defer cancel()
|
|
||||||
resp, err := mihomoHttp.HttpRequestWithProxy(ctx, pp.Vehicle().Url(),
|
|
||||||
http.MethodGet, nil, nil, pp.Vehicle().Proxy())
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
userInfoStr := strings.TrimSpace(resp.Header.Get("subscription-userinfo"))
|
func (pp *proxySetProvider) SetProvider(provider types.ProxyProvider) {
|
||||||
if userInfoStr == "" {
|
if httpVehicle, ok := pp.Vehicle().(*resource.HTTPVehicle); ok {
|
||||||
resp2, err := mihomoHttp.HttpRequestWithProxy(ctx, pp.Vehicle().Url(),
|
httpVehicle.SetProvider(provider)
|
||||||
http.MethodGet, http.Header{"User-Agent": {"Quantumultx"}}, nil, pp.Vehicle().Proxy())
|
}
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp2.Body.Close()
|
|
||||||
userInfoStr = strings.TrimSpace(resp2.Header.Get("subscription-userinfo"))
|
|
||||||
if userInfoStr == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pp.subscriptionInfo = NewSubscriptionInfo(userInfoStr)
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pp *proxySetProvider) closeAllConnections() {
|
func (pp *proxySetProvider) closeAllConnections() {
|
||||||
@ -196,6 +175,9 @@ func NewProxySetProvider(name string, interval time.Duration, filter string, exc
|
|||||||
fetcher := resource.NewFetcher[[]C.Proxy](name, interval, vehicle, proxiesParseAndFilter(filter, excludeFilter, excludeTypeArray, filterRegs, excludeFilterReg, dialerProxy, override), proxiesOnUpdate(pd))
|
fetcher := resource.NewFetcher[[]C.Proxy](name, interval, vehicle, proxiesParseAndFilter(filter, excludeFilter, excludeTypeArray, filterRegs, excludeFilterReg, dialerProxy, override), proxiesOnUpdate(pd))
|
||||||
pd.Fetcher = fetcher
|
pd.Fetcher = fetcher
|
||||||
wrapper := &ProxySetProvider{pd}
|
wrapper := &ProxySetProvider{pd}
|
||||||
|
if httpVehicle, ok := vehicle.(*resource.HTTPVehicle); ok {
|
||||||
|
httpVehicle.SetProvider(wrapper)
|
||||||
|
}
|
||||||
runtime.SetFinalizer(wrapper, (*ProxySetProvider).Close)
|
runtime.SetFinalizer(wrapper, (*ProxySetProvider).Close)
|
||||||
return wrapper, nil
|
return wrapper, nil
|
||||||
}
|
}
|
||||||
@ -205,16 +187,21 @@ func (pp *ProxySetProvider) Close() error {
|
|||||||
return pp.proxySetProvider.Close()
|
return pp.proxySetProvider.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pp *ProxySetProvider) SetProvider(provider types.ProxyProvider) {
|
||||||
|
pp.proxySetProvider.SetProvider(provider)
|
||||||
|
}
|
||||||
|
|
||||||
// CompatibleProvider for auto gc
|
// CompatibleProvider for auto gc
|
||||||
type CompatibleProvider struct {
|
type CompatibleProvider struct {
|
||||||
*compatibleProvider
|
*compatibleProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
type compatibleProvider struct {
|
type compatibleProvider struct {
|
||||||
name string
|
name string
|
||||||
healthCheck *HealthCheck
|
healthCheck *HealthCheck
|
||||||
proxies []C.Proxy
|
subscriptionInfo *SubscriptionInfo
|
||||||
version uint32
|
proxies []C.Proxy
|
||||||
|
version uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *compatibleProvider) MarshalJSON() ([]byte, error) {
|
func (cp *compatibleProvider) MarshalJSON() ([]byte, error) {
|
||||||
@ -284,6 +271,10 @@ func (cp *compatibleProvider) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cp *compatibleProvider) SetSubscriptionInfo(userInfo string) {
|
||||||
|
cp.subscriptionInfo = NewSubscriptionInfo(userInfo)
|
||||||
|
}
|
||||||
|
|
||||||
func NewCompatibleProvider(name string, proxies []C.Proxy, hc *HealthCheck) (*CompatibleProvider, error) {
|
func NewCompatibleProvider(name string, proxies []C.Proxy, hc *HealthCheck) (*CompatibleProvider, error) {
|
||||||
if len(proxies) == 0 {
|
if len(proxies) == 0 {
|
||||||
return nil, errors.New("provider need one proxy at least")
|
return nil, errors.New("provider need one proxy at least")
|
||||||
@ -313,7 +304,6 @@ func proxiesOnUpdate(pd *proxySetProvider) func([]C.Proxy) {
|
|||||||
return func(elm []C.Proxy) {
|
return func(elm []C.Proxy) {
|
||||||
pd.setProxies(elm)
|
pd.setProxies(elm)
|
||||||
pd.version += 1
|
pd.version += 1
|
||||||
pd.getSubscriptionInfo()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,7 @@ type SubscriptionInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewSubscriptionInfo(userinfo string) (si *SubscriptionInfo) {
|
func NewSubscriptionInfo(userinfo string) (si *SubscriptionInfo) {
|
||||||
userinfo = strings.ToLower(userinfo)
|
userinfo = strings.ReplaceAll(strings.ToLower(userinfo), " ", "")
|
||||||
userinfo = strings.ReplaceAll(userinfo, " ", "")
|
|
||||||
si = new(SubscriptionInfo)
|
si = new(SubscriptionInfo)
|
||||||
|
|
||||||
for _, field := range strings.Split(userinfo, ";") {
|
for _, field := range strings.Split(userinfo, ";") {
|
||||||
|
@ -17,9 +17,10 @@ var (
|
|||||||
fileMode os.FileMode = 0o666
|
fileMode os.FileMode = 0o666
|
||||||
defaultCache *CacheFile
|
defaultCache *CacheFile
|
||||||
|
|
||||||
bucketSelected = []byte("selected")
|
bucketSelected = []byte("selected")
|
||||||
bucketFakeip = []byte("fakeip")
|
bucketFakeip = []byte("fakeip")
|
||||||
bucketETag = []byte("etag")
|
bucketETag = []byte("etag")
|
||||||
|
bucketSubscriptionInfo = []byte("subscriptioninfo")
|
||||||
)
|
)
|
||||||
|
|
||||||
// CacheFile store and update the cache file
|
// CacheFile store and update the cache file
|
||||||
|
41
component/profile/cachefile/subscriptioninfo.go
Normal file
41
component/profile/cachefile/subscriptioninfo.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package cachefile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/metacubex/mihomo/log"
|
||||||
|
|
||||||
|
"github.com/metacubex/bbolt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *CacheFile) SetSubscriptionInfo(name string, userInfo string) {
|
||||||
|
if c.DB == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := c.DB.Batch(func(t *bbolt.Tx) error {
|
||||||
|
bucket, err := t.CreateBucketIfNotExists(bucketSubscriptionInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucket.Put([]byte(name), []byte(userInfo))
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("[CacheFile] write cache to %s failed: %s", c.DB.Path(), err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *CacheFile) GetSubscriptionInfo(name string) (userInfo string) {
|
||||||
|
if c.DB == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.DB.View(func(t *bbolt.Tx) error {
|
||||||
|
if bucket := t.Bucket(bucketSubscriptionInfo); bucket != nil {
|
||||||
|
if v := bucket.Get([]byte(name)); v != nil {
|
||||||
|
userInfo = string(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
@ -84,11 +84,12 @@ func NewFileVehicle(path string) *FileVehicle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HTTPVehicle struct {
|
type HTTPVehicle struct {
|
||||||
url string
|
url string
|
||||||
path string
|
path string
|
||||||
proxy string
|
proxy string
|
||||||
header http.Header
|
header http.Header
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
|
provider types.ProxyProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTPVehicle) Url() string {
|
func (h *HTTPVehicle) Url() string {
|
||||||
@ -111,6 +112,10 @@ func (h *HTTPVehicle) Write(buf []byte) error {
|
|||||||
return safeWrite(h.path, buf)
|
return safeWrite(h.path, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HTTPVehicle) SetProvider(provider types.ProxyProvider) {
|
||||||
|
h.provider = provider
|
||||||
|
}
|
||||||
|
|
||||||
func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []byte, hash utils.HashType, err error) {
|
func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []byte, hash utils.HashType, err error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, h.timeout)
|
ctx, cancel := context.WithTimeout(ctx, h.timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -133,6 +138,12 @@ func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []b
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if subscriptionInfo := resp.Header.Get("subscription-userinfo"); h.provider != nil && subscriptionInfo != "" {
|
||||||
|
cachefile.Cache().SetSubscriptionInfo(h.provider.Name(), subscriptionInfo)
|
||||||
|
h.provider.SetSubscriptionInfo(subscriptionInfo)
|
||||||
|
}
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||||
if setIfNoneMatch && resp.StatusCode == http.StatusNotModified {
|
if setIfNoneMatch && resp.StatusCode == http.StatusNotModified {
|
||||||
return nil, oldHash, nil
|
return nil, oldHash, nil
|
||||||
|
@ -213,6 +213,8 @@ func (at AdapterType) String() string {
|
|||||||
return "WireGuard"
|
return "WireGuard"
|
||||||
case Tuic:
|
case Tuic:
|
||||||
return "Tuic"
|
return "Tuic"
|
||||||
|
case Ssh:
|
||||||
|
return "Ssh"
|
||||||
|
|
||||||
case Relay:
|
case Relay:
|
||||||
return "Relay"
|
return "Relay"
|
||||||
@ -224,8 +226,6 @@ func (at AdapterType) String() string {
|
|||||||
return "URLTest"
|
return "URLTest"
|
||||||
case LoadBalance:
|
case LoadBalance:
|
||||||
return "LoadBalance"
|
return "LoadBalance"
|
||||||
case Ssh:
|
|
||||||
return "Ssh"
|
|
||||||
default:
|
default:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,7 @@ type ProxyProvider interface {
|
|||||||
Version() uint32
|
Version() uint32
|
||||||
RegisterHealthCheckTask(url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint)
|
RegisterHealthCheckTask(url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint)
|
||||||
HealthCheckURL() string
|
HealthCheckURL() string
|
||||||
|
SetSubscriptionInfo(userInfo string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuleProvider interface
|
// RuleProvider interface
|
||||||
|
Loading…
Reference in New Issue
Block a user