后端代码同步

pull/8/head
zhangchenhao 2025-05-08 11:19:53 +08:00
parent 5124663aab
commit 312f10d06d
7 changed files with 523 additions and 521 deletions

View File

@ -37,8 +37,9 @@ func Deploy(cfg map[string]any, logger *public.Logger) error {
case "aliyun-cdn": case "aliyun-cdn":
logger.Debug("部署到阿里云CDN...") logger.Debug("部署到阿里云CDN...")
return DeployAliCdn(cfg) return DeployAliCdn(cfg)
// case "aliyun-oss": case "aliyun-oss":
logger.Debug("部署到阿里云OSS...")
return DeployOss(cfg)
default: default:
return fmt.Errorf("不支持的部署: %s", providerName) return fmt.Errorf("不支持的部署: %s", providerName)
} }

View File

@ -14,7 +14,7 @@ type SSHConfig struct {
Password string // 可选 Password string // 可选
PrivateKey string // 可选 PrivateKey string // 可选
Host string Host string
Port string Port float64
} }
type RemoteFile struct { type RemoteFile struct {
@ -24,7 +24,7 @@ type RemoteFile struct {
func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) { func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) {
var methods []ssh.AuthMethod var methods []ssh.AuthMethod
if privateKey != "" { if privateKey != "" {
signer, err := ssh.ParsePrivateKey([]byte(privateKey)) signer, err := ssh.ParsePrivateKey([]byte(privateKey))
if err != nil { if err != nil {
@ -32,71 +32,71 @@ func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) {
} }
methods = append(methods, ssh.PublicKeys(signer)) methods = append(methods, ssh.PublicKeys(signer))
} }
if password != "" { if password != "" {
methods = append(methods, ssh.Password(password)) methods = append(methods, ssh.Password(password))
} }
if len(methods) == 0 { if len(methods) == 0 {
return nil, fmt.Errorf("no authentication methods provided") return nil, fmt.Errorf("no authentication methods provided")
} }
return methods, nil return methods, nil
} }
func writeMultipleFilesViaSSH(config SSHConfig, files []RemoteFile, preCmd, postCmd string) error { func writeMultipleFilesViaSSH(config SSHConfig, files []RemoteFile, preCmd, postCmd string) error {
addr := fmt.Sprintf("%s:%s", config.Host, config.Port) addr := fmt.Sprintf("%s:%d", config.Host, int(config.Port))
authMethods, err := buildAuthMethods(config.Password, config.PrivateKey) authMethods, err := buildAuthMethods(config.Password, config.PrivateKey)
if err != nil { if err != nil {
return err return err
} }
sshConfig := &ssh.ClientConfig{ sshConfig := &ssh.ClientConfig{
User: config.User, User: config.User,
Auth: authMethods, Auth: authMethods,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), HostKeyCallback: ssh.InsecureIgnoreHostKey(),
} }
client, err := ssh.Dial("tcp", addr, sshConfig) client, err := ssh.Dial("tcp", addr, sshConfig)
if err != nil { if err != nil {
return fmt.Errorf("failed to dial: %v", err) return fmt.Errorf("failed to dial: %v", err)
} }
defer client.Close() defer client.Close()
session, err := client.NewSession() session, err := client.NewSession()
if err != nil { if err != nil {
return fmt.Errorf("会话创建失败: %v", err) return fmt.Errorf("会话创建失败: %v", err)
} }
defer session.Close() defer session.Close()
var script bytes.Buffer var script bytes.Buffer
if preCmd != "" { if preCmd != "" {
script.WriteString(preCmd + " && ") script.WriteString(preCmd + " && ")
} }
for i, file := range files { for i, file := range files {
if i > 0 { if i > 0 {
script.WriteString(" && ") script.WriteString(" && ")
} }
dirCmd := fmt.Sprintf("mkdir -p $(dirname %q)", file.Path) dirCmd := fmt.Sprintf("mkdir -p $(dirname %q)", file.Path)
writeCmd := fmt.Sprintf("printf %%s '%s' > %s", file.Content, file.Path) writeCmd := fmt.Sprintf("printf %%s '%s' > %s", file.Content, file.Path)
script.WriteString(dirCmd + " && " + writeCmd) script.WriteString(dirCmd + " && " + writeCmd)
} }
if postCmd != "" { if postCmd != "" {
script.WriteString(" && " + postCmd) script.WriteString(" && " + postCmd)
} }
cmd := script.String() cmd := script.String()
if err := session.Run(cmd); err != nil { if err := session.Run(cmd); err != nil {
return fmt.Errorf("运行出错: %v", err) return fmt.Errorf("运行出错: %v", err)
} }
return nil return nil
} }
@ -127,7 +127,7 @@ func DeploySSH(cfg map[string]any) error {
if !ok { if !ok {
return fmt.Errorf("参数错误keyPath") return fmt.Errorf("参数错误keyPath")
} }
certPath, ok := cfg["keyPath"].(string) certPath, ok := cfg["certPath"].(string)
if !ok { if !ok {
return fmt.Errorf("参数错误certPath") return fmt.Errorf("参数错误certPath")
} }
@ -155,8 +155,8 @@ func DeploySSH(cfg map[string]any) error {
} }
// 自动创建多级目录 // 自动创建多级目录
files := []RemoteFile{ files := []RemoteFile{
{Path: keyPath, Content: certPem}, {Path: certPath, Content: certPem},
{Path: certPath, Content: keyPem}, {Path: keyPath, Content: keyPem},
} }
err = writeMultipleFilesViaSSH(providerConfig, files, beforeCmd, afterCmd) err = writeMultipleFilesViaSSH(providerConfig, files, beforeCmd, afterCmd)
if err != nil { if err != nil {

View File

@ -1,189 +1,189 @@
package report package report
import ( import (
"ALLinSSL/backend/public" "ALLinSSL/backend/public"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/jordan-wright/email" "github.com/jordan-wright/email"
"net/smtp" "net/smtp"
"time" "time"
) )
func GetSqlite() (*public.Sqlite, error) { func GetSqlite() (*public.Sqlite, error) {
s, err := public.NewSqlite("data/data.db", "") s, err := public.NewSqlite("data/data.db", "")
if err != nil { if err != nil {
return nil, err return nil, err
} }
s.Connect() s.Connect()
s.TableName = "report" s.TableName = "report"
return s, nil return s, nil
} }
func GetList(search string, p, limit int64) ([]map[string]any, int, error) { func GetList(search string, p, limit int64) ([]map[string]any, int, error) {
var data []map[string]any var data []map[string]any
var count int64 var count int64
s, err := GetSqlite() s, err := GetSqlite()
if err != nil { if err != nil {
return data, 0, err return data, 0, err
} }
defer s.Close() defer s.Close()
var limits []int64 var limits []int64
if p >= 0 && limit >= 0 { if p >= 0 && limit >= 0 {
limits = []int64{0, limit} limits = []int64{0, limit}
if p > 1 { if p > 1 {
limits[0] = (p - 1) * limit limits[0] = (p - 1) * limit
limits[1] = p * limit limits[1] = p * limit
} }
} }
if search != "" { if search != "" {
count, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Count() count, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Count()
data, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Limit(limits).Order("update_time", "desc").Select() data, err = s.Where("name like ?", []interface{}{"%" + search + "%"}).Limit(limits).Order("update_time", "desc").Select()
} else { } else {
count, err = s.Count() count, err = s.Count()
data, err = s.Order("update_time", "desc").Limit(limits).Select() data, err = s.Order("update_time", "desc").Limit(limits).Select()
} }
if err != nil { if err != nil {
return data, 0, err return data, 0, err
} }
return data, int(count), nil return data, int(count), nil
} }
func GetReport(id string) (map[string]any, error) { func GetReport(id string) (map[string]any, error) {
s, err := GetSqlite() s, err := GetSqlite()
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer s.Close() defer s.Close()
data, err := s.Where("id=?", []interface{}{id}).Select() data, err := s.Where("id=?", []interface{}{id}).Select()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(data) == 0 { if len(data) == 0 {
return nil, fmt.Errorf("没有找到此通知配置") return nil, fmt.Errorf("没有找到此通知配置")
} }
return data[0], nil return data[0], nil
} }
func AddReport(Type, config, name string) error { func AddReport(Type, config, name string) error {
s, err := GetSqlite() s, err := GetSqlite()
if err != nil { if err != nil {
return err return err
} }
defer s.Close() defer s.Close()
now := time.Now().Format("2006-01-02 15:04:05") now := time.Now().Format("2006-01-02 15:04:05")
_, err = s.Insert(map[string]interface{}{ _, err = s.Insert(map[string]interface{}{
"name": name, "name": name,
"type": Type, "type": Type,
"config": config, "config": config,
"create_time": now, "create_time": now,
"update_time": now, "update_time": now,
}) })
return err return err
} }
func UpdReport(id, config, name string) error { func UpdReport(id, config, name string) error {
s, err := GetSqlite() s, err := GetSqlite()
if err != nil { if err != nil {
return err return err
} }
defer s.Close() defer s.Close()
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{ _, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{
"name": name, "name": name,
"config": config, "config": config,
}) })
return err return err
} }
func DelReport(id string) error { func DelReport(id string) error {
s, err := GetSqlite() s, err := GetSqlite()
if err != nil { if err != nil {
return err return err
} }
defer s.Close() defer s.Close()
_, err = s.Where("id=?", []interface{}{id}).Delete() _, err = s.Where("id=?", []interface{}{id}).Delete()
return err return err
} }
func NotifyTest(id string) error { func NotifyTest(id string) error {
if id == "" { if id == "" {
return fmt.Errorf("缺少参数") return fmt.Errorf("缺少参数")
} }
providerData, err := GetReport(id) providerData, err := GetReport(id)
if err != nil { if err != nil {
return err return err
} }
params := map[string]any{ params := map[string]any{
"provider_id": id, "provider_id": id,
"body": "测试消息通道", "body": "测试消息通道",
"subject": "测试消息通道", "subject": "测试消息通道",
} }
switch providerData["type"] { switch providerData["type"] {
case "mail": case "mail":
err = NotifyMail(params) err = NotifyMail(params)
} }
return err return err
} }
func Notify(params map[string]any) error { func Notify(params map[string]any) error {
if params == nil { if params == nil {
return fmt.Errorf("缺少参数") return fmt.Errorf("缺少参数")
} }
providerName, ok := params["provider"].(string) providerName, ok := params["provider"].(string)
if !ok { if !ok {
return fmt.Errorf("通知类型错误") return fmt.Errorf("通知类型错误")
} }
switch providerName { switch providerName {
case "mail": case "mail":
return NotifyMail(params) return NotifyMail(params)
// case "btpanel-site": // case "btpanel-site":
// return NotifyBt(params) // return NotifyBt(params)
default: default:
return fmt.Errorf("不支持的通知类型") return fmt.Errorf("不支持的通知类型")
} }
} }
func NotifyMail(params map[string]any) error { func NotifyMail(params map[string]any) error {
if params == nil { if params == nil {
return fmt.Errorf("缺少参数") return fmt.Errorf("缺少参数")
} }
providerID := params["provider_id"].(string) providerID := params["provider_id"].(string)
// fmt.Println(providerID) // fmt.Println(providerID)
providerData, err := GetReport(providerID) providerData, err := GetReport(providerID)
if err != nil { if err != nil {
return err return err
} }
configStr := providerData["config"].(string) configStr := providerData["config"].(string)
var config map[string]string var config map[string]string
err = json.Unmarshal([]byte(configStr), &config) err = json.Unmarshal([]byte(configStr), &config)
if err != nil { if err != nil {
return fmt.Errorf("解析配置失败: %v", err) return fmt.Errorf("解析配置失败: %v", err)
} }
e := email.NewEmail() e := email.NewEmail()
e.From = config["sender"] e.From = config["sender"]
e.To = []string{config["receiver"]} e.To = []string{config["receiver"]}
e.Subject = params["subject"].(string) e.Subject = params["subject"].(string)
e.Text = []byte(params["body"].(string)) e.Text = []byte(params["body"].(string))
addr := fmt.Sprintf("%s:%s", config["smtpHost"], config["smtpPort"]) addr := fmt.Sprintf("%s:%s", config["smtpHost"], config["smtpPort"])
auth := smtp.PlainAuth("", config["sender"], config["password"], config["smtpHost"]) auth := smtp.PlainAuth("", config["sender"], config["password"], config["smtpHost"])
// 使用 SSL通常是 465 // 使用 SSL通常是 465
if config["smtpPort"] == "465" { if config["smtpPort"] == "465" {
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
InsecureSkipVerify: true, // 开发阶段跳过证书验证,生产建议关闭 InsecureSkipVerify: true, // 开发阶段跳过证书验证,生产建议关闭
ServerName: config["smtpHost"], ServerName: config["smtpHost"],
} }
return e.SendWithTLS(addr, auth, tlsConfig) return e.SendWithTLS(addr, auth, tlsConfig)
} }
// 普通明文发送25端口非推荐 // 普通明文发送25端口非推荐
return e.Send(addr, auth) return e.Send(addr, auth)
} }

