metaai-sdk 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- metaai_api/__init__.py +20 -0
- metaai_api/api_server.py +256 -0
- metaai_api/client.py +140 -0
- metaai_api/exceptions.py +6 -0
- metaai_api/main.py +534 -0
- metaai_api/utils.py +291 -0
- metaai_api/video_generation.py +679 -0
- metaai_sdk-2.0.0.dist-info/METADATA +846 -0
- metaai_sdk-2.0.0.dist-info/RECORD +12 -0
- metaai_sdk-2.0.0.dist-info/WHEEL +5 -0
- metaai_sdk-2.0.0.dist-info/licenses/LICENSE +28 -0
- metaai_sdk-2.0.0.dist-info/top_level.txt +1 -0
metaai_api/utils.py
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import random
|
|
3
|
+
import time
|
|
4
|
+
from typing import Dict, Optional
|
|
5
|
+
|
|
6
|
+
from requests_html import HTMLSession
|
|
7
|
+
import requests
|
|
8
|
+
from bs4 import BeautifulSoup
|
|
9
|
+
|
|
10
|
+
from metaai_api.exceptions import FacebookInvalidCredentialsException
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def generate_offline_threading_id() -> str:
|
|
14
|
+
"""
|
|
15
|
+
Generates an offline threading ID.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
str: The generated offline threading ID.
|
|
19
|
+
"""
|
|
20
|
+
# Maximum value for a 64-bit integer in Python
|
|
21
|
+
max_int = (1 << 64) - 1
|
|
22
|
+
mask22_bits = (1 << 22) - 1
|
|
23
|
+
|
|
24
|
+
# Function to get the current timestamp in milliseconds
|
|
25
|
+
def get_current_timestamp():
|
|
26
|
+
return int(time.time() * 1000)
|
|
27
|
+
|
|
28
|
+
# Function to generate a random 64-bit integer
|
|
29
|
+
def get_random_64bit_int():
|
|
30
|
+
return random.getrandbits(64)
|
|
31
|
+
|
|
32
|
+
# Combine timestamp and random value
|
|
33
|
+
def combine_and_mask(timestamp, random_value):
|
|
34
|
+
shifted_timestamp = timestamp << 22
|
|
35
|
+
masked_random = random_value & mask22_bits
|
|
36
|
+
return (shifted_timestamp | masked_random) & max_int
|
|
37
|
+
|
|
38
|
+
timestamp = get_current_timestamp()
|
|
39
|
+
random_value = get_random_64bit_int()
|
|
40
|
+
threading_id = combine_and_mask(timestamp, random_value)
|
|
41
|
+
|
|
42
|
+
return str(threading_id)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def extract_value(text: str, start_str: str, end_str: str) -> str:
|
|
46
|
+
"""
|
|
47
|
+
Helper function to extract a specific value from the given text using a key.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
text (str): The text from which to extract the value.
|
|
51
|
+
start_str (str): The starting key.
|
|
52
|
+
end_str (str): The ending key.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
str: The extracted value.
|
|
56
|
+
"""
|
|
57
|
+
start = text.find(start_str) + len(start_str)
|
|
58
|
+
end = text.find(end_str, start)
|
|
59
|
+
return text[start:end]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def format_response(response: dict) -> str:
|
|
63
|
+
"""
|
|
64
|
+
Formats the response from Meta AI to remove unnecessary characters.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
response (dict): The dictionary containing the response to format.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
str: The formatted response.
|
|
71
|
+
"""
|
|
72
|
+
text = ""
|
|
73
|
+
for content in (
|
|
74
|
+
response.get("data", {})
|
|
75
|
+
.get("node", {})
|
|
76
|
+
.get("bot_response_message", {})
|
|
77
|
+
.get("composed_text", {})
|
|
78
|
+
.get("content", [])
|
|
79
|
+
):
|
|
80
|
+
text += content["text"] + "\n"
|
|
81
|
+
return text
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# Function to perform the login
|
|
85
|
+
def get_fb_session(email, password, proxies=None):
|
|
86
|
+
login_url = "https://www.facebook.com/login/?next"
|
|
87
|
+
headers = {
|
|
88
|
+
"authority": "mbasic.facebook.com",
|
|
89
|
+
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
90
|
+
"accept-language": "en-US,en;q=0.9",
|
|
91
|
+
"sec-ch-ua": '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
|
92
|
+
"sec-ch-ua-mobile": "?0",
|
|
93
|
+
"sec-ch-ua-platform": '"macOS"',
|
|
94
|
+
"sec-fetch-dest": "document",
|
|
95
|
+
"sec-fetch-mode": "navigate",
|
|
96
|
+
"sec-fetch-site": "none",
|
|
97
|
+
"sec-fetch-user": "?1",
|
|
98
|
+
"upgrade-insecure-requests": "1",
|
|
99
|
+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
|
|
100
|
+
}
|
|
101
|
+
# Send the GET request
|
|
102
|
+
response = requests.get(login_url, headers=headers, proxies=proxies)
|
|
103
|
+
soup = BeautifulSoup(response.text, "html.parser")
|
|
104
|
+
|
|
105
|
+
# Parse necessary parameters from the login form
|
|
106
|
+
lsd = soup.find("input", {"name": "lsd"})["value"]
|
|
107
|
+
jazoest = soup.find("input", {"name": "jazoest"})["value"]
|
|
108
|
+
|
|
109
|
+
# Define the URL and body for the POST request to submit the login form
|
|
110
|
+
post_url = "https://www.facebook.com/login/?next"
|
|
111
|
+
data = {
|
|
112
|
+
"lsd": lsd,
|
|
113
|
+
"jazoest": jazoest,
|
|
114
|
+
"login_source": "comet_headerless_login",
|
|
115
|
+
"email": email,
|
|
116
|
+
"pass": password,
|
|
117
|
+
"login": "1",
|
|
118
|
+
"next": None,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
headers = {
|
|
122
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:132.0) Gecko/20100101 Firefox/132.0",
|
|
123
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
124
|
+
"Accept-Language": "en-US,en;q=0.5",
|
|
125
|
+
"Accept-Encoding": None,
|
|
126
|
+
"Referer": "https://www.facebook.com/",
|
|
127
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
128
|
+
"Origin": "https://www.facebook.com",
|
|
129
|
+
"DNT": "1",
|
|
130
|
+
"Sec-GPC": "1",
|
|
131
|
+
"Connection": "keep-alive",
|
|
132
|
+
"cookie": f"datr={response.cookies.get('datr')};",
|
|
133
|
+
"Upgrade-Insecure-Requests": "1",
|
|
134
|
+
"Sec-Fetch-Dest": "document",
|
|
135
|
+
"Sec-Fetch-Mode": "navigate",
|
|
136
|
+
"Sec-Fetch-Site": "same-origin",
|
|
137
|
+
"Sec-Fetch-User": "?1",
|
|
138
|
+
"Priority": "u=0, i",
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
from requests import cookies
|
|
142
|
+
|
|
143
|
+
# Send the POST request
|
|
144
|
+
session = requests.session()
|
|
145
|
+
jar = cookies.RequestsCookieJar()
|
|
146
|
+
session.proxies = proxies
|
|
147
|
+
session.cookies = jar
|
|
148
|
+
|
|
149
|
+
result = session.post(post_url, headers=headers, data=data)
|
|
150
|
+
if "sb" not in jar or "xs" not in jar:
|
|
151
|
+
raise FacebookInvalidCredentialsException(
|
|
152
|
+
"Was not able to login to Facebook. Please check your credentials. "
|
|
153
|
+
"You may also have been rate limited. Try to connect to Facebook manually."
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
cookies = {
|
|
157
|
+
**result.cookies.get_dict(),
|
|
158
|
+
"sb": jar["sb"],
|
|
159
|
+
"xs": jar["xs"],
|
|
160
|
+
"fr": jar["fr"],
|
|
161
|
+
"c_user": jar["c_user"],
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
response_login = {
|
|
165
|
+
"cookies": cookies,
|
|
166
|
+
"headers": result.headers,
|
|
167
|
+
"response": response.text,
|
|
168
|
+
}
|
|
169
|
+
meta_ai_cookies = get_cookies()
|
|
170
|
+
|
|
171
|
+
url = "https://www.meta.ai/state/"
|
|
172
|
+
|
|
173
|
+
payload = f'__a=1&lsd={meta_ai_cookies["lsd"]}'
|
|
174
|
+
headers = {
|
|
175
|
+
"authority": "www.meta.ai",
|
|
176
|
+
"accept": "*/*",
|
|
177
|
+
"accept-language": "en-US,en;q=0.9",
|
|
178
|
+
"cache-control": "no-cache",
|
|
179
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
180
|
+
"cookie": f'ps_n=1; ps_l=1; dpr=2; _js_datr={meta_ai_cookies["_js_datr"]}; abra_csrf={meta_ai_cookies["abra_csrf"]}; datr={meta_ai_cookies["datr"]};; ps_l=1; ps_n=1',
|
|
181
|
+
"origin": "https://www.meta.ai",
|
|
182
|
+
"pragma": "no-cache",
|
|
183
|
+
"referer": "https://www.meta.ai/",
|
|
184
|
+
"sec-fetch-mode": "cors",
|
|
185
|
+
"sec-fetch-site": "same-origin",
|
|
186
|
+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
response = requests.request(
|
|
190
|
+
"POST", url, headers=headers, data=payload, proxies=proxies
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
state = extract_value(response.text, start_str='"state":"', end_str='"')
|
|
194
|
+
|
|
195
|
+
url = f"https://www.facebook.com/oidc/?app_id=1358015658191005&scope=openid%20linking&response_type=code&redirect_uri=https%3A%2F%2Fwww.meta.ai%2Fauth%2F&no_universal_links=1&deoia=1&state={state}"
|
|
196
|
+
payload = {}
|
|
197
|
+
headers = {
|
|
198
|
+
"authority": "www.facebook.com",
|
|
199
|
+
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
200
|
+
"accept-language": "en-US,en;q=0.9",
|
|
201
|
+
"cache-control": "no-cache",
|
|
202
|
+
"cookie": f"datr={response_login['cookies']['datr']}; sb={response_login['cookies']['sb']}; c_user={response_login['cookies']['c_user']}; xs={response_login['cookies']['xs']}; fr={response_login['cookies']['fr']}; abra_csrf={meta_ai_cookies['abra_csrf']};",
|
|
203
|
+
"sec-fetch-dest": "document",
|
|
204
|
+
"sec-fetch-mode": "navigate",
|
|
205
|
+
"sec-fetch-site": "cross-site",
|
|
206
|
+
"sec-fetch-user": "?1",
|
|
207
|
+
"upgrade-insecure-requests": "1",
|
|
208
|
+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
|
|
209
|
+
}
|
|
210
|
+
session = requests.session()
|
|
211
|
+
session.proxies = proxies
|
|
212
|
+
response = session.get(url, headers=headers, data=payload, allow_redirects=False)
|
|
213
|
+
|
|
214
|
+
next_url = response.headers["Location"]
|
|
215
|
+
|
|
216
|
+
url = next_url
|
|
217
|
+
|
|
218
|
+
payload = {}
|
|
219
|
+
headers = {
|
|
220
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:125.0) Gecko/20100101 Firefox/125.0",
|
|
221
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
222
|
+
"Accept-Language": "en-US,en;q=0.5",
|
|
223
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
224
|
+
"Referer": "https://www.meta.ai/",
|
|
225
|
+
"Connection": "keep-alive",
|
|
226
|
+
"Cookie": f'dpr=2; abra_csrf={meta_ai_cookies["abra_csrf"]}; datr={meta_ai_cookies["_js_datr"]}',
|
|
227
|
+
"Upgrade-Insecure-Requests": "1",
|
|
228
|
+
"Sec-Fetch-Dest": "document",
|
|
229
|
+
"Sec-Fetch-Mode": "navigate",
|
|
230
|
+
"Sec-Fetch-Site": "cross-site",
|
|
231
|
+
"Sec-Fetch-User": "?1",
|
|
232
|
+
"TE": "trailers",
|
|
233
|
+
}
|
|
234
|
+
session.get(url, headers=headers, data=payload)
|
|
235
|
+
cookies = session.cookies.get_dict()
|
|
236
|
+
if "abra_sess" not in cookies:
|
|
237
|
+
raise FacebookInvalidCredentialsException(
|
|
238
|
+
"Was not able to login to Facebook. Please check your credentials. "
|
|
239
|
+
"You may also have been rate limited. Try to connect to Facebook manually."
|
|
240
|
+
)
|
|
241
|
+
logging.info("Successfully logged in to Facebook.")
|
|
242
|
+
return cookies
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def get_cookies() -> dict:
|
|
246
|
+
"""
|
|
247
|
+
Extracts necessary cookies from the Meta AI main page.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
dict: A dictionary containing essential cookies.
|
|
251
|
+
"""
|
|
252
|
+
session = HTMLSession()
|
|
253
|
+
response = session.get("https://www.meta.ai/")
|
|
254
|
+
return {
|
|
255
|
+
"_js_datr": extract_value(
|
|
256
|
+
response.text, start_str='_js_datr":{"value":"', end_str='",'
|
|
257
|
+
),
|
|
258
|
+
"abra_csrf": extract_value(
|
|
259
|
+
response.text, start_str='abra_csrf":{"value":"', end_str='",'
|
|
260
|
+
),
|
|
261
|
+
"datr": extract_value(
|
|
262
|
+
response.text, start_str='datr":{"value":"', end_str='",'
|
|
263
|
+
),
|
|
264
|
+
"lsd": extract_value(
|
|
265
|
+
response.text, start_str='"LSD",[],{"token":"', end_str='"}'
|
|
266
|
+
),
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def get_session(
|
|
271
|
+
proxy: Optional[Dict] = None, test_url: str = "https://api.ipify.org/?format=json"
|
|
272
|
+
) -> requests.Session:
|
|
273
|
+
"""
|
|
274
|
+
Get a session with the proxy set.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
proxy (Dict): The proxy to use
|
|
278
|
+
test_url (str): A test site from which we check that the proxy is installed correctly.
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
requests.Session: A session with the proxy set.
|
|
282
|
+
"""
|
|
283
|
+
session = requests.Session()
|
|
284
|
+
if not proxy:
|
|
285
|
+
return session
|
|
286
|
+
response = session.get(test_url, proxies=proxy, timeout=10)
|
|
287
|
+
if response.status_code == 200:
|
|
288
|
+
session.proxies = proxy
|
|
289
|
+
return session
|
|
290
|
+
else:
|
|
291
|
+
raise Exception("Proxy is not working.")
|