VibesAI-api 1.3.2__tar.gz → 1.4.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: VibesAI-api
3
- Version: 1.3.2
3
+ Version: 1.4.0
4
4
  Summary: Unofficial Python API client for vibes.ai
5
5
  Author-email: Ashiq Hussain Mir <imsrenpsycho@gmail.com>
6
6
  License: MIT
@@ -29,7 +29,7 @@ This package was built by reverse-engineering the vibes.ai Next.js bundles and o
29
29
 
30
30
  ```bash
31
31
  # 1) Install
32
- pip install -e /home/z/my-project/download/vibes-api
32
+ pip install VibesAI-api
33
33
 
34
34
  # 2) Set your cookie (grab from DevTools → Application → Cookies → vibes.ai)
35
35
  export VIBES_META_SESSION="e60e910a-242a-...-K54E"
@@ -555,7 +555,7 @@ python /home/z/my-project/download/vibes-api/examples/01_generate_video.py
555
555
 
556
556
  ```bash
557
557
  # Install in editable mode
558
- pip install -e /home/z/my-project/download/vibes-api
558
+ pip install VibesAI-api
559
559
 
560
560
  # Run tests (requires VIBES_META_SESSION env var)
561
561
  pytest
@@ -10,7 +10,7 @@ This package was built by reverse-engineering the vibes.ai Next.js bundles and o
10
10
 
11
11
  ```bash
12
12
  # 1) Install
13
- pip install -e /home/z/my-project/download/vibes-api
13
+ pip install VibesAI-api
14
14
 
15
15
  # 2) Set your cookie (grab from DevTools → Application → Cookies → vibes.ai)
16
16
  export VIBES_META_SESSION="e60e910a-242a-...-K54E"
@@ -536,7 +536,7 @@ python /home/z/my-project/download/vibes-api/examples/01_generate_video.py
536
536
 
537
537
  ```bash
538
538
  # Install in editable mode
539
- pip install -e /home/z/my-project/download/vibes-api
539
+ pip install VibesAI-api
540
540
 
541
541
  # Run tests (requires VIBES_META_SESSION env var)
542
542
  pytest
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: VibesAI-api
3
- Version: 1.3.2
3
+ Version: 1.4.0
4
4
  Summary: Unofficial Python API client for vibes.ai
5
5
  Author-email: Ashiq Hussain Mir <imsrenpsycho@gmail.com>
6
6
  License: MIT
@@ -29,7 +29,7 @@ This package was built by reverse-engineering the vibes.ai Next.js bundles and o
29
29
 
30
30
  ```bash
31
31
  # 1) Install
32
- pip install -e /home/z/my-project/download/vibes-api
32
+ pip install VibesAI-api
33
33
 
34
34
  # 2) Set your cookie (grab from DevTools → Application → Cookies → vibes.ai)
35
35
  export VIBES_META_SESSION="e60e910a-242a-...-K54E"
@@ -555,7 +555,7 @@ python /home/z/my-project/download/vibes-api/examples/01_generate_video.py
555
555
 
556
556
  ```bash
557
557
  # Install in editable mode
558
- pip install -e /home/z/my-project/download/vibes-api
558
+ pip install VibesAI-api
559
559
 
560
560
  # Run tests (requires VIBES_META_SESSION env var)
561
561
  pytest
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "VibesAI-api"
3
- version = "1.3.2"
3
+ version = "1.4.0"
4
4
  description = "Unofficial Python API client for vibes.ai"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -42,9 +42,9 @@ class TestImports(unittest.TestCase):
42
42
  for name in vibes_api.__all__:
43
43
  self.assertTrue(hasattr(vibes_api, name), f"Missing export: {name}")
44
44
 
45
- def test_version_is_1_3_0(self):
45
+ def test_version_is_1_4_0(self):
46
46
  import vibes_api
47
- self.assertEqual(vibes_api.__version__, "1.3.0")
47
+ self.assertEqual(vibes_api.__version__, "1.4.0")
48
48
 
49
49
  def test_no_syntax_errors(self):
50
50
  import vibes_api.client
@@ -94,7 +94,7 @@ from .ingredients import (
94
94
  )
95
95
  from .composition import Composition
96
96
 
97
- __version__ = "1.3.0"
97
+ __version__ = "1.4.0"
98
98
  __all__ = [
99
99
  # Client
100
100
  "VibesClient",
@@ -182,6 +182,7 @@ class VibesClient:
182
182
  on_cookie_refresh: Optional[callable] = None,
183
183
  on_session_expired: Optional[callable] = None,
184
184
  auto_relogin: bool = False,
185
+ auth_meta_cookies: Optional[str] = None,
185
186
  ):
186
187
  self.base_url = base_url.rstrip("/")
187
188
  self.timeout = timeout
@@ -191,6 +192,7 @@ class VibesClient:
191
192
  self.on_cookie_refresh = on_cookie_refresh
192
193
  self.on_session_expired = on_session_expired
