feat: 重构配置层,添加 json 支持

This commit is contained in:
Mmx233
2023-08-28 22:03:03 +08:00
parent 2a098e00dd
commit 6f283a93f5
19 changed files with 318 additions and 272 deletions

View File

@@ -1,32 +1,33 @@
package main
import (
"github.com/Mmx233/BitSrunLoginGo/internal/config"
"github.com/Mmx233/BitSrunLoginGo/internal/config/flags"
"github.com/Mmx233/BitSrunLoginGo/internal/controllers"
"github.com/Mmx233/BitSrunLoginGo/internal/global"
"github.com/Mmx233/BitSrunLoginGo/tools"
log "github.com/sirupsen/logrus"
"net"
)
func main() {
if global.Config.Settings.Guardian.Enable {
if config.Settings.Guardian.Enable {
//进入守护模式
controllers.Guardian()
} else {
//登录流程
var err error
if global.Config.Settings.Basic.Interfaces == "" { //单网卡
if config.Settings.Basic.Interfaces == "" { //单网卡
var eth *tools.Eth
if global.Flags.Interface != "" {
netEth, e := net.InterfaceByName(global.Flags.Interface)
if flags.Interface != "" {
netEth, e := net.InterfaceByName(flags.Interface)
if e != nil {
log.Warnf("获取指定网卡 %s 失败,使用默认网卡: %v", global.Flags.Interface, e)
log.Warnf("获取指定网卡 %s 失败,使用默认网卡: %v", flags.Interface, e)
} else {
eth, e = tools.ConvertInterface(*netEth)
if e != nil {
log.Warnf("获取指定网卡 %s ip 地址失败,使用默认网卡: %v", global.Flags.Interface, e)
log.Warnf("获取指定网卡 %s ip 地址失败,使用默认网卡: %v", flags.Interface, e)
} else if eth == nil {
log.Warnf("指定网卡 %s 无可用 ip 地址,使用默认网卡", global.Flags.Interface)
log.Warnf("指定网卡 %s 无可用 ip 地址,使用默认网卡", flags.Interface)
} else {
log.Debugf("使用指定网卡 %s ip: %s", eth.Name, eth.Addr.String())
}
@@ -34,14 +35,14 @@ func main() {
}
if err = controllers.Login(eth, false); err != nil {
log.Errorln("登录出错: ", err)
if !global.Config.Settings.Log.DebugLevel {
if !config.Settings.Log.DebugLevel {
log.Infoln("开启调试日志debug_level获取详细信息")
}
return
}
} else { //多网卡
log.Infoln("多网卡模式")
interfaces, _ := tools.GetInterfaceAddr(global.Config.Settings.Basic.Interfaces)
interfaces, _ := tools.GetInterfaceAddr(config.Settings.Basic.Interfaces)
for _, eth := range interfaces {
log.Infoln("使用网卡: ", eth.Name)
if err = controllers.Login(&eth, false); err != nil {

69
internal/config/config.go Normal file
View File

@@ -0,0 +1,69 @@
package config
import (
"github.com/Mmx233/BitSrunLoginGo/internal/config/flags"
"github.com/Mmx233/BitSrunLoginGo/pkg/srun"
"github.com/Mmx233/tool"
log "github.com/sirupsen/logrus"
"os"
"time"
)
type ConfFromFile struct {
Form srun.LoginForm `json:"form" yaml:"form"`
Meta srun.LoginMeta `json:"meta" yaml:"meta"`
Settings SettingsConf `json:"settings" yaml:"settings"`
}
var (
Form *srun.LoginForm
Meta *srun.LoginMeta
Settings *SettingsConf
Timeout time.Duration
)
func init() {
reader := newReaderFromPath(flags.Path)
// 生成配置文件
exist, err := tool.File.Exists(flags.Path)
if err != nil {
log.Fatalln("[init] 读取配置文件失败:", err)
} else if !exist {
var data []byte
data, err = reader.Marshal(&defaultConfig)
if err != nil {
log.Fatalln("[init] 生成配置文件失败:", err)
}
if err = os.WriteFile(flags.Path, data, 0600); err != nil {
log.Fatalln("[init] 写入配置文件失败:", err)
}
log.Infoln("[init] 已生成配置文件,请编辑 '" + flags.Path + "' 然后重试")
os.Exit(0)
}
// 读取配置文件
data, err := os.ReadFile(flags.Path)
if err != nil {
log.Fatalln("[init] 读取配置失败:", err)
}
var fileConf ConfFromFile
if err = reader.Unmarshal(data, &fileConf); err != nil {
log.Fatalln("[init] 解析配置失败:", err)
}
Form = &fileConf.Form
Meta = &fileConf.Meta
Settings = &fileConf.Settings
Timeout = time.Duration(Settings.Basic.Timeout) * time.Second
// flag 配置覆写
if flags.Debug {
Settings.Log.DebugLevel = true
}
if flags.Acid != "" {
Meta.Acid = flags.Acid
}
initLog()
}

View File

@@ -0,0 +1,39 @@
package config
import (
"github.com/Mmx233/BitSrunLoginGo/pkg/srun"
)
var defaultConfig = ConfFromFile{
Form: srun.LoginForm{
Domain: "www.msftconnecttest.com",
UserType: "cmcc",
},
Meta: srun.LoginMeta{
N: "200",
Type: "1",
Acid: "5",
Enc: "srun_bx1",
},
Settings: SettingsConf{
Basic: BasicConf{
Timeout: 5,
},
Guardian: GuardianConf{
Duration: 300,
},
Log: LogConf{
FilePath: "./",
},
DDNS: DdnsConf{
Enable: false,
TTL: 600,
Domain: "www.example.com",
Provider: "cloudflare",
Config: map[string]interface{}{
"zone": "",
"token": "",
},
},
},
}

View File

@@ -0,0 +1,26 @@
package flags
import (
"flag"
)
var (
// Path 配置文件路径
Path string
Interface string
Debug bool
AutoAcid bool
Acid string
)
func init() {
flag.StringVar(&Path, "config", "Config.yaml", "config path")
flag.StringVar(&Interface, "interface", "", "specify the eth name")
flag.BoolVar(&Debug, "debug", false, "enable debug mode")
flag.BoolVar(&AutoAcid, "auto-acid", false, "auto detect acid")
flag.StringVar(&Acid, "acid", "", "specify acid value")
flag.Parse()
}

48
internal/config/log.go Normal file
View File

@@ -0,0 +1,48 @@
package config
import (
"io"
"os"
"strings"
"time"
nested "github.com/antonfisher/nested-logrus-formatter"
log "github.com/sirupsen/logrus"
)
func initLog() {
if Settings.Log.DebugLevel {
log.SetLevel(log.DebugLevel)
}
if Settings.Log.WriteFile {
//日志路径初始化与处理
if !strings.HasSuffix(Settings.Log.FilePath, "/") {
Settings.Log.FilePath += "/"
}
e := os.MkdirAll(Settings.Log.FilePath, os.ModePerm)
if e != nil {
log.Fatalln(e)
}
if Settings.Log.FileName == "" {
Settings.Log.FileName = time.Now().Format("2006.01.02-15.04.05") + ".log"
}
f, e := os.OpenFile(Settings.Log.FilePath+Settings.Log.FileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if e != nil {
log.Fatalln(e)
}
//设置双重输出
mw := io.MultiWriter(os.Stdout, f)
log.SetOutput(mw)
//设置输出格式
log.SetFormatter(&nested.Formatter{
HideKeys: true,
NoColors: Settings.Log.WriteFile,
TimestampFormat: "2006-01-02 15:04:05",
})
}
}

37
internal/config/models.go Normal file
View File

@@ -0,0 +1,37 @@
package config
type (
GuardianConf struct {
Enable bool `json:"enable" yaml:"enable"`
Duration uint `json:"duration" yaml:"duration"`
}
BasicConf struct {
Https bool `json:"https" yaml:"https"`
SkipCertVerify bool `json:"skip_cert_verify" yaml:"skip_cert_verify"`
Timeout uint `json:"timeout" yaml:"timeout"`
Interfaces string `json:"interfaces" yaml:"interfaces"`
}
LogConf struct {
DebugLevel bool `json:"debug_level" yaml:"debug_level"`
WriteFile bool `json:"write_file" yaml:"write_file"`
FilePath string `json:"file_path" yaml:"log_path"`
FileName string `json:"file_name" yaml:"log_name"`
}
DdnsConf struct {
Enable bool `json:"enable" yaml:"enable"`
TTL uint `json:"ttl" yaml:"ttl"`
Domain string `json:"domain" yaml:"domain"`
Provider string `json:"provider" yaml:"provider"`
Config map[string]interface{} `json:"config" json:"config" yaml:"config"`
}
)
type SettingsConf struct {
Basic BasicConf `json:"basic" yaml:"basic"`
Guardian GuardianConf `json:"guardian" yaml:"guardian"`
Log LogConf `json:"log" yaml:"log"`
DDNS DdnsConf `json:"ddns" yaml:"ddns"`
}

45
internal/config/reader.go Normal file
View File

@@ -0,0 +1,45 @@
package config
import (
"encoding/json"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"path"
)
func newReaderFromPath(pathname string) Reader {
switch path.Ext(pathname) {
case ".json":
return Json{}
case ".yaml":
return Yaml{}
default:
log.Warnf("未知配置类型,使用 yaml 进行解析")
return Yaml{}
}
}
type Reader interface {
Marshal(v any) ([]byte, error)
Unmarshal(data []byte, v any) error
}
type Json struct {
}
func (Json) Marshal(v any) ([]byte, error) {
return json.MarshalIndent(v, "", " ")
}
func (Json) Unmarshal(data []byte, v any) error {
return json.Unmarshal(data, v)
}
type Yaml struct {
}
func (Yaml) Marshal(v any) ([]byte, error) {
return yaml.Marshal(v)
}
func (Yaml) Unmarshal(data []byte, v any) error {
return yaml.Unmarshal(data, v)
}

View File

@@ -1,7 +1,7 @@
package controllers
import (
"github.com/Mmx233/BitSrunLoginGo/internal/global"
"github.com/Mmx233/BitSrunLoginGo/internal/config"
"time"
"github.com/Mmx233/BitSrunLoginGo/tools"
@@ -12,7 +12,7 @@ import (
func Guardian() {
log.Infoln("[以守护模式启动]")
GuardianDuration := time.Duration(global.Config.Settings.Guardian.Duration) * time.Second
GuardianDuration := time.Duration(config.Settings.Guardian.Duration) * time.Second
var c = make(chan bool)
for {
@@ -20,13 +20,13 @@ func Guardian() {
defer func() {
_ = recover()
}()
if global.Config.Settings.Basic.Interfaces == "" { //单网卡
if config.Settings.Basic.Interfaces == "" { //单网卡
e := Login(nil, true)
if e != nil {
log.Errorln("登录出错: ", e)
}
} else { //多网卡
interfaces, e := tools.GetInterfaceAddr(global.Config.Settings.Basic.Interfaces)
interfaces, e := tools.GetInterfaceAddr(config.Settings.Basic.Interfaces)
if e == nil {
for _, eth := range interfaces {
log.Debugf("使用 %s 网口登录 ", eth.Name)

View File

@@ -1,7 +1,9 @@
package controllers
import (
"github.com/Mmx233/BitSrunLoginGo/internal/global"
"errors"
"github.com/Mmx233/BitSrunLoginGo/internal/config"
"github.com/Mmx233/BitSrunLoginGo/internal/config/flags"
"github.com/Mmx233/BitSrunLoginGo/internal/pkg/dns"
"github.com/Mmx233/BitSrunLoginGo/pkg/srun"
"github.com/Mmx233/BitSrunLoginGo/tools"
@@ -14,23 +16,23 @@ func Login(eth *tools.Eth, debugOutput bool) error {
// 登录配置初始化
httpClient := tools.HttpPackSelect(eth).Client
srunClient := srun.New(&srun.Conf{
Https: global.Config.Settings.Basic.Https,
Https: config.Settings.Basic.Https,
LoginInfo: srun.LoginInfo{
Form: global.Config.Form,
Meta: global.Config.Meta,
Form: *config.Form,
Meta: *config.Meta,
},
Client: httpClient,
})
// 嗅探 acid
if global.Flags.AutoAcid {
if flags.AutoAcid {
log.Debugln("开始嗅探 acid")
acid, e := srunClient.DetectAcid()
if e != nil {
if e == srun.ErrAcidCannotFound {
acid, err := srunClient.DetectAcid()
if err != nil {
if errors.Is(err, srun.ErrAcidCannotFound) {
log.Errorln("找不到 acid使用配置 acid")
} else {
log.Errorf("嗅探 acid 失败,使用配置 acid: %v", e)
log.Errorf("嗅探 acid 失败,使用配置 acid: %v", err)
}
} else {
log.Debugf("使用嗅探 acid: %s", acid)
@@ -60,7 +62,7 @@ func Login(eth *tools.Eth, debugOutput bool) error {
if online {
output("已登录~")
if global.Config.Settings.DDNS.Enable && global.Config.Settings.Guardian.Enable && ipLast != ip {
if config.Settings.DDNS.Enable && config.Settings.Guardian.Enable && ipLast != ip {
if ddns(ip, httpClient) == nil {
ipLast = ip
}
@@ -76,7 +78,7 @@ func Login(eth *tools.Eth, debugOutput bool) error {
log.Infoln("登录成功~")
if global.Config.Settings.DDNS.Enable {
if config.Settings.DDNS.Enable {
_ = ddns(ip, httpClient)
}
}
@@ -88,11 +90,11 @@ var ipLast string
func ddns(ip string, httpClient *http.Client) error {
return dns.Run(&dns.Config{
Provider: global.Config.Settings.DDNS.Provider,
Provider: config.Settings.DDNS.Provider,
IP: ip,
Domain: global.Config.Settings.DDNS.Domain,
TTL: global.Config.Settings.DDNS.TTL,
Conf: global.Config.Settings.DDNS.Config,
Domain: config.Settings.DDNS.Domain,
TTL: config.Settings.DDNS.TTL,
Conf: config.Settings.DDNS.Config,
Http: httpClient,
})
}

View File

@@ -1,83 +0,0 @@
package global
import (
"github.com/Mmx233/BitSrunLoginGo/internal/global/models"
"github.com/Mmx233/BitSrunLoginGo/pkg/srun"
"github.com/Mmx233/tool"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"os"
"time"
)
var Config models.Config
var Timeout time.Duration
func createDefaultConfig() error {
configFile, err := os.OpenFile(Flags.Path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer configFile.Close()
return yaml.NewEncoder(configFile).Encode(&models.Config{
Form: srun.LoginForm{
Domain: "www.msftconnecttest.com",
UserType: "cmcc",
},
Meta: srun.LoginMeta{
N: "200",
Type: "1",
Acid: "5",
Enc: "srun_bx1",
},
Settings: models.Settings{
Basic: models.Basic{
Timeout: 5,
},
Guardian: models.Guardian{
Duration: 300,
},
Log: models.Log{
FilePath: "./",
},
DDNS: models.DDNS{
Enable: false,
TTL: 600,
Domain: "www.example.com",
},
},
})
}
func initConfig() {
// 生成配置文件
if exist, err := tool.File.Exists(Flags.Path); err != nil {
log.Fatalln("[init] 读取配置文件失败:", err)
} else if !exist {
err = createDefaultConfig()
if err != nil {
log.Fatalln("[init] 生成配置文件失败:", err)
}
log.Infoln("[init] 已生成配置文件,请编辑 '" + Flags.Path + "' 然后重试")
os.Exit(0)
}
// 读取配置文件
configBytes, err := os.ReadFile(Flags.Path)
if err != nil {
log.Fatalln("[init] 读取配置失败:", err)
}
if err = yaml.Unmarshal(configBytes, &Config); err != nil {
log.Fatalln("[init] 解析配置失败:", err)
}
// flag 配置覆写
if Flags.Debug {
Config.Settings.Log.DebugLevel = true
}
if Flags.Acid != "" {
Config.Meta.Acid = Flags.Acid
}
}

View File

@@ -1,27 +0,0 @@
package global
import (
"flag"
)
var Flags struct {
// 配置文件路径
Path string
// settings overwrite
Interface string
Debug bool
AutoAcid bool
Acid string
}
func initFlags() {
flag.StringVar(&Flags.Path, "config", "Config.yaml", "config path")
flag.StringVar(&Flags.Interface, "interface", "", "specify the eth name")
flag.BoolVar(&Flags.Debug, "debug", false, "enable debug mode")
flag.BoolVar(&Flags.AutoAcid, "auto-acid", false, "auto detect acid")
flag.StringVar(&Flags.Acid, "acid", "", "specify acid value")
flag.Parse()
}

View File

@@ -1,18 +0,0 @@
package global
import (
"time"
)
func init() {
initFlags()
//配置文件初始化
initConfig()
//初始化常变量
Timeout = time.Duration(Config.Settings.Basic.Timeout) * time.Second
//初始化日志配置
initLog()
}

View File

@@ -1,48 +0,0 @@
package global
import (
"io"
"os"
"strings"
"time"
nested "github.com/antonfisher/nested-logrus-formatter"
log "github.com/sirupsen/logrus"
)
func initLog() {
if Config.Settings.Log.DebugLevel {
log.SetLevel(log.DebugLevel)
}
if Config.Settings.Log.WriteFile {
//日志路径初始化与处理
if !strings.HasSuffix(Config.Settings.Log.FilePath, "/") {
Config.Settings.Log.FilePath += "/"
}
e := os.MkdirAll(Config.Settings.Log.FilePath, os.ModePerm)
if e != nil {
log.Fatalln(e)
}
if Config.Settings.Log.FileName == "" {
Config.Settings.Log.FileName = time.Now().Format("2006.01.02-15.04.05") + ".log"
}
f, e := os.OpenFile(Config.Settings.Log.FilePath+Config.Settings.Log.FileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if e != nil {
log.Fatalln(e)
}
//设置双重输出
mw := io.MultiWriter(os.Stdout, f)
log.SetOutput(mw)
//设置输出格式
log.SetFormatter(&nested.Formatter{
HideKeys: true,
NoColors: Config.Settings.Log.WriteFile,
TimestampFormat: "2006-01-02 15:04:05",
})
}
}

View File

@@ -1,45 +0,0 @@
package models
import (
"github.com/Mmx233/BitSrunLoginGo/pkg/srun"
)
type Guardian struct {
Enable bool `yaml:"enable"`
Duration uint `yaml:"duration"`
}
type Basic struct {
Https bool `yaml:"https"`
SkipCertVerify bool `yaml:"skip_cert_verify"`
Timeout uint `yaml:"timeout"`
Interfaces string `yaml:"interfaces"`
}
type Log struct {
DebugLevel bool `yaml:"debug_level"`
WriteFile bool `yaml:"write_file"`
FilePath string `yaml:"log_path"`
FileName string `yaml:"log_name"`
}
type DDNS struct {
Enable bool `yaml:"enable"`
TTL uint `yaml:"ttl"`
Domain string `yaml:"domain"`
Provider string `yaml:"provider"`
Config map[string]interface{} `yaml:",inline"`
}
type Settings struct {
Basic Basic `yaml:"basic"`
Guardian Guardian `yaml:"guardian"`
Log Log `yaml:"log"`
DDNS DDNS `yaml:"ddns"`
}
type Config struct {
Form srun.LoginForm `yaml:"form"`
Meta srun.LoginMeta `yaml:"meta"`
Settings Settings `yaml:"settings"`
}

View File

@@ -1,18 +1,18 @@
package srun
type LoginForm struct {
Domain string `json:"domain"`
UserName string `json:"username"`
Domain string `json:"domain" yaml:"domain"`
Username string `json:"username" yaml:"username"`
//运营商类型
UserType string `json:"user_type"`
PassWord string `json:"password"`
UserType string `json:"user_type" yaml:"userType"`
Password string `json:"password" yaml:"password"`
}
type LoginMeta struct {
N string `json:"n"`
Type string `json:"type"`
Acid string `json:"acid"`
Enc string `json:"enc"`
N string `json:"n" yaml:"n"`
Type string `json:"type" yaml:"type"`
Acid string `json:"acid" yaml:"acid"`
Enc string `json:"enc" yaml:"enc"`
}
type LoginInfo struct {

View File

@@ -63,10 +63,10 @@ func (c Srun) DoLogin(clientIP string) error {
log.Debugln("正在获取 Token")
if c.LoginInfo.Form.UserType != "" {
c.LoginInfo.Form.UserName += "@" + c.LoginInfo.Form.UserType
c.LoginInfo.Form.Username += "@" + c.LoginInfo.Form.UserType
}
res, e := c.api.GetChallenge(c.LoginInfo.Form.UserName, clientIP)
res, e := c.api.GetChallenge(c.LoginInfo.Form.Username, clientIP)
if e != nil {
return e
}
@@ -80,8 +80,8 @@ func (c Srun) DoLogin(clientIP string) error {
log.Debugln("发送登录请求")
info, e := json.Marshal(map[string]string{
"username": c.LoginInfo.Form.UserName,
"password": c.LoginInfo.Form.PassWord,
"username": c.LoginInfo.Form.Username,
"password": c.LoginInfo.Form.Password,
"ip": clientIP,
"acid": c.LoginInfo.Meta.Acid,
"enc_ver": c.LoginInfo.Meta.Enc,
@@ -93,14 +93,14 @@ func (c Srun) DoLogin(clientIP string) error {
Md5Str := Md5(tokenStr)
EncryptedMd5 := "{MD5}" + Md5Str
EncryptedChkstr := Sha1(
tokenStr + c.LoginInfo.Form.UserName + tokenStr + Md5Str +
tokenStr + c.LoginInfo.Form.Username + tokenStr + Md5Str +
tokenStr + c.LoginInfo.Meta.Acid + tokenStr + clientIP +
tokenStr + c.LoginInfo.Meta.N + tokenStr + c.LoginInfo.Meta.Type +
tokenStr + EncryptedInfo,
)
res, e = c.api.Login(
c.LoginInfo.Form.UserName,
c.LoginInfo.Form.Username,
EncryptedMd5,
c.LoginInfo.Meta.Acid,
clientIP,

View File

@@ -1,7 +1,7 @@
package tools
import (
"github.com/Mmx233/BitSrunLoginGo/internal/global"
"github.com/Mmx233/BitSrunLoginGo/internal/config"
"net/http"
)
@@ -14,10 +14,10 @@ var HttpPack *Http
var httpTools map[string]*Http
func init() {
if global.Config.Settings.Basic.Interfaces == "" {
if config.Settings.Basic.Interfaces == "" {
HttpPack = genHttpPack(nil)
} else {
httpTools = make(map[string]*Http, 0)
httpTools = make(map[string]*Http)
}
}

View File

@@ -3,7 +3,7 @@
package tools
import (
"github.com/Mmx233/BitSrunLoginGo/internal/global"
"github.com/Mmx233/BitSrunLoginGo/internal/config"
"github.com/Mmx233/tool"
"net"
"net/http"
@@ -15,15 +15,15 @@ func genHttpPack(eth *Eth) *Http {
addr = eth.Addr
}
tr := tool.GenHttpTransport(&tool.HttpTransportOptions{
Timeout: global.Timeout,
Timeout: config.Timeout,
LocalAddr: addr,
SkipSslCertVerify: global.Config.Settings.Basic.SkipCertVerify,
SkipSslCertVerify: config.Settings.Basic.SkipCertVerify,
})
tr.Proxy = http.ProxyFromEnvironment
return &Http{
Client: tool.GenHttpClient(&tool.HttpClientOptions{
Transport: tr,
Timeout: global.Timeout,
Timeout: config.Timeout,
}),
}
}

View File

@@ -35,7 +35,7 @@ func genHttpPack(eth *Eth) *Http {
DialContext: dialer.DialContext,
TLSHandshakeTimeout: global.Timeout,
IdleConnTimeout: global.Timeout,
TLSClientConfig: &tls.Config{InsecureSkipVerify: global.Config.Settings.Basic.SkipCertVerify},
TLSClientConfig: &tls.Config{InsecureSkipVerify: config.Settings.Basic.SkipCertVerify},
}
tr.Proxy = http.ProxyFromEnvironment
return &Http{