VibesAI-api 1.3.2__tar.gz → 1.4.2__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.
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/PKG-INFO +3 -3
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/README.md +2 -2
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/VibesAI_api.egg-info/PKG-INFO +3 -3
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/pyproject.toml +1 -1
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/server/__init__.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/server/app.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/tests/test_all.py +2 -2
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/vibes_api/__init__.py +1 -1
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/vibes_api/client.py +124 -57
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/LICENSE +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/VibesAI_api.egg-info/SOURCES.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/VibesAI_api.egg-info/dependency_links.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/VibesAI_api.egg-info/entry_points.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/VibesAI_api.egg-info/requires.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/VibesAI_api.egg-info/top_level.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/setup.cfg +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/vibes_api/cli.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/vibes_api/composition.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/vibes_api/ingredients.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.2}/vibes_api/models.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: VibesAI-api
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.2
|
|
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 -
|
|
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 -
|
|
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 -
|
|
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 -
|
|
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
|
+
Version: 1.4.2
|
|
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 -
|
|
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 -
|
|
558
|
+
pip install VibesAI-api
|
|
559
559
|
|
|
560
560
|
# Run tests (requires VIBES_META_SESSION env var)
|
|
561
561
|
pytest
|
|
File without changes
|
|
File without changes
|
|
@@ -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
|
|
45
|
+
def test_version_is_1_4_2(self):
|
|
46
46
|
import vibes_api
|
|
47
|
-
self.assertEqual(vibes_api.__version__, "1.
|
|
47
|
+
self.assertEqual(vibes_api.__version__, "1.4.2")
|
|
48
48
|
|
|
49
49
|
def test_no_syntax_errors(self):
|
|
50
50
|
import vibes_api.client
|
|
@@ -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")
|
|
@@ -258,19 +264,22 @@ class VibesClient:
|
|
|
258
264
|
|
|
259
265
|
Returns True if the session was successfully restored.
|
|
260
266
|
"""
|
|
267
|
+
# Don't retry re-login if we're already in the middle of one
|
|
268
|
+
if self._session_expired:
|
|
269
|
+
return False
|
|
270
|
+
|
|
261
271
|
self._session_expired = True
|
|
262
272
|
|
|
263
|
-
# Call the session expired callback
|
|
264
273
|
if self.on_session_expired:
|
|
265
274
|
try:
|
|
266
275
|
self.on_session_expired(self._current_meta_session)
|
|
267
276
|
except Exception:
|
|
268
277
|
pass
|
|
269
278
|
|
|
270
|
-
|
|
271
|
-
if self.auto_relogin:
|
|
279
|
+
if self.auto_relogin and self.auth_meta_cookies:
|
|
272
280
|
new_cookie = self._attempt_oidc_relogin()
|
|
273
281
|
if new_cookie:
|
|
282
|
+
# _set_cookie resets _session_expired to False
|
|
274
283
|
self._set_cookie(new_cookie)
|
|
275
284
|
if self.on_cookie_refresh:
|
|
276
285
|
try:
|
|
@@ -279,60 +288,117 @@ class VibesClient:
|
|
|
279
288
|
pass
|
|
280
289
|
return True
|
|
281
290
|
|
|
291
|
+
# Reset the flag so future 401s can attempt re-login again
|
|
292
|
+
self._session_expired = False
|
|
282
293
|
return False
|
|
283
294
|
|
|
284
295
|
def _attempt_oidc_relogin(self) -> Optional[str]:
|
|
285
|
-
"""Attempt to re-login via the OIDC flow using
|
|
296
|
+
"""Attempt to re-login via the OIDC flow using auth.meta.com cookies.
|
|
286
297
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
(from facebook.com/meta.com cookies), the flow completes
|
|
290
|
-
automatically and a new ``meta_session`` cookie is set.
|
|
298
|
+
Follows the full OIDC redirect chain using requests.get() (not Session)
|
|
299
|
+
to avoid cookie/header interference between steps.
|
|
291
300
|
|
|
292
|
-
Returns the new cookie value, or None if re-login failed.
|
|
301
|
+
Returns the new meta_session cookie value, or None if re-login failed.
|
|
293
302
|
"""
|
|
294
|
-
|
|
303
|
+
if not self.auth_meta_cookies:
|
|
304
|
+
return None
|
|
295
305
|
|
|
296
|
-
|
|
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
|
|
306
|
+
ua = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
|
|
305
307
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
308
|
+
for attempt in range(3):
|
|
309
|
+
try:
|
|
310
|
+
# Step 1: Start OIDC flow at vibes.ai
|
|
311
|
+
r1 = requests.get(
|
|
312
|
+
f"{self.base_url}/api/meta-oidc/start",
|
|
313
|
+
headers={"User-Agent": ua, "Cookie": "cookie_ack=true"},
|
|
314
|
+
allow_redirects=False, timeout=15,
|
|
315
|
+
)
|
|
316
|
+
if r1.status_code not in (302, 307):
|
|
317
|
+
if attempt < 2:
|
|
318
|
+
time.sleep(5)
|
|
319
|
+
continue
|
|
320
|
+
return None
|
|
321
|
+
redirect_url = r1.headers.get("Location", "")
|
|
322
|
+
if not redirect_url:
|
|
323
|
+
return None
|
|
324
|
+
|
|
325
|
+
# Extract oauth_csrf_token from Set-Cookie
|
|
326
|
+
csrf_token = None
|
|
327
|
+
for part in r1.headers.get("Set-Cookie", "").split(";"):
|
|
328
|
+
if part.strip().startswith("oauth_csrf_token="):
|
|
329
|
+
csrf_token = part.strip()[len("oauth_csrf_token="):]
|
|
330
|
+
break
|
|
331
|
+
|
|
332
|
+
# Step 2: auth.meta.com (with auth.meta.com cookies only)
|
|
333
|
+
r2 = requests.get(
|
|
334
|
+
redirect_url,
|
|
335
|
+
headers={"User-Agent": ua, "Cookie": self.auth_meta_cookies},
|
|
336
|
+
allow_redirects=False, timeout=15,
|
|
337
|
+
)
|
|
338
|
+
if r2.status_code not in (302, 307):
|
|
339
|
+
# 400 = auth.meta.com rate limited or cookies expired
|
|
340
|
+
# Don't retry — makes rate limiting worse
|
|
341
|
+
return None
|
|
342
|
+
redirect2 = r2.headers.get("Location", "")
|
|
343
|
+
if not redirect2 or "code=" not in redirect2:
|
|
344
|
+
return None
|
|
345
|
+
|
|
346
|
+
# Step 3: auth.meta.ai/ecto (code exchange)
|
|
347
|
+
r3 = requests.get(
|
|
348
|
+
redirect2,
|
|
349
|
+
headers={"User-Agent": ua},
|
|
350
|
+
allow_redirects=False, timeout=15,
|
|
351
|
+
)
|
|
352
|
+
if r3.status_code not in (302, 307):
|
|
353
|
+
return None
|
|
354
|
+
redirect3 = r3.headers.get("Location", "")
|
|
355
|
+
if not redirect3 or "vibes.ai" not in redirect3:
|
|
356
|
+
return None
|
|
357
|
+
|
|
358
|
+
# Step 4: vibes.ai callback (CSRF token only, no old session)
|
|
359
|
+
callback_cookie = "cookie_ack=true"
|
|
360
|
+
if csrf_token:
|
|
361
|
+
callback_cookie += f";oauth_csrf_token={csrf_token}"
|
|
362
|
+
r4 = requests.get(
|
|
363
|
+
redirect3,
|
|
364
|
+
headers={"User-Agent": ua, "Cookie": callback_cookie},
|
|
365
|
+
allow_redirects=False, timeout=15,
|
|
366
|
+
)
|
|
309
367
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
368
|
+
# Check Set-Cookie for new meta_session
|
|
369
|
+
set_cookie = r4.headers.get("Set-Cookie", "").replace(",", ";")
|
|
370
|
+
for part in set_cookie.split(";"):
|
|
371
|
+
part = part.strip()
|
|
372
|
+
if part.startswith("meta_session="):
|
|
373
|
+
val = part[len("meta_session="):]
|
|
374
|
+
if val and val != "deleted" and val != self._current_meta_session:
|
|
375
|
+
return val
|
|
376
|
+
|
|
377
|
+
# Step 5: Follow final redirect if no cookie in step 4
|
|
378
|
+
final_redirect = r4.headers.get("Location", "")
|
|
379
|
+
if final_redirect and "error=" not in final_redirect:
|
|
380
|
+
if not final_redirect.startswith("http"):
|
|
381
|
+
final_redirect = f"{self.base_url}{final_redirect}"
|
|
382
|
+
r5 = requests.get(
|
|
383
|
+
final_redirect,
|
|
384
|
+
headers={"User-Agent": ua, "Cookie": "cookie_ack=true"},
|
|
385
|
+
allow_redirects=True, timeout=15,
|
|
386
|
+
)
|
|
387
|
+
set_cookie_5 = r5.headers.get("Set-Cookie", "").replace(",", ";")
|
|
388
|
+
for part in set_cookie_5.split(";"):
|
|
389
|
+
part = part.strip()
|
|
390
|
+
if part.startswith("meta_session="):
|
|
391
|
+
val = part[len("meta_session="):]
|
|
392
|
+
if val and val != "deleted" and val != self._current_meta_session:
|
|
393
|
+
return val
|
|
316
394
|
|
|
317
|
-
# Check if we're back on vibes.ai (OIDC callback completed)
|
|
318
|
-
if "vibes.ai" not in current_url:
|
|
319
395
|
return None
|
|
320
396
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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
|
|
397
|
+
except Exception:
|
|
398
|
+
if attempt < 2:
|
|
399
|
+
time.sleep(5)
|
|
400
|
+
continue
|
|
401
|
+
pass
|
|
336
402
|
|
|
337
403
|
return None
|
|
338
404
|
|
|
@@ -449,9 +515,10 @@ class VibesClient:
|
|
|
449
515
|
except VibesAPIError as e:
|
|
450
516
|
if e.status == 401 and not self._session_expired:
|
|
451
517
|
if self._handle_401():
|
|
452
|
-
# Session was restored — retry the request
|
|
518
|
+
# Session was restored — retry the request ONCE
|
|
453
519
|
resp = self.session.get(self._url(path), params=params, timeout=self.timeout, **kw)
|
|
454
520
|
return self._check(resp)
|
|
521
|
+
# Re-login failed or not enabled — raise the original error
|
|
455
522
|
raise
|
|
456
523
|
|
|
457
524
|
def _post(self, path: str, json_body: Optional[dict] = None, **kw) -> dict:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|