def login(self, username, password, gmail, gpasswd): """Login to Snapchat account Returns a dict containing user information on successful login, the data returned is similar to get_updates. :param username Snapchat username :param password Snapchat password :param gmail Gmail address :param gpasswd Gmail password """ self.gmail = gmail self.gpasswd = gpasswd i = 0 logged_in = False while i < 4 and logged_in == False: i += 1 now = str(timestamp()) req_token = make_request_token(STATIC_TOKEN, now) gauth_token = get_auth_token(gmail, gpasswd) self.gauth = gauth_token[0] self.expiry = gauth_token[1] string = username + "|" + password + "|" + now + "|" + req_token dtoken = self._get_device_token() self._unset_auth() attestation = get_attestation(username, password, now) r = self._request('/loq/login', { 'username': username, 'password': password, 'height': 1280, 'width': 720, 'max_video_height': 640, 'max_video_width': 480, 'dsig': hmac.new(str(dtoken['dtoken1v']),string,sha256).hexdigest()[:20], 'dtoken1i': dtoken['dtoken1i'], 'ptoken': "ie", 'attestation': attestation, 'sflag': 1, 'application_id': 'com.snapchat.android', 'req_token': req_token }, { 'now': now, 'gauth': self._get_gauth() }, None, True, 'post', { 'X-Snapchat-Client-Auth': get_client_auth_token(username, password, now)['signature'] }) result = r.json() if 'updates_response' in result: logged_in = True if 'auth_token' in result['updates_response']: self.auth_token = result['updates_response']['auth_token'] if 'username' in result['updates_response']: self.username = username if self.username is None and self.auth_token is None: raise Exception(result.get('message', 'unknown error')) return result
def upload(self, path): """Upload media Returns the media ID on success. The media ID is used when sending the snap. """ if not os.path.exists(path): raise ValueError('No such file: {0}'.format(path)) with open(path, 'rb') as f: data = f.read() media_type = get_media_type(data) if media_type is None: raise ValueError('Could not determine media type for given data') media_id = make_media_id(self.username) now = str(timestamp()) r = self._request('/ph/upload', { 'media_id': media_id, 'type': media_type, 'timestamp': now, 'username': self.username, 'zipped': '0' }, {'now': now, 'gauth': self._get_gauth()}, files={'data': data}) return media_id if len(r.content) == 0 else None
def upload(self, path): """Upload media Returns the media ID on success. The media ID is used when sending the snap. """ if not os.path.exists(path): raise ValueError('No such file: {0}'.format(path)) with open(path, 'rb') as f: data = f.read() media_type = get_media_type(data) if media_type is None: raise ValueError('Could not determine media type for given data') media_id = make_media_id(self.username) now = str(timestamp()) r = self._request('/ph/upload', { 'media_id': media_id, 'type': media_type, 'timestamp': now, 'username': self.username, 'zipped': '0' }, { 'now': now, 'gauth': self._get_gauth() }, files={'data': data}) return media_id if len(r.content) == 0 else None
def _get_conversation_auth(self, to): """Gets conversation auth for a certain user. Only takes in one user, returns a dict. """ now = str(timestamp()) r = self._request('/loq/conversation_auth_token',{ 'username': self.username, 'timestamp': now, 'conversation_id': self.username + "~" + to }, {'now': now, 'gauth': self._get_gauth()}) return r.json()
def get_blob_dry(self, snap_id): """Get the image or video of a given snap Returns the image or a video of the given snap or None if data is invalid. :param snap_id: Snap id to fetch """ now = str(timestamp()) return self._dry_request('/bq/blob', {'id': snap_id, 'timestamp':now, 'username': self.username}, {'now': now, 'gauth': self._get_gauth()}, req_type='get')
def delete_friend(self, username): """Remove user from friends Returns true on success. :param username: Username to remove from friends """ now = str(timestamp()) r = self._request('/bq/friend', { 'action': 'delete', 'friend': username, 'timestamp': now, 'username': self.username }, {'now': now, 'gauth': self._get_gauth()}) return r.json()
def send_to_story(self, media_id, time=5, media_type=0, is_zip=0): """Send a snap to your story. Requires a media_id returned by the upload method Returns true if the snap was sent successfully. """ now = str(timestamp()) r = self._request('/bq/post_story', { 'username': self.username, 'media_id': media_id, 'client_id': media_id, 'time': time, 'type': media_type, 'zipped': is_zip }, {'now': now, 'gauth': self._get_gauth()}) return r.json()
def get_my_story(self): now = str(timestamp()) r = self._request('/bq/stories', { 'timestamp': now, 'screen_height_in': 4.527565, 'screen_height_px': 1920, 'screen_width_in': 2.5590599, 'screen_width_px': 1080, 'username': self.username, 'features_map': {} }) result = r.json()['my_stories'] return result
def get_story_blob(self, story_id, story_key, story_iv): """Get the image or video of a given snap Returns the decrypted image or a video of the given snap or None if data is invalid. :param story_id: Media id to fetch :param story_key: Encryption key of the story :param story_iv: Encryption IV of the story """ now = str(timestamp()) r = self._request('/bq/story_blob', {'story_id': story_id}, raise_for_status=False, req_type='get') data = decrypt_story(r.content, story_key, story_iv) return data
def _get_conversation_auth(self, to): """Gets conversation auth for a certain user. Only takes in one user, returns a dict. """ now = str(timestamp()) r = self._request( '/loq/conversation_auth_token', { 'username': self.username, 'timestamp': now, 'conversation_id': self.username + "~" + to }, { 'now': now, 'gauth': self._get_gauth() }) return r.json()
def block(self, username): """Block a user Returns true on success. :param username: Username to block """ now = (str(timestamp())) r = self._request('/bq/friend', { 'action': 'block', 'friend': username, 'username': self.username, 'features_map': '{}', 'timestamp': now }, {'gauth': self._get_gauth()}) return r.json().get('message') == '{0} was blocked'.format(username)
def get_my_story(self): now = str(timestamp()) r = self._request( '/bq/stories', { 'timestamp': now, 'screen_height_in': 4.527565, 'screen_height_px': 1920, 'screen_width_in': 2.5590599, 'screen_width_px': 1080, 'username': self.username, 'features_map': {} }) result = r.json()['my_stories'] return result
def send(self, media_id, recipients, time=5): """Send a snap. Requires a media_id returned by the upload method Returns true if the snap was sent successfully. """ now = str(timestamp()) recipients = '["' + '","'.join(recipients) + '"]' r = self._request('/loq/send', { 'media_id': media_id, 'zipped': '0', 'recipients': recipients, 'username': self.username, 'time': time, 'timestamp': now, 'features_map': '{}' }, {'now': now, 'gauth': self._get_gauth()}) return len(r.content) == 0
def send_events(self, events, data=None): """Send event data Returns true on success. :param events: List of events to send :param data: Additional data to send """ now = str(timestamp()) if data is None: data = {} r = self._request('/bq/update_snaps', { 'events': json.dumps(events), 'json': json.dumps(data), 'username': self.username }, {'now': now,'gauth': self._get_gauth()}) return len(r.content) == 0
def block(self, username): """Block a user Returns true on success. :param username: Username to block """ now = (str(timestamp())) r = self._request( '/bq/friend', { 'action': 'block', 'friend': username, 'username': self.username, 'features_map': '{}', 'timestamp': now }, {'gauth': self._get_gauth()}) return r.json().get('message') == '{0} was blocked'.format(username)
def delete_friend(self, username): """Remove user from friends Returns true on success. :param username: Username to remove from friends """ now = str(timestamp()) r = self._request( '/bq/friend', { 'action': 'delete', 'friend': username, 'timestamp': now, 'username': self.username }, { 'now': now, 'gauth': self._get_gauth() }) return r.json()
def send_to_story(self, media_id, time=5, media_type=0, is_zip=0): """Send a snap to your story. Requires a media_id returned by the upload method Returns true if the snap was sent successfully. """ now = str(timestamp()) r = self._request( '/bq/post_story', { 'username': self.username, 'media_id': media_id, 'client_id': media_id, 'time': time, 'type': media_type, 'zipped': is_zip }, { 'now': now, 'gauth': self._get_gauth() }) return r.json()
def get_conversation_info(self, tos): messages = {} if not isinstance(tos, list): tos = [tos] for to in tos: auth_info = self._get_conversation_auth(to) if 'messaging_auth' in auth_info: payload = auth_info['messaging_auth']['payload'] mac = auth_info['messaging_auth']['mac'] conv_id = str(uuid1()) messages = { 'presences': { self.username: True, to: False }, 'receiving_video': False, 'supports_here': True, 'header': { 'auth': { 'mac': mac, 'payload': payload }, 'to': [to], 'conv_id': self.username + "~" + to, 'from': self.username, 'conn_sequence_number': 0 }, 'retried': False, 'id': conv_id, 'type': 'presence' } now = str(timestamp()) r = self._request( '/loq/conversation_post_messages', { 'auth_token': self._get_gauth(), 'messages': messages, 'timestamp': now, 'username': self.username }, { 'now': now, 'gauth': self._get_gauth() }) return r
def add_friend(self, username): """Add user as friend Returns JSON response. Expected messages: Success: '{username} is now your friend!' Pending: '{username} is private. Friend request sent.' Failure: 'Sorry! Couldn't find {username}' :param username: Username to add as a friend """ now = str(timestamp()) r = self._request('/bq/friend', { 'action': 'add', 'friend': username, 'timestamp': now, 'username': self.username, 'added_by': 'ADDED_BY_USERNAME' }, {'now': now, 'gauth': self._get_gauth()}) return r.json()
def get_blob(self, snap_id): """Get the image or video of a given snap Returns the image or a video of the given snap or None if data is invalid. :param snap_id: Snap id to fetch """ now = str(timestamp()) r = self._request('/bq/blob', { 'id': snap_id, 'timestamp': now, 'username': self.username }, { 'now': now, 'gauth': self._get_gauth() }, req_type='get') return r.content
def send_events(self, events, data=None): """Send event data Returns true on success. :param events: List of events to send :param data: Additional data to send """ now = str(timestamp()) if data is None: data = {} r = self._request( '/bq/update_snaps', { 'events': json.dumps(events), 'json': json.dumps(data), 'username': self.username }, { 'now': now, 'gauth': self._get_gauth() }) return len(r.content) == 0
def upload_raw(self, data): """Upload media Returns the media ID on success. The media ID is used when sending the snap. """ media_type = get_media_type(data) if media_type is None: raise ValueError('Could not determine media type for given data') media_id = make_media_id(self.username) now = str(timestamp()) r = self._request('/ph/upload', { 'media_id': media_id, 'type': media_type, 'timestamp': now, 'username': self.username, 'zipped': '0' }, {'now': now, 'gauth': self._get_gauth()}, files={'data': data}) return media_id if len(r.content) == 0 else None
def send(self, media_id, recipients, time=5): """Send a snap. Requires a media_id returned by the upload method Returns true if the snap was sent successfully. """ now = str(timestamp()) recipients = '["' + '","'.join(recipients) + '"]' r = self._request( '/loq/send', { 'media_id': media_id, 'zipped': '0', 'recipients': recipients, 'username': self.username, 'time': time, 'timestamp': now, 'features_map': '{}' }, { 'now': now, 'gauth': self._get_gauth() }) return len(r.content) == 0
def get_snaptag(self): """Get a QR code-like image used to add friends on Snapchat. Returns False if unable to get a QR code. """ updates = self.get_updates() if not updates: return False else: qr_path = updates['updates_response']['qr_path'] now = str(timestamp()) r = self._request('/bq/snaptag_download', { 'image': qr_path, 'username': self.username, 'timestamp': now }, { 'now': now, 'gauth': self._get_gauth() }) return r.content
def get_updates(self, update_timestamp=0): """Get user, friend and snap updates Returns a dict containing user, friends and snap information. :param update_timestamp: Optional timestamp (epoch in seconds) to limit updates """ now = str(timestamp()) r = self._request('/loq/all_updates', { 'timestamp': now, 'username': self.username, 'height': 1280, 'width': 720, 'max_video_height': 640, 'max_video_width': 480 }, { 'now': now, 'gauth': self._get_gauth() }) result = r.json() if 'auth_token' in result: self.auth_token = result['auth_token'] return result
def add_friend(self, username): """Add user as friend Returns JSON response. Expected messages: Success: '{username} is now your friend!' Pending: '{username} is private. Friend request sent.' Failure: 'Sorry! Couldn't find {username}' :param username: Username to add as a friend """ now = str(timestamp()) r = self._request( '/bq/friend', { 'action': 'add', 'friend': username, 'timestamp': now, 'username': self.username, 'added_by': 'ADDED_BY_USERNAME' }, { 'now': now, 'gauth': self._get_gauth() }) return r.json()
def get_conversation_info(self, tos): messages = {} if not isinstance(tos, list): tos = [tos] for to in tos: auth_info = self._get_conversation_auth(to) if 'messaging_auth' in auth_info: payload = auth_info['messaging_auth']['payload'] mac = auth_info['messaging_auth']['mac'] conv_id = str(uuid1()) messages = { 'presences': {self.username: True, to: False}, 'receiving_video': False, 'supports_here': True, 'header': { 'auth': { 'mac': mac, 'payload': payload }, 'to': [to], 'conv_id': self.username + "~" + to, 'from': self.username, 'conn_sequence_number': 0 }, 'retried': False, 'id': conv_id, 'type': 'presence' } now = str(timestamp()) r = self._request('/loq/conversation_post_messages',{ 'auth_token': self._get_gauth(), 'messages': messages, 'timestamp': now, 'username': self.username },{'now': now, 'gauth': self._get_gauth()}) return r
def get_updates(self, update_timestamp=0): """Get user, friend and snap updates Returns a dict containing user, friends and snap information. :param update_timestamp: Optional timestamp (epoch in seconds) to limit updates """ now = str(timestamp()) r = self._request( '/loq/all_updates', { 'timestamp': now, 'username': self.username, 'height': 1280, 'width': 720, 'max_video_height': 640, 'max_video_width': 480 }, { 'now': now, 'gauth': self._get_gauth() }) result = r.json() if 'auth_token' in result: self.auth_token = result['auth_token'] return result
def login(self, username, password, gmail, gpasswd): """Login to Snapchat account Returns a dict containing user information on successful login, the data returned is similar to get_updates. :param username Snapchat username :param password Snapchat password :param gmail Gmail address :param gpasswd Gmail password """ self.gmail = gmail self.gpasswd = gpasswd i = 0 logged_in = False while i < 4 and logged_in == False: i += 1 now = str(timestamp()) req_token = make_request_token(STATIC_TOKEN, now) gauth_token = get_auth_token(gmail, gpasswd) self.gauth = gauth_token[0] self.expiry = gauth_token[1] string = username + "|" + password + "|" + now + "|" + req_token dtoken = self._get_device_token() self._unset_auth() attestation = get_attestation(username, password, now) r = self._request( '/loq/login', { 'username': username, 'password': password, 'height': 1280, 'width': 720, 'max_video_height': 640, 'max_video_width': 480, 'dsig': hmac.new(str(dtoken['dtoken1v']), string, sha256).hexdigest()[:20], 'dtoken1i': dtoken['dtoken1i'], 'ptoken': "ie", 'attestation': attestation, 'sflag': 1, 'application_id': 'com.snapchat.android', 'req_token': req_token }, { 'now': now, 'gauth': self._get_gauth() }, None, True, 'post', { 'X-Snapchat-Client-Auth': get_client_auth_token(username, password, now)['signature'] }) result = r.json() if 'updates_response' in result: logged_in = True if 'auth_token' in result['updates_response']: self.auth_token = result['updates_response']['auth_token'] if 'username' in result['updates_response']: self.username = username if self.username is None and self.auth_token is None: raise Exception(result.get('message', 'unknown error')) return result