SocialDragon/snapchat/api.go

167 lines
4.6 KiB
Go

package snapchat
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"io"
"io/ioutil"
"log"
"os"
"github.com/disintegration/imaging"
"git.1750studios.com/AniNite/SocialDragon/config"
)
// ConversationsT Snapchat conversations
type ConversationsT struct {
ConversationsResponse []conversationsResponseT `json:"conversations_response"`
}
type conversationsResponseT struct {
PendingReceivedSnaps []snapT `json:"pending_received_snaps"`
}
type snapT struct {
ID string `json:"id"`
Username string `json:"sn"`
Movie int `json:"m"`
Rotation int `json:"mo"`
}
// GetConversations returns a list of snapchat conversations
func GetConversations() (*ConversationsT, error) {
var conversations ConversationsT
headers := map[string]string{
"X-Snapchat-UUID": config.C.Snapchat.GetConversations.UUID,
"X-Snapchat-Client-Auth-Token": config.C.Snapchat.GetConversations.ClientAuthToken,
}
data := map[string]string{
"checksum_dict": "{}",
"friends_request": "{\"friends_sync_token\":\"3\"}",
"req_token": config.C.Snapchat.GetConversations.RequestToken,
"timestamp": config.C.Snapchat.GetConversations.Timestamp,
"username": config.C.Snapchat.UserName,
}
res, err := GetHTTPResource("/loq/conversations", headers, data)
if err != nil {
return nil, err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
jerr := json.Unmarshal(body, &conversations)
if jerr != nil {
return nil, jerr
}
return &conversations, nil
}
// GetBlob downloads the given snap
func GetBlob(snap snapT) (string, error) {
headers := map[string]string{
"X-Snapchat-UUID": config.C.Snapchat.GetBlob.UUID,
"X-Snapchat-Client-Auth-Token": config.C.Snapchat.GetBlob.ClientAuthToken,
}
data := map[string]string{
"id": snap.ID,
"req_token": config.C.Snapchat.GetBlob.RequestToken,
"timestamp": config.C.Snapchat.GetBlob.Timestamp,
"username": config.C.Snapchat.UserName,
}
res, err := GetHTTPResource("/bq/blob", headers, data)
if err != nil {
return "", err
}
name, uname := imageNameGenerator(snap.ID)
defer res.Body.Close()
ext, err := rotateImage(snap, res.Body, name)
if err != nil {
return "", err
}
return uname + ext, nil
}
// MarkAsSeen marks the given snap as seen, optionally screenshotted
func MarkAsSeen(snap snapT, screenshotted bool) error {
headers := map[string]string{
"X-Snapchat-UUID": config.C.Snapchat.MarkAsSeen.UUID,
"X-Snapchat-Client-Auth-Token": config.C.Snapchat.MarkAsSeen.ClientAuthToken,
}
data := map[string]string{
"req_token": config.C.Snapchat.MarkAsSeen.RequestToken,
"timestamp": config.C.Snapchat.MarkAsSeen.Timestamp,
"username": config.C.Snapchat.UserName,
}
if screenshotted {
data["json"] = "{\"" + snap.ID + "\":{\"t\":1467469712.44128,\"replayed\":0,\"c\":1,\"stack_id\":\"E437851F-2AA8-4C6C-AE11-5FB49FBF93C0\",\"sv\":0,\"es_id\":\"cssek-0::TgcQVwLCU3kHIEj+o6s2CQ==:QTm2VyfemhN5owtHmVuMpik4hwFNz4gSpUQ9D9zlWxatYA==\"}}"
} else {
data["json"] = "{\"" + snap.ID + "\":{\"t\":1467469712.44128,\"replayed\":0,\"stack_id\":\"E437851F-2AA8-4C6C-AE11-5FB49FBF93C0\",\"sv\":0,\"es_id\":\"cssek-0::TgcQVwLCU3kHIEj+o6s2CQ==:QTm2VyfemhN5owtHmVuMpik4hwFNz4gSpUQ9D9zlWxatYA==\"}}"
}
res, err := GetHTTPResource("/bq/update_snaps", headers, data)
if err != nil {
return err
}
defer res.Body.Close()
return nil
}
func imageNameGenerator(seed string) (string, string) {
seedBytes := []byte(seed)
sha256Bytes := sha256.Sum256(seedBytes)
hash := hex.EncodeToString(sha256Bytes[:])
folders := config.C.ContentDirectory + "/" + hash[0:2] + "/" + hash[0:4] + "/"
urls := config.C.ContentWebDirectory + "/" + hash[0:2] + "/" + hash[0:4] + "/"
if err := os.MkdirAll(folders, 0775); err != nil {
log.Fatalf("FAT Could not create ContentDirectory, error: %+v", err)
}
finalPath := folders + hash
finalURL := urls + hash
return finalPath, finalURL
}
func rotateImage(snap snapT, data io.Reader, path string) (string, error) {
if snap.Movie != 0 {
ext := ".mp4"
blob, err := ioutil.ReadAll(data)
if err != nil {
return "", err
}
if len(blob) == 0 {
return "", errors.New("Empty response")
}
err = ioutil.WriteFile(path+ext, blob, 0644)
if err != nil {
return "", err
}
return ext, nil
}
ext := ".jpg"
image, err := imaging.Decode(data)
if err != nil {
return "", err
}
switch snap.Rotation {
case 1:
image = imaging.Rotate180(image)
break
case 2:
image = imaging.Rotate90(image)
break
case 3:
image = imaging.Rotate270(image)
break
default:
break
}
err = imaging.Save(image, path+ext)
if err != nil {
return "", err
}
return ext, nil
}