Skip to content

Commit

Permalink
Align auto-convert feature between web gui and cli
Browse files Browse the repository at this point in the history
We have been auto-converting images for the web gui, while prompting the
user from the CLI composer. Given that the CLI prompt is causing issues
with the new "non-interactive" cli composer, I believe it's reasonable
to avoid this complexity by doing auto-convertion on the command line
aswell.

We could consider adding a config options to let the user control this
behavior in the future. But until then, let's keep it simple.

Resolves #431
  • Loading branch information
martinhpedersen committed Jan 20, 2024
1 parent 41b2d07 commit 04ef16e
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 111 deletions.
75 changes: 75 additions & 0 deletions attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"bytes"
"image"
"image/jpeg"
"io"
"log"
"mime"
"path"
"path/filepath"
"strings"

"github.com/la5nta/wl2k-go/fbb"
"github.com/nfnt/resize"
)

func addAttachment(msg *fbb.Message, filename string, contentType string, r io.Reader) error {
p, err := io.ReadAll(r)
if err != nil {
return err
}
if ok, mediaType := isConvertableImageMediaType(filename, contentType); ok {
log.Printf("Auto converting '%s' [%s]...", filename, mediaType)
if converted, err := convertImage(p); err != nil {
log.Printf("Error converting image: %s", err)
} else {
log.Printf("Done converting '%s'.", filename)
ext := filepath.Ext(filename)
filename = filename[:len(filename)-len(ext)] + ".jpg"
p = converted
}
}
msg.AddFile(fbb.NewFile(filename, p))
return nil
}

func isConvertableImageMediaType(filename, contentType string) (convertable bool, mediaType string) {
if contentType != "" {
mediaType, _, _ = mime.ParseMediaType(contentType)
}
if mediaType == "" {
mediaType = mime.TypeByExtension(path.Ext(filename))
}

switch mediaType {
case "image/svg+xml":
// This is a text file
return false, mediaType
default:
return strings.HasPrefix(mediaType, "image/"), mediaType
}
}

func convertImage(orig []byte) ([]byte, error) {
img, _, err := image.Decode(bytes.NewReader(orig))
if err != nil {
return nil, err
}

// Scale down
if img.Bounds().Dx() > 600 {
img = resize.Resize(600, 0, img, resize.NearestNeighbor)
}

// Re-encode as low quality jpeg
var buf bytes.Buffer
if err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: 40}); err != nil {
return orig, err
}
if buf.Len() >= len(orig) {
return orig, nil
}
return buf.Bytes(), nil
}
37 changes: 6 additions & 31 deletions cli_composer.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,11 @@ func noninteractiveComposeMessage(from string, subject string, attachments []str
msg.SetSubject(subject)

// Handle Attachments. Since we're not interactive, treat errors as fatal so the user can fix
for _, filename := range attachments {
file, err := readAttachment(filename)
if err != nil {
for _, path := range attachments {
if err := addAttachmentFromPath(msg, path); err != nil {
fmt.Fprint(os.Stderr, err.Error()+"\nAborting! (Message not posted)\n")
os.Exit(1)
}
msg.AddFile(file)
}

// Read the message body from stdin
Expand Down Expand Up @@ -247,45 +245,22 @@ func interactiveComposeMessage(replyMsg *fbb.Message) {
if path == "" {
break
}

file, err := readAttachment(path)
if err != nil {
if err := addAttachmentFromPath(msg, path); err != nil {
log.Println(err)
continue
}

msg.AddFile(file)
}
fmt.Println(msg)
postMessage(msg)
}

func readAttachment(path string) (*fbb.File, error) {
func addAttachmentFromPath(msg *fbb.Message, path string) error {
f, err := os.Open(path)
if err != nil {
return nil, err
return err
}
defer f.Close()

name := filepath.Base(path)

var resizeImage bool
if isConvertableImageMediaType(name, "") {
fmt.Print("This seems to be an image. Auto resize? [Y/n]: ")
ans := readLine()
resizeImage = ans == "" || strings.EqualFold("y", ans)
}

var data []byte

data, err = ioutil.ReadAll(f)
if resizeImage {
data, err = convertImage(data)
ext := filepath.Ext(name)
name = name[:len(name)-len(ext)] + ".jpg"
}

return fbb.NewFile(name, data), err
return addAttachment(msg, filepath.Base(path), "", f)
}

var stdin *bufio.Reader
Expand Down
58 changes: 0 additions & 58 deletions convert_image.go

This file was deleted.

26 changes: 4 additions & 22 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ func postOutboundMessageHandler(w http.ResponseWriter, r *http.Request) {
if r.MultipartForm != nil {
files := r.MultipartForm.File["files"]
for _, f := range files {
err := attachFile(f, msg)
err := addAttachmentFromMultipartFile(msg, f)
switch err := err.(type) {
case nil:
// No problem
Expand Down Expand Up @@ -345,7 +345,7 @@ func postOutboundMessageHandler(w http.ResponseWriter, r *http.Request) {
_, _ = fmt.Fprintf(w, "Message posted (%.2f kB)", float64(buf.Len()/1024))
}

func attachFile(f *multipart.FileHeader, msg *fbb.Message) error {
func addAttachmentFromMultipartFile(msg *fbb.Message, f *multipart.FileHeader) error {
// For some unknown reason, we receive this empty unnamed file when no
// attachment is provided. Prior to Go 1.10, this was filtered by
// multipart.Reader.
Expand All @@ -361,28 +361,10 @@ func attachFile(f *multipart.FileHeader, msg *fbb.Message) error {
if err != nil {
return HTTPError{err, http.StatusInternalServerError}
}

p, err := io.ReadAll(file)
_ = file.Close()
if err != nil {
defer file.Close()
if err := addAttachment(msg, f.Filename, f.Header.Get("Content-Type"), file); err != nil {
return HTTPError{err, http.StatusInternalServerError}
}

if isConvertableImageMediaType(f.Filename, f.Header.Get("Content-Type")) {
log.Printf("Auto converting '%s' [%s]...", f.Filename, f.Header.Get("Content-Type"))

if converted, err := convertImage(p); err != nil {
log.Printf("Error converting image: %s", err)
} else {
log.Printf("Done converting '%s'.", f.Filename)

ext := path.Ext(f.Filename)
f.Filename = f.Filename[:len(f.Filename)-len(ext)] + ".jpg"
p = converted
}
}

msg.AddFile(fbb.NewFile(f.Filename, p))
return nil
}

Expand Down

0 comments on commit 04ef16e

Please sign in to comment.