style: rename controllers to login, cancel internal/pkg

This commit is contained in:
Mmx
2024-10-14 12:50:59 +08:00
parent e963917d87
commit 20c4d3df55
14 changed files with 31 additions and 31 deletions

View File

@@ -0,0 +1,179 @@
package aliyun
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/Mmx233/BitSrunLoginGo/internal/dns/util"
"github.com/Mmx233/tool"
"math/rand"
"net/http"
"net/url"
"sort"
"time"
)
type Aliyun struct {
AccessKeyId string `json:"access_key_id,omitempty" yaml:"access_key_id,omitempty"`
AccessKeySecret string `json:"access_key_secret,omitempty" yaml:"access_key_secret,omitempty"`
}
type DnsProvider struct {
TTL uint
Http *tool.Http
Aliyun
}
func New(ttl uint, conf Aliyun, Http *http.Client) (*DnsProvider, error) {
if conf.AccessKeyId == "" || conf.AccessKeySecret == "" {
return nil, errors.New("aliyun AccessKey 不能为空")
}
return &DnsProvider{
TTL: ttl,
Http: tool.NewHttpTool(Http),
Aliyun: conf,
}, nil
}
func (a DnsProvider) SendRequest(Type, Action string, data map[string]interface{}) (*http.Response, error) {
var reqOpt = tool.DoHttpReq{
Url: "https://alidns.aliyuncs.com",
}
data["Format"] = "json"
data["Version"] = "2015-01-09"
data["SignatureMethod"] = "HMAC-SHA1"
data["SignatureVersion"] = "1.0"
data["SignatureNonce"] = fmt.Sprint(tool.RandMath(rand.NewSource(time.Now().UnixNano())).Num(10000000, 90000000))
data["Timestamp"] = time.Now().UTC().Format("2006-01-02T15:04:05Z")
data["Action"] = Action
data["AccessKeyId"] = a.AccessKeyId
signStr := Type + "&" + url.QueryEscape("/") + "&"
var keys = make([]string, len(data))
var i int
for k := range data {
keys[i] = k
i++
}
sort.Strings(keys)
for i, k := range keys {
str := k + "=" + url.QueryEscape(fmt.Sprint(data[k]))
if i == 0 {
str = url.QueryEscape(str)
} else {
str = url.QueryEscape("&" + str)
}
signStr += str
}
mac := hmac.New(sha1.New, []byte(a.AccessKeySecret+"&"))
_, err := mac.Write([]byte(signStr))
if err != nil {
return nil, err
}
data["Signature"] = base64.StdEncoding.EncodeToString(mac.Sum(nil))
if Type == "GET" || Type == "DELETE" {
reqOpt.Query = data
} else {
reqOpt.Body = data
}
resp, err := a.Http.Request(Type, &reqOpt)
if err != nil {
return nil, err
}
if resp.StatusCode > 299 {
defer resp.Body.Close()
var res Response
if err = json.NewDecoder(resp.Body).Decode(&res); err != nil {
return nil, err
}
return nil, errors.New(res.Message)
}
return resp, nil
}
func (a DnsProvider) DomainRecordStatus(subDomain, rootDomain string) (*DomainStatus, bool, error) {
resp, err := a.SendRequest("GET", "DescribeDomainRecords", map[string]interface{}{
"DomainName": rootDomain,
"SearchMode": "EXACT",
"KeyWord": subDomain,
"PageSize": 1,
"Type": "A",
})
if err != nil {
return nil, false, err
}
defer resp.Body.Close()
var res DomainStatusRes
if err = json.NewDecoder(resp.Body).Decode(&res); err != nil {
return nil, false, err
}
if res.TotalCount == 0 || len(res.DomainRecords.Record) == 0 {
return nil, false, nil
}
return &res.DomainRecords.Record[0], true, nil
}
func (a DnsProvider) UpdateRecord(RecordId, subDomain, ip string) error {
resp, err := a.SendRequest("POST", "UpdateDomainRecord", map[string]interface{}{
"RecordId": RecordId,
"RR": subDomain,
"Type": "A",
"Value": ip,
"TTL": a.TTL,
})
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
func (a DnsProvider) NewRecord(subDomain, rootDomain, ip string) error {
resp, err := a.SendRequest("POST", "AddDomainRecord", map[string]interface{}{
"DomainName": rootDomain,
"RR": subDomain,
"Type": "A",
"Value": ip,
"TTL": a.TTL,
})
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
func (a DnsProvider) SetDomainRecord(domain, ip string) error {
subDomain, rootDomain, err := dnsUtil.DecodeDomain(domain)
if err != nil {
return err
}
record, exist, err := a.DomainRecordStatus(subDomain, rootDomain)
if err != nil {
return err
}
if exist {
if record.Value == ip {
return nil
}
return a.UpdateRecord(record.RecordId, subDomain, ip)
} else {
return a.NewRecord(subDomain, rootDomain, ip)
}
}

View File

@@ -0,0 +1,19 @@
package aliyun
type Response struct {
Code string `json:"code"`
Message string `json:"message"`
}
type DomainStatus struct {
DomainName string `json:"DomainName"`
RecordId string `json:"RecordId"`
Value string `json:"Value"`
}
type DomainStatusRes struct {
TotalCount uint `json:"TotalCount"`
DomainRecords struct {
Record []DomainStatus `json:"Record"`
} `json:"DomainRecords"`
}

View File

@@ -0,0 +1,67 @@
package cloudflare
import (
"context"
"errors"
"github.com/cloudflare/cloudflare-go"
"net/http"
)
type Cloudflare struct {
Zone string `json:"zone" yaml:"zone"`
Token string `json:"token" yaml:"token"`
}
type DnsProvider struct {
Api *cloudflare.API
TTL int
ZoneResource *cloudflare.ResourceContainer
Cloudflare
}
func New(ttl int, conf Cloudflare, Http *http.Client) (*DnsProvider, error) {
var p = DnsProvider{
TTL: ttl,
Cloudflare: conf,
}
if p.Zone == "" {
return nil, errors.New("cloudflare zone 不能为空")
}
if p.Token == "" {
return nil, errors.New("cloudflare token 不能为空")
}
p.ZoneResource = cloudflare.ZoneIdentifier(p.Zone)
var err error
p.Api, err = cloudflare.NewWithAPIToken(p.Token, cloudflare.HTTPClient(Http))
return &p, err
}
func (a DnsProvider) SetDomainRecord(domain, ip string) error {
records, _, err := a.Api.ListDNSRecords(context.Background(), a.ZoneResource, cloudflare.ListDNSRecordsParams{
Type: "A",
Name: domain,
})
if err != nil {
return err
}
if len(records) == 0 {
_, err = a.Api.CreateDNSRecord(context.Background(), a.ZoneResource, cloudflare.CreateDNSRecordParams{
Type: "A",
Name: domain,
Content: ip,
TTL: a.TTL,
})
return err
} else {
record := records[0]
if record.Content == ip {
return nil
}
_, err = a.Api.UpdateDNSRecord(context.Background(), a.ZoneResource, cloudflare.UpdateDNSRecordParams{
ID: record.ID,
Content: ip,
})
return err
}
}

56
internal/dns/dns.go Normal file
View File

@@ -0,0 +1,56 @@
package dns
import (
"errors"
"fmt"
"github.com/Mmx233/BitSrunLoginGo/internal/dns/aliyun"
"github.com/Mmx233/BitSrunLoginGo/internal/dns/cloudflare"
"github.com/Mmx233/BitSrunLoginGo/internal/dns/dnspod"
log "github.com/sirupsen/logrus"
)
func Run(c *Config) error {
if c.Logger == nil {
c.Logger = log.New()
}
if c.TTL == 0 {
c.TTL = 600
}
c.Logger.Infof("开始 %s DDNS 流程", c.Provider)
var dns Provider
var err error
switch c.Provider {
case "aliyun":
dns, err = aliyun.New(c.TTL, c.Conf.Aliyun, c.Http)
case "cloudflare":
dns, err = cloudflare.New(int(c.TTL), c.Conf.Cloudflare, c.Http)
case "dnspod":
dns, err = dnspod.New(uint64(c.TTL), c.Conf.DnsPod, c.Http.Transport)
default:
var msg string
if c.Provider == "" {
msg = "DDNS 模块 dns 运营商不能为空"
} else {
msg = fmt.Sprintf("DDNS 模块 dns 运营商 %s 不支持", c.Provider)
}
c.Logger.Warnln(msg)
return errors.New(msg)
}
if err != nil {
c.Logger.Warnf("解析 DDNS config 失败:%v", err)
return err
}
// 修改 dns 记录
if err = dns.SetDomainRecord(c.Domain, c.IP); err != nil {
c.Logger.Warnf("设置 dns 解析记录失败:%v", err)
return err
}
c.Logger.Infof("DDNS 配置应用成功: %s | %s", c.Domain, c.IP)
return nil
}

View File

@@ -0,0 +1,72 @@
package dnspod
import (
"github.com/Mmx233/BitSrunLoginGo/internal/dns/util"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/regions"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
"net/http"
"strings"
)
type DnsPod struct {
SecretId string `json:"secret_id,omitempty" yaml:"secret_id,omitempty"`
SecretKey string `json:"secret_key,omitempty" yaml:"secret_key,omitempty"`
}
type DnsProvider struct {
Client *dnspod.Client
TTL uint64
DnsPod
}
func New(ttl uint64, conf DnsPod, Http http.RoundTripper) (*DnsProvider, error) {
var p = DnsProvider{TTL: ttl, DnsPod: conf}
var err error
p.Client, err = dnspod.NewClient(common.NewCredential(p.SecretId, p.SecretKey), regions.Guangzhou, profile.NewClientProfile())
p.Client.WithHttpTransport(Http)
return &p, err
}
func (a DnsProvider) SetDomainRecord(domain, ip string) error {
subDomain, rootDomain, err := dnsUtil.DecodeDomain(domain)
if err != nil {
return err
}
var (
recordType = "A"
recordLine = "默认"
limit uint64 = 1
)
reqRecordList := dnspod.NewDescribeRecordListRequest()
reqRecordList.Domain = &rootDomain
reqRecordList.Subdomain = &subDomain
reqRecordList.Limit = &limit
res, err := a.Client.DescribeRecordList(reqRecordList)
if (err != nil && strings.Contains(err.Error(), dnspod.RESOURCENOTFOUND_NODATAOFRECORD)) || (err == nil && len(res.Response.RecordList) == 0) {
reqNewRecord := dnspod.NewCreateRecordRequest()
reqNewRecord.TTL = &a.TTL
reqNewRecord.Domain = &rootDomain
reqNewRecord.RecordType = &recordType
reqNewRecord.RecordLine = &recordLine
reqNewRecord.Value = &ip
reqNewRecord.SubDomain = &subDomain
_, err = a.Client.CreateRecord(reqNewRecord)
return err
} else if err != nil {
return err
}
reqModifyRecord := dnspod.NewModifyRecordRequest()
reqModifyRecord.Domain = &rootDomain
reqModifyRecord.SubDomain = &subDomain
reqModifyRecord.Value = &ip
reqModifyRecord.RecordId = res.Response.RecordList[0].RecordId
reqModifyRecord.RecordLine = &recordLine
reqModifyRecord.RecordType = &recordType
_, err = a.Client.ModifyRecord(reqModifyRecord)
return err
}

21
internal/dns/models.go Normal file
View File

@@ -0,0 +1,21 @@
package dns
import (
"github.com/Mmx233/BitSrunLoginGo/internal/config"
log "github.com/sirupsen/logrus"
"net/http"
)
type Provider interface {
SetDomainRecord(domain, ip string) error
}
type Config struct {
Provider string
IP string
Domain string
TTL uint
Conf config.DdnsProviderConfigSum
Http *http.Client
Logger log.FieldLogger
}

View File

@@ -0,0 +1,18 @@
package dnsUtil
import (
"errors"
"strings"
)
func DecodeDomain(domain string) (subStr string, rootDomain string, e error) {
t := strings.Split(domain, ".")
if len(t) == 1 {
return "", "", errors.New("域名不合法")
} else if len(t) == 2 {
return "@", domain, nil
}
l := len(t)
return strings.Join(t[:l-2], "."), strings.Join(t[l-2:l], "."), nil
}