Files
BitSrunLoginGo/internal/login/login.go
2024-10-25 16:12:07 +08:00

223 lines
5.2 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 login
import (
"context"
"errors"
"net/http"
"sync"
"time"
"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"
dns2 "github.com/Mmx233/BitSrunLoginGo/internal/dns"
"github.com/Mmx233/BitSrunLoginGo/internal/http_client"
"github.com/Mmx233/BitSrunLoginGo/pkg/srun"
"github.com/Mmx233/BitSrunLoginGo/tools"
log "github.com/sirupsen/logrus"
)
var ipLast string
var debugTip sync.Once
type Conf struct {
Logger log.FieldLogger
IsOnlineDetectLogDebugLevel bool
}
func Login(conf Conf) error {
logger := conf.Logger
if config.Settings.Basic.Interfaces == "" { //单网卡
err := Single(SingleConf{
Conf: 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 Interfaces(conf)
}
}
func ddns(logger log.FieldLogger, ip string, httpClient *http.Client) error {
return dns2.Run(&dns2.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 Interfaces(conf Conf) 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 := Single(SingleConf{
Conf: 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 SingleConf struct {
Conf
Eth *tools.Eth
}
func Single(conf SingleConf) 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 SingleConf) error {
logger := conf.Logger
// 登录配置初始化
httpClient := http_client.ClientSelect(conf.Eth)
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
}