【调整】暗色主题样式

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,156 @@
package main
import (
"ALLinSSL/plugins/aliyun/cas"
"ALLinSSL/plugins/aliyun/esa"
"fmt"
"strconv"
"strings"
)
func uploadToCAS(cfg map[string]any) (*Response, error) {
if cfg == nil {
return nil, fmt.Errorf("config cannot be nil")
}
certStr, ok := cfg["cert"].(string)
if !ok || certStr == "" {
return nil, fmt.Errorf("cert is required and must be a string")
}
keyStr, ok := cfg["key"].(string)
if !ok || keyStr == "" {
return nil, fmt.Errorf("key is required and must be a string")
}
accessKey, ok := cfg["access_key"].(string)
if !ok || accessKey == "" {
return nil, fmt.Errorf("access_key is required and must be a string")
}
secretKey, ok := cfg["secret_key"].(string)
if !ok || secretKey == "" {
return nil, fmt.Errorf("secret_key is required and must be a string")
}
endpoint, ok := cfg["endpoint"].(string)
if !ok || endpoint == "" {
endpoint = "cas.ap-southeast-1.aliyuncs.com" // 默认值
}
name, ok := cfg["name"].(string)
if !ok || name == "" {
name = "allinssl-certificate" // 默认名称
}
client, err := cas.CreateClient(accessKey, secretKey, endpoint)
if err != nil {
return nil, fmt.Errorf("failed to create CAS client: %w", err)
}
// 上传证书到 CAS
err = cas.UploadToCas(client, certStr, keyStr, name)
if err != nil {
return nil, fmt.Errorf("failed to upload certificate to CAS: %w", err)
}
return &Response{
Status: "success",
Message: "CAS upload successful",
Result: nil,
}, nil
}
func deployToESA(cfg map[string]any) (*Response, error) {
if cfg == nil {
return nil, fmt.Errorf("config cannot be nil")
}
certPEM, ok := cfg["cert"].(string)
if !ok || certPEM == "" {
return nil, fmt.Errorf("cert is required and must be a string")
}
privkeyPEM, ok := cfg["key"].(string)
if !ok || privkeyPEM == "" {
return nil, fmt.Errorf("key is required and must be a string")
}
accessKey, ok := cfg["access_key"].(string)
if !ok || accessKey == "" {
return nil, fmt.Errorf("access_key is required and must be a string")
}
secretKey, ok := cfg["secret_key"].(string)
if !ok || secretKey == "" {
return nil, fmt.Errorf("secret_key is required and must be a string")
}
var siteID int64
switch v := cfg["site_id"].(type) {
case float64:
siteID = int64(v)
case string:
var err error
siteID, err = strconv.ParseInt(v, 10, 64)
if err != nil {
return nil, fmt.Errorf("site_id format error: %w", err)
}
case int:
siteID = int64(v)
default:
return nil, fmt.Errorf("site_id format error")
}
var delRepeatDomainCert bool
switch v := cfg["del_repeat_domain_cert"].(type) {
case bool:
delRepeatDomainCert = v
case string:
if v == "true" {
delRepeatDomainCert = true
}
case nil:
delRepeatDomainCert = false
}
client, err := esa.CreateEsaClient(accessKey, secretKey)
if err != nil {
return nil, fmt.Errorf("failed to create ESA client: %w", err)
}
// 检查是否需要删除重复的域名证书
if delRepeatDomainCert {
// 解析现有证书的域名
certObj, err := ParseCertificate([]byte(certPEM))
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %w", err)
}
domainSet := make(map[string]bool)
if certObj.Subject.CommonName != "" {
domainSet[certObj.Subject.CommonName] = true
}
for _, dns := range certObj.DNSNames {
domainSet[dns] = true
}
// 转成切片并拼接成逗号分隔的字符串
var domains []string
for domain := range domainSet {
domains = append(domains, domain)
}
domainList := strings.Join(domains, ",")
certList, err := esa.ListCertFromESA(client, siteID)
if err != nil {
return nil, fmt.Errorf("failed to list certificates from ESA: %w", err)
}
for _, cert := range certList {
if *cert.SAN == domainList {
err = esa.DeleteEsaCert(client, siteID, *cert.Id)
if err != nil {
return nil, fmt.Errorf("failed to delete existing certificate: %w", err)
}
}
}
}
err = esa.UploadCertToESA(client, siteID, certPEM, privkeyPEM)
if err != nil {
return nil, fmt.Errorf("failed to upload certificate to ESA: %w", err)
}
return &Response{
Status: "success",
Message: "ESA deployment successful",
Result: nil,
}, nil
}

