【调整】暗色主题样式

This commit is contained in:
cai
2025-12-12 17:39:52 +08:00
parent 13669666e4
commit d01b42139c
1199 changed files with 203816 additions and 4592 deletions

View File

@@ -0,0 +1,84 @@
package bt
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
)
// 生成 API 签名
func (c *Config) generateSignature(method, path string, body string) (string, string) {
timestamp := fmt.Sprintf("%d", time.Now().Unix())
signingString := fmt.Sprintf("%s\n%s\n%s\n%s\n%s",
c.AccountID,
timestamp,
strings.ToUpper(method),
path,
body,
)
h := hmac.New(sha256.New, []byte(c.SecretKey))
h.Write([]byte(signingString))
signature := hex.EncodeToString(h.Sum(nil))
return timestamp, signature
}
// 发起 API 请求
func (c *Config) MakeRequest(method, path string, data interface{}) (map[string]interface{}, error) {
url := strings.TrimRight(c.BaseURL, "/") + path
var bodyStr string
var bodyBytes []byte
if data != nil {
b, err := json.Marshal(data)
if err != nil {
return nil, err
}
bodyStr = string(b)
bodyBytes = b
}
timestamp, signature := c.generateSignature(method, path, bodyStr)
req, err := http.NewRequest(method, url, bytes.NewBuffer(bodyBytes))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Account-ID", c.AccountID)
req.Header.Set("X-Access-Key", c.AccessKey)
req.Header.Set("X-Timestamp", timestamp)
req.Header.Set("X-Signature", signature)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result map[string]interface{}
if err := json.Unmarshal(respBytes, &result); err != nil {
return nil, err
}
if !result["status"].(bool) {
return nil, fmt.Errorf("API 请求失败: %v", result["msg"])
}
return result, nil
}

View File

@@ -0,0 +1,197 @@
package bt
import (
"fmt"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/platform/config/env"
"time"
)
const (
envNamespace = "BTDOMAIN_"
EnvAccountID = envNamespace + "ACCOUNT_ID"
EnvAccessKey = envNamespace + "ACCESS_KEY"
EnvSecretKey = envNamespace + "SECRET_KEY"
EnvBaseURL = envNamespace + "BASE_URL"
EnvTTL = envNamespace + "TTL"
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
)
var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
type Config struct {
AccountID string
AccessKey string
SecretKey string
BaseURL string
PropagationTimeout time.Duration
PollingInterval time.Duration
TTL int
HTTPTimeout time.Duration
}
func NewConfig(accountID, accessKey, secretKey, baseURL string) *Config {
return &Config{
AccountID: accountID,
AccessKey: accessKey,
SecretKey: secretKey,
BaseURL: baseURL,
TTL: 600,
PropagationTimeout: dns01.DefaultPropagationTimeout,
PollingInterval: dns01.DefaultPollingInterval,
HTTPTimeout: 30 * time.Second,
}
}
func NewDefaultConfig() *Config {
return &Config{
BaseURL: env.GetOrDefaultString(EnvBaseURL, "https://dmp.bt.cn"),
TTL: env.GetOrDefaultInt(EnvTTL, 600),
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
}
}
type DNSProvider struct {
config *Config
}
func NewDNSProvider() (*DNSProvider, error) {
values, err := env.Get(EnvAccountID, EnvAccessKey, EnvSecretKey)
if err != nil {
return nil, fmt.Errorf("westcn: %w", err)
}
config := NewDefaultConfig()
config.AccountID = values[EnvAccountID]
config.AccessKey = values[EnvAccessKey]
config.SecretKey = values[EnvSecretKey]
return NewDNSProviderConfig(config)
}
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, nil
}
return &DNSProvider{config: config}, nil
}
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
return d.config.addDNSRecord(domain, keyAuth)
}
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
return d.config.removeDNSRecord(domain, keyAuth)
}
func (c *Config) GetDomainId(domain string) (int, int) {
domain = dns01.UnFqdn(domain)
resp, err := c.MakeRequest("POST", "/api/v1/dns/manage/list_domains", map[string]interface{}{
"p": "1",
"rows": "100",
"keyword": domain,
})
if err != nil {
return 0, 0
}
if !resp["status"].(bool) {
return 0, 0
}
data := resp["data"].(map[string]interface{})
list := data["data"].([]interface{})
for _, item := range list {
d := item.(map[string]interface{})
if d["full_domain"].(string) == domain {
return int(d["local_id"].(float64)), int(d["domain_type"].(float64))
}
}
return 0, 0
}
func (c *Config) addDNSRecord(domain, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
EffectiveFQDN := dns01.UnFqdn(info.EffectiveFQDN)
rootDomain, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
if err != nil {
return fmt.Errorf("无法获取域名的根域名: %w", err)
}
subDomain, err := dns01.ExtractSubDomain(EffectiveFQDN, rootDomain)
if err != nil {
return fmt.Errorf("无法获取域名的子域名: %w", err)
}
domainId, domainType := c.GetDomainId(rootDomain)
if domainId == 0 {
return nil
}
_, err = c.MakeRequest("POST", "/api/v1/dns/record/create", map[string]interface{}{
"domain_id": domainId,
"domain_type": domainType,
"record": subDomain,
"value": info.Value,
"type": "TXT",
})
return err
}
func (c *Config) removeDNSRecord(domain, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
EffectiveFQDN := dns01.UnFqdn(info.EffectiveFQDN)
rootDomain, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
if err != nil {
return fmt.Errorf("无法获取域名的根域名: %w", err)
}
subDomain, err := dns01.ExtractSubDomain(EffectiveFQDN, rootDomain)
if err != nil {
return fmt.Errorf("无法获取域名的子域名: %w", err)
}
domainId, domainType := c.GetDomainId(rootDomain)
if domainId == 0 {
return nil
}
resp, err := c.MakeRequest("POST", "/api/v1/dns/record/list", map[string]interface{}{
"domain_id": domainId,
"domain_type": domainType,
"p": "1",
"rows": "100",
"searchKey": subDomain,
})
if err != nil {
return err
}
if !resp["status"].(bool) {
return nil
}
data := resp["data"].(map[string]interface{})
list := data["data"].([]interface{})
for _, item := range list {
d := item.(map[string]interface{})
if d["record"].(string) == subDomain && d["type"].(string) == "TXT" && d["value"].(string) == info.Value {
_, err = c.MakeRequest("POST", "/api/v1/dns/record/delete", map[string]interface{}{
"domain_id": domainId,
"domain_type": domainType,
"record_id": int(d["record_id"].(float64)),
})
return err
}
}
return nil
}

