style: apply gci, gofmt, gofumpt, golines to channels and config

This commit is contained in:
zhouliang 2026-02-24 13:52:43 +08:00
parent abe0375ce9
commit 82d46a7684
4 changed files with 40 additions and 34 deletions

View file

@ -19,11 +19,12 @@ import (
"github.com/emersion/go-imap/client" "github.com/emersion/go-imap/client"
charset "github.com/emersion/go-message/charset" charset "github.com/emersion/go-message/charset"
"github.com/emersion/go-message/mail" "github.com/emersion/go-message/mail"
"golang.org/x/text/encoding/simplifiedchinese"
"github.com/sipeed/picoclaw/pkg/bus" "github.com/sipeed/picoclaw/pkg/bus"
"github.com/sipeed/picoclaw/pkg/config" "github.com/sipeed/picoclaw/pkg/config"
"github.com/sipeed/picoclaw/pkg/logger" "github.com/sipeed/picoclaw/pkg/logger"
"github.com/sipeed/picoclaw/pkg/utils" "github.com/sipeed/picoclaw/pkg/utils"
"golang.org/x/text/encoding/simplifiedchinese"
) )
func init() { func init() {
@ -227,9 +228,9 @@ func (c *EmailChannel) Send(ctx context.Context, msg bus.OutboundMessage) error
defer client.Close() defer client.Close()
if err = client.StartTLS(&tls.Config{ServerName: host}); err != nil { if err = client.StartTLS(&tls.Config{ServerName: host}); err != nil {
// Some servers on 587 do not require STARTTLS; continue anyway // Some servers on 587 do not require STARTTLS; continue anyway
logger.WarnCF("email", "STARTTLS failed, connection may be unencrypted; credentials could be sent in plaintext", map[string]interface{}{ logger.WarnCF("email",
"error": err.Error(), "STARTTLS failed, connection may be unencrypted; credentials could be sent in plaintext",
}) map[string]interface{}{"error": err.Error()})
_ = err _ = err
} }
auth := smtp.PlainAuth("", c.config.Username, c.config.Password, host) auth := smtp.PlainAuth("", c.config.Username, c.config.Password, host)
@ -291,7 +292,9 @@ func (c *EmailChannel) connect() error {
status, err := cl.Select(mailbox, false) status, err := cl.Select(mailbox, false)
if err != nil { if err != nil {
if strings.Contains(err.Error(), "Unsafe Login") || strings.Contains(err.Error(), "不安全") { if strings.Contains(err.Error(), "Unsafe Login") || strings.Contains(err.Error(), "不安全") {
return fmt.Errorf("failed to select mailbox %s: %w (hint: 163/QQ/126 require app password, not account password)", mailbox, err) return fmt.Errorf(
"failed to select mailbox %s: %w (hint: 163/QQ/126 require app password, not account password)",
mailbox, err)
} }
return fmt.Errorf("failed to select mailbox %s: %w", mailbox, err) return fmt.Errorf("failed to select mailbox %s: %w", mailbox, err)
} }
@ -832,7 +835,7 @@ func (c *EmailChannel) saveAttachmentToLocal(uid uint32, index int, filename str
if dir == "" { if dir == "" {
return "" return ""
} }
if err := os.MkdirAll(dir, 0700); err != nil { if err := os.MkdirAll(dir, 0o700); err != nil {
logger.DebugCF("email", "Failed to create attachment dir", map[string]interface{}{"error": err.Error(), "dir": dir}) logger.DebugCF("email", "Failed to create attachment dir", map[string]interface{}{"error": err.Error(), "dir": dir})
return "" return ""
} }

View file

@ -13,13 +13,13 @@ import (
"github.com/bytedance/mockey" "github.com/bytedance/mockey"
"github.com/emersion/go-imap" "github.com/emersion/go-imap"
"github.com/emersion/go-imap/client" "github.com/emersion/go-imap/client"
"github.com/stretchr/testify/assert"
"github.com/sipeed/picoclaw/pkg/bus" "github.com/sipeed/picoclaw/pkg/bus"
"github.com/sipeed/picoclaw/pkg/config" "github.com/sipeed/picoclaw/pkg/config"
"github.com/stretchr/testify/assert"
) )
func TestEmailChannel_sanitizeHeaderValue(t *testing.T) { func TestEmailChannel_sanitizeHeaderValue(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
s string s string
@ -61,6 +61,7 @@ func TestEmailChannel_parseFilenameFromDisposition(t *testing.T) {
}) })
} }
} }
func TestEmailChannel_decodeRFC2047Filename(t *testing.T) { func TestEmailChannel_decodeRFC2047Filename(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@ -93,7 +94,8 @@ func TestEmailChannel_extractEmailBodyAndAttachments(t *testing.T) {
}) })
t.Run("plain text body", func(t *testing.T) { t.Run("plain text body", func(t *testing.T) {
mimeBytes := []byte("From: a@b.com\r\nTo: c@d.com\r\nSubject: Test\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nHello world") mimeBytes := []byte(
"From: a@b.com\r\nTo: c@d.com\r\nSubject: Test\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nHello world")
section := &imap.BodySectionName{} section := &imap.BodySectionName{}
msg := &imap.Message{ msg := &imap.Message{
Uid: 1, Uid: 1,
@ -172,7 +174,6 @@ func TestEmailChannel_extractEmailBodyAndAttachments(t *testing.T) {
}, },
} }
t.Run("body part max bytes", func(t *testing.T) { t.Run("body part max bytes", func(t *testing.T) {
mimeBytes := attachmentwithText mimeBytes := attachmentwithText
section := &imap.BodySectionName{} section := &imap.BodySectionName{}
msg := &imap.Message{ msg := &imap.Message{
@ -189,7 +190,6 @@ func TestEmailChannel_extractEmailBodyAndAttachments(t *testing.T) {
} }
func TestEmailChannel_extractTextFromHTML(t *testing.T) { func TestEmailChannel_extractTextFromHTML(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
s string s string
@ -282,24 +282,32 @@ func TestEmailChannel_checkNewEmails(t *testing.T) {
mockey.Mock(mockey.GetMethod(mockClient, "UidSearch")).To(func(imapClient *client.Client, criteria *imap.SearchCriteria) ([]uint32, error) { mockey.Mock(mockey.GetMethod(mockClient, "UidSearch")).To(func(imapClient *client.Client, criteria *imap.SearchCriteria) ([]uint32, error) {
return []uint32{21}, nil return []uint32{21}, nil
}).Build() }).Build()
mockey.Mock(mockey.GetMethod(mockClient, "UidFetch")).To(func(imapClient *client.Client, seqset *imap.SeqSet, items []imap.FetchItem, ch chan *imap.Message) error { mockey.Mock(mockey.GetMethod(mockClient, "UidFetch")).To(
mimeBytes := []byte("From: a@b.com\r\nTo: c@d.com\r\nSubject: Test\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nHello world") func(imapClient *client.Client, seqset *imap.SeqSet, items []imap.FetchItem, ch chan *imap.Message) error {
section := &imap.BodySectionName{} mimeBytes := []byte(
msg := &imap.Message{ "From: a@b.com\r\nTo: c@d.com\r\nSubject: Test\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nHello world")
Uid: 1, section := &imap.BodySectionName{}
Envelope: &imap.Envelope{Subject: "Test"}, msg := &imap.Message{
Body: map[*imap.BodySectionName]imap.Literal{section: bytes.NewReader(mimeBytes)}, Uid: 1,
} Envelope: &imap.Envelope{Subject: "Test"},
ch <- msg Body: map[*imap.BodySectionName]imap.Literal{section: bytes.NewReader(mimeBytes)},
close(ch) }
return nil ch <- msg
}).Build() close(ch)
return nil
}).Build()
mockClient.SetState(imap.SelectedState, &imap.MailboxStatus{
UidNext: 20,
})
mockey.Mock(mockey.GetMethod(mockClient, "State")).To(func(*client.Client) imap.ConnState { mockey.Mock(mockey.GetMethod(mockClient, "State")).To(func(*client.Client) imap.ConnState {
return imap.SelectedState return imap.SelectedState
}).Build() }).Build()
mockey.Mock(mockey.GetMethod(mockClient, "UidStore")).To(func(imapClient *client.Client, seqset *imap.SeqSet, item imap.StoreItem, value interface{}, ch chan *imap.Message) error { mockey.Mock(mockey.GetMethod(mockClient, "UidStore")).To(
return nil func(imapClient *client.Client, seqset *imap.SeqSet, item imap.StoreItem, value interface{},
}).Build() ch chan *imap.Message,
) error {
return nil
}).Build()
// --------------- mock end --------------- // --------------- mock end ---------------
ctx := context.Background() ctx := context.Background()
c.CheckNewEmails(context.Background()) c.CheckNewEmails(context.Background())
@ -308,7 +316,6 @@ func TestEmailChannel_checkNewEmails(t *testing.T) {
assert.True(t, ok) assert.True(t, ok)
assert.True(t, strings.Contains(messge.Content, "Hello world")) assert.True(t, strings.Contains(messge.Content, "Hello world"))
}) })
} }
func TestEmailChannel_runIdleLoop(t *testing.T) { func TestEmailChannel_runIdleLoop(t *testing.T) {
@ -322,7 +329,7 @@ func TestEmailChannel_runIdleLoop(t *testing.T) {
// mock connect to return mockClient // mock connect to return mockClient
mockey.PatchConvey("runIdleLoop", t, func() { mockey.PatchConvey("runIdleLoop", t, func() {
// --------------- mock start --------------- // --------------- mock start ---------------
var hasCheckEmail = false hasCheckEmail := false
c := &EmailChannel{ c := &EmailChannel{
BaseChannel: &BaseChannel{ BaseChannel: &BaseChannel{
bus: bus.NewMessageBus(), bus: bus.NewMessageBus(),
@ -357,9 +364,7 @@ func TestEmailChannel_runIdleLoop(t *testing.T) {
triggerChannel <- struct{}{} triggerChannel <- struct{}{}
time.Sleep(time.Second) time.Sleep(time.Second)
assert.True(t, hasCheckEmail) assert.True(t, hasCheckEmail)
}) })
} }
func TestEmailChannel_lifecycleCheck(t *testing.T) { func TestEmailChannel_lifecycleCheck(t *testing.T) {

View file

@ -179,9 +179,8 @@ func (m *Manager) initChannels() error {
logger.DebugC("channels", "Attempting to initialize Email channel") logger.DebugC("channels", "Attempting to initialize Email channel")
email, err := NewEmailChannel(m.config.Channels.Email, m.bus) email, err := NewEmailChannel(m.config.Channels.Email, m.bus)
if err != nil { if err != nil {
logger.ErrorCF("channels", "Failed to initialize Email channel", map[string]interface{}{ logger.ErrorCF("channels", "Failed to initialize Email channel",
"error": err.Error(), map[string]interface{}{"error": err.Error()})
})
} else { } else {
m.channels["email"] = email m.channels["email"] = email
logger.InfoC("channels", "Email channel enabled successfully") logger.InfoC("channels", "Email channel enabled successfully")

View file

@ -468,7 +468,6 @@ type ExecConfig struct {
CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"` CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"`
} }
type ToolsConfig struct { type ToolsConfig struct {
Web WebToolsConfig `json:"web"` Web WebToolsConfig `json:"web"`
Cron CronToolsConfig `json:"cron"` Cron CronToolsConfig `json:"cron"`