View File

@@ -0,0 +1,31 @@
package cas
import (
cas "github.com/alibabacloud-go/cas-20200407/v4/client"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
)
func CreateClient(accessKey, accessSecret, endpoint string) (*cas.Client, error) {
if endpoint == "" {
endpoint = "cas.ap-southeast-1.aliyuncs.com"
}
config := &openapi.Config{
AccessKeyId: tea.String(accessKey),
AccessKeySecret: tea.String(accessSecret),
Endpoint: tea.String(endpoint),
}
return cas.NewClient(config)
}
func UploadToCas(client *cas.Client, cert, key, name string) error {
uploadUserCertificateRequest := &cas.UploadUserCertificateRequest{
Name: tea.String(name),
Cert: tea.String(cert),
Key: tea.String(key),
}
runtime := &util.RuntimeOptions{}
_, err := client.UploadUserCertificateWithOptions(uploadUserCertificateRequest, runtime)
return err
}

View File

@@ -0,0 +1,63 @@
package esa
import (
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
esa "github.com/alibabacloud-go/esa-20240910/v2/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
)
// CreateEsaClient creates a new ESA client with the provided access key and secret.
func CreateEsaClient(accessKey, accessSecret string) (*esa.Client, error) {
config := &openapi.Config{
AccessKeyId: tea.String(accessKey),
AccessKeySecret: tea.String(accessSecret),
Endpoint: tea.String("esa.ap-southeast-1.aliyuncs.com"),
}
return esa.NewClient(config)
}
// UploadCertToESA uploads the certificate and private key to Alibaba Cloud ESA.
func UploadCertToESA(client *esa.Client, id int64, certPEM, privkeyPEM string) error {
req := esa.SetCertificateRequest{
SiteId: tea.Int64(id),
Type: tea.String("upload"),
Certificate: tea.String(certPEM),
PrivateKey: tea.String(privkeyPEM),
}
runtime := &util.RuntimeOptions{}
_, err := client.SetCertificateWithOptions(&req, runtime)
if err != nil {
return err
}
return nil
}
// ListCertFromESA retrieves the list of certificates from Alibaba Cloud ESA for a given site ID.
func ListCertFromESA(client *esa.Client, id int64) ([]*esa.ListCertificatesResponseBodyResult, error) {
req := esa.ListCertificatesRequest{
SiteId: tea.Int64(id),
}
runtime := &util.RuntimeOptions{}
resp, err := client.ListCertificatesWithOptions(&req, runtime)
if err != nil {
return nil, err
}
return resp.Body.Result, nil
}
// DeleteEsaCert deletes a certificate from Alibaba Cloud ESA by its ID.
func DeleteEsaCert(client *esa.Client, id int64, certID string) error {
req := esa.DeleteCertificateRequest{
SiteId: tea.Int64(id),
Id: tea.String(certID),
}
runtime := &util.RuntimeOptions{}
_, err := client.DeleteCertificateWithOptions(&req, runtime)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,123 @@
package main
import (
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"io"
"os"
)
type ActionInfo struct {
Name string `json:"name"`
Description string `json:"description"`
Params map[string]any `json:"params,omitempty"` // 可选参数
}
type Request struct {
Action string `json:"action"`
Params map[string]interface{} `json:"params"`
}
type Response struct {
Status string `json:"status"`
Message string `json:"message"`
Result map[string]interface{} `json:"result"`
}
var pluginMeta = map[string]interface{}{
"name": "aliyun",
"description": "部署到阿里云",
"version": "1.0.0",
"author": "主包",
"config": map[string]interface{}{
"access_key": "阿里云 AccessKey",
"secret_key": "阿里云 SecretKey",
},
"actions": []ActionInfo{
{
Name: "deployToESA",
Description: "部署到阿里云esa",
Params: map[string]any{
"site_id": "站点 ID",
"del_repeat_domain_cert": "是否删除重复的域名证书,默认 false",
},
},
{
Name: "uploadToCAS",
Description: "上传到阿里云cas",
Params: map[string]any{
"name": "证书名称",
},
},
},
}
// **解析 PEM 格式的证书**
func ParseCertificate(certPEM []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(certPEM)
if block == nil {
return nil, fmt.Errorf("无法解析证书 PEM")
}
return x509.ParseCertificate(block.Bytes)
}
func outputJSON(resp *Response) {
_ = json.NewEncoder(os.Stdout).Encode(resp)
}
func outputError(msg string, err error) {
outputJSON(&Response{
Status: "error",
Message: fmt.Sprintf("%s: %v", msg, err),
})
}
func main() {
var req Request
input, err := io.ReadAll(os.Stdin)
if err != nil {
outputError("读取输入失败", err)
return
}
if err := json.Unmarshal(input, &req); err != nil {
outputError("解析请求失败", err)
return
}
switch req.Action {
case "get_metadata":
outputJSON(&Response{
Status: "success",
Message: "插件信息",
Result: pluginMeta,
})
case "list_actions":
outputJSON(&Response{
Status: "success",
Message: "支持的动作",
Result: map[string]interface{}{"actions": pluginMeta["actions"]},
})
case "deployToESA":
rep, err := deployToESA(req.Params)
if err != nil {
outputError("ESA 部署失败", err)
return
}
outputJSON(rep)
case "uploadToCAS":
rep, err := uploadToCAS(req.Params)
if err != nil {
outputError("CAS 上传失败", err)
return
}
outputJSON(rep)
default:
outputJSON(&Response{
Status: "error",
Message: "未知 action: " + req.Action,
})
}
}

View File

@@ -0,0 +1,225 @@
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
)
type Auth struct {
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key"`
}
func NewAuth(accessKey, secretKey string) *Auth {
return &Auth{
AccessKey: accessKey,
SecretKey: secretKey,
}
}
func Cdn(cfg map[string]any) (*Response, error) {
if cfg == nil {
return nil, fmt.Errorf("config cannot be nil")
}
certStr, ok := cfg["cert"].(string)
if !ok || certStr == "" {
return nil, fmt.Errorf("cert is required and must be a string")
}
keyStr, ok := cfg["key"].(string)
if !ok || keyStr == "" {
return nil, fmt.Errorf("key is required and must be a string")
}
accessKey, ok := cfg["access_key"].(string)
if !ok || accessKey == "" {
return nil, fmt.Errorf("access_key is required and must be a string")
}
secretKey, ok := cfg["secret_key"].(string)
if !ok || secretKey == "" {
return nil, fmt.Errorf("secret_key is required and must be a string")
}
domain, ok := cfg["domain"].(string)
if !ok || domain == "" {
return nil, fmt.Errorf("domain is required and must be a string")
}
sha256, err := GetSHA256(certStr)
if err != nil {
return nil, fmt.Errorf("failed to get SHA256 of cert: %w", err)
}
note := fmt.Sprintf("allinssl-%s", sha256)
a := NewAuth(accessKey, secretKey)
// 检查证书是否已存在于 CDN
// 只根据证书名称检查是否存在,格式为 "allinssl-<sha256>"
certList, err := a.listCertFromCdn()
if err != nil {
return nil, fmt.Errorf("failed to list certs from CDN: %w", err)
}
var certID float64
for _, cert := range certList {
if cert["note"] == note {
certID, ok = cert["id"].(float64)
if !ok {
certID = 0
}
}
}
// 如果证书不存在,则上传证书到 CDN
if certID == 0 {
certID, err = a.uploadCertToCdn(certStr, keyStr, note)
if err != nil || certID == 0 {
return nil, fmt.Errorf("failed to upload to CDN: %w", err)
}
}
// 绑定证书到域名
bindRes, err := a.bindCertToCdn(certID, domain)
if err != nil {
return nil, fmt.Errorf("failed to bind cert to CDN: %w", err)
}
return &Response{
Status: "success",
Message: "Certificate uploaded and bound successfully",
Result: bindRes,
}, nil
}
func (a Auth) uploadCertToCdn(cert, key, note string) (float64, error) {
params := map[string]any{
"cert": cert,
"private": key,
"note": note,
}
res, err := a.DogeCloudAPI("/cdn/cert/upload.json", params, true)
if err != nil {
return 0, fmt.Errorf("failed to call DogeCloud API: %w", err)
}
code, ok := res["code"].(float64)
if !ok {
return 0, fmt.Errorf("invalid response format: code not found")
}
if code != 200 {
return 0, fmt.Errorf("DogeCloud API error: %s", res["msg"])
}
data, ok := res["data"].(map[string]any)
if !ok {
return 0, fmt.Errorf("invalid response format: data not found")
}
certID, ok := data["id"].(float64)
if !ok {
return 0, fmt.Errorf("invalid response format: id not found")
}
return certID, nil
}
func (a Auth) listCertFromCdn() ([]map[string]any, error) {
res, err := a.DogeCloudAPI("/cdn/cert/list.json", map[string]interface{}{}, true)
if err != nil {
return nil, fmt.Errorf("failed to call DogeCloud API: %w", err)
}
code, ok := res["code"].(float64)
if !ok {
return nil, fmt.Errorf("invalid response format: code not found")
}
if code != 200 {
return nil, fmt.Errorf("DogeCloud API error: %s", res["msg"])
}
data, ok := res["data"].(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid response format: data not found")
}
certList, ok := data["certs"].([]any)
if !ok {
return nil, fmt.Errorf("invalid response format: certs not found")
}
certs := make([]map[string]any, 0, len(certList))
for _, cert := range certList {
certMap, ok := cert.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid response format: cert item is not a map")
}
certs = append(certs, certMap)
}
return certs, nil
}
func (a Auth) bindCertToCdn(certID float64, domain string) (map[string]interface{}, error) {
params := map[string]interface{}{
"id": certID,
"domain": domain,
}
res, err := a.DogeCloudAPI("/cdn/cert/bind.json", params, true)
if err != nil {
return nil, fmt.Errorf("failed to call DogeCloud API: %w", err)
}
code, ok := res["code"].(float64)
if !ok {
return nil, fmt.Errorf("invalid response format: code not found")
}
if code != 200 {
return nil, fmt.Errorf("DogeCloud API error: %s", res["msg"])
}
return res, nil
}
// DogeCloudAPI 调用多吉云的 API 根据多吉云官网示例修改
func (a Auth) DogeCloudAPI(apiPath string, data map[string]interface{}, jsonMode bool) (map[string]interface{}, error) {
AccessKey := a.AccessKey
SecretKey := a.SecretKey
body := ""
mime := ""
if jsonMode {
_body, err := json.Marshal(data)
if err != nil {
return nil, err
}
body = string(_body)
mime = "application/json"
} else {
values := url.Values{}
for k, v := range data {
values.Set(k, v.(string))
}
body = values.Encode()
mime = "application/x-www-form-urlencoded"
}
signStr := apiPath + "\n" + body
hmacObj := hmac.New(sha1.New, []byte(SecretKey))
hmacObj.Write([]byte(signStr))
sign := hex.EncodeToString(hmacObj.Sum(nil))
Authorization := "TOKEN " + AccessKey + ":" + sign
req, err := http.NewRequest("POST", "https://api.dogecloud.com"+apiPath, strings.NewReader(body))
if err != nil {
return nil, err // 创建请求错误
}
req.Header.Add("Content-Type", mime)
req.Header.Add("Authorization", Authorization)
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
} // 网络错误
defer resp.Body.Close()
r, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err // 读取响应错误
}
var result map[string]interface{}
err = json.Unmarshal(r, &result)
if err != nil {
return nil, err
}
return result, nil
}

