Skip to content

Commit

Permalink
improve SendFile using subject
Browse files Browse the repository at this point in the history
  • Loading branch information
cnuss committed Jan 20, 2024
1 parent e25674a commit f81d3a7
Showing 1 changed file with 47 additions and 48 deletions.
95 changes: 47 additions & 48 deletions imessage/bluebubbles/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -664,41 +663,44 @@ func (bb *blueBubbles) SendMessage(chatID, text string, replyTo string, replyToP
func (bb *blueBubbles) SendFile(chatID, text, filename string, pathOnDisk string, replyTo string, replyToPart int, mimeType string, voiceMemo bool, metadata imessage.MessageMetadata) (*imessage.SendResponse, error) {
bb.log.Trace().Str("chatID", chatID).Str("text", text).Str("filename", filename).Str("pathOnDisk", pathOnDisk).Str("replyTo", replyTo).Int("replyToPart", replyToPart).Str("mimeType", mimeType).Bool("voiceMemo", voiceMemo).Interface("metadata", metadata).Msg("SendFile")

// Prepare the payload for the POST request
payload := map[string]interface{}{
"chatGuid": chatID,
"name": filename,
attachment, err := os.ReadFile(pathOnDisk)
if err != nil {
return nil, err
}

bb.log.Info().Int("attachmentSize", len(attachment)).Msg("Read attachment from disk")

formData := map[string]interface{}{
"chatGuid": chatID,
"tempGuid": fmt.Sprintf("temp-%s", RandString(8)),
"name": filename,
// TODO: check blueblubbles (/api/v1/server/info) if private-api is enabled
// if it is, use private-api and keep "text" as subject
// if it is not, use apple-script and send "text" using SendMessage
"method": "private-api",
"attachment": attachment,
"isAudioMessage": voiceMemo,
"subject": text,
"selectedMessageGuid": replyTo,
"partIndex": fmt.Sprint(replyToPart),
"partIndex": replyToPart,
}

// Define the API endpoint path
path := "/api/v1/message/attachment"

// Make the API POST request with file
var response SendTextResponse
if err := bb.apiPostWithFile(path, payload, pathOnDisk, &response); err != nil {
if err := bb.apiPostAsFormData(path, formData, &response); err != nil {
return nil, err
}

if response.Status == 200 {
bb.log.Debug().Msg("Sent a file!")

bb.SendMessage(chatID, text, replyTo, replyToPart, nil, nil)

var imessageSendResponse = imessage.SendResponse{
GUID: response.Data.GUID,
Service: response.Data.Handle.Service,
Time: time.Unix(0, response.Data.DateCreated*int64(time.Millisecond)),
}

return &imessageSendResponse, nil
} else {
bb.log.Error().Any("response", response).Msg("Failure when sending message to BlueBubbles")
// bb.SendMessage(chatID, text, replyTo, replyToPart, nil, nil)

return nil, errors.New("could not send message")
var imessageSendResponse = imessage.SendResponse{
GUID: response.Data.GUID,
Service: response.Data.Handle.Service,
Time: time.Unix(0, response.Data.DateCreated*int64(time.Millisecond)),
}

return &imessageSendResponse, nil
}

func (bb *blueBubbles) SendFileCleanup(sendFileDir string) {
Expand Down Expand Up @@ -920,36 +922,33 @@ func (bb *blueBubbles) apiRequest(method, path string, payload interface{}, targ
return nil
}

func (bb *blueBubbles) apiPostWithFile(path string, params map[string]interface{}, filePath string, target interface{}) error {
func (bb *blueBubbles) apiPostAsFormData(path string, formData map[string]interface{}, target interface{}) error {
url := bb.apiUrl(path, map[string]string{})

// Create a new buffer to store the file content
var body bytes.Buffer
writer := multipart.NewWriter(&body)

// Add the file to the request
fileWriter, err := writer.CreateFormFile("attachment", filepath.Base(filePath))
if err != nil {
bb.log.Error().Err(err).Msg("Error creating form file")
return err
}

file, err := os.Open(filePath)
if err != nil {
bb.log.Error().Err(err).Msg("Error opening file")
return err
}
defer file.Close()

_, err = io.Copy(fileWriter, file)
if err != nil {
bb.log.Error().Err(err).Msg("Error copying file content")
return err
}

// Add other parameters to the request
for key, value := range params {
_ = writer.WriteField(key, fmt.Sprint(value))
for key, value := range formData {
switch v := value.(type) {
case int, bool:
writer.WriteField(key, fmt.Sprint(v))
case string:
writer.WriteField(key, v)
case []byte:
part, err := writer.CreateFormFile(key, "file.bin")
if err != nil {
bb.log.Error().Err(err).Msg("Error creating form-data field")
return err
}
_, err = part.Write(v)
if err != nil {
bb.log.Error().Err(err).Msg("Error writing file to form-data")
return err
}
default:
return fmt.Errorf("unable to serialze %s (type %T) into form-data", key, v)
}
}

// Close the multipart writer
Expand Down

0 comments on commit f81d3a7

Please sign in to comment.