From ea2b3614ebcb53ddc9d74efe73335b5adb1541c0 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 28 Apr 2023 21:59:26 +0300 Subject: [PATCH 1/2] Upload files with separate request in mac-nosip connector --- imessage/interface.go | 7 ++++++- imessage/ios/ipc.go | 8 +++++++- imessage/ios/requests.go | 9 +++++++++ imessage/mac-nosip/nosip.go | 18 ++++++++++++++++++ imessage/mac/send.go | 2 +- portal.go | 15 +++++++++++---- 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/imessage/interface.go b/imessage/interface.go index 423ab6bd..b4ef670f 100644 --- a/imessage/interface.go +++ b/imessage/interface.go @@ -65,7 +65,7 @@ type API interface { PrepareDM(guid string) error SendMessage(chatID, text string, replyTo string, replyToPart int, richLink *RichLink, metadata MessageMetadata) (*SendResponse, error) - SendFile(chatID, text, filename string, pathOnDisk string, replyTo string, replyToPart int, mimeType string, voiceMemo bool, metadata MessageMetadata) (*SendResponse, error) + SendFile(chatID, text, filename string, pathOnDisk, guid string, replyTo string, replyToPart int, mimeType string, voiceMemo bool, metadata MessageMetadata) (*SendResponse, error) SendFileCleanup(sendFileDir string) SendTapback(chatID, targetGUID string, targetPart int, tapback TapbackType, remove bool) (*SendResponse, error) SendReadReceipt(chatID, readUpTo string) error @@ -81,6 +81,11 @@ type API interface { Capabilities() ConnectorCapabilities } +type FilePreparingAPI interface { + API + SendFilePrepare(filename string, data []byte) (guid string, err error) +} + var TempFilePermissions os.FileMode = 0640 var TempDirPermissions os.FileMode = 0700 diff --git a/imessage/ios/ipc.go b/imessage/ios/ipc.go index 8381fd64..7c5faa4b 100644 --- a/imessage/ios/ipc.go +++ b/imessage/ios/ipc.go @@ -71,6 +71,7 @@ func timeToFloat(time time.Time) float64 { type APIWithIPC interface { imessage.API SetIPC(*ipc.Processor) + GetIPC() *ipc.Processor SetContactProxy(api imessage.ContactAPI) SetChatInfoProxy(api imessage.ChatInfoAPI) } @@ -121,6 +122,10 @@ func (ios *iOSConnector) SetIPC(proc *ipc.Processor) { ios.IPC = proc } +func (ios *iOSConnector) GetIPC() *ipc.Processor { + return ios.IPC +} + func (ios *iOSConnector) SetContactProxy(api imessage.ContactAPI) { ios.contactProxy = api } @@ -517,12 +522,13 @@ func (ios *iOSConnector) SendMessage(chatID, text string, replyTo string, replyT return &resp, err } -func (ios *iOSConnector) SendFile(chatID, text, filename string, pathOnDisk string, replyTo string, replyToPart int, mimeType string, voiceMemo bool, metadata imessage.MessageMetadata) (*imessage.SendResponse, error) { +func (ios *iOSConnector) SendFile(chatID, text, filename, pathOnDisk, guid, replyTo string, replyToPart int, mimeType string, voiceMemo bool, metadata imessage.MessageMetadata) (*imessage.SendResponse, error) { var resp imessage.SendResponse err := ios.IPC.Request(context.Background(), ReqSendMedia, &SendMediaRequest{ ChatGUID: chatID, Text: text, Attachment: imessage.Attachment{ + GUID: guid, FileName: filename, PathOnDisk: pathOnDisk, MimeType: mimeType, diff --git a/imessage/ios/requests.go b/imessage/ios/requests.go index e095e426..da0ea78c 100644 --- a/imessage/ios/requests.go +++ b/imessage/ios/requests.go @@ -25,6 +25,7 @@ import ( const ( ReqSendMessage ipc.Command = "send_message" + ReqUploadMedia ipc.Command = "upload_media" ReqSendMedia ipc.Command = "send_media" ReqSendTapback ipc.Command = "send_tapback" ReqSendReadReceipt ipc.Command = "send_read_receipt" @@ -66,6 +67,14 @@ type SendMediaRequest struct { Metadata imessage.MessageMetadata `json:"metadata,omitempty"` } +type UploadMediaRequest struct { + PathOnDisk string `json:"path_on_disk"` +} + +type UploadMediaResponse struct { + GUID string `json:"guid"` +} + type SendTapbackRequest struct { ChatGUID string `json:"chat_guid"` TargetGUID string `json:"target_guid"` diff --git a/imessage/mac-nosip/nosip.go b/imessage/mac-nosip/nosip.go index 0b92325e..75f9a58d 100644 --- a/imessage/mac-nosip/nosip.go +++ b/imessage/mac-nosip/nosip.go @@ -17,6 +17,7 @@ package mac_nosip import ( + "context" "encoding/json" "errors" "fmt" @@ -320,6 +321,23 @@ func (mac *MacNoSIPConnector) Capabilities() imessage.ConnectorCapabilities { } } +func (mac *MacNoSIPConnector) SendFilePrepare(filename string, data []byte) (string, error) { + dir, path, err := imessage.SendFilePrepare(filename, data) + if err != nil { + return "", fmt.Errorf("failed to write file to disk: %w", err) + } + var resp ios.UploadMediaResponse + ctx := context.Background() + err = mac.GetIPC().Request(ctx, ios.ReqUploadMedia, &ios.UploadMediaRequest{ + PathOnDisk: path, + }, &resp) + if err != nil { + return "", fmt.Errorf("failed to upload file: %w", err) + } + mac.SendFileCleanup(dir) + return resp.GUID, nil +} + func init() { imessage.Implementations["mac-nosip"] = NewMacNoSIPConnector } diff --git a/imessage/mac/send.go b/imessage/mac/send.go index 5c634f0d..5326c13f 100644 --- a/imessage/mac/send.go +++ b/imessage/mac/send.go @@ -182,7 +182,7 @@ func (mac *macOSDatabase) SendMessage(chatID, text string, replyTo string, reply return nil, mac.sendMessageWithRetry(sendMessage, sendMessageWithService, sendMessageBuddy, imessage.ParseIdentifier(chatID), text) } -func (mac *macOSDatabase) SendFile(chatID, text, filename string, pathOnDisk string, replyTo string, replyToPart int, mimeType string, voiceMemo bool, metadata imessage.MessageMetadata) (*imessage.SendResponse, error) { +func (mac *macOSDatabase) SendFile(chatID, text, filename, pathOnDisk, guid, replyTo string, replyToPart int, mimeType string, voiceMemo bool, metadata imessage.MessageMetadata) (*imessage.SendResponse, error) { if voiceMemo { mac.log.Warn("received a request to send a file as a voice memo, but mac does not support this. sending as regular attachment.") } diff --git a/portal.go b/portal.go index 60105666..e5a2266d 100644 --- a/portal.go +++ b/portal.go @@ -1313,8 +1313,13 @@ func (portal *Portal) handleMatrixMediaDirect(url id.ContentURI, file *event.Enc } } - var dir, filePath string - dir, filePath, err = imessage.SendFilePrepare(filename, data) + var dir, filePath, guid string + prep, ok := portal.bridge.IM.(imessage.FilePreparingAPI) + if ok { + guid, err = prep.SendFilePrepare(filename, data) + } else { + dir, filePath, err = imessage.SendFilePrepare(filename, data) + } if err != nil { portal.log.Errorfln("failed to prepare to send file: %w", err) return @@ -1333,8 +1338,10 @@ func (portal *Portal) handleMatrixMediaDirect(url id.ContentURI, file *event.Enc } } - resp, err = portal.bridge.IM.SendFile(portal.getTargetGUID("media message", evt.ID, ""), caption, filename, filePath, messageReplyID, messageReplyPart, mimeType, isVoiceMemo, metadata) - portal.bridge.IM.SendFileCleanup(dir) + resp, err = portal.bridge.IM.SendFile(portal.getTargetGUID("media message", evt.ID, ""), caption, filename, filePath, guid, messageReplyID, messageReplyPart, mimeType, isVoiceMemo, metadata) + if dir != "" { + portal.bridge.IM.SendFileCleanup(dir) + } return } From 1b0bd30c5070f47bc0598dd88c3173d58adaf3b8 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 28 Apr 2023 22:03:38 +0300 Subject: [PATCH 2/2] Move file cleanup to after sending message --- imessage/interface.go | 2 +- imessage/mac-nosip/nosip.go | 9 ++++----- portal.go | 6 ++---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/imessage/interface.go b/imessage/interface.go index b4ef670f..1af22deb 100644 --- a/imessage/interface.go +++ b/imessage/interface.go @@ -83,7 +83,7 @@ type API interface { type FilePreparingAPI interface { API - SendFilePrepare(filename string, data []byte) (guid string, err error) + SendFilePrepare(filename string, data []byte) (dir, guid string, err error) } var TempFilePermissions os.FileMode = 0640 diff --git a/imessage/mac-nosip/nosip.go b/imessage/mac-nosip/nosip.go index 75f9a58d..79d28767 100644 --- a/imessage/mac-nosip/nosip.go +++ b/imessage/mac-nosip/nosip.go @@ -321,10 +321,10 @@ func (mac *MacNoSIPConnector) Capabilities() imessage.ConnectorCapabilities { } } -func (mac *MacNoSIPConnector) SendFilePrepare(filename string, data []byte) (string, error) { +func (mac *MacNoSIPConnector) SendFilePrepare(filename string, data []byte) (string, string, error) { dir, path, err := imessage.SendFilePrepare(filename, data) if err != nil { - return "", fmt.Errorf("failed to write file to disk: %w", err) + return dir, "", fmt.Errorf("failed to write file to disk: %w", err) } var resp ios.UploadMediaResponse ctx := context.Background() @@ -332,10 +332,9 @@ func (mac *MacNoSIPConnector) SendFilePrepare(filename string, data []byte) (str PathOnDisk: path, }, &resp) if err != nil { - return "", fmt.Errorf("failed to upload file: %w", err) + return dir, "", fmt.Errorf("failed to upload file: %w", err) } - mac.SendFileCleanup(dir) - return resp.GUID, nil + return dir, resp.GUID, nil } func init() { diff --git a/portal.go b/portal.go index e5a2266d..3adcfda8 100644 --- a/portal.go +++ b/portal.go @@ -1316,7 +1316,7 @@ func (portal *Portal) handleMatrixMediaDirect(url id.ContentURI, file *event.Enc var dir, filePath, guid string prep, ok := portal.bridge.IM.(imessage.FilePreparingAPI) if ok { - guid, err = prep.SendFilePrepare(filename, data) + dir, guid, err = prep.SendFilePrepare(filename, data) } else { dir, filePath, err = imessage.SendFilePrepare(filename, data) } @@ -1339,9 +1339,7 @@ func (portal *Portal) handleMatrixMediaDirect(url id.ContentURI, file *event.Enc } resp, err = portal.bridge.IM.SendFile(portal.getTargetGUID("media message", evt.ID, ""), caption, filename, filePath, guid, messageReplyID, messageReplyPart, mimeType, isVoiceMemo, metadata) - if dir != "" { - portal.bridge.IM.SendFileCleanup(dir) - } + portal.bridge.IM.SendFileCleanup(dir) return }