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 }