193
194
  self.auto_relogin = auto_relogin
195
+ self.auth_meta_cookies = auth_meta_cookies
194
196
  self._background_thread = None
195
197
  self._background_stop = None
196
198
  self._session_expired = False
@@ -213,11 +215,7 @@ class VibesClient:
213
215
  self._session_expired = False
214
216
 
215
217
  def update_cookie(self, meta_session: str) -> None:
216
- """Update the session cookie at runtime.
217
-
218
- Use this when the ``on_session_expired`` callback fires and
219
- you've obtained a fresh cookie (e.g., from the browser).
220
- """
218
+ """Update the session cookie at runtime."""
221
219
  self._set_cookie(meta_session)
222
220
  if self.on_cookie_refresh:
223
221
  try:
@@ -225,16 +223,24 @@ class VibesClient:
225
223
  except Exception:
226
224
  pass
227
225
 
226
+ def set_auth_meta_cookies(self, cookies: str) -> None:
227
+ """Set the auth.meta.com cookies for automatic re-login.
228
+
229
+ Parameters
230
+ ----------
231
+ cookies : str
232
+ Cookie string from auth.meta.com (e.g.,
233
+ ``"ps_n=1;datr=...;fs=...;locale=en_GB;ps_l=1"``).
234
+ Get these from DevTools → Application → Cookies → auth.meta.com.
235
+ """
236
+ self.auth_meta_cookies = cookies
237
+ self.auto_relogin = True # Enable auto re-login
238
+
228
239
  def get_current_cookie(self) -> str:
229
240
  return self._current_meta_session
230
241
 
231
242
  def _maybe_refresh_cookie(self, resp: requests.Response) -> None:
232
- """Intercept Set-Cookie headers and update the session cookie.
233
-
234
- Note: vibes.ai does NOT send Set-Cookie on regular API responses.
235
- This is kept for completeness — if the server ever adds sliding
236
- session behavior, this will automatically pick it up.
237
- """
243
+ """Intercept Set-Cookie headers and update the session cookie."""
238
244
  if not self.auto_refresh:
239
245
  return
240
246
  set_cookie = resp.headers.get("Set-Cookie") or resp.headers.get("set-cookie")
@@ -260,14 +266,12 @@ class VibesClient:
260
266
  """
261
267
  self._session_expired = True
262
268
 
263
- # Call the session expired callback
264
269
  if self.on_session_expired:
265
270
  try:
266
271
  self.on_session_expired(self._current_meta_session)
267
272
  except Exception:
268
273
  pass
269
274
 
270
- # Attempt auto re-login via headless browser
271
275
  if self.auto_relogin:
272
276
  new_cookie = self._attempt_oidc_relogin()
273
277
  if new_cookie:
@@ -282,57 +286,118 @@ class VibesClient:
282
286
  return False
283
287
 
284
288
  def _attempt_oidc_relogin(self) -> Optional[str]:
285
- """Attempt to re-login via the OIDC flow using a headless browser.
289
+ """Attempt to re-login via the OIDC flow using auth.meta.com cookies.
286
290
 
287
- This navigates to ``/api/meta-oidc/start`` which redirects to
288
- Meta's OIDC login. If the browser has an active Meta session
289
- (from facebook.com/meta.com cookies), the flow completes
290
- automatically and a new ``meta_session`` cookie is set.
291
-
292
- Returns the new cookie value, or None if re-login failed.
293
- """
294
- import subprocess, json as _json
291
+ This follows the full OIDC redirect chain:
292
+ 1. vibes.ai/api/meta-oidc/start gets oauth_csrf_token cookie
293
+ 2. auth.meta.com/oidc gets authorization code (using auth cookies)
294
+ 3. auth.meta.ai/ecto exchanges code for vibes.ai callback URL
295
+ 4. vibes.ai/api/meta-oidc/callback → creates new session
295
296
 
296
- try:
297
- # Use agent-browser CLI to navigate to the OIDC start URL
298
- # The browser must have Meta cookies for this to work
299
- result = subprocess.run(
300
- ["agent-browser", "open", f"{self.base_url}/api/meta-oidc/start"],
301
- capture_output=True, text=True, timeout=30,
302
- )
303
- if result.returncode != 0:
304
- return None
297
+ Requires ``auth_meta_cookies`` to be set (auth.meta.com cookies).
305
298
 
