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.
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/PKG-INFO +3 -3
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/README.md +2 -2
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/VibesAI_api.egg-info/PKG-INFO +3 -3
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/pyproject.toml +1 -1
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/tests/test_all.py +2 -2
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/vibes_api/__init__.py +1 -1
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/vibes_api/client.py +122 -57
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/LICENSE +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/VibesAI_api.egg-info/SOURCES.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/VibesAI_api.egg-info/dependency_links.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/VibesAI_api.egg-info/entry_points.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/VibesAI_api.egg-info/requires.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/VibesAI_api.egg-info/top_level.txt +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/server/__init__.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/server/app.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/setup.cfg +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/vibes_api/cli.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/vibes_api/composition.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/vibes_api/ingredients.py +0 -0
- {vibesai_api-1.3.2 → vibesai_api-1.4.0}/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.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 -
|
|
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.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 -
|
|
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
|
|
@@ -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_0(self):
|
|
46
46
|
import vibes_api
|
|
47
|
-
self.assertEqual(vibes_api.__version__, "1.
|
|
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
|
|
@@ -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
|
|
289
|
+
"""Attempt to re-login via the OIDC flow using auth.meta.com cookies.
|
|
286
290
|
|
|
287
|
-
This
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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
|
-
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|