diff options
Diffstat (limited to 'vendor/github.com/Rhymen/go-whatsapp/media.go')
-rw-r--r-- | vendor/github.com/Rhymen/go-whatsapp/media.go | 112 |
1 files changed, 58 insertions, 54 deletions
diff --git a/vendor/github.com/Rhymen/go-whatsapp/media.go b/vendor/github.com/Rhymen/go-whatsapp/media.go index b15b9ae2..87827d9c 100644 --- a/vendor/github.com/Rhymen/go-whatsapp/media.go +++ b/vendor/github.com/Rhymen/go-whatsapp/media.go @@ -10,10 +10,8 @@ import ( "fmt" "io" "io/ioutil" - "mime/multipart" "net/http" - "os" - "strings" + "net/url" "time" "github.com/Rhymen/go-whatsapp/crypto/cbc" @@ -95,7 +93,50 @@ func downloadMedia(url string) (file []byte, mac []byte, err error) { return data[:n-10], data[n-10 : n], nil } -func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (url string, mediaKey []byte, fileEncSha256 []byte, fileSha256 []byte, fileLength uint64, err error) { +type MediaConn struct { + Status int `json:"status"` + MediaConn struct { + Auth string `json:"auth"` + TTL int `json:"ttl"` + Hosts []struct { + Hostname string `json:"hostname"` + IPs []string `json:"ips"` + } `json:"hosts"` + } `json:"media_conn"` +} + +func (wac *Conn) queryMediaConn() (hostname, auth string, ttl int, err error) { + queryReq := []interface{}{"query", "mediaConn"} + ch, err := wac.writeJson(queryReq) + if err != nil { + return "", "", 0, err + } + + var resp MediaConn + select { + case r := <-ch: + if err = json.Unmarshal([]byte(r), &resp); err != nil { + return "", "", 0, fmt.Errorf("error decoding query media conn response: %v", err) + } + case <-time.After(wac.msgTimeout): + return "", "", 0, fmt.Errorf("query media conn timed out") + } + + if resp.Status != 200 { + return "", "", 0, fmt.Errorf("query media conn responded with %d", resp.Status) + } + + return resp.MediaConn.Hosts[0].Hostname, resp.MediaConn.Auth, resp.MediaConn.TTL, nil +} + +var mediaTypeMap = map[MediaType]string{ + MediaImage: "/mms/image", + MediaVideo: "/mms/video", + MediaDocument: "/mms/document", + MediaAudio: "/mms/audio", +} + +func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (downloadURL string, mediaKey []byte, fileEncSha256 []byte, fileSha256 []byte, fileLength uint64, err error) { data, err := ioutil.ReadAll(reader) if err != nil { return "", nil, nil, nil, 0, err @@ -128,67 +169,30 @@ func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (url string, mediaK sha.Write(append(enc, mac...)) fileEncSha256 = sha.Sum(nil) - var filetype string - switch appInfo { - case MediaImage: - filetype = "image" - case MediaAudio: - filetype = "audio" - case MediaDocument: - filetype = "document" - case MediaVideo: - filetype = "video" - } - - uploadReq := []interface{}{"action", "encr_upload", filetype, base64.StdEncoding.EncodeToString(fileEncSha256)} - ch, err := wac.writeJson(uploadReq) - if err != nil { - return "", nil, nil, nil, 0, err + hostname, auth, _, err := wac.queryMediaConn() + token := base64.URLEncoding.EncodeToString(fileEncSha256) + q := url.Values{ + "auth": []string{auth}, + "token": []string{token}, } - - var resp map[string]interface{} - select { - case r := <-ch: - if err = json.Unmarshal([]byte(r), &resp); err != nil { - return "", nil, nil, nil, 0, fmt.Errorf("error decoding upload response: %v", err) - } - case <-time.After(wac.msgTimeout): - return "", nil, nil, nil, 0, fmt.Errorf("restore session init timed out") + path := mediaTypeMap[appInfo] + uploadURL := url.URL{ + Scheme: "https", + Host: hostname, + Path: fmt.Sprintf("%s/%s", path, token), + RawQuery: q.Encode(), } - if int(resp["status"].(float64)) != 200 { - return "", nil, nil, nil, 0, fmt.Errorf("upload responsed with %d", resp["status"]) - } + body := bytes.NewReader(append(enc, mac...)) - var b bytes.Buffer - w := multipart.NewWriter(&b) - hashWriter, err := w.CreateFormField("hash") - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - } - io.Copy(hashWriter, strings.NewReader(base64.StdEncoding.EncodeToString(fileEncSha256))) - - fileWriter, err := w.CreateFormFile("file", "blob") - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - } - io.Copy(fileWriter, bytes.NewReader(append(enc, mac...))) - err = w.Close() - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - } - - req, err := http.NewRequest("POST", resp["url"].(string), &b) + req, err := http.NewRequest("POST", uploadURL.String(), body) if err != nil { return "", nil, nil, nil, 0, err } - req.Header.Set("Content-Type", w.FormDataContentType()) req.Header.Set("Origin", "https://web.whatsapp.com") req.Header.Set("Referer", "https://web.whatsapp.com/") - req.URL.Query().Set("f", "j") - client := &http.Client{} // Submit the request res, err := client.Do(req) |