Browse Source

Able to send file

Piotr Czajkowski 3 years ago
parent
commit
977cfe7aba
3 changed files with 185 additions and 4 deletions
  1. 108 4
      bullet.go
  2. 68 0
      fileUpload.go
  3. 9 0
      pushInterface.go

+ 108 - 4
bullet.go

@@ -2,8 +2,12 @@ package bullet
 
 import (
 	"encoding/json"
+	"fmt"
 	"io"
+	"mime"
 	"net/http"
+	"path/filepath"
+	"time"
 )
 
 const (
@@ -21,8 +25,8 @@ func NewBullet(token string) Bullet {
 	return b
 }
 
-func (b Bullet) newRequest(body io.Reader) (*http.Request, error) {
-	request, err := http.NewRequest(http.MethodPost, "https://api.pushbullet.com/v2/pushes", body)
+func (b Bullet) newRequest(body io.Reader, URL string) (*http.Request, error) {
+	request, err := http.NewRequest(http.MethodPost, URL, body)
 	if err != nil {
 		return nil, err
 	}
@@ -32,13 +36,21 @@ func (b Bullet) newRequest(body io.Reader) (*http.Request, error) {
 	return request, nil
 }
 
-func (b Bullet) send(push pushStruct) error {
+func (b Bullet) newRequestPush(body io.Reader) (*http.Request, error) {
+	return b.newRequest(body, "https://api.pushbullet.com/v2/pushes")
+}
+
+func (b Bullet) newRequestUpload(body io.Reader) (*http.Request, error) {
+	return b.newRequest(body, "https://api.pushbullet.com/v2/upload-request")
+}
+
+func (b Bullet) send(push pushInterface) error {
 	reader, errReader := push.getReader()
 	if errReader != nil {
 		return errReader
 	}
 
-	request, errRequest := b.newRequest(reader)
+	request, errRequest := b.newRequestPush(reader)
 	if errRequest != nil {
 		return errRequest
 	}
@@ -79,3 +91,95 @@ func (b Bullet) SendLink(title, text, link string) error {
 
 	return err
 }
+
+func (b Bullet) requestUpload(file fileUpload) (*fileUpload, error) {
+	reader, errReader := file.getReader()
+	if errReader != nil {
+		return nil, errReader
+	}
+
+	request, errRequest := b.newRequestUpload(reader)
+	if errRequest != nil {
+		return nil, errRequest
+	}
+
+	client := http.Client{}
+	response, errResponse := client.Do(request)
+	if errResponse != nil {
+		return nil, errResponse
+	}
+	defer response.Body.Close()
+
+	if response.StatusCode != http.StatusOK {
+		var errBullet bulletError
+		decoder := json.NewDecoder(response.Body)
+		errJSON := decoder.Decode(&errBullet)
+		if errJSON != nil {
+			return nil, errJSON
+		}
+
+		return nil, errBullet.getError()
+	}
+
+	var result fileUpload
+	decoder := json.NewDecoder(response.Body)
+	errJSON := decoder.Decode(&result)
+	if errJSON != nil {
+		return nil, errJSON
+	}
+
+	return &result, nil
+}
+
+func (b Bullet) uploadFile(path string) (*fileUpload, error) {
+	extension := filepath.Ext(path)
+	mimeType := mime.TypeByExtension(extension)
+	if mimeType == "" {
+		mimeType = "application/octet-stream"
+	}
+
+	filename := filepath.Base(path)
+	fileUpload := newFileUpload(filename, mimeType)
+
+	uploadResponse, errUpload := b.requestUpload(fileUpload)
+	if errUpload != nil {
+		return nil, errUpload
+	}
+
+	request, errRequest := getFileRequest(path, *uploadResponse)
+	if errRequest != nil {
+		return nil, errRequest
+	}
+
+	client := http.Client{}
+	response, errResponse := client.Do(request)
+	if errResponse != nil {
+		return nil, errResponse
+	}
+	defer response.Body.Close()
+
+	if response.StatusCode < http.StatusOK || response.StatusCode >= http.StatusMultipleChoices {
+		return nil, fmt.Errorf("Error uploading file: %s", response.Status)
+	}
+
+	return uploadResponse, nil
+}
+
+//SendFile sends file push with given title, text and file
+func (b Bullet) SendFile(title, text, file string) error {
+	uploadResult, errUpload := b.uploadFile(file)
+	if errUpload != nil {
+		return errUpload
+	}
+
+	if title != "" {
+		uploadResult.Title = title
+	} else {
+		uploadResult.Title = time.Now().Format(shortTimeFormat)
+	}
+	uploadResult.Body = text
+	uploadResult.Type = "file"
+
+	err := b.send(uploadResult)
+	return err
+}

+ 68 - 0
fileUpload.go

@@ -0,0 +1,68 @@
+package bullet
+
+import (
+	"bytes"
+	"encoding/json"
+	"io"
+	"mime/multipart"
+	"net/http"
+	"os"
+)
+
+type fileUpload struct {
+	FileName  string `json:"file_name"`
+	FileType  string `json:"file_type"`
+	Type      string `json:"type"`
+	Title     string `json:"title"`
+	Body      string `json:"body"`
+	FileUrl   string `json:"file_url"`
+	UploadUrl string `json:"upload_url"`
+}
+
+func newFileUpload(filename, fileType string) fileUpload {
+	f := fileUpload{Type: "file", FileName: filename, FileType: fileType}
+	return f
+}
+
+func (f fileUpload) getReader() (*bytes.Buffer, error) {
+	jsonBytes, err := json.Marshal(f)
+	if err != nil {
+		return nil, err
+	}
+
+	buffer := bytes.NewBuffer(jsonBytes)
+	return buffer, err
+}
+
+func getFileRequest(filePath string, upload fileUpload) (*http.Request, error) {
+	buffer := &bytes.Buffer{}
+	multipartWriter := multipart.NewWriter(buffer)
+
+	file, errOpen := os.Open(filePath)
+	if errOpen != nil {
+		return nil, errOpen
+	}
+	defer file.Close()
+
+	writer, errWriter := multipartWriter.CreateFormFile("file", upload.FileName)
+	if errWriter != nil {
+		return nil, errWriter
+	}
+	_, errCopy := io.Copy(writer, file)
+	if errCopy != nil {
+		return nil, errCopy
+	}
+
+	errMultipartClose := multipartWriter.Close()
+	if errMultipartClose != nil {
+		return nil, errMultipartClose
+	}
+
+	request, errRequest := http.NewRequest(http.MethodPost, upload.UploadUrl, buffer)
+	if errRequest != nil {
+		return nil, errRequest
+	}
+	request.Header.Add("Content-Type", multipartWriter.FormDataContentType())
+
+	return request, nil
+}

+ 9 - 0
pushInterface.go

@@ -0,0 +1,9 @@
+package bullet
+
+import (
+	"bytes"
+)
+
+type pushInterface interface {
+	getReader() (*bytes.Buffer, error)
+}