fix: remove premature media file cleanup in channel handlers
Media files (photos, voice, audio, documents) downloaded by channel handlers were immediately deleted via defer when handleMessage returned. However, HandleMessage publishes to an async message bus, so the agent goroutine would attempt to access already-deleted files. Remove the eager defer cleanup from telegram, discord, slack, and line channels. Temp files in os.TempDir()/picoclaw_media/ are managed by the OS temp directory lifecycle. Fixes media/voice/document processing being non-functional across all affected channels.
This commit is contained in:
parent
e23795e51b
commit
e91c68ed34
4 changed files with 16 additions and 64 deletions
|
|
@ -3,7 +3,6 @@ package channels
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -210,19 +209,10 @@ func (c *DiscordChannel) handleMessage(s *discordgo.Session, m *discordgo.Messag
|
||||||
content := m.Content
|
content := m.Content
|
||||||
content = c.stripBotMention(content)
|
content = c.stripBotMention(content)
|
||||||
mediaPaths := make([]string, 0, len(m.Attachments))
|
mediaPaths := make([]string, 0, len(m.Attachments))
|
||||||
localFiles := make([]string, 0, len(m.Attachments))
|
// Note: media files in os.TempDir()/picoclaw_media/ are not cleaned up here
|
||||||
|
// because HandleMessage publishes to an async message bus. The consumer
|
||||||
// Ensure temp files are cleaned up when function returns
|
// goroutine may still need these files after this function returns.
|
||||||
defer func() {
|
// Temp files are managed by OS temp directory lifecycle.
|
||||||
for _, file := range localFiles {
|
|
||||||
if err := os.Remove(file); err != nil {
|
|
||||||
logger.DebugCF("discord", "Failed to cleanup temp file", map[string]any{
|
|
||||||
"file": file,
|
|
||||||
"error": err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for _, attachment := range m.Attachments {
|
for _, attachment := range m.Attachments {
|
||||||
isAudio := utils.IsAudioFile(attachment.Filename, attachment.ContentType)
|
isAudio := utils.IsAudioFile(attachment.Filename, attachment.ContentType)
|
||||||
|
|
@ -230,8 +220,6 @@ func (c *DiscordChannel) handleMessage(s *discordgo.Session, m *discordgo.Messag
|
||||||
if isAudio {
|
if isAudio {
|
||||||
localPath := c.downloadAttachment(attachment.URL, attachment.Filename)
|
localPath := c.downloadAttachment(attachment.URL, attachment.Filename)
|
||||||
if localPath != "" {
|
if localPath != "" {
|
||||||
localFiles = append(localFiles, localPath)
|
|
||||||
|
|
||||||
transcribedText := ""
|
transcribedText := ""
|
||||||
if c.transcriber != nil && c.transcriber.IsAvailable() {
|
if c.transcriber != nil && c.transcriber.IsAvailable() {
|
||||||
ctx, cancel := context.WithTimeout(c.getContext(), transcriptionTimeout)
|
ctx, cancel := context.WithTimeout(c.getContext(), transcriptionTimeout)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -307,18 +306,10 @@ func (c *LINEChannel) processEvent(event lineEvent) {
|
||||||
|
|
||||||
var content string
|
var content string
|
||||||
var mediaPaths []string
|
var mediaPaths []string
|
||||||
localFiles := []string{}
|
// Note: media files in os.TempDir()/picoclaw_media/ are not cleaned up here
|
||||||
|
// because HandleMessage publishes to an async message bus. The consumer
|
||||||
defer func() {
|
// goroutine may still need these files after this function returns.
|
||||||
for _, file := range localFiles {
|
// Temp files are managed by OS temp directory lifecycle.
|
||||||
if err := os.Remove(file); err != nil {
|
|
||||||
logger.DebugCF("line", "Failed to cleanup temp file", map[string]interface{}{
|
|
||||||
"file": file,
|
|
||||||
"error": err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
case "text":
|
case "text":
|
||||||
|
|
@ -330,21 +321,18 @@ func (c *LINEChannel) processEvent(event lineEvent) {
|
||||||
case "image":
|
case "image":
|
||||||
localPath := c.downloadContent(msg.ID, "image.jpg")
|
localPath := c.downloadContent(msg.ID, "image.jpg")
|
||||||
if localPath != "" {
|
if localPath != "" {
|
||||||
localFiles = append(localFiles, localPath)
|
|
||||||
mediaPaths = append(mediaPaths, localPath)
|
mediaPaths = append(mediaPaths, localPath)
|
||||||
content = "[image]"
|
content = "[image]"
|
||||||
}
|
}
|
||||||
case "audio":
|
case "audio":
|
||||||
localPath := c.downloadContent(msg.ID, "audio.m4a")
|
localPath := c.downloadContent(msg.ID, "audio.m4a")
|
||||||
if localPath != "" {
|
if localPath != "" {
|
||||||
localFiles = append(localFiles, localPath)
|
|
||||||
mediaPaths = append(mediaPaths, localPath)
|
mediaPaths = append(mediaPaths, localPath)
|
||||||
content = "[audio]"
|
content = "[audio]"
|
||||||
}
|
}
|
||||||
case "video":
|
case "video":
|
||||||
localPath := c.downloadContent(msg.ID, "video.mp4")
|
localPath := c.downloadContent(msg.ID, "video.mp4")
|
||||||
if localPath != "" {
|
if localPath != "" {
|
||||||
localFiles = append(localFiles, localPath)
|
|
||||||
mediaPaths = append(mediaPaths, localPath)
|
mediaPaths = append(mediaPaths, localPath)
|
||||||
content = "[video]"
|
content = "[video]"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package channels
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -232,19 +231,10 @@ func (c *SlackChannel) handleMessageEvent(ev *slackevents.MessageEvent) {
|
||||||
content = c.stripBotMention(content)
|
content = c.stripBotMention(content)
|
||||||
|
|
||||||
var mediaPaths []string
|
var mediaPaths []string
|
||||||
localFiles := []string{} // 跟踪需要清理的本地文件
|
// Note: media files in os.TempDir()/picoclaw_media/ are not cleaned up here
|
||||||
|
// because HandleMessage publishes to an async message bus. The consumer
|
||||||
// 确保临时文件在函数返回时被清理
|
// goroutine may still need these files after this function returns.
|
||||||
defer func() {
|
// Temp files are managed by OS temp directory lifecycle.
|
||||||
for _, file := range localFiles {
|
|
||||||
if err := os.Remove(file); err != nil {
|
|
||||||
logger.DebugCF("slack", "Failed to cleanup temp file", map[string]interface{}{
|
|
||||||
"file": file,
|
|
||||||
"error": err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if ev.Message != nil && len(ev.Message.Files) > 0 {
|
if ev.Message != nil && len(ev.Message.Files) > 0 {
|
||||||
for _, file := range ev.Message.Files {
|
for _, file := range ev.Message.Files {
|
||||||
|
|
@ -252,7 +242,6 @@ func (c *SlackChannel) handleMessageEvent(ev *slackevents.MessageEvent) {
|
||||||
if localPath == "" {
|
if localPath == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
localFiles = append(localFiles, localPath)
|
|
||||||
mediaPaths = append(mediaPaths, localPath)
|
mediaPaths = append(mediaPaths, localPath)
|
||||||
|
|
||||||
if utils.IsAudioFile(file.Name, file.Mimetype) && c.transcriber != nil && c.transcriber.IsAvailable() {
|
if utils.IsAudioFile(file.Name, file.Mimetype) && c.transcriber != nil && c.transcriber.IsAvailable() {
|
||||||
|
|
|
||||||
|
|
@ -221,19 +221,10 @@ func (c *TelegramChannel) handleMessage(ctx context.Context, message *telego.Mes
|
||||||
|
|
||||||
content := ""
|
content := ""
|
||||||
mediaPaths := []string{}
|
mediaPaths := []string{}
|
||||||
localFiles := []string{} // 跟踪需要清理的本地文件
|
// Note: media files in os.TempDir()/picoclaw_media/ are not cleaned up here
|
||||||
|
// because HandleMessage publishes to an async message bus. The consumer
|
||||||
// 确保临时文件在函数返回时被清理
|
// goroutine may still need these files after this function returns.
|
||||||
defer func() {
|
// Temp files are managed by OS temp directory lifecycle.
|
||||||
for _, file := range localFiles {
|
|
||||||
if err := os.Remove(file); err != nil {
|
|
||||||
logger.DebugCF("telegram", "Failed to cleanup temp file", map[string]interface{}{
|
|
||||||
"file": file,
|
|
||||||
"error": err.Error(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if message.Text != "" {
|
if message.Text != "" {
|
||||||
content += message.Text
|
content += message.Text
|
||||||
|
|
@ -250,7 +241,6 @@ func (c *TelegramChannel) handleMessage(ctx context.Context, message *telego.Mes
|
||||||
photo := message.Photo[len(message.Photo)-1]
|
photo := message.Photo[len(message.Photo)-1]
|
||||||
photoPath := c.downloadPhoto(ctx, photo.FileID)
|
photoPath := c.downloadPhoto(ctx, photo.FileID)
|
||||||
if photoPath != "" {
|
if photoPath != "" {
|
||||||
localFiles = append(localFiles, photoPath)
|
|
||||||
mediaPaths = append(mediaPaths, photoPath)
|
mediaPaths = append(mediaPaths, photoPath)
|
||||||
if content != "" {
|
if content != "" {
|
||||||
content += "\n"
|
content += "\n"
|
||||||
|
|
@ -262,7 +252,6 @@ func (c *TelegramChannel) handleMessage(ctx context.Context, message *telego.Mes
|
||||||
if message.Voice != nil {
|
if message.Voice != nil {
|
||||||
voicePath := c.downloadFile(ctx, message.Voice.FileID, ".ogg")
|
voicePath := c.downloadFile(ctx, message.Voice.FileID, ".ogg")
|
||||||
if voicePath != "" {
|
if voicePath != "" {
|
||||||
localFiles = append(localFiles, voicePath)
|
|
||||||
mediaPaths = append(mediaPaths, voicePath)
|
mediaPaths = append(mediaPaths, voicePath)
|
||||||
|
|
||||||
transcribedText := ""
|
transcribedText := ""
|
||||||
|
|
@ -297,7 +286,6 @@ func (c *TelegramChannel) handleMessage(ctx context.Context, message *telego.Mes
|
||||||
if message.Audio != nil {
|
if message.Audio != nil {
|
||||||
audioPath := c.downloadFile(ctx, message.Audio.FileID, ".mp3")
|
audioPath := c.downloadFile(ctx, message.Audio.FileID, ".mp3")
|
||||||
if audioPath != "" {
|
if audioPath != "" {
|
||||||
localFiles = append(localFiles, audioPath)
|
|
||||||
mediaPaths = append(mediaPaths, audioPath)
|
mediaPaths = append(mediaPaths, audioPath)
|
||||||
if content != "" {
|
if content != "" {
|
||||||
content += "\n"
|
content += "\n"
|
||||||
|
|
@ -309,7 +297,6 @@ func (c *TelegramChannel) handleMessage(ctx context.Context, message *telego.Mes
|
||||||
if message.Document != nil {
|
if message.Document != nil {
|
||||||
docPath := c.downloadFile(ctx, message.Document.FileID, "")
|
docPath := c.downloadFile(ctx, message.Document.FileID, "")
|
||||||
if docPath != "" {
|
if docPath != "" {
|
||||||
localFiles = append(localFiles, docPath)
|
|
||||||
mediaPaths = append(mediaPaths, docPath)
|
mediaPaths = append(mediaPaths, docPath)
|
||||||
if content != "" {
|
if content != "" {
|
||||||
content += "\n"
|
content += "\n"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue