metaai-sdk 2.3.6__py3-none-any.whl → 3.0.1__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/api_server.py CHANGED
@@ -107,12 +107,14 @@ class ImageRequest(BaseModel):
107
107
  new_conversation: bool = False
108
108
  media_ids: Optional[list] = None
109
109
  attachment_metadata: Optional[dict] = None # {'file_size': int, 'mime_type': str}
110
+ orientation: Optional[str] = None # 'VERTICAL', 'LANDSCAPE' (not HORIZONTAL), or 'SQUARE'
110
111
 
111
112
 
112
113
  class VideoRequest(BaseModel):
113
114
  prompt: str
114
115
  media_ids: Optional[list] = None
115
116
  attachment_metadata: Optional[dict] = None # {'file_size': int, 'mime_type': str}
117
+ orientation: Optional[str] = None # 'VERTICAL', 'LANDSCAPE', or 'SQUARE'
116
118
  wait_before_poll: int = Field(10, ge=0, le=60)
117
119
  max_attempts: int = Field(30, ge=1, le=60)
118
120
  wait_seconds: int = Field(5, ge=1, le=30)
@@ -206,7 +208,14 @@ async def chat(body: ChatRequest, cookies: Dict[str, str] = Depends(get_cookies)
206
208
  raise HTTPException(status_code=400, detail="Streaming not supported via HTTP JSON; set stream=false")
207
209
  ai = MetaAI(cookies=cookies, proxy=_get_proxies())
208
210
  try:
209
- return cast(Dict[str, Any], ai.prompt(body.message, stream=False, new_conversation=body.new_conversation, media_ids=body.media_ids, attachment_metadata=body.attachment_metadata))
211
+ return cast(Dict[str, Any], await run_in_threadpool(
212
+ ai.prompt,
213
+ body.message,
214
+ stream=False,
215
+ new_conversation=body.new_conversation,
216
+ media_ids=body.media_ids,
217
+ attachment_metadata=body.attachment_metadata
218
+ ))
210
219
  except Exception as exc: # noqa: BLE001
211
220
  await cache.refresh_after_error()
212
221
  raise HTTPException(status_code=502, detail=str(exc)) from exc
@@ -218,13 +227,15 @@ async def image(body: ImageRequest, cookies: Dict[str, str] = Depends(get_cookie
218
227
  try:
219
228
  # Automatically prepend "generate image of" to the prompt
220
229
  prompt = f"generate image of {body.prompt}" if not body.prompt.lower().startswith(("generate image", "create image")) else body.prompt
221
- return cast(Dict[str, Any], ai.prompt(
222
- prompt,
223
- stream=False,
224
- new_conversation=body.new_conversation,
225
- media_ids=body.media_ids,
230
+ return cast(Dict[str, Any], await run_in_threadpool(
231
+ ai.prompt,
232
+ prompt,
233
+ stream=False,
234
+ new_conversation=body.new_conversation,
235
+ media_ids=body.media_ids,
226
236
  attachment_metadata=body.attachment_metadata,
227
- is_image_generation=True # Image generation uses DISCOVER entrypoint
237
+ is_image_generation=True, # Image generation uses DISCOVER entrypoint
238
+ orientation=body.orientation # Support VERTICAL, HORIZONTAL, SQUARE
228
239
  ))
229
240
  except Exception as exc: # noqa: BLE001
230
241
  await cache.refresh_after_error()
@@ -233,6 +244,10 @@ async def image(body: ImageRequest, cookies: Dict[str, str] = Depends(get_cookie
233
244
 
234
245
  @app.post("/video")
235
246
  async def video(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookies)) -> Dict[str, Any]:
247
+ # Force refresh cookies before video generation for best results
248
+ await cache.refresh_if_needed(force=True)
249
+ cookies = await cache.snapshot()
250
+
236
251
  ai = MetaAI(cookies=cookies, proxy=_get_proxies())
237
252
  try:
238
253
  # Automatically prepend "generate a video" to the prompt
@@ -242,6 +257,7 @@ async def video(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookie
242
257
  prompt,
243
258
  body.media_ids,
244
259
  body.attachment_metadata,
260
+ body.orientation,
245
261
  body.wait_before_poll,
246
262
  body.max_attempts,
247
263
  body.wait_seconds,
@@ -254,6 +270,10 @@ async def video(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookie
254
270
 
255
271
  @app.post("/video/async")
256
272
  async def video_async(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookies)) -> Dict[str, str]:
273
+ # Force refresh cookies before video generation
274
+ await cache.refresh_if_needed(force=True)
275
+ cookies = await cache.snapshot()
276
+
257
277
  job = await jobs.create()
258
278
  asyncio.create_task(_run_video_job(job.job_id, body, cookies))
259
279
  return {"job_id": job.job_id, "status": "pending"}
@@ -322,6 +342,7 @@ async def _run_video_job(job_id: str, body: VideoRequest, cookies: Dict[str, str
322
342
  body.prompt,
323
343
  body.media_ids,
324
344
  body.attachment_metadata,
345
+ body.orientation,
325
346
  body.wait_before_poll,
326
347
  body.max_attempts,
327
348
  body.wait_seconds,
metaai_api/main.py CHANGED
@@ -12,6 +12,8 @@ from metaai_api.utils import (
12
12
  generate_offline_threading_id,
13
13
  extract_value,
14
14
  format_response,
15
+ detect_challenge_page,
16
+ handle_meta_ai_challenge,
15
17
  )
16
18
 
17
19
  from metaai_api.utils import get_fb_session, get_session
@@ -29,7 +31,13 @@ class MetaAI:
29
31
  """
30
32
 
31
33
  def __init__(
32
- self, fb_email: Optional[str] = None, fb_password: Optional[str] = None, cookies: Optional[dict] = None, proxy: Optional[dict] = None
34
+ self,
35
+ fb_email: Optional[str] = None,
36
+ fb_password: Optional[str] = None,
37
+ cookies: Optional[dict] = None,
38
+ proxy: Optional[dict] = None,
39
+ lsd: Optional[str] = None,
40
+ fb_dtsg: Optional[str] = None
33
41
  ):
34
42
  self.session = get_session()
35
43
  self.session.headers.update(
@@ -47,37 +55,116 @@ class MetaAI:
47
55
 
48
56
  if cookies is not None:
49
57
  self.cookies = cookies
58
+ # Add manually provided tokens if available
59
+ if lsd:
60
+ self.cookies["lsd"] = lsd
61
+ if fb_dtsg:
62
+ self.cookies["fb_dtsg"] = fb_dtsg
50
63
  # Auto-fetch lsd and fb_dtsg if not present in cookies
51
64
  if "lsd" not in self.cookies or "fb_dtsg" not in self.cookies:
52
65
  self._fetch_missing_tokens()
53
66
  else:
54
67
  self.cookies = self.get_cookies()
68
+ # Override with manually provided tokens if available
69
+ if lsd:
70
+ self.cookies["lsd"] = lsd
71
+ if fb_dtsg:
72
+ self.cookies["fb_dtsg"] = fb_dtsg
55
73
 
56
74
  self.external_conversation_id = None
57
75
  self.offline_threading_id = None
58
76
 
59
- def _fetch_missing_tokens(self):
77
+ def _fetch_missing_tokens(self, max_retries: int = 3):
60
78
  """
61
79
  Fetch lsd and fb_dtsg tokens if they're missing from cookies.
80
+ Handles Meta AI challenge pages automatically.
81
+
82
+ Args:
83
+ max_retries (int): Maximum number of retry attempts.
62
84
  """
63
85
  try:
64
- cookies_str = "; ".join([f"{k}={v}" for k, v in self.cookies.items() if v])
65
-
66
86
  session = HTMLSession()
67
- headers = {"cookie": cookies_str}
68
- response = session.get("https://www.meta.ai/", headers=headers)
87
+ # Set cookies on session object (not as header string)
88
+ session.cookies.update(self.cookies)
69
89
 
70
- if "lsd" not in self.cookies:
71
- lsd = extract_value(response.text, start_str='"LSD",[],{"token":"', end_str='"')
72
- if lsd:
73
- self.cookies["lsd"] = lsd
90
+ headers = {
91
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
92
+ "Accept-Language": "en-US,en;q=0.9",
93
+ }
74
94
 
75
- if "fb_dtsg" not in self.cookies:
76
- fb_dtsg = extract_value(response.text, start_str='DTSGInitData",[],{"token":"', end_str='"')
77
- if fb_dtsg:
78
- self.cookies["fb_dtsg"] = fb_dtsg
95
+ for attempt in range(max_retries):
96
+ logging.info(f"Fetching tokens from Meta AI (attempt {attempt + 1}/{max_retries})...")
97
+ response = session.get("https://meta.ai", headers=headers)
98
+
99
+ # Check if we got a challenge page
100
+ challenge_url = detect_challenge_page(response.text)
101
+ if challenge_url:
102
+ logging.warning("Meta AI returned a challenge page. Attempting to handle it...")
103
+ if handle_meta_ai_challenge(session, challenge_url=challenge_url, cookies_dict=self.cookies):
104
+ # Retry fetching tokens after handling challenge
105
+ response = session.get("https://meta.ai", headers=headers)
106
+ else:
107
+ logging.error("Failed to handle Meta AI challenge.")
108
+ if attempt < max_retries - 1:
109
+ time.sleep(2)
110
+ continue
111
+ else:
112
+ break
113
+
114
+ # Extract tokens from HTTP response - try multiple patterns
115
+ if "lsd" not in self.cookies:
116
+ # Try JavaScript pattern first (original method)
117
+ lsd = extract_value(response.text, start_str='"LSD",[],{"token":"', end_str='"}')
118
+
119
+ # If not found, try HTML input field pattern
120
+ if not lsd:
121
+ from bs4 import BeautifulSoup
122
+ soup = BeautifulSoup(response.text, 'html.parser')
123
+ lsd_input = soup.find("input", {"name": "lsd"})
124
+ if lsd_input and lsd_input.get("value"):
125
+ lsd = lsd_input["value"] # type: ignore
126
+
127
+ if lsd:
128
+ self.cookies["lsd"] = lsd
129
+ logging.info("Successfully fetched lsd token.")
130
+ else:
131
+ logging.warning("Could not extract lsd token from response.")
132
+
133
+ if "fb_dtsg" not in self.cookies:
134
+ # Try JavaScript pattern first (original method)
135
+ fb_dtsg = extract_value(response.text, start_str='DTSGInitData",[],{"token":"', end_str='"')
136
+
137
+ # If not found, try alternative patterns
138
+ if not fb_dtsg:
139
+ fb_dtsg = extract_value(response.text, start_str='"DTSGInitialData",[],{"token":"', end_str='"')
140
+ if not fb_dtsg:
141
+ fb_dtsg = extract_value(response.text, start_str='{"token":"', end_str='","async_get_token"')
142
+
143
+ if fb_dtsg:
144
+ self.cookies["fb_dtsg"] = fb_dtsg
145
+ logging.info("Successfully fetched fb_dtsg token.")
146
+ else:
147
+ logging.warning("Could not extract fb_dtsg token from response.")
148
+ if fb_dtsg:
149
+ self.cookies["fb_dtsg"] = fb_dtsg
150
+ logging.info("Successfully fetched fb_dtsg token.")
151
+ else:
152
+ logging.warning("Could not extract fb_dtsg token from response.")
153
+
154
+ # Check if we got both tokens
155
+ if ("lsd" in self.cookies and self.cookies["lsd"]) and \
156
+ ("fb_dtsg" in self.cookies and self.cookies["fb_dtsg"]):
157
+ logging.info("Token fetch completed successfully.")
158
+ break
159
+
160
+ if attempt < max_retries - 1:
161
+ logging.warning(f"Tokens not fully fetched. Retrying in 2 seconds...")
162
+ time.sleep(2)
163
+
79
164
  except Exception as e:
80
- pass # Silent fail, features may not work without tokens
165
+ logging.error(f"Error fetching tokens: {e}")
166
+ logging.warning("Some features may not work without lsd/fb_dtsg tokens.")
167
+ logging.info("Consider manually providing 'lsd' and 'fb_dtsg' tokens in the MetaAI constructor.")
81
168
 
82
169
  def get_access_token(self) -> str:
83
170
  """
@@ -619,6 +706,7 @@ class MetaAI:
619
706
  def get_cookies(self) -> dict:
620
707
  """
621
708
  Extracts necessary cookies from the Meta AI main page.
709
+ Handles challenge pages automatically.
622
710
 
623
711
  Returns:
624
712
  dict: A dictionary containing essential cookies.
@@ -629,10 +717,25 @@ class MetaAI:
629
717
  if self.fb_email is not None and self.fb_password is not None:
630
718
  fb_session = get_fb_session(self.fb_email, self.fb_password)
631
719
  headers = {"cookie": f"abra_sess={fb_session['abra_sess']}"}
720
+
632
721
  response = session.get(
633
- "https://www.meta.ai/",
722
+ "https://meta.ai",
634
723
  headers=headers,
635
724
  )
725
+
726
+ # Check for challenge page
727
+ challenge_url = detect_challenge_page(response.text)
728
+ if challenge_url:
729
+ logging.warning("Meta AI returned a challenge page during get_cookies. Attempting to handle it...")
730
+ cookies_dict = {}
731
+ if fb_session:
732
+ cookies_dict = {"abra_sess": fb_session["abra_sess"]}
733
+ if handle_meta_ai_challenge(session, challenge_url=challenge_url, cookies_dict=cookies_dict):
734
+ # Retry after handling challenge
735
+ response = session.get("https://meta.ai", headers=headers)
736
+ else:
737
+ logging.error("Failed to handle challenge page in get_cookies.")
738
+
636
739
  cookies = {
637
740
  "_js_datr": extract_value(
638
741
  response.text, start_str='_js_datr":{"value":"', end_str='",'
metaai_api/utils.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import random
3
+ import re
3
4
  import time
4
5
  from typing import Dict, Optional
5
6
 
@@ -54,11 +55,87 @@ def extract_value(text: str, start_str: str, end_str: str) -> str:
54
55
  Returns:
55
56
  str: The extracted value.
56
57
  """
57
- start = text.find(start_str) + len(start_str)
58
+ start = text.find(start_str)
59
+ if start == -1:
60
+ return ""
61
+ start += len(start_str)
58
62
  end = text.find(end_str, start)
63
+ if end == -1:
64
+ return ""
59
65
  return text[start:end]
60
66
 
61
67
 
68
+ def detect_challenge_page(html_text: str) -> Optional[str]:
69
+ """
70
+ Detect if Meta AI returned a challenge/verification page.
71
+
72
+ Args:
73
+ html_text (str): The HTML response text.
74
+
75
+ Returns:
76
+ Optional[str]: The challenge verification URL if found, None otherwise.
77
+ """
78
+ # Check for challenge page indicators
79
+ if "executeChallenge" in html_text or "__rd_verify" in html_text:
80
+ # Extract the verification URL using regex
81
+ match = re.search(r"fetch\('(/__rd_verify[^']+)'", html_text)
82
+ if match:
83
+ return match.group(1)
84
+ return None
85
+
86
+
87
+ def handle_meta_ai_challenge(session: requests.Session, base_url: str = "https://meta.ai",
88
+ challenge_url: Optional[str] = None, cookies_dict: Optional[dict] = None,
89
+ max_retries: int = 3) -> bool:
90
+ """
91
+ Handle Meta AI challenge page by making the verification POST request.
92
+
93
+ Args:
94
+ session (requests.Session): The requests session to use.
95
+ base_url (str): The base URL for Meta AI.
96
+ challenge_url (Optional[str]): The challenge verification URL.
97
+ cookies_dict (Optional[dict]): Cookies to include in the request.
98
+ max_retries (int): Maximum number of retry attempts.
99
+
100
+ Returns:
101
+ bool: True if challenge was handled successfully, False otherwise.
102
+ """
103
+ if not challenge_url:
104
+ return False
105
+
106
+ full_url = f"{base_url}{challenge_url}"
107
+ headers = {
108
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
109
+ "Accept": "*/*",
110
+ "Accept-Language": "en-US,en;q=0.9",
111
+ "Referer": base_url,
112
+ "Origin": base_url,
113
+ }
114
+
115
+ if cookies_dict:
116
+ cookies_str = "; ".join([f"{k}={v}" for k, v in cookies_dict.items() if v])
117
+ headers["Cookie"] = cookies_str
118
+
119
+ try:
120
+ for attempt in range(max_retries):
121
+ logging.info(f"Handling Meta AI challenge (attempt {attempt + 1}/{max_retries})...")
122
+ response = session.post(full_url, headers=headers, timeout=10)
123
+
124
+ if response.status_code == 200:
125
+ logging.info("Challenge handled successfully.")
126
+ # Wait a moment for the challenge to process
127
+ time.sleep(2)
128
+ return True
129
+
130
+ time.sleep(1)
131
+
132
+ logging.warning(f"Failed to handle challenge after {max_retries} attempts.")
133
+ return False
134
+ except Exception as e:
135
+ logging.error(f"Error handling Meta AI challenge: {e}")
136
+ return False
137
+
138
+
62
139
  def format_response(response: dict) -> str:
63
140
  """
64
141
  Formats the response from Meta AI to remove unnecessary characters.
@@ -140,8 +217,16 @@ def get_fb_session(email, password, proxies=None):
140
217
  soup = BeautifulSoup(response.text, "html.parser")
141
218
 
142
219
  # Parse necessary parameters from the login form
143
- lsd = soup.find("input", {"name": "lsd"})["value"]
144
- jazoest = soup.find("input", {"name": "jazoest"})["value"]
220
+ lsd_input = soup.find("input", {"name": "lsd"})
221
+ jazoest_input = soup.find("input", {"name": "jazoest"})
222
+
223
+ if not lsd_input or not jazoest_input:
224
+ raise FacebookInvalidCredentialsException(
225
+ "Could not find login form parameters. Facebook may have changed their login page."
226
+ )
227
+
228
+ lsd = lsd_input["value"] # type: ignore
229
+ jazoest = jazoest_input["value"] # type: ignore
145
230
 
146
231
  # Define the URL and body for the POST request to submit the login form
147
232
  post_url = "https://www.facebook.com/login/?next"
@@ -180,7 +265,7 @@ def get_fb_session(email, password, proxies=None):
180
265
  # Send the POST request
181
266
  session = requests.session()
182
267
  jar = cookies.RequestsCookieJar()
183
- session.proxies = proxies
268
+ session.proxies = proxies # type: ignore
184
269
  session.cookies = jar
185
270
 
186
271
  result = session.post(post_url, headers=headers, data=data)
@@ -245,7 +330,7 @@ def get_fb_session(email, password, proxies=None):
245
330
  "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",
246
331
  }
247
332
  session = requests.session()
248
- session.proxies = proxies
333
+ session.proxies = proxies # type: ignore
249
334
  response = session.get(url, headers=headers, data=payload, allow_redirects=False)
250
335
 
251
336
  next_url = response.headers["Location"]
@@ -287,7 +372,7 @@ def get_cookies() -> dict:
287
372
  dict: A dictionary containing essential cookies.
288
373
  """
289
374
  session = HTMLSession()
290
- response = session.get("https://www.meta.ai/")
375
+ response = session.get("https://meta.ai")
291
376
  return {
292
377
  "_js_datr": extract_value(
293
378
  response.text, start_str='_js_datr":{"value":"', end_str='",'
@@ -74,7 +74,7 @@ class VideoGenerator:
74
74
  # Fetch Meta AI page with cookies
75
75
  session = HTMLSession()
76
76
  headers = {"cookie": cookies_str}
77
- response = session.get("https://www.meta.ai/", headers=headers)
77
+ response = session.get("https://meta.ai", headers=headers)
78
78
 
79
79
  # Extract lsd and fb_dtsg
80
80
  lsd = extract_value(response.text, start_str='"LSD",[],{"token":"', end_str='"')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaai-sdk
3
- Version: 2.3.6
3
+ Version: 3.0.1
4
4
  Summary: Feature-rich Python SDK for Meta AI - Chat, Image & Video Generation powered by Llama 3
5
5
  Author-email: Ashiq Hussain Mir <imseldrith@gmail.com>
6
6
  License-Expression: MIT
@@ -91,18 +91,18 @@ All in one SDK
91
91
 
92
92
  ### 🌟 Core Capabilities
93
93
 
94
- | Feature | Description | Status |
95
- | ---------------------------- | ------------------------------------------------ | -------- |
96
- | 💬 **Intelligent Chat** | Powered by Llama 3 with internet access | ✅ Ready |
97
- | 📤 **Image Upload** | Upload & analyze images, generate similar images | ✅ Ready |
98
- | 🎨 **Image Generation** | Create stunning AI-generated images | ✅ Ready |
99
- | 🎬 **Video Generation** | Generate videos from text or uploaded images | ✅ Ready |
100
- | 🔍 **Image Analysis** | Describe, analyze, and extract info from images | ✅ Ready |
101
- | 🌐 **Real-time Data** | Get current information via Bing integration | ✅ Ready |
102
- | 📚 **Source Citations** | Responses include verifiable sources | ✅ Ready |
103
- | 🔄 **Streaming Support** | Real-time response streaming | ✅ Ready |
104
- | 🔐 **Auto Token Management** | Automatic authentication handling | ✅ Ready |
105
- | 🌍 **Proxy Support** | Route requests through proxies | ✅ Ready |
94
+ | Feature | Description | Status |
95
+ | ------------------------------ | ------------------------------------------------ | -------- |
96
+ | 💬 **Intelligent Chat** | Powered by Llama 3 with internet access | ✅ Ready |
97
+ | 📤 **Image Upload** | Upload & analyze images, generate similar images | ✅ Ready |
98
+ | 🎨 **Image Generation** | Create stunning AI-generated images | ✅ Ready |
99
+ | 🎬 **Video Generation** | Generate videos from text or uploaded images | ✅ Ready |
100
+ | 🔍 **Image Analysis** | Describe, analyze, and extract info from images | ✅ Ready |
101
+ | 🌐 **Real-time Data** | Get current information via Bing integration | ✅ Ready |
102
+ | 📚 **Source Citations** | Responses include verifiable sources | ✅ Ready |
103
+ | 🔄 **Streaming Support** | Real-time response streaming | ✅ Ready |
104
+ | 🔐 **Flexible Authentication** | Auto-fetch or manual token provision | ✅ Ready |
105
+ | 🌍 **Proxy Support** | Route requests through proxies | ✅ Ready |
106
106
 
107
107
  ---
108
108
 
@@ -217,7 +217,57 @@ This calculation uses the compound interest formula: A = P(1 + r/n)^(nt)
217
217
 
218
218
  ---
219
219
 
220
- ## 💬 Chat Features
220
+ ## Authentication Options
221
+
222
+ The SDK supports **flexible authentication** with two modes:
223
+
224
+ ### Mode 1: Automatic Token Fetching (Recommended)
225
+
226
+ Provide basic cookies - `lsd` and `fb_dtsg` tokens are automatically fetched from Meta AI:
227
+
228
+ ```python
229
+ from metaai_api import MetaAI
230
+
231
+ # Provide basic cookies only
232
+ cookies = {
233
+ "datr": "your_datr_value",
234
+ "abra_sess": "your_abra_sess_value",
235
+ "dpr": "1.25",
236
+ "wd": "1920x1080"
237
+ }
238
+
239
+ ai = MetaAI(cookies=cookies)
240
+ # SDK automatically fetches lsd and fb_dtsg tokens!
241
+ ```
242
+
243
+ ### Mode 2: Manual Token Provision (Fallback)
244
+
245
+ Provide all tokens manually if automatic fetching fails:
246
+
247
+ ```python
248
+ from metaai_api import MetaAI
249
+
250
+ # Provide cookies + manual tokens
251
+ cookies = {
252
+ "datr": "your_datr_value",
253
+ "abra_sess": "your_abra_sess_value",
254
+ "dpr": "1.25",
255
+ "wd": "1920x1080"
256
+ }
257
+
258
+ ai = MetaAI(
259
+ cookies=cookies,
260
+ lsd="AVq1234567890", # Manual token
261
+ fb_dtsg="ABCD:EFGH:123456789" # Manual token
262
+ )
263
+ # No auto-fetch needed!
264
+ ```
265
+
266
+ > **💡 Tip:** Start with **Mode 1** (automatic). Only use **Mode 2** if you encounter token fetching issues.
267
+
268
+ ---
269
+
270
+ ## �💬 Chat Features
221
271
 
222
272
  ### Streaming Responses
223
273
 
@@ -389,6 +439,11 @@ Create AI-generated videos from text descriptions!
389
439
  4. Click any request → **Headers** → Copy **Cookie** value
390
440
  5. Extract these values: `datr`, `abra_sess`, `dpr`, `wd`
391
441
 
442
+ > **💡 Note:** The SDK supports **two authentication modes**:
443
+ >
444
+ > - **Automatic** (Recommended): Provide basic cookies, `lsd` and `fb_dtsg` tokens are auto-fetched
445
+ > - **Manual**: Optionally provide `lsd` and `fb_dtsg` tokens directly if automatic fetching fails
446
+
392
447
  ### Example 1: Generate Your First Video
393
448
 
394
449
  ```python
@@ -442,6 +497,44 @@ else:
442
497
  🆔 Conversation ID: abc123-def456-ghi789
443
498
  ```
444
499
 
500
+ ### Example 1b: Manual Token Provision (Optional)
501
+
502
+ If automatic token fetching fails or you prefer to provide tokens directly:
503
+
504
+ ```python
505
+ from metaai_api import MetaAI
506
+
507
+ # Your browser cookies + manually extracted tokens
508
+ cookies = {
509
+ "datr": "your_datr_value_here",
510
+ "abra_sess": "your_abra_sess_value_here",
511
+ "dpr": "1.25",
512
+ "wd": "1920x1080"
513
+ }
514
+
515
+ # Initialize with manual tokens (no auto-fetch needed)
516
+ ai = MetaAI(
517
+ cookies=cookies,
518
+ lsd="AVq1234567890", # Manually extracted lsd token
519
+ fb_dtsg="ABCD:EFGH:123456789" # Manually extracted fb_dtsg token
520
+ )
521
+
522
+ # Generate a video - tokens are already provided!
523
+ result = ai.generate_video("A peaceful zen garden with koi fish")
524
+
525
+ if result["success"]:
526
+ print("✅ Video generated successfully with manual tokens!")
527
+ print(f"🎬 Video URL: {result['video_urls'][0]}")
528
+ ```
529
+
530
+ **How to extract `lsd` and `fb_dtsg` tokens:**
531
+
532
+ 1. Open https://meta.ai in your browser (logged in)
533
+ 2. Press **F12** → **Console** tab
534
+ 3. Run: `document.cookie`
535
+ 4. Look for `lsd=...` and `fb_dtsg=...` values
536
+ 5. Alternatively, right-click → **View Page Source** → Search for `"LSD",[],{"token":"` and `DTSGInitData",[],{"token":"`
537
+
445
538
  ### Example 2: Generate Multiple Videos
446
539
 
447
540
  ```python
@@ -0,0 +1,13 @@
1
+ metaai_api/__init__.py,sha256=YT4Dn_m1Fm3Hh10D4Z9jtmADjQHnZSsdtwIn8IlCjN4,714
2
+ metaai_api/api_server.py,sha256=Tb5spAef-kKglEfGP96Fzruw8V0hHUKLqgrz04RDH0M,14000
3
+ metaai_api/client.py,sha256=Th46qW1l8OS8Hu5pj0aGFn4iQNz62A3sbXko-LP-SAU,5263
4
+ metaai_api/exceptions.py,sha256=MRRAppZa0OFA0QLSvC0nABgZN_Ll1dUq9JfhECTqV-Q,114
5
+ metaai_api/image_upload.py,sha256=DQ2xqKdM1I_pF1rZBsB7-QTvXLzke2_0XiIOxFhpc70,6563
6
+ metaai_api/main.py,sha256=PjK2aYjZ0FU17pot3p3n2mcyzMREqd2xnz59rsgRRGE,41918
7
+ metaai_api/utils.py,sha256=xdQzu82rQEFqB3yaT0bEEaAg67fYugr2SQth9HdEOJo,15050
8
+ metaai_api/video_generation.py,sha256=ENtyRN9nO49XBtPaAEVRdICchdVyEtnMCYLTha4kz1k,37480
9
+ metaai_sdk-3.0.1.dist-info/licenses/LICENSE,sha256=hRLLSBixyX0tRh2k0iOGoF7nx-l-vBChNffFfVOIEtc,1290
10
+ metaai_sdk-3.0.1.dist-info/METADATA,sha256=q3vaAK3OzrZnZ7g4i1o1g9lI9KxVGDTJ7lV9l4PlBJQ,31597
11
+ metaai_sdk-3.0.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
12
+ metaai_sdk-3.0.1.dist-info/top_level.txt,sha256=R6YCiIQLYFKKaqhNZXDwXbpj1u01P_YhcMCVbJiDUJs,11
13
+ metaai_sdk-3.0.1.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- metaai_api/__init__.py,sha256=YT4Dn_m1Fm3Hh10D4Z9jtmADjQHnZSsdtwIn8IlCjN4,714
2
- metaai_api/api_server.py,sha256=hb1C3rEarPOHF6W-qqENaxrZWwn8A0qUrjSVlRtNV2s,13248
3
- metaai_api/client.py,sha256=Th46qW1l8OS8Hu5pj0aGFn4iQNz62A3sbXko-LP-SAU,5263
4
- metaai_api/exceptions.py,sha256=MRRAppZa0OFA0QLSvC0nABgZN_Ll1dUq9JfhECTqV-Q,114
5
- metaai_api/image_upload.py,sha256=DQ2xqKdM1I_pF1rZBsB7-QTvXLzke2_0XiIOxFhpc70,6563
6
- metaai_api/main.py,sha256=nskRHsJknxV_wJ25nJAetDodypKtQ_Lz2gpYqtfTyi0,36743
7
- metaai_api/utils.py,sha256=qzfIO3WkRH-gSV99b8RiECnMOku8lZEY3Jka9lTLExA,11979
8
- metaai_api/video_generation.py,sha256=JWrSyx7UhHFOHNiyNds7V_hGkwPHB_SiiApe9jQfp0U,37485
9
- metaai_sdk-2.3.6.dist-info/licenses/LICENSE,sha256=hRLLSBixyX0tRh2k0iOGoF7nx-l-vBChNffFfVOIEtc,1290
10
- metaai_sdk-2.3.6.dist-info/METADATA,sha256=iBoQvNSnECGFK-T2WKIO7tJjAnAmJ98-9h-ID9dzDgU,28998
11
- metaai_sdk-2.3.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
12
- metaai_sdk-2.3.6.dist-info/top_level.txt,sha256=R6YCiIQLYFKKaqhNZXDwXbpj1u01P_YhcMCVbJiDUJs,11
13
- metaai_sdk-2.3.6.dist-info/RECORD,,