View File

@@ -0,0 +1,117 @@
package main
import (
"crypto/sha256"
"crypto/x509"
"encoding/hex"
"encoding/json"
"encoding/pem"
"fmt"
"io"
"os"
)
type ActionInfo struct {
Name string `json:"name"`
Description string `json:"description"`
Params map[string]any `json:"params,omitempty"`
}
type Request struct {
Action string `json:"action"`
Params map[string]interface{} `json:"params"`
}
type Response struct {
Status string `json:"status"`
Message string `json:"message"`
Result map[string]interface{} `json:"result"`
}
var pluginMeta = map[string]interface{}{
"name": "doge",
"description": "部署到多吉云",
"version": "1.0.0",
"author": "主包",
"config": map[string]interface{}{
"access_key": "多吉云 AccessKey",
"secret_key": "多吉云 SecretKey",
},
"actions": []ActionInfo{
{
Name: "cdn",
Description: "部署到多吉云cdn",
Params: map[string]any{
"domain": "CDN 域名",
},
},
},
}
func GetSHA256(certStr string) (string, error) {
certPEM := []byte(certStr)
block, _ := pem.Decode(certPEM)
if block == nil {
return "", fmt.Errorf("无法解析证书 PEM")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return "", fmt.Errorf("解析证书失败: %v", err)
}
sha256Hash := sha256.Sum256(cert.Raw)
return hex.EncodeToString(sha256Hash[:]), nil
}
func outputJSON(resp *Response) {
_ = json.NewEncoder(os.Stdout).Encode(resp)
}
func outputError(msg string, err error) {
outputJSON(&Response{
Status: "error",
Message: fmt.Sprintf("%s: %v", msg, err),
})
}
func main() {
var req Request
input, err := io.ReadAll(os.Stdin)
if err != nil {
outputError("读取输入失败", err)
return
}
if err := json.Unmarshal(input, &req); err != nil {
outputError("解析请求失败", err)
return
}
switch req.Action {
case "get_metadata":
outputJSON(&Response{
Status: "success",
Message: "插件信息",
Result: pluginMeta,
})
case "list_actions":
outputJSON(&Response{
Status: "success",
Message: "支持的动作",
Result: map[string]interface{}{"actions": pluginMeta["actions"]},
})
case "cdn":
rep, err := Cdn(req.Params)
if err != nil {
outputError("CDN 部署失败", err)
return
}
outputJSON(rep)
default:
outputJSON(&Response{
Status: "error",
Message: "未知 action: " + req.Action,
})
}
}

