This commit is contained in:
ZhuoQinghui 2024-11-01 11:51:40 +08:00
parent efa1752faf
commit 6ed343cf06
10 changed files with 475 additions and 46 deletions

18
go.mod
View File

@ -5,18 +5,25 @@ go 1.22.0
toolchain go1.23.2 toolchain go1.23.2
require ( require (
github.com/charmbracelet/bubbletea v1.1.2
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/go-acme/lego/v4 v4.19.1 github.com/go-acme/lego/v4 v4.19.1
github.com/spf13/cobra v1.8.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
github.com/aliyun/alibaba-cloud-sdk-go v1.63.15 // indirect github.com/aliyun/alibaba-cloud-sdk-go v1.63.15 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/charmbracelet/lipgloss v0.13.0 // indirect
github.com/charmbracelet/x/ansi v0.4.0 // indirect
github.com/charmbracelet/x/term v0.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect github.com/cloudwego/iasm v0.2.0 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-jose/go-jose/v4 v4.0.4 // indirect
@ -24,16 +31,25 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect github.com/goccy/go-json v0.10.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/miekg/dns v1.1.62 // indirect github.com/miekg/dns v1.1.62 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
@ -41,7 +57,7 @@ require (
golang.org/x/mod v0.21.0 // indirect golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.29.0 // indirect golang.org/x/net v0.29.0 // indirect
golang.org/x/sync v0.8.0 // indirect golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.18.0 // indirect golang.org/x/text v0.18.0 // indirect
golang.org/x/tools v0.25.0 // indirect golang.org/x/tools v0.25.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect google.golang.org/protobuf v1.34.2 // indirect

40
go.sum
View File

@ -4,21 +4,34 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXY
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/aliyun/alibaba-cloud-sdk-go v1.63.15 h1:r2uwBUQhLhcPzaWz9tRJqc8MjYwHb+oF2+Q6467BF14= github.com/aliyun/alibaba-cloud-sdk-go v1.63.15 h1:r2uwBUQhLhcPzaWz9tRJqc8MjYwHb+oF2+Q6467BF14=
github.com/aliyun/alibaba-cloud-sdk-go v1.63.15/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/alibaba-cloud-sdk-go v1.63.15/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/charmbracelet/bubbletea v1.1.2 h1:naQXF2laRxyLyil/i7fxdpiz1/k06IKquhm4vBfHsIc=
github.com/charmbracelet/bubbletea v1.1.2/go.mod h1:9HIU/hBV24qKjlehyj8z1r/tR9TYTQEag+cWZnuXo8E=
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
github.com/charmbracelet/x/ansi v0.4.0 h1:NqwHA4B23VwsDn4H3VcNX1W1tOmgnvY1NDx5tOXdnOU=
github.com/charmbracelet/x/ansi v0.4.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
@ -47,6 +60,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@ -64,8 +79,14 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -73,6 +94,12 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
@ -84,6 +111,14 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@ -135,10 +170,11 @@ golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=

View File

@ -3,5 +3,6 @@ package main
import "acme-mana/src" import "acme-mana/src"
func main() { func main() {
src.Start() //src.Start()
src.StartProgram()
} }

View File

@ -9,6 +9,7 @@ import (
"encoding/json" "encoding/json"
"encoding/pem" "encoding/pem"
"github.com/go-acme/lego/v4/certificate" "github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/go-acme/lego/v4/providers/dns/alidns" "github.com/go-acme/lego/v4/providers/dns/alidns"
@ -75,6 +76,31 @@ func Apply(domain Domain) {
saveCertFile(cert, name) saveCertFile(cert, name)
} }
func getProvider() challenge.Provider {
config := GetAppConfig()
switch config.Use {
case "alidns":
return getAliProvider()
}
return nil
}
func getAliProvider() challenge.Provider {
ali := GetAppConfig().Provider.Ali
conf := alidns.NewDefaultConfig()
conf.RegionID = ali.RegionID
conf.APIKey = ali.APIKey
conf.SecretKey = ali.SecretKey
provider, err := alidns.NewDNSProviderConfig(conf)
if err != nil {
log.Fatal(err)
}
return provider
}
func getTencentProvider() challenge.Provider {
return nil
}
// saveCertFile 保存证书文件 // saveCertFile 保存证书文件
func saveCertFile(cert *certificate.Resource, name string) { func saveCertFile(cert *certificate.Resource, name string) {
dir := GetAppConfig().CertDir dir := GetAppConfig().CertDir

268
src/cmd/cmd.go Normal file
View File

@ -0,0 +1,268 @@
package cmd
import (
"github.com/spf13/cobra"
)
func InitCmd() (*cobra.Command, error) {
rootCmd := &cobra.Command{
Use: "acme-mana",
Short: "ACME协议客户端",
Long: "基于 ACME 协议实现自动申请证书和续签证书",
}
rootCmd.AddCommand(initConfCmd())
rootCmd.AddCommand(initServerCmd())
rootCmd.AddCommand(initTaskCmd())
rootCmd.AddCommand(initProviderCmd())
rootCmd.AddCommand(certCmd())
rootCmd.AddCommand(acmeCmd())
err := rootCmd.Execute()
return rootCmd, err
}
func initConfCmd() *cobra.Command {
confCmd := &cobra.Command{
Use: "conf",
Short: "应用配置命令",
Long: "对当前应用配置进行操作",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
confShow := &cobra.Command{
Use: "show",
Short: "查看配置列表",
Long: "查看系统配置列表",
Run: func(cmd *cobra.Command, args []string) {
confShow(cmd, args)
},
}
confCmd.AddCommand(confShow)
return confCmd
}
func initServerCmd() *cobra.Command {
serverCmd := &cobra.Command{
Use: "server",
Short: "服务相关命令",
Long: "配置服务相关参数, 如监听端口,监听地址等",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
editCmd := &cobra.Command{
Use: "edit",
Short: "编辑服务配置",
Long: "编辑服务配置",
Run: func(cmd *cobra.Command, args []string) {
editServer(cmd, args)
},
}
stateCmd := &cobra.Command{
Use: "state",
Short: "查看服务状态",
Long: "查看服务状态",
Run: func(cmd *cobra.Command, args []string) {
serverState(cmd, args)
},
}
startCmd := &cobra.Command{
Use: "start",
Short: "启动服务",
Long: "启动服务",
Run: func(cmd *cobra.Command, args []string) {
startServer(cmd, args)
},
}
stopCmd := &cobra.Command{
Use: "stop",
Short: "停止服务",
Long: "停止服务",
Run: func(cmd *cobra.Command, args []string) {
stopServer(cmd, args)
},
}
serverCmd.AddCommand(editCmd)
serverCmd.AddCommand(stateCmd)
serverCmd.AddCommand(startCmd)
serverCmd.AddCommand(stopCmd)
return serverCmd
}
func initTaskCmd() *cobra.Command {
taskCmd := &cobra.Command{
Use: "task",
Short: "定时任务相关命令",
Long: "自动刷新证书定时任务的相关命令",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
editTask := &cobra.Command{
Use: "edit",
Short: "编辑定时任务配置",
Long: "编辑定时任务配置",
Run: func(cmd *cobra.Command, args []string) {
editTask(cmd, args)
},
}
startTask := &cobra.Command{
Use: "start",
Short: "启动定时任务",
Long: "启动定时任务",
Run: func(cmd *cobra.Command, args []string) {
startTask(cmd, args)
},
}
stopTask := &cobra.Command{
Use: "stop",
Short: "停止定时任务",
Long: "停止定时任务",
Run: func(cmd *cobra.Command, args []string) {
stopTask(cmd, args)
},
}
statusTask := &cobra.Command{
Use: "status",
Short: "查看定时任务状态",
Long: "查看定时任务状态",
Run: func(cmd *cobra.Command, args []string) {
statusTask(cmd, args)
},
}
runTask := &cobra.Command{
Use: "run",
Short: "手动执行一次任务",
Long: "手动执行一次任务",
Run: func(cmd *cobra.Command, args []string) {
runTask(cmd, args)
},
}
taskCmd.AddCommand(editTask)
taskCmd.AddCommand(startTask)
taskCmd.AddCommand(stopTask)
taskCmd.AddCommand(statusTask)
taskCmd.AddCommand(runTask)
return taskCmd
}
func initProviderCmd() *cobra.Command {
providerCmd := &cobra.Command{
Use: "provider",
Short: "DNS服务商相关命令",
Long: "DNS服务商相关命令",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
providerSupport := &cobra.Command{
Use: "support",
Short: "列出支持的DNS服务商",
Long: "列出支持的DNS服务商",
Run: func(cmd *cobra.Command, args []string) {
providerSupport(cmd, args)
},
}
providerList := &cobra.Command{
Use: "list",
Short: "列出已配置的DNS服务商",
Long: "列出已配置的DNS服务商",
Run: func(cmd *cobra.Command, args []string) {
providerList(cmd, args)
},
}
providerAdd := &cobra.Command{
Use: "add",
Short: "添加DNS服务商",
Long: "添加DNS服务商",
Run: func(cmd *cobra.Command, args []string) {
providerAdd(cmd, args)
},
}
providerEdit := &cobra.Command{
Use: "edit",
Short: "编辑DNS服务商",
Long: "编辑DNS服务商",
Run: func(cmd *cobra.Command, args []string) {
providerEdit(cmd, args)
},
}
providerDelete := &cobra.Command{
Use: "delete",
Short: "删除DNS服务商",
Long: "删除DNS服务商",
Run: func(cmd *cobra.Command, args []string) {
providerDelete(cmd, args)
},
}
providerCmd.AddCommand(providerSupport)
providerCmd.AddCommand(providerList)
providerCmd.AddCommand(providerAdd)
providerCmd.AddCommand(providerEdit)
providerCmd.AddCommand(providerDelete)
return providerCmd
}
func certCmd() *cobra.Command {
certCmd := &cobra.Command{
Use: "cert",
Short: "证书配置相关命令",
Long: "证书配置相关命令",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
certList := &cobra.Command{
Use: "list",
Short: "列出已配置的证书",
Long: "列出已配置的证书",
Run: func(cmd *cobra.Command, args []string) {
certList(cmd, args)
},
}
certAdd := &cobra.Command{
Use: "add",
Short: "添加证书",
Long: "添加证书",
Run: func(cmd *cobra.Command, args []string) {
certAdd(cmd, args)
},
}
certDelete := &cobra.Command{
Use: "delete",
Short: "删除证书",
Long: "删除证书",
Run: func(cmd *cobra.Command, args []string) {
certDelete(cmd, args)
},
}
editCert := &cobra.Command{
Use: "edit",
Short: "编辑证书",
Long: "编辑证书",
Run: func(cmd *cobra.Command, args []string) {
editCert(cmd, args)
},
}
certCmd.AddCommand(certList)
certCmd.AddCommand(certAdd)
certCmd.AddCommand(certDelete)
certCmd.AddCommand(editCert)
return certCmd
}
func acmeCmd() *cobra.Command {
acmeCmd := &cobra.Command{
Use: "acme",
Short: "ACME相关命令",
Long: "ACME相关命令",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
return acmeCmd
}

78
src/cmd/handler.go Normal file
View File

@ -0,0 +1,78 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func confShow(cmd *cobra.Command, args []string) {
fmt.Println("show conf")
}
func editServer(cmd *cobra.Command, args []string) {
fmt.Println("edit server")
}
func serverState(cmd *cobra.Command, args []string) {
fmt.Println("server state")
}
func startServer(cmd *cobra.Command, args []string) {
fmt.Println("start server")
}
func stopServer(cmd *cobra.Command, args []string) {
fmt.Println("stop server")
}
func editTask(cmd *cobra.Command, args []string) {
fmt.Println("edit task")
}
func runTask(cmd *cobra.Command, args []string) {
fmt.Println("run task")
}
func statusTask(cmd *cobra.Command, args []string) {
fmt.Println("status task")
}
func stopTask(cmd *cobra.Command, args []string) {
fmt.Println("stop task")
}
func startTask(cmd *cobra.Command, args []string) {
fmt.Println("start task")
}
func providerDelete(cmd *cobra.Command, args []string) {
fmt.Println("delete provider")
}
func providerEdit(cmd *cobra.Command, args []string) {
fmt.Println("edit provider")
}
func providerAdd(cmd *cobra.Command, args []string) {
fmt.Println("add provider")
}
func providerList(cmd *cobra.Command, args []string) {
fmt.Println("list provider")
}
func providerSupport(cmd *cobra.Command, args []string) {
fmt.Println("support provider")
}
func editCert(cmd *cobra.Command, args []string) {
fmt.Println("edit cert")
}
func certDelete(cmd *cobra.Command, args []string) {
fmt.Println("delete cert")
}
func certAdd(cmd *cobra.Command, args []string) {
fmt.Println("add cert")
}
func certList(cmd *cobra.Command, args []string) {
fmt.Println("list cert")
}

View File

@ -66,10 +66,9 @@ func readNewConf() *AppConfig {
conf.Encrypt.PubKey = scanConf("请输入RSA公钥", "请输入RSA公钥") conf.Encrypt.PubKey = scanConf("请输入RSA公钥", "请输入RSA公钥")
} }
codes := []string{"alidns", "tencentcloud", "cloudflare"} msg := fmt.Sprintf("请输入DNS提供商; 当前支持的: %s", strings.Join(DnsProviderSupports, ","))
msg := fmt.Sprintf("请输入DNS提供商; 当前支持的: %s", strings.Join(codes, ",")) errMsg := fmt.Sprintf("不支持的DNS提供商; 当前支持的: %s", strings.Join(DnsProviderSupports, ","))
errMsg := fmt.Sprintf("不支持的DNS提供商; 当前支持的: %s", strings.Join(codes, ",")) conf.Use = scanConfDefaultCheck(msg, "", DnsProviderSupports, errMsg)
conf.Use = scanConfDefaultCheck(msg, "", codes, errMsg)
switch conf.Use { switch conf.Use {
case "alidns": case "alidns":
fmt.Printf("阿里云DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/alidns/index.html") fmt.Printf("阿里云DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/alidns/index.html")

View File

@ -2,6 +2,7 @@ package src
import ( import (
"encoding/json" "encoding/json"
tea "github.com/charmbracelet/bubbletea"
"log" "log"
"net" "net"
"os" "os"
@ -26,6 +27,8 @@ func Start() {
} }
command := args[1] command := args[1]
switch command { switch command {
case "help":
showHelp()
case "block": case "block":
doTask() doTask()
case "start": case "start":
@ -49,9 +52,7 @@ func Start() {
} }
} }
/* // 初始化日志文件
初始化日志文件
*/
func initLog() { func initLog() {
pwd, err := os.Getwd() pwd, err := os.Getwd()
if err != nil { if err != nil {
@ -74,9 +75,24 @@ func initLog() {
stderr = errFile stderr = errFile
} }
/* func showHelp() {
守护进程启动 tea.Println("")
*/ log.Printf(`
Usage: acme-mana [command] [options]
Commands:
help Show this help message
start Start the daemon
stop Stop the daemon
status Check the status of the daemon
dump Dump the configuration file
domains List all domains
pubkey Show the public key
apply Manually apply for a certificate
block Block the
`)
}
// 守护进程启动
func daemonStart() { func daemonStart() {
GetAppConfig() GetAppConfig()
isDaemon := os.Getenv("GO_DAEMON") isDaemon := os.Getenv("GO_DAEMON")
@ -125,34 +141,12 @@ func daemonStart() {
} }
/* // 守护进程停止
守护进程停止
*/
func daemonStop() { func daemonStop() {
//pid, err := readPID()
//if err != nil {
// log.Fatalf("Failed to stop daemon: %v", err)
//}
//
//process, err := os.FindProcess(pid)
//if err != nil {
// log.Fatalf("Failed to find process: %v", err)
//}
//
//err = process.Signal(syscall.SIGTERM)
//if err != nil {
// log.Fatalf("Failed to stop process: %v", err)
//}
//
//os.Remove(PidFile)
//os.Remove(SocketFile)
//log.Println("Daemon stopped.")
sendCommand("stop") sendCommand("stop")
} }
/* // 守护进程状态
守护进程状态
*/
func daemonStatus() { func daemonStatus() {
if isRunning() { if isRunning() {
log.Println("Daemon is running.") log.Println("Daemon is running.")
@ -161,6 +155,7 @@ func daemonStatus() {
} }
} }
// 输出配置文件
func dumpConfig() { func dumpConfig() {
//config, err := json.Marshal(GetAppConfig()) //config, err := json.Marshal(GetAppConfig())
config, err := json.MarshalIndent(GetAppConfig(), "", " ") config, err := json.MarshalIndent(GetAppConfig(), "", " ")
@ -170,6 +165,7 @@ func dumpConfig() {
log.Println(string(config)) log.Println(string(config))
} }
// 手动执行一次证书申请
func applyOnce() { func applyOnce() {
if len(os.Args) < 3 { if len(os.Args) < 3 {
log.Fatalf("Please enter domain name!") log.Fatalf("Please enter domain name!")
@ -185,6 +181,7 @@ func applyOnce() {
Apply(*domain) Apply(*domain)
} }
// 输出域名列表
func showDomains() { func showDomains() {
domains := GetAppConfig().Domains domains := GetAppConfig().Domains
// 格式化为json并打印 // 格式化为json并打印
@ -195,6 +192,7 @@ func showDomains() {
log.Println(string(config)) log.Println(string(config))
} }
// 输出公钥
func showPubkey() { func showPubkey() {
key := GetAppConfig().Encrypt.PubKey key := GetAppConfig().Encrypt.PubKey
log.Println(key) log.Println(key)
@ -245,10 +243,7 @@ func doTask() {
select {} select {}
} }
/* // 是否已启动
*
是否已启动
*/
func isRunning() bool { func isRunning() bool {
log.Println("Checking if daemon is running...") log.Println("Checking if daemon is running...")
pid, err := readPID() pid, err := readPID()
@ -268,10 +263,7 @@ func isRunning() bool {
//return err == nil //return err == nil
} }
/* // 读取PID文件
*
读取PID文件
*/
func readPID() (int, error) { func readPID() (int, error) {
log.Println("Reading PID file...") log.Println("Reading PID file...")
data, err := os.ReadFile(PidFile) data, err := os.ReadFile(PidFile)

11
src/program.go Normal file
View File

@ -0,0 +1,11 @@
package src
import "acme-mana/src/cmd"
func StartProgram() {
_, err := cmd.InitCmd()
if err != nil {
panic(err)
return
}
}

View File

@ -7,6 +7,8 @@ const CertFileName = "fullchain.pem"
const KeyFileName = "privkey.pem" const KeyFileName = "privkey.pem"
const CertInfoFileName = "info.json" const CertInfoFileName = "info.json"
var DnsProviderSupports = []string{"alidns", "tencentcloud", "cloudflare"}
var appConfig *AppConfig = ReadConfig() var appConfig *AppConfig = ReadConfig()
func GetAppConfig() *AppConfig { func GetAppConfig() *AppConfig {