snapper

package module
v0.0.0-...-d57f268 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2023 License: MIT Imports: 17 Imported by: 0

README

Snapper

Snapper is a lightweight, easy-to-use Go library for interacting with Snapchat's Web API.

Installation

Use the package manager to install snapper.

go get github.com/0xzer/snapper

Features

  • Fetch account information
  • Fetch information about a snapchatter
  • Fetch a users bitmoji
  • List Friends (friendmojis, streaks, display name & more!)
  • List Conversations/Groups
  • Sync/DeltaSync Conversations/Groups (Batch & Single)
  • Send typing notifications (Groups & Conversations)
  • Query messages in conversations/groups (with message history support!)
  • Update Conversations/Groups
    • Change group title
    • Mark as read
    • Leave Group
    • Change Retention Policy
    • Clear from chat feed
    • Change notification preference
    • Add participants
  • Update Messages
    • Read
    • Release
    • Save
    • Unsave
    • Erase (delete message)
    • Save to camera roll
    • Screenshot
    • Screenrecord
    • Replay
    • React
    • Remove reaction
  • Create Conversations/Groups
  • Send Messages
    • Chat text messages
    • Send to multiple conversations/groups
    • Reply to messages
    • Set save policy on each message you send
    • Snaps (coming soon!)
    • Sticker (coming soon!)
    • Share (coming soon!)
    • Note (coming soon!)
    • SnapReply (coming soon!)
    • Location (coming soon!)
  • Generate fidelius keys

Usage

  • More examples here
package main

import (
	"encoding/json"
	"log"
        "github.com/rs/zerolog"
	"github.com/0xzer/snapper"
	"github.com/0xzer/snapper/protos"
)

var cli *snapper.Client

func main() {
        cookieStr := "sc-cookies-accepted=; EssentialSession=; Preferences=; Performance=; Marketing=; __Host-X-Snap-Client-Cookie=; __Host-sc-a-session=; sc-a-nonce=; __Host-sc-a-nonce=;sc-a-csrf=; blizzard_client_id="
	sess, err := snapper.NewSessionFromCookies(cookieStr) // or snapper.NewSessionFromFile("session.json")
	if err != nil {
		log.Fatal(err)
	}

	cli = snapper.NewClient(sess, zerolog.Logger{}, nil)

	sendChatMessage()

	err = cli.SaveSession("session.json")
	if err != nil {
		log.Fatal(err)
	}
}

func sendChatMessage() {
	conversations := getExampleConversations()
	firstConversation := conversations[0]

	messageBuilder := cli.NewCreateMessageBuilder().
	AddConversationDestination(firstConversation).
	SetTextMessage("hello!").
	SetSavePolicy(protos.ContentEnvelope_SavePolicy_LIFETIME)
	
	sent, err := cli.Messaging.SendContentMessage(messageBuilder)
	if err != nil {
		log.Fatal(err)
	}

	log.Println(sent)
}

func getExampleConversations() []*protos.Conversation {
	conversationEntries, err := cli.Messaging.SyncConversations(nil, nil)
	if err != nil {
		log.Fatal(err)
	}

	conversationsBatch := cli.Messaging.BatchRequestFromEntry(conversationEntries.GetConversations())
	batchDeltaSync, err := cli.Messaging.BatchDeltaSync(conversationsBatch)
	if err != nil {
		log.Fatal(err)
	}

	return cli.Messaging.BatchResponseToConversationSlice(batchDeltaSync)
}

Documentation

Index

Constants