View File

@@ -0,0 +1,165 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"io"
"math/rand"
"net/http"
"net/url"
"strings"
"time"
)
type LoginInfo struct {
account string
password string
}
type LoginResponse struct {
Code string
Message string
Data string
Success bool
}
type HTTPSConfig struct {
HTTPSStatus string `json:"https_status"`
CertificateSource string `json:"certificate_source"`
CertificateName string `json:"certificate_name"`
CertificateValue string `json:"certificate_value"`
PrivateKey string `json:"private_key"`
}
type DeployConfig struct {
DomainID string `json:"doMainId"`
HTTPS HTTPSConfig `json:"https"`
}
func randomString(n int) string {
rand.Seed(time.Now().UnixNano())
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, n)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
return string(b)
}
const baseUrl = "https://www.kuocaiyun.com/"
func login(loginInfo LoginInfo) (string, error) {
loginUrl := baseUrl + "login/loginUser"
formData := url.Values{}
formData.Set("userAccount", loginInfo.account)
formData.Set("userPwd", loginInfo.password)
formData.Set("remember", "true")
resp, err := http.Post(loginUrl, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
const emptyString = ""
if err != nil {
outputError("请求失败", err)
return emptyString, err
}
if resp.StatusCode != 200 {
return emptyString, errors.New("请求失败:" + string(rune(resp.StatusCode)))
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
outputError("关闭响应流失败", err)
}
}(resp.Body)
// 读取响应体
var loginResp LoginResponse
if err := json.NewDecoder(resp.Body).Decode(&loginResp); err != nil {
outputError("解析登录请求结果失败", err)
return emptyString, err
}
if !loginResp.Success || loginResp.Data == "" {
return emptyString, errors.New("登录请求失败:" + loginResp.Message)
}
return loginResp.Data, nil
}
func deployCert(token string, domainId string, certKey string, certValue string) (map[string]interface{}, error) {
deployUrl := baseUrl + "CdnDomainHttps/httpsConfiguration"
params := DeployConfig{
DomainID: domainId,
HTTPS: HTTPSConfig{
HTTPSStatus: "on",
CertificateSource: "0",
CertificateName: "cert_" + randomString(13),
CertificateValue: certValue,
PrivateKey: certKey,
},
}
// 序列化参数
jsonData, err := json.Marshal(params)
if err != nil {
return nil, fmt.Errorf("JSON序列化失败: %v", err)
}
req, err := http.NewRequest("POST", deployUrl, strings.NewReader(string(jsonData)))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Cookie", "kuocai_cdn_token="+token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("HTTP请求失败: %v", err)
}
defer resp.Body.Close()
// 解析响应
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("响应解析失败: %v", err)
}
if !result["success"].(bool) {
return result, fmt.Errorf("更新证书失败")
}
return result, nil
}
func Upload(cfg map[string]any) (*Response, error) {
if cfg == nil {
return nil, fmt.Errorf("config cannot be nil")
}
certStr, ok := cfg["cert"].(string)
if !ok || certStr == "" {
return nil, fmt.Errorf("cert is required and must be a string")
}
keyStr, ok := cfg["key"].(string)
if !ok || keyStr == "" {
return nil, fmt.Errorf("key is required and must be a string")
}
username, ok := cfg["username"].(string)
if !ok || username == "" {
return nil, fmt.Errorf("username is required and must be a string")
}
password, ok := cfg["password"].(string)
if !ok || password == "" {
return nil, fmt.Errorf("password is required and must be a string")
}
domainId, ok := cfg["domainId"].(string)
if !ok || domainId == "" {
return nil, fmt.Errorf("domainId is required and must be a string")
}
token, err := login(LoginInfo{account: username, password: password})
if err != nil || token == "" {
return nil, fmt.Errorf("fetch token failed, err %v", err)
}
res, err := deployCert(token, domainId, keyStr, certStr)
if err != nil {
return nil, err
}
return &Response{
Status: "success",
Message: "success",
Result: res,
}, nil
}

