-
Notifications
You must be signed in to change notification settings - Fork 4
/
utils.py
95 lines (71 loc) · 2.81 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# -*- coding: utf-8 -*-
"""
This module contains methods for creating request tokens and
encryption/decryption of snaps
"""
from hashlib import sha256
from time import time
from uuid import uuid4
import requests
from Crypto.Cipher import AES
URL = 'https://feelinsonice-hrd.appspot.com/bq/'
SECRET = b'iEk21fuwZApXlz93750dmW22pw389dPwOk'
STATIC_TOKEN = 'm198sOkJEn37DjqZ32lpRu76xmw288xSQ9'
BLOB_ENCRYPTION_KEY = 'M02cnQ51Ji97vwT4'
HASH_PATTERN = ('00011101111011100011110101011110'
'11010001001110011000110001000110')
def make_request_token(a, b):
hash_a = sha256(SECRET + a.encode('utf-8')).hexdigest()
hash_b = sha256(b.encode('utf-8') + SECRET).hexdigest()
return ''.join((hash_b[i] if c == '1' else hash_a[i]
for i, c in enumerate(HASH_PATTERN)))
def get_token(auth_token=None):
return STATIC_TOKEN if auth_token is None else auth_token
def pkcs5_pad(data, blocksize=16):
pad_count = blocksize - len(data) % blocksize
return data + (chr(pad_count) * pad_count).encode('utf-8')
def decrypt(data):
cipher = AES.new(BLOB_ENCRYPTION_KEY, AES.MODE_ECB)
return cipher.decrypt(pkcs5_pad(data))
def decrypt_story(data, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
return cipher.decrypt(pkcs5_pad(data))
def encrypt(data):
cipher = AES.new(BLOB_ENCRYPTION_KEY, AES.MODE_ECB)
return cipher.encrypt(pkcs5_pad(data))
def timestamp():
return int(round(time() * 1000))
def request(endpoint, auth_token, data=None, files=None,
raise_for_status=True, req_type='post'):
"""Wrapper method for calling Snapchat API which adds the required auth
token before sending the request.
:param endpoint: URL for API endpoint
:param data: Dictionary containing form data
:param raise_for_status: Raise exception for 4xx and 5xx status codes
:param req_type: The request type (GET, POST). Defaults to POST
"""
now = timestamp()
if data is None:
data = {}
headers = {
'User-Agent': 'Snapchat/8.1.1 (iPhone5,1; iOS 6.1.4; gzip)',
'Accept-Language': 'en-US;q=1, en;q=0.9',
'Accept-Locale': 'en'
}
if req_type == 'post':
data.update({
'timestamp': now,
'req_token': make_request_token(auth_token or STATIC_TOKEN,
str(now))
})
r = requests.post(URL + endpoint, data=data, files=files,
headers=headers)
else:
r = requests.get(URL + endpoint, params=data, headers=headers)
if raise_for_status:
r.raise_for_status()
return r
def make_media_id(username):
"""Create a unique media identifier. Used when uploading media"""
return '{username}~{uuid}'.format(username=username.upper(),
uuid=str(uuid4()))