From abc9c93b4ef0957dbdd8fcdcdb291af2e8885eb7 Mon Sep 17 00:00:00 2001 From: mei Date: Mon, 6 Oct 2025 17:26:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(pkg/github):=20Github=E9=81=97=E8=A8=80?= =?UTF-8?q?=E4=BB=93=E5=BA=93=20fix(internal/sendMail):=20=E9=87=8D?= =?UTF-8?q?=E8=AF=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/github.go | 1 + internal/sendMail.go | 69 +++++++++++++++++++++++------ main.go | 2 + pkg/github.go | 102 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 14 deletions(-) create mode 100644 internal/github.go create mode 100644 pkg/github.go diff --git a/internal/github.go b/internal/github.go new file mode 100644 index 0000000..5bf0569 --- /dev/null +++ b/internal/github.go @@ -0,0 +1 @@ +package internal diff --git a/internal/sendMail.go b/internal/sendMail.go index d438928..13f5aca 100644 --- a/internal/sendMail.go +++ b/internal/sendMail.go @@ -3,28 +3,65 @@ package internal import ( "fmt" "log" + "time" "github.com/ssdomei232/goodBaby/configs" "github.com/wneessen/go-mail" ) +const ( + maxRetries = 10 + retryDelay = 10 * time.Second +) + func SendMail() { config, err := configs.GetConfig() if err != nil { log.Printf("获取配置文件失败: %v", err) + return } + for _, address := range config.MailList { - sendMailMsg(address, config.MailContent) + sendMailMsgWithRetry(address, config.MailContent, config.MailTitle) } } -func sendMailMsg(address string, msg string) { - config, err := configs.GetConfig() - if err != nil { - log.Printf("获取配置文件失败: %v", err) +func sendMailMsgWithRetry(address string, msg string, title string) { + var lastErr error + + // 重试循环 + for i := 0; i <= maxRetries; i++ { + if i > 0 { + log.Printf("第 %d 次重试发送邮件给 %s", i, address) + } + + err := sendMailMsg(address, msg, title) + if err == nil { + // 发送成功 + fmt.Printf("邮件成功发送给 %s\n", address) + return + } + + lastErr = err + log.Printf("发送邮件给 %s 失败: %v", address, err) + + // 如果不是最后一次重试,则等待后重试 + if i < maxRetries { + time.Sleep(retryDelay * time.Duration(i+1)) // 递增延迟 + } } - mailMsg := fmt.Sprintf("Hello,\nThis is a test email sent from Go!%s", msg) + // 所有重试都失败 + log.Printf("发送邮件给 %s 经过 %d 次重试后仍然失败: %v", address, maxRetries, lastErr) +} + +func sendMailMsg(address string, msg string, title string) error { + config, err := configs.GetConfig() + if err != nil { + return fmt.Errorf("获取配置文件失败: %v", err) + } + + mailMsg := fmt.Sprintf("Hello,\nThis is a test email sent from Go!\n%s", msg) client, err := mail.NewClient( config.SMTPConfig.Host, @@ -35,22 +72,26 @@ func sendMailMsg(address string, msg string) { mail.WithSMTPAuth(mail.SMTPAuthPlain), ) if err != nil { - log.Println(err) - return + return fmt.Errorf("创建邮件客户端失败: %v", err) } // 创建邮件 message := mail.NewMsg() - message.From(config.SMTPConfig.User) - message.To(address) - message.Subject(config.MailTitle) + if err := message.From(config.SMTPConfig.User); err != nil { + return fmt.Errorf("设置发件人失败: %v", err) + } + + if err := message.To(address); err != nil { + return fmt.Errorf("设置收件人失败: %v", err) + } + + message.Subject(title) message.SetBodyString(mail.TypeTextPlain, mailMsg) // 发送邮件 if err := client.DialAndSend(message); err != nil { - log.Println(err) - return + return fmt.Errorf("发送邮件失败: %v", err) } - fmt.Println("Email sent successfully!") + return nil } diff --git a/main.go b/main.go index 8091a05..6267cad 100644 --- a/main.go +++ b/main.go @@ -17,11 +17,13 @@ func init() { if err != nil { log.Printf("获取配置文件失败: %v", err) } + if config.Debug { duration = time.Duration(config.DisconnectDuration) * time.Second } else { duration = time.Duration(config.DisconnectDuration) * time.Hour } + timer = time.NewTimer(duration) go func() { <-timer.C diff --git a/pkg/github.go b/pkg/github.go new file mode 100644 index 0000000..f5bd049 --- /dev/null +++ b/pkg/github.go @@ -0,0 +1,102 @@ +package pkg + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "net/http" +) + +// RepositoryVisibility 用于更新仓库可见性的请求体 +type RepositoryVisibility struct { + Private bool `json:"private"` +} + +// MakeRepositoryPublic 将指定的GitHub仓库从私有设置为公开 +func MakeRepositoryPublic(owner, repo, token string) error { + // GitHub API URL for updating repository visibility + url := fmt.Sprintf("https://api.github.com/repos/%s/%s", owner, repo) + + // 创建请求体,将 private 设置为 false 表示公开仓库 + visibility := RepositoryVisibility{ + Private: false, // false 表示公开仓库 + } + + // 将请求体序列化为 JSON + jsonData, err := json.Marshal(visibility) + if err != nil { + return fmt.Errorf("序列化请求体失败: %v", err) + } + + // 创建 PATCH 请求 + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(jsonData)) + if err != nil { + return fmt.Errorf("创建请求失败: %v", err) + } + + // 设置请求头 + req.Header.Set("Authorization", fmt.Sprintf("token %s", token)) + req.Header.Set("Accept", "application/vnd.github.v3+json") + req.Header.Set("Content-Type", "application/json") + + // 发送请求 + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("发送请求失败: %v", err) + } + defer resp.Body.Close() + + // 检查响应状态 + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("请求失败,状态码: %d", resp.StatusCode) + } + + log.Printf("仓库 %s/%s 已成功设置为公开", owner, repo) + return nil +} + +// MakeRepositoryPrivate 将指定的GitHub仓库从公开设置为私有(附加功能) +func MakeRepositoryPrivate(owner, repo, token string) error { + // GitHub API URL for updating repository visibility + url := fmt.Sprintf("https://api.github.com/repos/%s/%s", owner, repo) + + // 创建请求体,将 private 设置为 true 表示私有仓库 + visibility := RepositoryVisibility{ + Private: true, // true 表示私有仓库 + } + + // 将请求体序列化为 JSON + jsonData, err := json.Marshal(visibility) + if err != nil { + return fmt.Errorf("序列化请求体失败: %v", err) + } + + // 创建 PATCH 请求 + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(jsonData)) + if err != nil { + return fmt.Errorf("创建请求失败: %v", err) + } + + // 设置请求头 + req.Header.Set("Authorization", fmt.Sprintf("token %s", token)) + req.Header.Set("Accept", "application/vnd.github.v3+json") + req.Header.Set("Content-Type", "application/json") + + // 发送请求 + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("发送请求失败: %v", err) + } + defer resp.Body.Close() + + // 检查响应状态 + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("请求失败,状态码: %d", resp.StatusCode) + } + + log.Printf("仓库 %s/%s 已成功设置为私有", owner, repo) + return nil +}