View File

@@ -0,0 +1,96 @@
package main
import (
"encoding/json"
"fmt"
"io"
"os"
)
type ActionInfo struct {
Name string `json:"name"`
Description string `json:"description"`
Params map[string]any `json:"params,omitempty"`
}
type Request struct {
Action string `json:"action"`
Params map[string]interface{} `json:"params"`
}
type Response struct {
Status string `json:"status"`
Message string `json:"message"`
Result map[string]interface{} `json:"result"`
}
var pluginMeta = map[string]interface{}{
"name": "kuocai",
"description": "部署到括彩云",
"version": "1.0.0",
"author": "coclyun",
"config": map[string]interface{}{
"username": "括彩云账号",
"password": "括彩云密码",
},
"actions": []ActionInfo{
{
Name: "upload",
Description: "部署到括彩云",
Params: map[string]any{},
},
},
}
func outputJSON(resp *Response) {
_ = json.NewEncoder(os.Stdout).Encode(resp)
}
func outputError(msg string, err error) {
outputJSON(&Response{
Status: "error",
Message: fmt.Sprintf("%s: %v", msg, err),
})
}
func main() {
var req Request
input, err := io.ReadAll(os.Stdin)
if err != nil {
outputError("读取输入失败", err)
return
}
if err := json.Unmarshal(input, &req); err != nil {
outputError("解析请求失败", err)
return
}
switch req.Action {
case "get_metadata":
outputJSON(&Response{
Status: "success",
Message: "插件信息",
Result: pluginMeta,
})
case "list_actions":
outputJSON(&Response{
Status: "success",
Message: "支持的动作",
Result: map[string]interface{}{"actions": pluginMeta["actions"]},
})
case "upload":
rep, err := Upload(req.Params)
if err != nil {
outputError("CDN 部署失败", err)
return
}
outputJSON(rep)
default:
outputJSON(&Response{
Status: "error",
Message: "未知 action: " + req.Action,
})
}
}