View File

@@ -0,0 +1,242 @@
// This file is originally from Certimate by fudiwei
// Source: https://github.com/usual2970/certimate/blob/main/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go
// License: MIT
package jdcloud
import (
"errors"
"fmt"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/platform/config/env"
jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core"
jddnsapi "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/apis"
jddnsclient "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/client"
jddnsmodel "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/models"
)
const (
envNamespace = "JDCLOUD_"
EnvAccessKeyID = envNamespace + "ACCESS_KEY_ID"
EnvAccessKeySecret = envNamespace + "ACCESS_KEY_SECRET"
EnvRegionId = envNamespace + "REGION_ID"
EnvTTL = envNamespace + "TTL"
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
)
var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
type Config struct {
AccessKeyID string
AccessKeySecret string
RegionId string
PropagationTimeout time.Duration
PollingInterval time.Duration
TTL int32
HTTPTimeout time.Duration
}
type DNSProvider struct {
client *jddnsclient.DomainserviceClient
config *Config
}
func NewDefaultConfig() *Config {
return &Config{
TTL: int32(env.GetOrDefaultInt(EnvTTL, 300)),
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute),
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
}
}
func NewDNSProvider() (*DNSProvider, error) {
values, err := env.Get(EnvAccessKeyID, EnvAccessKeySecret)
if err != nil {
return nil, fmt.Errorf("jdcloud: %w", err)
}
config := NewDefaultConfig()
config.AccessKeyID = values[EnvAccessKeyID]
config.AccessKeySecret = values[EnvAccessKeySecret]
config.RegionId = values[EnvRegionId]
return NewDNSProviderConfig(config)
}
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, errors.New("jdcloud: the configuration of the DNS provider is nil")
}
clientCredentials := jdcore.NewCredentials(config.AccessKeyID, config.AccessKeySecret)
client := jddnsclient.NewDomainserviceClient(clientCredentials)
clientConfig := &client.Config
clientConfig.SetTimeout(config.HTTPTimeout)
client.SetConfig(clientConfig)
client.SetLogger(jdcore.NewDefaultLogger(jdcore.LogWarn))
return &DNSProvider{
client: client,
config: config,
}, nil
}
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
if err != nil {
return fmt.Errorf("jdcloud: could not find zone for domain %q: %w", domain, err)
}
subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
if err != nil {
return fmt.Errorf("jdcloud: %w", err)
}
if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil {
return fmt.Errorf("jdcloud: %w", err)
}
return nil
}
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
if err != nil {
return fmt.Errorf("jdcloud: could not find zone for domain %q: %w", domain, err)
}
subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
if err != nil {
return fmt.Errorf("jdcloud: %w", err)
}
if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil {
return fmt.Errorf("jdcloud: %w", err)
}
return nil
}
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}
func (d *DNSProvider) getDNSZone(zoneName string) (*jddnsmodel.DomainInfo, error) {
pageNumber := 1
pageSize := 10
for {
request := jddnsapi.NewDescribeDomainsRequest(d.config.RegionId, pageNumber, pageSize)
request.SetDomainName(zoneName)
response, err := d.client.DescribeDomains(request)
if err != nil {
return nil, err
}
for _, item := range response.Result.DataList {
if item.DomainName == zoneName {
return &item, nil
}
}
if len(response.Result.DataList) < pageSize {
break
}
pageNumber++
}
return nil, fmt.Errorf("jdcloud: zone %s not found", zoneName)
}
func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jddnsmodel.DomainInfo, *jddnsmodel.RRInfo, error) {
zone, err := d.getDNSZone(zoneName)
if err != nil {
return nil, nil, err
}
pageNumber := 1
pageSize := 10
for {
request := jddnsapi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id))
request.SetSearch(subDomain)
request.SetPageNumber(pageNumber)
request.SetPageSize(pageSize)
response, err := d.client.DescribeResourceRecord(request)
if err != nil {
return zone, nil, err
}
for _, record := range response.Result.DataList {
if record.Type == "TXT" && record.HostRecord == subDomain {
return zone, &record, nil
}
}
if len(response.Result.DataList) < pageSize {
break
}
pageNumber++
}
return zone, nil, nil
}
func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain)
if err != nil {
return err
}
if record == nil {
request := jddnsapi.NewCreateResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), &jddnsmodel.AddRR{
Type: "TXT",
HostRecord: subDomain,
HostValue: value,
Ttl: int(d.config.TTL),
ViewValue: -1,
})
_, err := d.client.CreateResourceRecord(request)
return err
} else {
request := jddnsapi.NewModifyResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id), &jddnsmodel.UpdateRR{
Type: "TXT",
HostRecord: subDomain,
HostValue: value,
Ttl: int(d.config.TTL),
ViewValue: -1,
})
_, err := d.client.ModifyResourceRecord(request)
return err
}
}
func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain)
if err != nil {
return err
}
if record == nil {
return nil
} else {
request := jddnsapi.NewDeleteResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id))
_, err = d.client.DeleteResourceRecord(request)
return err
}
}