View File

@ -27,7 +27,7 @@ func Get() (Setting, error) {
Timeout: public.TimeOut, Timeout: public.TimeOut,
Secure: public.Secure, Secure: public.Secure,
} }
setting.Https = public.GetSettingIgnoreError("https") setting.Https = public.GetSettingIgnoreError("https")
key, err := os.ReadFile("data/https/key.pem") key, err := os.ReadFile("data/https/key.pem")
if err != nil { if err != nil {
@ -60,7 +60,7 @@ func Get() (Setting, error) {
func Save(setting *Setting) error { func Save(setting *Setting) error {
var restart bool var restart bool
var reload bool var reload bool
s, err := public.NewSqlite("data/data.db", "") s, err := public.NewSqlite("data/data.db", "")
if err != nil { if err != nil {
return err return err
@ -79,7 +79,7 @@ func Save(setting *Setting) error {
if setting.Username != "" { if setting.Username != "" {
data["username"] = setting.Username data["username"] = setting.Username
} }
salt := user[0]["salt"].(string) salt := user[0]["salt"].(string)
passwd := setting.Password + salt passwd := setting.Password + salt
// fmt.Println(passwd) // fmt.Println(passwd)
@ -98,10 +98,12 @@ func Save(setting *Setting) error {
if setting.Timeout != 0 { if setting.Timeout != 0 {
s.Where("key = 'timeout'", []interface{}{}).Update(map[string]interface{}{"value": setting.Timeout}) s.Where("key = 'timeout'", []interface{}{}).Update(map[string]interface{}{"value": setting.Timeout})
public.TimeOut = setting.Timeout public.TimeOut = setting.Timeout
restart = true
} }
if setting.Secure != "" { if setting.Secure != "" {
s.Where("key = 'secure'", []interface{}{}).Update(map[string]interface{}{"value": setting.Secure}) s.Where("key = 'secure'", []interface{}{}).Update(map[string]interface{}{"value": setting.Secure})
public.TimeOut = setting.Timeout public.TimeOut = setting.Timeout
restart = true
} }
if setting.Https == "1" { if setting.Https == "1" {
if setting.Key == "" || setting.Cert == "" { if setting.Key == "" || setting.Cert == "" {
@ -122,7 +124,6 @@ func Save(setting *Setting) error {
os.WriteFile("data/https/cert.pem", []byte(setting.Cert), 0644) os.WriteFile("data/https/cert.pem", []byte(setting.Cert), 0644)
restart = true restart = true
} }
if restart { if restart {
Restart() Restart()
return nil return nil

View File

@ -1,117 +1,117 @@
package workflow package workflow
import ( import (
"ALLinSSL/backend/public" "ALLinSSL/backend/public"
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
) )
// GetSqliteObjWH 工作流执行历史记录表对象 // GetSqliteObjWH 工作流执行历史记录表对象
func GetSqliteObjWH() (*public.Sqlite, error) { func GetSqliteObjWH() (*public.Sqlite, error) {
s, err := public.NewSqlite("data/data.db", "") s, err := public.NewSqlite("data/data.db", "")
if err != nil { if err != nil {
return nil, err return nil, err
} }
s.Connect() s.Connect()
s.TableName = "workflow_history" s.TableName = "workflow_history"
return s, nil return s, nil
} }
// GetListWH 获取工作流执行历史记录列表 // GetListWH 获取工作流执行历史记录列表
func GetListWH(id string, p, limit int64) ([]map[string]any, int, error) { func GetListWH(id string, p, limit int64) ([]map[string]any, int, error) {
var data []map[string]any var data []map[string]any
var count int64 var count int64
s, err := GetSqliteObjWH() s, err := GetSqliteObjWH()
if err != nil { if err != nil {
return data, 0, err return data, 0, err
} }
defer s.Close() defer s.Close()
var limits []int64 var limits []int64
if p >= 0 && limit >= 0 { if p >= 0 && limit >= 0 {
limits = []int64{0, limit} limits = []int64{0, limit}
if p > 1 { if p > 1 {
limits[0] = (p - 1) * limit limits[0] = (p - 1) * limit
limits[1] = p * limit limits[1] = p * limit
} }
} }
if id == "" { if id == "" {
count, err = s.Count() count, err = s.Count()
data, err = s.Limit(limits).Order("create_time", "desc").Select() data, err = s.Limit(limits).Order("create_time", "desc").Select()
} else { } else {
count, err = s.Where("workflow_id=?", []interface{}{id}).Count() count, err = s.Where("workflow_id=?", []interface{}{id}).Count()
data, err = s.Where("workflow_id=?", []interface{}{id}).Limit(limits).Order("create_time", "desc").Select() data, err = s.Where("workflow_id=?", []interface{}{id}).Limit(limits).Order("create_time", "desc").Select()
} }
if err != nil { if err != nil {
return data, 0, err return data, 0, err
} }
return data, int(count), nil return data, int(count), nil
} }
// 添加工作流执行历史记录 // 添加工作流执行历史记录
func AddWorkflowHistory(workflowID, execType string) (string, error) { func AddWorkflowHistory(workflowID, execType string) (string, error) {
s, err := GetSqliteObjWH() s, err := GetSqliteObjWH()
if err != nil { if err != nil {
return "", err return "", err
} }
defer s.Close() defer s.Close()
now := time.Now().Format("2006-01-02 15:04:05") now := time.Now().Format("2006-01-02 15:04:05")
ID := public.GenerateUUID() ID := public.GenerateUUID()
_, err = s.Insert(map[string]interface{}{ _, err = s.Insert(map[string]interface{}{
"id": ID, "id": ID,
"workflow_id": workflowID, "workflow_id": workflowID,
"status": "running", "status": "running",
"exec_type": execType, "exec_type": execType,
"create_time": now, "create_time": now,
}) })
if err != nil { if err != nil {
return "", err return "", err
} }
_ = UpdDb(workflowID, map[string]interface{}{"last_run_status": "running", "last_run_time": now}) _ = UpdDb(workflowID, map[string]interface{}{"last_run_status": "running", "last_run_time": now})
return ID, nil return ID, nil
} }
// 工作流执行结束 // 工作流执行结束
func UpdateWorkflowHistory(id, status string) error { func UpdateWorkflowHistory(id, status string) error {
s, err := GetSqliteObjWH() s, err := GetSqliteObjWH()
if err != nil { if err != nil {
return err return err
} }
defer s.Close() defer s.Close()
now := time.Now().Format("2006-01-02 15:04:05") now := time.Now().Format("2006-01-02 15:04:05")
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{ _, err = s.Where("id=?", []interface{}{id}).Update(map[string]interface{}{
"status": status, "status": status,
"end_time": now, "end_time": now,
}) })
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func StopWorkflow(id string) error { func StopWorkflow(id string) error {
s, err := GetSqliteObjWH() s, err := GetSqliteObjWH()
if err != nil { if err != nil {
return err return err
} }
defer s.Close() defer s.Close()
data, err := s.Where("id=?", []interface{}{id}).Select() data, err := s.Where("id=?", []interface{}{id}).Select()
if err != nil { if err != nil {
return err return err
} }
if len(data) == 0 { if len(data) == 0 {
return nil return nil
} }
SetWorkflowStatus(data[0]["workflow_id"].(string), id, "fail") SetWorkflowStatus(data[0]["workflow_id"].(string), id, "fail")
return nil return nil
} }
func GetExecLog(id string) (string, error) { func GetExecLog(id string) (string, error) {
log, err := os.ReadFile(filepath.Join(public.GetSettingIgnoreError("workflow_log_path"), id+".log")) log, err := os.ReadFile(filepath.Join(public.GetSettingIgnoreError("workflow_log_path"), id+".log"))
if err != nil { if err != nil {
return "", err return "", err
} }
return string(log), nil return string(log), nil
} }

View File

@ -11,7 +11,7 @@ import (
func init() { func init() {
os.MkdirAll("data", os.ModePerm) os.MkdirAll("data", os.ModePerm)
dbPath := "data/data.db" dbPath := "data/data.db"
_, _ = filepath.Abs(dbPath) _, _ = filepath.Abs(dbPath)
// fmt.Println("数据库路径:", absPath) // fmt.Println("数据库路径:", absPath)
@ -176,15 +176,15 @@ func init() {
INSERT INTO access_type (name, type) VALUES ('ssh', 'host'); INSERT INTO access_type (name, type) VALUES ('ssh', 'host');
INSERT INTO access_type (name, type) VALUES ('btpanel', 'host'); INSERT INTO access_type (name, type) VALUES ('btpanel', 'host');
INSERT INTO access_type (name, type) VALUES ('1panel', 'host');`) INSERT INTO access_type (name, type) VALUES ('1panel', 'host');`)
uuidStr := public.GenerateUUID() uuidStr := public.GenerateUUID()
randomStr := public.RandomString(8) randomStr := public.RandomString(8)
port, err := public.GetFreePort() port, err := public.GetFreePort()
if err != nil { if err != nil {
port = 20773 port = 20773
} }
Isql := fmt.Sprintf( Isql := fmt.Sprintf(
`INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('log_path', 'logs/ALLinSSL.log', '2025-04-15 15:58', '2025-04-15 15:58', 1, null); `INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('log_path', 'logs/ALLinSSL.log', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ( 'workflow_log_path', 'logs/workflows/', '2025-04-15 15:58', '2025-04-15 15:58', 1, null); INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ( 'workflow_log_path', 'logs/workflows/', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
@ -194,7 +194,7 @@ INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('session_key', '%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null); INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('session_key', '%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('secure', '/%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null); INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('secure', '/%s', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);
INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('port', '%d', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);`, uuidStr, uuidStr, randomStr, port) INSERT INTO settings (key, value, create_time, update_time, active, type) VALUES ('port', '%d', '2025-04-15 15:58', '2025-04-15 15:58', 1, null);`, uuidStr, uuidStr, randomStr, port)
insertDefaultData(db, "settings", Isql) insertDefaultData(db, "settings", Isql)
} }
@ -206,7 +206,7 @@ func insertDefaultData(db *sql.DB, table, insertSQL string) {
// fmt.Println("检查数据行数失败:", err) // fmt.Println("检查数据行数失败:", err)
return return
} }
// 如果表为空,则插入默认数据 // 如果表为空,则插入默认数据
if count == 0 { if count == 0 {
// fmt.Println("表为空,插入默认数据...") // fmt.Println("表为空,插入默认数据...")

View File

@ -1,181 +1,181 @@
package public package public
import ( import (
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
"io" "io"
"math/big" "math/big"
"net" "net"
"net/http" "net/http"
"strings" "strings"
) )
const defaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" const defaultCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
// GetSettingIgnoreError 获取系统配置-忽略错误 // GetSettingIgnoreError 获取系统配置-忽略错误
func GetSettingIgnoreError(key string) string { func GetSettingIgnoreError(key string) string {
s, err := NewSqlite("data/data.db", "") s, err := NewSqlite("data/data.db", "")
if err != nil { if err != nil {
return "" return ""
} }
s.Connect() s.Connect()
defer s.Close() defer s.Close()
s.TableName = "settings" s.TableName = "settings"
res, err := s.Where("key=?", []interface{}{key}).Select() res, err := s.Where("key=?", []interface{}{key}).Select()
if err != nil { if err != nil {
return "" return ""
} }
if len(res) == 0 { if len(res) == 0 {
return "" return ""
} }
setting, ok := res[0]["value"].(string) setting, ok := res[0]["value"].(string)
if !ok { if !ok {
return "" return ""
} }
return setting return setting
} }
func UpdateSetting(key, val string) error { func UpdateSetting(key, val string) error {
s, err := NewSqlite("data/data.db", "") s, err := NewSqlite("data/data.db", "")
if err != nil { if err != nil {
return err return err
} }
s.Connect() s.Connect()
defer s.Close() defer s.Close()
s.TableName = "settings" s.TableName = "settings"
_, err = s.Where("key=?", []interface{}{key}).Update(map[string]any{"value": val}) _, err = s.Where("key=?", []interface{}{key}).Update(map[string]any{"value": val})
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func GetSettingsFromType(typ string) ([]map[string]any, error) { func GetSettingsFromType(typ string) ([]map[string]any, error) {
db := "data/data.db" db := "data/data.db"
s, err := NewSqlite(db, "") s, err := NewSqlite(db, "")
if err != nil { if err != nil {
return nil, err return nil, err
} }
s.Connect() s.Connect()
defer s.Close() defer s.Close()
s.TableName = "settings" s.TableName = "settings"
res, err := s.Where("type=?", []interface{}{typ}).Select() res, err := s.Where("type=?", []interface{}{typ}).Select()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return res, nil return res, nil
} }
// GetFreePort 获取一个可用的随机端口 // GetFreePort 获取一个可用的随机端口
func GetFreePort() (int, error) { func GetFreePort() (int, error) {
// 端口为 0表示让系统自动分配一个可用端口 // 端口为 0表示让系统自动分配一个可用端口
ln, err := net.Listen("tcp", "localhost:0") ln, err := net.Listen("tcp", "localhost:0")
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer ln.Close() defer ln.Close()
addr := ln.Addr().String() addr := ln.Addr().String()
// 提取端口号 // 提取端口号
parts := strings.Split(addr, ":") parts := strings.Split(addr, ":")
if len(parts) < 2 { if len(parts) < 2 {
return 0, fmt.Errorf("invalid address: %s", addr) return 0, fmt.Errorf("invalid address: %s", addr)
} }
var port int var port int
fmt.Sscanf(parts[len(parts)-1], "%d", &port) fmt.Sscanf(parts[len(parts)-1], "%d", &port)
return port, nil return port, nil
} }
// RandomString 生成指定长度的随机字符串 // RandomString 生成指定长度的随机字符串
func RandomString(length int) string { func RandomString(length int) string {
if str, err := RandomStringWithCharset(length, defaultCharset); err != nil { if str, err := RandomStringWithCharset(length, defaultCharset); err != nil {
return "allinssl" return "allinssl"
} else { } else {
return str return str
} }
} }
// RandomStringWithCharset 使用指定字符集生成随机字符串 // RandomStringWithCharset 使用指定字符集生成随机字符串
func RandomStringWithCharset(length int, charset string) (string, error) { func RandomStringWithCharset(length int, charset string) (string, error) {
result := make([]byte, length) result := make([]byte, length)
charsetLen := big.NewInt(int64(len(charset))) charsetLen := big.NewInt(int64(len(charset)))
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
num, err := rand.Int(rand.Reader, charsetLen) num, err := rand.Int(rand.Reader, charsetLen)
if err != nil { if err != nil {
return "", err return "", err
} }
result[i] = charset[num.Int64()] result[i] = charset[num.Int64()]
} }
return string(result), nil return string(result), nil
} }
// GenerateUUID 生成 UUID // GenerateUUID 生成 UUID
func GenerateUUID() string { func GenerateUUID() string {
// 生成一个新的 UUID // 生成一个新的 UUID
uuidStr := strings.ReplaceAll(uuid.New().String(), "-", "") uuidStr := strings.ReplaceAll(uuid.New().String(), "-", "")
// 返回 UUID 的字符串表示 // 返回 UUID 的字符串表示
return uuidStr return uuidStr
} }
func GetLocalIP() (string, error) { func GetLocalIP() (string, error) {
interfaces, err := net.Interfaces() interfaces, err := net.Interfaces()
if err != nil { if err != nil {
return "", err return "", err
} }
for _, iface := range interfaces { for _, iface := range interfaces {
if iface.Flags&net.FlagUp == 0 { if iface.Flags&net.FlagUp == 0 {
continue // 接口未启用 continue // 接口未启用
} }
if iface.Flags&net.FlagLoopback != 0 { if iface.Flags&net.FlagLoopback != 0 {
continue // 忽略回环地址 continue // 忽略回环地址
} }
addrs, err := iface.Addrs() addrs, err := iface.Addrs()
if err != nil { if err != nil {
continue continue
} }
for _, addr := range addrs { for _, addr := range addrs {
var ip net.IP var ip net.IP
switch v := addr.(type) { switch v := addr.(type) {
case *net.IPNet: case *net.IPNet:
ip = v.IP ip = v.IP
case *net.IPAddr: case *net.IPAddr:
ip = v.IP ip = v.IP
} }
// 只返回 IPv4 内网地址 // 只返回 IPv4 内网地址
if ip != nil && ip.To4() != nil && !ip.IsLoopback() { if ip != nil && ip.To4() != nil && !ip.IsLoopback() {
return ip.String(), nil return ip.String(), nil
} }
} }
} }
return "", fmt.Errorf("没有找到内网 IP") return "", fmt.Errorf("没有找到内网 IP")
} }
func GetPublicIP() (string, error) { func GetPublicIP() (string, error) {
resp, err := http.Get("https://www.bt.cn/Api/getIpAddress") resp, err := http.Get("https://www.bt.cn/Api/getIpAddress")
if err != nil { if err != nil {
return "", fmt.Errorf("请求失败: %v", err) return "", fmt.Errorf("请求失败: %v", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP状态错误: %v", resp.Status) return "", fmt.Errorf("HTTP状态错误: %v", resp.Status)
} }
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return "", fmt.Errorf("读取响应失败: %v", err) return "", fmt.Errorf("读取响应失败: %v", err)
} }
return string(body), nil return string(body), nil
} }