View Source
const (
	Conversation destination = iota
	Story
	PhoneNumber
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Account

type Account struct {
	// contains filtered or unexported fields
}

func (*Account) Authenticate

func (a *Account) Authenticate() error

func (*Account) Friends

func (a *Account) Friends() (*FriendsResponse, error)

func (*Account) Info

func (a *Account) Info() (*User, error)

func (*Account) InitializeWebKey

func (a *Account) InitializeWebKey() (*types.FideliusKeys, error)

type AccountResponse

type AccountResponse struct {
	Data UserData `json:"data,omitempty"`
}

type AddedFriend

type AddedFriend struct {
	Name                          string `json:"name"`
	UserID                        string `json:"user_id"`
	Type                          int    `json:"type"`
	Display                       string `json:"display"`
	Ts                            int64  `json:"ts"`
	ReverseTs                     int    `json:"reverse_ts"`
	Direction                     string `json:"direction"`
	Expiration                    int    `json:"expiration"`
	AddSource                     string `json:"add_source"`
	AddSourceType                 string `json:"add_source_type"`
	IsIncomingFriendRequestViewed bool   `json:"is_incoming_friend_request_viewed"`
	MutableUsername               string `json:"mutable_username"`
	SnapshotMetadata              string `json:"snapshot_metadata"`
	CameosSharingPolicy           int    `json:"cameos_sharing_policy"`
}

type Client

type Client struct {
	Request   *Request
	Messaging *Messaging
	Account   *Account
	Users     *Users

	Session *Session
	// contains filtered or unexported fields
}

func NewClient

func NewClient(session *Session, logger zerolog.Logger, proxy *string) *Client

pass in an empty logger if u don't want logging

func (*Client) HasUUID

func (c *Client) HasUUID(slice []*protos.UUID, target *protos.UUID) bool

func (*Client) NewCreateConversationBuilder

func (c *Client) NewCreateConversationBuilder() *CreateConversationBuilder

THIS WILL AUTOMATICALLY ADD YOU INTO THE PARTICIPANTS SO YOU DO NOT HAVE TO DO THAT YOURSELF

func (*Client) NewCreateMessageBuilder

func (c *Client) NewCreateMessageBuilder() *CreateMessageBuilder

func (*Client) NewUpdateConversationBuilder

func (c *Client) NewUpdateConversationBuilder(conversation *protos.Conversation) *UpdateConversationBuilder

func (*Client) NewUpdateMessageBuilder

func (c *Client) NewUpdateMessageBuilder(messageId int64) *UpdateMessageBuilder

func (*Client) RefreshSSOToken

func (c *Client) RefreshSSOToken() (string, error)

func (*Client) SaveSession

func (c *Client) SaveSession(path string) error

func (*Client) SetProxy

func (c *Client) SetProxy(proxy string) error

type CreateConversationBuilder

type CreateConversationBuilder struct {
	// contains filtered or unexported fields
}

func (*CreateConversationBuilder) AddParticipant

func (c *CreateConversationBuilder) AddParticipant(participant *protos.UUID) *CreateConversationBuilder

func (*CreateConversationBuilder) AddParticipants

func (c *CreateConversationBuilder) AddParticipants(participants []*protos.UUID) *CreateConversationBuilder

func (*CreateConversationBuilder) SetConversationType

func (c *CreateConversationBuilder) SetConversationType(conversationType protos.ConversationType) *CreateConversationBuilder

func (*CreateConversationBuilder) SetTitle

type CreateMessageBuilder

type CreateMessageBuilder struct {
	// contains filtered or unexported fields
}

func (*CreateMessageBuilder) AddConversationDestination

func (c *CreateMessageBuilder) AddConversationDestination(conversation *protos.Conversation) *CreateMessageBuilder

func (*CreateMessageBuilder) SetReplyMessage

func (c *CreateMessageBuilder) SetReplyMessage(messageId int64) *CreateMessageBuilder

messageId = the message id of the message to reply to

func (*CreateMessageBuilder) SetRetry

func (*CreateMessageBuilder) SetSavePolicy

func (*CreateMessageBuilder) SetTextMessage

func (c *CreateMessageBuilder) SetTextMessage(text string) *CreateMessageBuilder

type Devices

type Devices struct {
	OutBeta string `json:"out_beta"`
	Version int    `json:"version"`
}

type ExtraFriendmojiMutableDict

type ExtraFriendmojiMutableDict struct{}

type ExtraFriendmojiReadOnlyDict

type ExtraFriendmojiReadOnlyDict struct{}

type FideliusInfo

type FideliusInfo struct {
	Devices []Devices `json:"devices"`
}

type Friend

type Friend struct {
	Username                            string       `json:"name"`
	ID                                  string       `json:"user_id"`
	Type                                int          `json:"type"`
	DisplayName                         string       `json:"display"`
	Birthday                            string       `json:"birthday,omitempty"`
	Ts                                  int64        `json:"ts,omitempty"`
	ReverseTs                           int64        `json:"reverse_ts,omitempty"`
	Direction                           string       `json:"direction"`
	CanSeeCustomStories                 bool         `json:"can_see_custom_stories"`
	Expiration                          int          `json:"expiration"`
	FriendmojiString                    string       `json:"friendmoji_string"`
	Friendmojis                         []any        `json:"friendmojis"`
	SnapStreakCount                     int          `json:"snap_streak_count"`
	FideliusInfo                        FideliusInfo `json:"fidelius_info,omitempty"`
	IsPopular                           bool         `json:"is_popular"`
	IsStoryMuted                        bool         `json:"is_story_muted"`
	MutableUsername                     string       `json:"mutable_username"`
	IsCameosSharingSupported            bool         `json:"is_cameos_sharing_supported,omitempty"`
	CameosSharingPolicy                 int          `json:"cameos_sharing_policy"`
	PlusBadgeVisibility                 int          `json:"plus_badge_visibility"`
	BitmojiAvatarID                     string       `json:"bitmoji_avatar_id,omitempty"`
	BitmojiSelfieID                     string       `json:"bitmoji_selfie_id,omitempty"`
	BitmojiSceneID                      string       `json:"bitmoji_scene_id,omitempty"`
	BitmojiBackgroundID                 string       `json:"bitmoji_background_id,omitempty"`
	IsBitmojiFriendmojiSharingSupported bool         `json:"is_bitmoji_friendmoji_sharing_supported,omitempty"`
	IgnoredLink                         bool         `json:"ignored_link,omitempty"`
}

type FriendsResponse

type FriendsResponse struct {
	Friends                      []Friend                    `json:"friends"`
	FriendsSyncToken             string                      `json:"friends_sync_token"`
	FriendsSyncType              string                      `json:"friends_sync_type"`
	AddedFriends                 []AddedFriend               `json:"added_friends"`
	Bests                        []any                       `json:"bests"`
	ExtraFriendmojiMutableDict   ExtraFriendmojiMutableDict  `json:"extra_friendmoji_mutable_dict"`
	ExtraFriendmojiReadOnlyDict  ExtraFriendmojiReadOnlyDict `json:"extra_friendmoji_read_only_dict"`
	AddedFriendsSyncToken        string                      `json:"added_friends_sync_token"`
	AddedFriendsSyncType         string                      `json:"added_friends_sync_type"`
	BestsUserIds                 []any                       `json:"bests_user_ids"`
	IsResponseWithPartialColumns bool                        `json:"is_response_with_partial_columns"`
	InvitedUsers                 []any                       `json:"invited_users"`
}

type Messaging

type Messaging struct {
	// contains filtered or unexported fields
}

func (*Messaging) BatchDeltaSync

func (m *Messaging) BatchDeltaSync(deltaSyncRequests []*protos.DeltaSyncRequest) (*protos.BatchDeltaSyncResponse, error)

func (*Messaging) BatchRequestFromEntry

func (m *Messaging) BatchRequestFromEntry(conversations []*protos.ConversationEntry) []*protos.DeltaSyncRequest

func (*Messaging) BatchResponseToConversationSlice

func (m *Messaging) BatchResponseToConversationSlice(responses *protos.BatchDeltaSyncResponse) []*protos.Conversation

func (*Messaging) CreateConversation

func (m *Messaging) CreateConversation(createConversationBuilder *CreateConversationBuilder) (*protos.CreateConversationResponse, error)

func (*Messaging) DeltaSync

func (m *Messaging) DeltaSync(conversationId *protos.UUID, otherParticipantUserId *protos.UUID) (*protos.DeltaSyncResponse, error)

only thing needed is conversationId for now, so just pass that as nil. if you are having trouble, try passing in otherParticipantId aswell.

func (*Messaging) GetGroups

func (m *Messaging) GetGroups() (*protos.GetGroupsResponseWrapper, error)

func (*Messaging) GetOtherParticipantId

func (m *Messaging) GetOtherParticipantId(participants []*protos.UUID) *protos.UUID

func (*Messaging) QueryConversations

func (m *Messaging) QueryConversations(syncToken []byte, requestedPageSize int, paginationInfo *protos.QueryConversationsRequest_PaginationInfo) (*protos.QueryConversationsResponse, error)

the sync token you got earlier already contains all the information needed to query the conversation im sure this endpoint will eventually support batch requests aswell since the response does paginationInfo is not required, just pass nil if you don't want to send it

func (*Messaging) QueryMessages

func (m *Messaging) QueryMessages(conversationId *protos.UUID, requestedCountSize int, currentVersion int64) (*protos.QueryMessagesResponse, error)

currentVersion is the cursor from where to query messages from

func (*Messaging) SendContentMessage

func (m *Messaging) SendContentMessage(messageBuilder *CreateMessageBuilder) (*protos.CreateContentMessageResponse, error)

func (*Messaging) SendTypingNotification

func (m *Messaging) SendTypingNotification(conversationId *protos.UUID, lastCreatedMessageId int64) (*protos.SendTypingNotificationResponse, error)

func (*Messaging) SyncConversations

func (m *Messaging) SyncConversations(syncToken []byte, conversationVersionInfos []*protos.ConversationVersionInfo) (*protos.SyncConversationsResponse, error)

if it's the first SyncConversations request, pass nil as both syncToken & conversationVersionInfos.

func (*Messaging) UpdateContentMessage

func (m *Messaging) UpdateContentMessage(updateMessageBuilder *UpdateMessageBuilder) (*protos.UpdateContentMessageResponse, error)

func (*Messaging) UpdateConversation

func (m *Messaging) UpdateConversation(updateConversationBuilder *UpdateConversationBuilder) (*protos.UpdateConversationResponse, error)

type Proxy

type Proxy func(*http.Request) (*url.URL, error)

type Request

type Request struct {
	// contains filtered or unexported fields
}

func (*Request) MakeRequest

func (r *Request) MakeRequest(url string, method string, headers http.Header, payload []byte, requestType types.RequestType) (*http.Response, []byte, error)

type Session

type Session struct {
	CurrentUser  *User               `json:"currentUser,omitempty"`
	FideliusKeys *types.FideliusKeys `json:"fideliusKeys,omitempty"`
	SnapCookies  *types.SnapCookies  `json:"snapCookies,omitempty"`
	SnapTokens   *types.SnapTokens   `json:"snapTokens,omitempty"`
}

func NewSessionFromCookies

func NewSessionFromCookies(cookieStr string) (*Session, error)

func NewSessionFromFile

func NewSessionFromFile(path string) (*Session, error)

FROM JSON FILE

func (*Session) GetCurrentUser

func (s *Session) GetCurrentUser() *User

func (*Session) Save

func (s *Session) Save(path string) error

type Snapchatter

type Snapchatter struct {
	ID                  string `json:"user_id"`
	Username            string `json:"username"`
	DisplayName         string `json:"display_name"`
	BitmojiAvatarID     string `json:"bitmoji_avatar_id"`
	BitmojiSelfieID     string `json:"bitmoji_selfie_id"`
	MutableUsername     string `json:"mutable_username"`
	BitmojiBackgroundID string `json:"bitmoji_background_id,omitempty"`
}

type UpdateConversationBuilder

type UpdateConversationBuilder struct {
	// contains filtered or unexported fields
}

func (*UpdateConversationBuilder) AddParticipants

func (cb *UpdateConversationBuilder) AddParticipants(participants []*protos.UUID) *UpdateConversationBuilder

func (*UpdateConversationBuilder) SetClearFromFeed

func (cb *UpdateConversationBuilder) SetClearFromFeed() *UpdateConversationBuilder

func (*UpdateConversationBuilder) SetConversation

func (cb *UpdateConversationBuilder) SetConversation(conversation *protos.Conversation) *UpdateConversationBuilder

for reuse

func (*UpdateConversationBuilder) SetLeaveConversation

func (cb *UpdateConversationBuilder) SetLeaveConversation() *UpdateConversationBuilder

func (*UpdateConversationBuilder) SetNotificationPreference

func (cb *UpdateConversationBuilder) SetNotificationPreference(preference protos.ChatNotificationPreference) *UpdateConversationBuilder

func (*UpdateConversationBuilder) SetRead

func (cb *UpdateConversationBuilder) SetRead(lastMessageId int64) *UpdateConversationBuilder

func (*UpdateConversationBuilder) SetRetentionPolicy

func (*UpdateConversationBuilder) SetTitle

func (cb *UpdateConversationBuilder) SetTitle(newTitle string, oldTitle string) *UpdateConversationBuilder

type UpdateMessageBuilder

type UpdateMessageBuilder struct {
	// contains filtered or unexported fields
}

func (*UpdateMessageBuilder) SetConversation

func (m *UpdateMessageBuilder) SetConversation(conversation *protos.Conversation) *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetErase

delete message

func (*UpdateMessageBuilder) SetMessage

func (m *UpdateMessageBuilder) SetMessage(messageId int64) *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetReaction

func (m *UpdateMessageBuilder) SetReaction(intentType int64) *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetRead

func (*UpdateMessageBuilder) SetRelease

func (m *UpdateMessageBuilder) SetRelease() *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetRemoveReaction

func (m *UpdateMessageBuilder) SetRemoveReaction() *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetReplay

func (m *UpdateMessageBuilder) SetReplay(currentReplayCount int32) *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetSave

func (*UpdateMessageBuilder) SetSaveToCameraRoll

func (m *UpdateMessageBuilder) SetSaveToCameraRoll() *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetScreenRecord

func (m *UpdateMessageBuilder) SetScreenRecord() *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetScreenshot

func (m *UpdateMessageBuilder) SetScreenshot() *UpdateMessageBuilder

func (*UpdateMessageBuilder) SetUnsave

type User

type User struct {
	ID                       string       `json:"id"`
	EncodedUserId            *protos.UUID `json:"encodedUserId,omitempty"`
	BitmojiAvatarID          string       `json:"bitmojiAvatarId"`
	BitmojiSelfieID          string       `json:"bitmojiSelfieId"`
	BitmojiBackgroundID      string       `json:"bitmojiBackgroundId"`
	BitmojiSceneID           string       `json:"bitmojiSceneId"`
	IsEmployee               bool         `json:"isEmployee"`
	Username                 string       `json:"username"`
	DisplayName              string       `json:"displayName"`
	SnapPrivacy              int          `json:"snapPrivacy"`
	HasUserSeenDWeb          bool         `json:"hasUserSeenDWeb"`
	HasUserAcceptedMerlinJIT bool         `json:"hasUserAcceptedMerlinJIT"`
}

type UserData

type UserData struct {
	User User `json:"user,omitempty"`
}

type Users

type Users struct {
	// contains filtered or unexported fields
}

func (*Users) GetBitmojiImage

func (u *Users) GetBitmojiImage(bitmojiSelfieId string, bitmojiAvatarId string, scale string) ([]byte, error)

func (*Users) GetBitmojiURL

func (u *Users) GetBitmojiURL(bitmojiSelfieId string, bitmojiAvatarId string, scale string) string

scale is a number, 0-2 but in string for the url formatting

func (*Users) GetPublicInfo

func (u *Users) GetPublicInfo(userIds []string) ([]Snapchatter, error)

type UsersPublicInfoResponse

type UsersPublicInfoResponse struct {
	Snapchatters []Snapchatter `json:"snapchatters"`
}

Directories

Path Synopsis
data

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL