Files
BitSrunLoginGo/internal/controllers/login.go
2024-09-25 21:48:07 +08:00

222 lines
5.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package controllers
import (
"context"
"errors"
"github.com/Mmx233/BackoffCli/backoff"
"github.com/Mmx233/BitSrunLoginGo/internal/config"
"github.com/Mmx233/BitSrunLoginGo/internal/config/flags"
"github.com/Mmx233/BitSrunLoginGo/internal/config/keys"
"github.com/Mmx233/BitSrunLoginGo/internal/pkg/dns"
"github.com/Mmx233/BitSrunLoginGo/internal/pkg/http_client"
"github.com/Mmx233/BitSrunLoginGo/pkg/srun"
"github.com/Mmx233/BitSrunLoginGo/tools"
log "github.com/sirupsen/logrus"
"net/http"
"sync"
"time"
)
var ipLast string
var debugTip sync.Once
type LoginConf struct {
Logger log.FieldLogger
IsOnlineDetectLogDebugLevel bool
}
func Login(conf LoginConf) error {
logger := conf.Logger
if config.Settings.Basic.Interfaces == "" { //单网卡
err := LoginSingle(LoginSingleConf{
LoginConf: conf,
Eth: nil,
})
if err != nil {
logger.Errorln("登录出错: ", err)
debugTip.Do(func() {
if !config.Settings.Log.DebugLevel {
logger.Infoln("开启调试日志 (debug_level) 获取详细信息")
}
})
}
return err
} else { //多网卡
return LoginInterfaces(conf)
}
}
func ddns(logger log.FieldLogger, ip string, httpClient *http.Client) error {
return dns.Run(&dns.Config{
Logger: logger.WithField(keys.LogLoginModule, "ddns"),
Provider: config.Settings.DDNS.Provider,
IP: ip,
Domain: config.Settings.DDNS.Domain,
TTL: config.Settings.DDNS.TTL,
Conf: config.Settings.DDNS.Config,
Http: httpClient,
})
}
func LoginInterfaces(conf LoginConf) error {
logger := conf.Logger
interfaces, err := tools.GetInterfaceAddr(logger, config.Settings.Basic.Interfaces)
if err != nil {
return err
}
var interval = time.Duration(config.Settings.Basic.InterfacesInterval) * time.Second
var errCount int
for i, eth := range interfaces {
logger.Infoln("使用网卡: ", eth.Name)
if err := LoginSingle(LoginSingleConf{
LoginConf: conf,
Eth: &eth,
}); err != nil {
logger.Errorf("网卡 %s 登录出错: %v", eth.Name, err)
errCount++
}
if i != len(interfaces)-1 {
time.Sleep(interval)
}
}
if errCount > 0 {
return errors.New("multi interface login not completely succeed")
}
return nil
}
type LoginSingleConf struct {
LoginConf
Eth *tools.Eth
}
func LoginSingle(conf LoginSingleConf) error {
if config.Settings.Backoff.Enable {
return backoff.NewInstance(func(ctx context.Context) error {
return doLogin(conf)
}, config.BackoffConfig).Run(context.TODO())
} else {
return doLogin(conf)
}
}
func doLogin(conf LoginSingleConf) error {
logger := conf.Logger
// 登录配置初始化
httpClient := http_client.HttpPackSelect(conf.Eth).Client
srunClient := srun.New(&srun.Conf{
Logger: logger,
Https: config.Settings.Basic.Https,
LoginInfo: srun.LoginInfo{
Form: *config.Form,
Meta: *config.Meta,
},
Client: httpClient,
CustomHeader: config.Settings.CustomHeader,
})
srunDetector := srunClient.Api.NewDetector()
// Reality 与 Acid
var acidOnReality bool
if config.Settings.Reality.Enable {
logger := logger.WithField(keys.LogLoginModule, "reality")
logger.Debugln("开始 Reality 流程")
acid, _, err := srunDetector.Reality(config.Settings.Reality.Addr, flags.AutoAcid)
if err != nil {
logger.Warnln("Reality 请求异常:", err)
} else if flags.AutoAcid && acid != "" {
acidOnReality = true
logger.Debugf("使用嗅探 acid: %s", acid)
srunClient.LoginInfo.Meta.Acid = acid
}
}
if !acidOnReality && flags.AutoAcid {
logger := logger.WithField(keys.LogLoginModule, "acid")
logger.Debugln("开始嗅探")
acid, err := srunDetector.DetectAcid()
if err != nil {
if errors.Is(err, srun.ErrAcidCannotFound) {
logger.Warnln("找不到 acid使用配置 acid")
} else {
logger.Warnf("嗅探失败,使用配置 acid: %v", err)
}
} else {
logger.Debugf("使用嗅探 acid: %s", acid)
srunClient.LoginInfo.Meta.Acid = acid
}
}
if flags.AutoEnc {
logger := logger.WithField(keys.LogLoginModule, "enc")
logger.Debugln("开始嗅探")
enc, err := srunDetector.DetectEnc()
if err != nil {
if errors.Is(err, srun.ErrEnvCannotFound) {
logger.Warnln("找不到 enc使用配置 enc")
} else {
logger.Warnf("嗅探失败,使用配置 enc: %v", err)
}
} else {
logger.Debugf("使用嗅探 enc: %s", enc)
srunClient.LoginInfo.Meta.Enc = enc
}
}
// 选择输出函数
var _Println func(args ...interface{})
if conf.IsOnlineDetectLogDebugLevel {
_Println = logger.Debugln
} else {
_Println = logger.Infoln
}
_Println("正在获取登录状态")
online, ip, err := srunClient.LoginStatus()
if err != nil {
return err
}
var loginIp string
if config.Meta.DoubleStack {
logger.Debugln("使用双栈网络时认证 ip 为空")
} else {
loginIp = ip
logger.Debugln("认证客户端 ip: ", ip)
}
// 登录执行
if online {
_Println("已登录~")
if config.Settings.DDNS.Enable && config.Settings.Guardian.Enable && ipLast != ip {
if ddns(logger, ip, httpClient) == nil {
ipLast = ip
}
}
return nil
} else {
logger.Infoln("检测到用户未登录,开始尝试登录...")
if err = srunClient.DoLogin(loginIp); err != nil {
return err
}
logger.Infoln("登录成功~")
if config.Settings.DDNS.Enable {
_ = ddns(logger, ip, httpClient)
}
}
return nil
}