View File

@@ -0,0 +1,76 @@
package webhook
import (
"ALLinSSL/backend/public"
"fmt"
"github.com/go-acme/lego/v4/challenge/dns01"
"time"
)
type Config struct {
WebhookConfig *public.WebhookConfig
PropagationTimeout time.Duration
PollingInterval time.Duration
TTL int
HTTPTimeout time.Duration
}
type DNSProvider struct {
config *Config
dataTemp string
}
func NewConfig(WebhookConfigStr map[string]string) *Config {
WebhookConfig := &public.WebhookConfig{
Url: WebhookConfigStr["url"],
Data: WebhookConfigStr["data"],
Method: WebhookConfigStr["method"],
Headers: WebhookConfigStr["headers"],
IgnoreSSL: WebhookConfigStr["ignore_ssl"] == "1",
}
return &Config{
WebhookConfig: WebhookConfig,
TTL: 600,
PropagationTimeout: dns01.DefaultPropagationTimeout,
PollingInterval: dns01.DefaultPollingInterval,
HTTPTimeout: 30 * time.Second,
}
}
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, fmt.Errorf("配置不能为空")
}
return &DNSProvider{
config: config,
dataTemp: config.WebhookConfig.Data,
}, nil
}
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
d.config.WebhookConfig.Data = d.dataTemp
return d.send(domain, token, keyAuth, "present")
}
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
d.config.WebhookConfig.Data = d.dataTemp
return d.send(domain, token, keyAuth, "cleanup")
}
func (d *DNSProvider) send(domain, token, keyAuth, action string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
data, err := public.ReplaceJSONPlaceholders(d.config.WebhookConfig.Data, map[string]interface{}{"domain": info.EffectiveFQDN, "token": token, "keyAuth": info.Value, "action": action})
if err != nil {
return fmt.Errorf("替换JSON占位符失败: %w", err)
}
d.config.WebhookConfig.Data = data
return d.config.WebhookConfig.Send()
}