Explorar o código

feat: implement keybindings for opening and downloading attachments (#137)

* Added support for opening or downloading attachments

* Removed some debug statements

* Added close statements I forgot

* Added gitignore to ignore built executables

* Removed executables I accidentally added

* Fixed opening files not working on Windows

* Updated .gitignore to ignore .vscode

Co-authored-by: ayntgl <90600421+ayntgl@users.noreply.github.com>

* Deleted launch.json that doesn't need to be included

* Implemented suggestions on #137

Co-authored-by: ayntgl <90600421+ayntgl@users.noreply.github.com>
KodiCraft %!s(int64=4) %!d(string=hai) anos
pai
achega
7ef0f71b7b
Modificáronse 4 ficheiros con 125 adicións e 9 borrados
  1. 4 0
      .gitignore
  2. 32 9
      config/general.go
  3. 8 0
      config/keybindings.go
  4. 81 0
      ui/messages.go

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+discordo*
+
+# Visual Studio Code
+.vscode/

+ 32 - 9
config/general.go

@@ -1,27 +1,50 @@
 package config
 
+import (
+	"os"
+	"runtime"
+)
+
 type IdentifyConfig struct {
 	Os      string `toml:"os"`
 	Browser string `toml:"browser"`
 }
 
 type GeneralConfig struct {
-	UserAgent          string         `toml:"user_agent"`
-	FetchMessagesLimit int            `toml:"fetch_messages_limit"`
-	Mouse              bool           `toml:"mouse"`
-	Timestamps         bool           `toml:"timestamps"`
-	Identify           IdentifyConfig `toml:"identify"`
+	UserAgent              string         `toml:"user_agent"`
+	FetchMessagesLimit     int            `toml:"fetch_messages_limit"`
+	Mouse                  bool           `toml:"mouse"`
+	Timestamps             bool           `toml:"timestamps"`
+	Identify               IdentifyConfig `toml:"identify"`
+	AttachmentDownloadsDir string         `toml:"attachment_downloads_dir"`
 }
 
 func newGeneralConfig() GeneralConfig {
+
 	return GeneralConfig{
-		UserAgent:          "Mozilla/5.0 (X11; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0",
-		FetchMessagesLimit: 50,
-		Mouse:              true,
-		Timestamps:         false,
+		UserAgent:              "Mozilla/5.0 (X11; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0",
+		FetchMessagesLimit:     50,
+		Mouse:                  true,
+		Timestamps:             false,
+		AttachmentDownloadsDir: UserDownloadsDir(),
 		Identify: IdentifyConfig{
 			Os:      "Linux",
 			Browser: "Firefox",
 		},
 	}
 }
+
+func UserDownloadsDir() string {
+	// We try to set the download folder location to the default Downloads folder
+	var dlloc string
+	if runtime.GOOS == "windows" {
+		h, _ := os.UserHomeDir()
+		dlloc = h + "\\Downloads"
+	} else if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
+		h, _ := os.UserHomeDir()
+		dlloc = h + "/Downloads"
+	} else {
+		dlloc = os.TempDir() // Very lame fallback, I know
+	}
+	return dlloc
+}

+ 8 - 0
config/keybindings.go

@@ -7,12 +7,17 @@ type KeybindingsConfig struct {
 	ToggleMessageInputField string `toml:"toggle_message_input_field"`
 
 	OpenMessageActionsList string `toml:"open_message_actions_list"`
+
 	OpenExternalEditor     string `toml:"open_external_editor"`
 
+	OpenAttachment         string `toml:"open_attachment"`
+	DownloadAttachment     string `toml:"download_attachment"`
+
 	SelectPreviousMessage string `toml:"select_previous_message"`
 	SelectNextMessage     string `toml:"select_next_message"`
 	SelectFirstMessage    string `toml:"select_first_message"`
 	SelectLastMessage     string `toml:"select_last_message"`
+
 }
 
 func newKeybindingsConfig() KeybindingsConfig {
@@ -25,6 +30,9 @@ func newKeybindingsConfig() KeybindingsConfig {
 		OpenMessageActionsList: "Rune[a]",
 		OpenExternalEditor:     "Ctrl+E",
 
+		OpenAttachment: 		"Rune[o]",
+		DownloadAttachment:		"Rune[d]",
+
 		SelectPreviousMessage: "Up",
 		SelectNextMessage:     "Down",
 		SelectFirstMessage:    "Home",

+ 81 - 0
ui/messages.go

@@ -2,8 +2,12 @@ package ui
 
 import (
 	"io"
+	"io/ioutil"
+	"net/http"
 	"os"
 	"os/exec"
+	"path/filepath"
+	"runtime"
 	"strings"
 
 	"github.com/atotto/clipboard"
@@ -91,6 +95,83 @@ func (mtv *MessagesTextView) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
 			ScrollToHighlight()
 
 		return nil
+
+	case mtv.app.Config.Keybindings.OpenAttachment:
+		if ms[mtv.app.SelectedMessage].Attachments != nil {
+			for _, a := range ms[mtv.app.SelectedMessage].Attachments {
+				// We are caching the files, but files with the same name can still exist, so it ultimately does not matter
+				t, _ := os.UserCacheDir()
+				f, err := os.Create(filepath.Join(t, a.Filename))
+				if err != nil {
+					f.Close()
+					return nil
+				}
+				response, err := http.Get(a.URL)
+				if err != nil {
+					f.Close()
+					return nil
+				}
+
+				d, err := ioutil.ReadAll(response.Body)
+				if err != nil {
+					f.Close()
+					return nil
+				}
+				f.Write(d)
+				f.Close()
+				if runtime.GOOS == "windows" {
+					// On windows, `start` can do all the heavy lifting through `cmd`
+					cmd := exec.Command("cmd", "/C start "+f.Name())
+					err := cmd.Run()
+					if err != nil {
+						return nil
+					}
+				} else if runtime.GOOS == "linux" {
+					// On linux, we'll assume xdg-open exists and try using that
+					cmd := exec.Command("xdg-open", f.Name())
+					err := cmd.Run()
+					if err != nil {
+						return nil
+					}
+				} else if runtime.GOOS == "darwin" {
+					// On MacOS open should do the trick
+					cmd := exec.Command("open", f.Name())
+					err := cmd.Run()
+					if err != nil {
+						return nil
+					}
+				} else {
+					// If we're on none of those platforms, I think I made some sort of fatal mistake
+					return nil
+				}
+			}
+		}
+		return nil
+	case mtv.app.Config.Keybindings.DownloadAttachment:
+		if ms[mtv.app.SelectedMessage].Attachments != nil {
+			// Download the files to the configured location
+			for _, a := range ms[mtv.app.SelectedMessage].Attachments {
+				f, err := os.Create(filepath.Join(mtv.app.Config.General.AttachmentDownloadsDir + a.Filename))
+				if err != nil {
+					f.Close()
+					return nil
+				}
+
+				response, err := http.Get(a.URL)
+				if err != nil {
+					f.Close()
+					return nil
+				}
+
+				d, err := ioutil.ReadAll(response.Body)
+				if err != nil {
+					f.Close()
+					return nil
+				}
+				f.Write(d)
+				f.Close()
+			}
+		}
 	case mtv.app.Config.Keybindings.OpenMessageActionsList:
 		messageActionsList := tview.NewList()