306
- # Wait for redirects to complete
307
- import time as _time
308
- _time.sleep(3)
299
+ Returns the new meta_session cookie value, or None if re-login failed.
300
+ """
301
+ if not self.auth_meta_cookies:
302
+ return None
309
303
 
310
- # Get the current URL (should be back on vibes.ai)
311
- result = subprocess.run(
312
- ["agent-browser", "get", "url"],
313
- capture_output=True, text=True, timeout=10,
314
- )
315
- current_url = result.stdout.strip()
304
+ for attempt in range(3):
305
+ try:
306
+ # Step 1: Start OIDC flow at vibes.ai (get CSRF token + redirect URL)
307
+ s1 = requests.Session()
308
+ s1.headers.update({
309
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
310
+ "Cookie": f"meta_session={self._current_meta_session};cookie_ack=true",
311
+ })
312
+ r1 = s1.get(f"{self.base_url}/api/meta-oidc/start", allow_redirects=False, timeout=15)
313
+ if r1.status_code not in (302, 307):
314
+ if attempt < 2:
315
+ time.sleep(5)
316
+ continue
317
+ return None
318
+ redirect_url = r1.headers.get("Location", "")
319
+ if not redirect_url:
320
+ return None
321
+
322
+ # Extract oauth_csrf_token from Set-Cookie
323
+ csrf_token = None
324
+ set_cookie = r1.headers.get("Set-Cookie", "")
325
+ for part in set_cookie.split(";"):
326
+ part = part.strip()
327
+ if part.startswith("oauth_csrf_token="):
328
+ csrf_token = part[len("oauth_csrf_token="):]
329
+ break
330
+
331
+ # Step 2: auth.meta.com — use ONLY auth.meta.com cookies (no vibes.ai cookies)
332
+ s2 = requests.Session()
333
+ s2.headers.update({
334
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
335
+ "Cookie": self.auth_meta_cookies,
336
+ })
337
+ r2 = s2.get(redirect_url, allow_redirects=False, timeout=15)
338
+ if r2.status_code not in (302, 307):
339
+ if attempt < 2:
340
+ time.sleep(5)
341
+ continue
342
+ return None
343
+ redirect2 = r2.headers.get("Location", "")
344
+ if not redirect2 or "code=" not in redirect2:
345
+ return None
346
+
347
+ # Step 3: auth.meta.ai/ecto (code exchange) — no cookies needed
348
+ s3 = requests.Session()
349
+ s3.headers.update({
350
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
351
+ })
352
+ r3 = s3.get(redirect2, allow_redirects=False, timeout=15)
353
+ if r3.status_code not in (302, 307):
354
+ return None
355
+ redirect3 = r3.headers.get("Location", "")
356
+ if not redirect3 or "vibes.ai" not in redirect3:
357
+ return None
358
+
359
+ # Step 4: vibes.ai callback — need vibes.ai cookies + CSRF token
360
+ s4 = requests.Session()
361
+ s4.headers.update({
362
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
363
+ })
364
+ callback_cookie = f"meta_session={self._current_meta_session};cookie_ack=true"
365
+ if csrf_token:
366
+ callback_cookie += f";oauth_csrf_token={csrf_token}"
367
+ s4.headers.update({"Cookie": callback_cookie})
368
+ r4 = s4.get(redirect3, allow_redirects=False, timeout=15)
369
+
370
+ # Step 5: Follow final redirect
371
+ r5 = None
372
+ final_redirect = r4.headers.get("Location", "")
373
+ if final_redirect and "error=" not in final_redirect:
374
+ if not final_redirect.startswith("http"):
375
+ final_redirect = f"{self.base_url}{final_redirect}"
376
+ s4.headers.update({"Cookie": f"meta_session={self._current_meta_session};cookie_ack=true"})
377
+ r5 = s4.get(final_redirect, allow_redirects=True, timeout=15)
378
+
379
+ # Check for new meta_session in Set-Cookie headers from step 4 and 5
380
+ responses = [r4]
381
+ if r5 is not None:
382
+ responses.append(r5)
383
+ for resp in responses:
384
+ set_cookie = resp.headers.get("Set-Cookie", "")
385
+ # Multiple cookies are separated by comma — replace with semicolon for parsing
386
+ set_cookie = set_cookie.replace(",", ";")
387
+ for part in set_cookie.split(";"):
388
+ part = part.strip()
389
+ if part.startswith("meta_session="):
390
+ val = part[len("meta_session="):]
391
+ if val and val != "deleted" and val != self._current_meta_session:
392
+ return val
316
393
 
317
- # Check if we're back on vibes.ai (OIDC callback completed)
318
- if "vibes.ai" not in current_url:
319
394
  return None
320
395
 
321
- # Extract the new meta_session cookie
322
- result = subprocess.run(
323
- ["agent-browser", "cookies"],
324
- capture_output=True, text=True, timeout=10,
325
- )
326
- cookies_text = result.stdout.strip()
327
- for line in cookies_text.split("\n"):
328
- line = line.strip()
329
- if line.startswith("meta_session="):
330
- new_cookie = line[len("meta_session="):]
331
- if new_cookie and new_cookie != "deleted":
332
- return new_cookie
333
-
334
- except (subprocess.TimeoutExpired, FileNotFoundError, Exception):
335
- pass
396
+ except Exception:
397
+ if attempt < 2:
398
+ time.sleep(5)
399
+ continue
400
+ pass
336
401
 
337
402
  return None
338
403
 
File without changes
File without changes
File without changes