Merge pull request #23 from DmitryZagorulko/master

add file upload and download methods
This commit is contained in:
Alex Lushpai 2019-01-10 14:48:36 +03:00 committed by GitHub
commit b3d0370c21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 204 additions and 8 deletions

View File

@ -1,9 +1,11 @@
package v1
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
"time"
@ -437,7 +439,7 @@ func (c *MgClient) MessageSend(request MessageSendRequest) (MessageSendResponse,
var resp MessageSendResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PostRequest("/messages", []byte(outgoing))
data, status, err := c.PostRequest("/messages", bytes.NewBuffer(outgoing))
if err != nil {
return resp, status, err
}
@ -677,6 +679,112 @@ func (c *MgClient) CommandDelete(request string) (map[string]interface{}, int, e
return resp, status, err
}
// GetFile implement get file url
//
// Example:
//
// var client = v1.New("https://token.url", "cb8ccf05e38a47543ad8477d4999be73bff503ea6")
//
// data, status, err := client.GetFile("file_ID")
//
// if err != nil {
// fmt.Printf("%v", err)
// }
//
// fmt.Printf("%s\n", data.ID)
func (c *MgClient) GetFile(request string) (FullFileResponse, int, error) {
var resp FullFileResponse
var b []byte
data, status, err := c.GetRequest(fmt.Sprintf("/files/%s", request), b)
if err != nil {
return resp, status, err
}
if e := json.Unmarshal(data, &resp); e != nil {
return resp, status, e
}
if status != http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
// UploadFile upload file
//
// Example:
//
// resp, err := http.Get("https://via.placeholder.com/300")
// if err != nil {
// fmt.Printf("%v", err)
// }
//
// defer resp.Body.Close()
//
// var client = v1.New("https://token.url", "cb8ccf05e38a47543ad8477d4999be73bff503ea6")
//
// data, status, err := client.UploadFile(resp.Body)
//
// if err != nil {
// fmt.Printf("%v", err)
// }
//
// fmt.Printf("%s\n%s", data.ID, status)
func (c *MgClient) UploadFile(request io.Reader) (UploadFileResponse, int, error) {
var resp UploadFileResponse
data, status, err := c.PostRequest("/files/upload", request)
if err != nil {
return resp, status, err
}
if e := json.Unmarshal(data, &resp); e != nil {
return resp, status, e
}
if status != http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
// UploadFileByURL upload file by url
//
// Example:
//
// uploadFileResponse, st, err := c.UploadFileByURL(UploadFileByUrlRequest{
// Url: "https://via.placeholder.com/300",
// })
//
// if err != nil {
// fmt.Printf("%v", err)
// }
//
// fmt.Printf("%s\n%s", uploadFileResponse.ID, status)
func (c *MgClient) UploadFileByURL(request UploadFileByUrlRequest) (UploadFileResponse, int, error) {
var resp UploadFileResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PostRequest("/files/upload_by_url", bytes.NewBuffer(outgoing))
if err != nil {
return resp, status, err
}
if e := json.Unmarshal(data, &resp); e != nil {
return resp, status, e
}
if status != http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
// WsMeta let you receive url & headers to open web socket connection
func (c *MgClient) WsMeta(events []string) (string, http.Header, error) {
var url string

View File

@ -12,7 +12,6 @@ import (
"time"
"github.com/joho/godotenv"
"github.com/stretchr/testify/assert"
)
@ -42,7 +41,10 @@ var (
)
func client() *MgClient {
return New(mgURL, mgToken)
c := New(mgURL, mgToken)
c.Debug = true
return c
}
func TestMgClient_Bots(t *testing.T) {
@ -197,7 +199,7 @@ func TestMgClient_Messages(t *testing.T) {
assert.NotEmpty(t, data)
for _, message := range data {
assert.NotEmpty(t, message.Content)
assert.NotEmpty(t, message.ID)
}
}
@ -433,6 +435,55 @@ func TestMgClient_WsMeta(t *testing.T) {
assert.Equal(t, resToken, headers["X-Bot-Token"][0])
}
func TestMgClient_UploadFile(t *testing.T) {
c := client()
resp, err := http.Get("https://via.placeholder.com/300")
if err != nil {
t.Errorf("%v", err)
}
defer resp.Body.Close()
data, status, err := c.UploadFile(resp.Body)
if status != http.StatusOK {
t.Errorf("%v", err)
}
t.Logf("File %+v is upload", data)
}
func TestMgClient_ImageMessages(t *testing.T) {
c := client()
uploadFileResponse, st, err := c.UploadFileByURL(UploadFileByUrlRequest{
Url: "https://via.placeholder.com/300",
})
if st != http.StatusOK {
t.Errorf("%v", err)
}
t.Logf("File %+v is upload", uploadFileResponse.ID)
i, err := strconv.ParseUint(os.Getenv("MG_BOT_CHAT"), 10, 64)
message := MessageSendRequest{
Type: MsgTypeImage,
Scope: MessageScopePublic,
Items: []Item{{ID: uploadFileResponse.ID}},
ChatID: i,
}
data, status, err := c.MessageSend(message)
if err != nil {
t.Errorf("%d %v", status, err)
}
assert.NoError(t, err)
assert.NotEmpty(t, data.MessageID)
}
func RandStringBytesMaskImprSrc(n int) string {
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!

View File

@ -3,6 +3,7 @@ package v1
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
@ -21,11 +22,11 @@ func (c *MgClient) GetRequest(url string, parameters []byte) ([]byte, int, error
}
// PostRequest implements POST Request
func (c *MgClient) PostRequest(url string, parameters []byte) ([]byte, int, error) {
func (c *MgClient) PostRequest(url string, parameters io.Reader) ([]byte, int, error) {
return makeRequest(
"POST",
fmt.Sprintf("%s%s%s", c.URL, prefix, url),
bytes.NewBuffer(parameters),
parameters,
c,
)
}
@ -60,7 +61,7 @@ func (c *MgClient) DeleteRequest(url string, parameters []byte) ([]byte, int, er
)
}
func makeRequest(reqType, url string, buf *bytes.Buffer, c *MgClient) ([]byte, int, error) {
func makeRequest(reqType, url string, buf io.Reader, c *MgClient) ([]byte, int, error) {
var res []byte
req, err := http.NewRequest(reqType, url, buf)
if err != nil {
@ -71,7 +72,7 @@ func makeRequest(reqType, url string, buf *bytes.Buffer, c *MgClient) ([]byte, i
req.Header.Set("X-Bot-Token", c.Token)
if c.Debug {
log.Printf("MG BOT API Request: %s %s %s %s", reqType, url, c.Token, buf.String())
log.Printf("MG BOT API Request: %s %s %s %+v", reqType, url, c.Token, buf)
}
resp, err := c.httpClient.Do(req)

View File

@ -3,6 +3,7 @@ package v1
import (
"encoding/json"
"net/http"
"time"
)
const (
@ -50,6 +51,8 @@ const (
MsgTypeCommand string = "command"
MsgTypeOrder string = "order"
MsgTypeProduct string = "product"
MsgTypeFile string = "file"
MsgTypeImage string = "image"
MsgOrderStatusCodeNew = "new"
MsgOrderStatusCodeApproval = "approval"
@ -162,6 +165,7 @@ type (
Content string `url:"content,omitempty" json:"content"`
Product *MessageProduct `url:"product,omitempty" json:"product"`
Order *MessageOrder `url:"order,omitempty" json:"order"`
Items []Item `url:"order,omitempty" json:"items"`
Scope string `url:"scope,omitempty" json:"scope"`
ChatID uint64 `url:"chat_id,omitempty" json:"chat_id"`
QuoteMessageId uint64 `url:"quote_message_id,omitempty" json:"quote_message_id"`
@ -189,6 +193,10 @@ type (
Name string `url:"name,omitempty" json:"name"`
Description string `url:"description,omitempty" json:"description"`
}
UploadFileByUrlRequest struct {
Url string `json:"url"`
}
)
// Response types
@ -314,6 +322,24 @@ type (
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at,omitempty"`
}
FullFileResponse struct {
ID string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
Size int `json:"size,omitempty"`
Url string `json:"url,omitempty"`
}
UploadFileResponse struct {
ID string `json:"id"`
Hash string `json:"hash"`
Type string `json:"type"`
Meta FileMeta `json:"meta"`
MimeType string `json:"mime_type"`
Size int `json:"size"`
Url *string `json:"source_url"`
CreatedAt time.Time `json:"created_at"`
}
)
// WS event types
@ -499,6 +525,16 @@ type (
CreatedAt string `json:"created_at"`
ClosedAt *string `json:"closed_at"`
}
FileMeta struct {
Width *int `json:"width,omitempty"`
Height *int `json:"height,omitempty"`
}
Item struct {
ID string `json:"id"`
Caption string `json:"caption"`
}
)
// Channel settings