mirror of
https://gitlab.com/vyla-entertainment/documentation.git
synced 2026-11-14 22:47:26 -05:00
fixed syntax issues
This commit is contained in:
@@ -1,40 +1,36 @@
|
||||
# Contributing a Source Provider
|
||||
|
||||
<p class="page-description">Complete technical guide for authoring, testing, and contributing a new video scraping resolver to the Vyla SDK.</p>
|
||||
<p class="page-description">Technical guide for authoring, testing, and contributing a new video scraping resolver to the Vyla SDK.</p>
|
||||
|
||||
## Overview
|
||||
|
||||
The Vyla SDK maintains its high reliability through a distributed collection of independent provider scrapers located in `src/sources/`. We welcome contributions of new sources that expand coverage for movies, television, and international content.
|
||||
The Vyla SDK uses independent provider scrapers located in `src/sources/`. We welcome contributions that expand coverage for movies and television series.
|
||||
|
||||
---
|
||||
|
||||
## Scraper Architecture
|
||||
## Scraper Contract
|
||||
|
||||
Every provider module is a self-contained ES Module adhering to a single exported contract:
|
||||
Every provider module is an ES Module exporting a single function:
|
||||
|
||||
```typescript
|
||||
export async function getStream(args: StreamArgs): Promise<StreamResult | { allUrls: StreamResult[] }>
|
||||
```
|
||||
|
||||
### The `args` Object
|
||||
When your scraper's `getStream()` is invoked, the SDK passes a normalized `args` context containing:
|
||||
|
||||
| Field | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `id` | `string \| number` | The TMDB numeric media ID or string IMDb ID. |
|
||||
| `s` | `number \| null` | Season number for television episodes (or `null` for movies). |
|
||||
| `e` | `number \| null` | Episode number for television episodes (or `null` for movies). |
|
||||
| `clientIP` | `string \| null` | The viewer's client IP address (if passed from an upstream proxy). |
|
||||
| `fetch` | `Function` | Node.js fetch wrapper pre-configured with timeout controls. |
|
||||
| `imdbId` | `string \| null` | Automatically resolved IMDb ID (if TMDB API key is configured). |
|
||||
| `title` | `string \| null` | Verified media title string. |
|
||||
| `year` | `number \| null` | Media release year. |
|
||||
### Context Arguments (`args`)
|
||||
- `id` *(string | number)* — TMDB numeric ID or string IMDb ID.
|
||||
- `s` *(number | null)* — Season number for television series (or `null` for movies).
|
||||
- `e` *(number | null)* — Episode number for television series (or `null` for movies).
|
||||
- `clientIP` *(string | null)* — Client IP address forwarded for geo-token generation.
|
||||
- `fetch` *(Function)* — Pre-configured fetch wrapper with timeout controls.
|
||||
- `imdbId` *(string | null)* — Auto-resolved IMDb ID.
|
||||
- `title` *(string | null)* — Verified title string.
|
||||
- `year` *(number | null)* — Media release year.
|
||||
|
||||
---
|
||||
|
||||
## Step-by-Step Implementation Guide
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Create the Scraper Module
|
||||
### 1. Create the Scraper Module
|
||||
Create a new file in `src/sources/<source_name>.js`:
|
||||
|
||||
```javascript
|
||||
@@ -43,7 +39,7 @@ const BASE_URL = 'https://provider-domain.example.com';
|
||||
const DEFAULT_HEADERS = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
'Referer': `${BASE_URL}/`,
|
||||
'Origin': BASE_URL,
|
||||
'Origin': BASE_URL
|
||||
};
|
||||
|
||||
export async function getStream({ id, s, e, imdbId }) {
|
||||
@@ -80,9 +76,9 @@ export async function getStream({ id, s, e, imdbId }) {
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Register in `src/config.js`
|
||||
### 2. Register in `src/config.js`
|
||||
|
||||
Add your provider configuration to the `SOURCES` array in `src/config.js`:
|
||||
Add the source configuration:
|
||||
|
||||
```javascript
|
||||
{
|
||||
@@ -99,41 +95,36 @@ Add your provider configuration to the `SOURCES` array in `src/config.js`:
|
||||
}
|
||||
```
|
||||
|
||||
#### Configuration Field Guidelines:
|
||||
- `key`: Lowercase alphanumeric identifier without spaces (e.g. `vidlink`, `cinecat`).
|
||||
- `label`: Clean display title shown in UI menus.
|
||||
- `proxyParam`: Unique 2-to-4 character query flag used by the Stream API HLS proxy (must not collide with existing flags).
|
||||
- `timeout`: Maximum execution budget before aborting (typically 8,000ms–15,000ms).
|
||||
- `jitter`: Random delay ceiling (typically 300ms–500ms) to avoid server burst locks.
|
||||
**Key Fields:**
|
||||
- `key`: Lowercase identifier without spaces (e.g. `mysource`).
|
||||
- `label`: Clean display label for client UIs.
|
||||
- `proxyParam`: Unique 2-to-4 character query flag for the HLS proxy.
|
||||
- `timeout`: Maximum execution budget in ms (typically 8,000–15,000).
|
||||
- `jitter`: Random delay ceiling in ms (typically 300–500).
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Local Testing
|
||||
### 3. Local Testing
|
||||
|
||||
Run your scraper against known TMDB titles using the test runner:
|
||||
Run your scraper against known TMDB titles:
|
||||
|
||||
```bash
|
||||
# Test a known movie (The Dark Knight - TMDB 155)
|
||||
node test/index.js mysource 155
|
||||
|
||||
# Test a known TV episode (Breaking Bad S01E01 - TMDB 1396)
|
||||
node test/index.js mysource 1396 1 1
|
||||
```
|
||||
|
||||
Verify that:
|
||||
1. A valid URL is printed.
|
||||
2. The `type` is correctly identified as `'hls'` or `'mp4'`.
|
||||
1. A valid URL is returned.
|
||||
2. The format is correctly identified as `hls` or `mp4`.
|
||||
3. Required upstream headers (`Referer`, `Origin`, `User-Agent`) are included.
|
||||
4. Testing an invalid ID throws a clean error without crashing the process.
|
||||
4. An invalid ID throws a clean error without crashing.
|
||||
|
||||
---
|
||||
|
||||
## Contribution Rules & Checklist
|
||||
|
||||
Before submitting a Pull Request to the GitLab repository:
|
||||
## Contribution Checklist
|
||||
|
||||
- [ ] Code is formatted with clean ES Module syntax.
|
||||
- [ ] No hardcoded personal API keys or credentials.
|
||||
- [ ] Provider does not execute external untrusted `eval()` or un-sanitized script execution.
|
||||
- [ ] Upstream stream candidate URLs must be verified for playback.
|
||||
- [ ] Errors are thrown with informative messages (`throw new Error(...)`).
|
||||
- [ ] No untrusted `eval()` or un-sanitized script execution.
|
||||
- [ ] Upstream stream candidate URLs are verified for playback.
|
||||
- [ ] Descriptive errors are thrown with `throw new Error(...)`.
|
||||
|
||||
@@ -2,50 +2,32 @@
|
||||
|
||||
<p class="page-description">The official Node.js scraping and resolver library for movies, television series, subtitles, downloads, and manga.</p>
|
||||
|
||||
<img class="vyla-banner" src="/src/assets/images/devices.webp" alt="Vyla SDK developer tools and multi-platform support" loading="lazy" decoding="async" fetchpriority="low" />
|
||||
<img class="vyla-banner" src="/src/assets/images/devices.webp" alt="Vyla SDK developer tools" loading="lazy" decoding="async" fetchpriority="low" />
|
||||
|
||||
## Overview
|
||||
|
||||
`@vyla-entertainment/sdk` is the core media resolver engine powering the entire Vyla ecosystem. Available as a pure ES Module for Node.js environments, the SDK aggregates over 60 streaming providers, extracts multi-language subtitle tracks, discovers direct download packages, and interfaces with manga archives.
|
||||
|
||||
Whether you are building a custom backend API, an automated scraper pipeline, a command-line tool, or an embeddable player backend, the SDK provides a clean, typed JavaScript and TypeScript interface.
|
||||
`@vyla-entertainment/sdk` is the core media resolver engine for Vyla. It runs in Node.js (ES Modules) to query 60+ streaming scrapers, extract subtitles, find media downloads, and browse manga archives.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
Install the package via npm, pnpm, or yarn:
|
||||
|
||||
```bash
|
||||
npm install @vyla-entertainment/sdk
|
||||
```
|
||||
|
||||
### System Requirements
|
||||
- **Node.js**: v20.0.0 or higher (ESM native)
|
||||
- **TMDB API Key (Optional but Recommended)**: Required for sources that query metadata by IMDb ID or episode titles. Obtain a free key from [The Movie Database](https://www.themoviedb.org/).
|
||||
**Requirements:**
|
||||
- Node.js v20+ (ES Modules)
|
||||
- Optional: TMDB API key for title metadata
|
||||
|
||||
---
|
||||
|
||||
## SDK Capabilities
|
||||
## Capabilities
|
||||
|
||||
| Functional Engine | Primary Methods | Output Data & Features |
|
||||
| :--- | :--- | :--- |
|
||||
| **Stream Engine** | `getStream()`, `getSources()`, `probeSource()` | Direct MP4 and adaptive HLS (`.m3u8`) links, quality tags, and verified playback flags. |
|
||||
| **Subtitle Parser** | `getSubtitles()` | Multi-language WebVTT (`.vtt`) and SubRip (`.srt`) track descriptors with language labels. |
|
||||
| **Download Engine** | `getDownloads()` | Direct high-speed download links, file sizes in bytes, and container specifications (MKV/MP4). |
|
||||
| **Manga Engine** | `searchManga()`, `getManga()`, `getMangaChapter()` | Titles, covers, chapter indexes, and image page URLs bypassing TLS fingerprint protection. |
|
||||
|
||||
### 1. Video Stream Resolution
|
||||
Queries active providers for direct MP4 and adaptive HLS streaming links based on TMDB movie or TV identifiers.
|
||||
|
||||
### 2. Multi-Language Subtitles
|
||||
Extracts clean `.vtt` and `.srt` subtitle tracks from multiple open subtitle providers, categorized by language label.
|
||||
|
||||
### 3. Media Downloads
|
||||
Resolves high-speed direct media download packages (including MKV containers with file size metadata).
|
||||
|
||||
### 4. Manga Discovery & Reading
|
||||
Features a dedicated manga scraping module leveraging `node-tls-client` with Chrome 131 TLS fingerprinting to search manga, view chapters, and retrieve high-resolution page assets.
|
||||
- **Streaming**: Resolve direct MP4 and adaptive HLS (`.m3u8`) links with `getStream()`, `getSources()`, and `probeSource()`.
|
||||
- **Subtitles**: Fetch `.vtt` and `.srt` subtitle tracks with `getSubtitles()`.
|
||||
- **Downloads**: Find direct video files with file size metadata using `getDownloads()`.
|
||||
- **Manga**: Search titles, list chapters, and fetch page images with `searchManga()` and `getMangaChapter()`.
|
||||
|
||||
---
|
||||
|
||||
@@ -59,25 +41,24 @@ const sdk = new VylaSDK({
|
||||
});
|
||||
|
||||
const sources = sdk.getSources(true);
|
||||
console.log(`Active providers: ${sources.length}`);
|
||||
console.log(`Active sources: ${sources.length}`);
|
||||
|
||||
try {
|
||||
const stream = await sdk.getStream('vidlink', 155);
|
||||
console.log('Stream resolved:', stream.url);
|
||||
console.log('Format:', stream.type);
|
||||
console.log(stream.url, stream.type);
|
||||
} catch (err) {
|
||||
console.error('Resolution error:', err.message);
|
||||
console.error(err.message);
|
||||
}
|
||||
|
||||
const subtitles = await sdk.getSubtitles(155);
|
||||
console.log(`Found ${subtitles.length} subtitle tracks`);
|
||||
console.log(`Subtitles found: ${subtitles.length}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SDK Navigation
|
||||
## Documentation Sections
|
||||
|
||||
- **[SDK Quickstart](/sdk/vyla-sdk/quickstart)**: Practical, step-by-step tutorial for resolving movies, TV episodes, and handling errors.
|
||||
- **[Complete API Reference](/sdk/vyla-sdk/reference)**: Exhaustive documentation of all classes, methods, parameters, and TypeScript types.
|
||||
- **[Manga Module Guide](/sdk/vyla-sdk/manga)**: Guide for manga search, chapter page extraction, and aspect-ratio rendering.
|
||||
- **[Contributing a Source](/sdk/vyla-sdk/contributing)**: How to author, test, and contribute a new provider scraper.
|
||||
- **[Quickstart](/sdk/vyla-sdk/quickstart)** — Step-by-step tutorial for movies, TV episodes, and error handling.
|
||||
- **[API Reference](/sdk/vyla-sdk/reference)** — Complete methods, arguments, return shapes, and TypeScript types.
|
||||
- **[Manga Module](/sdk/vyla-sdk/manga)** — Manga search, chapter indexes, and page loading.
|
||||
- **[Contributing Scrapers](/sdk/vyla-sdk/contributing)** — How to write and test new source scrapers.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Vyla SDK API Reference
|
||||
|
||||
<p class="page-description">Complete technical reference for the `@vyla-entertainment/sdk` package: classes, methods, parameters, interfaces, and TypeScript definitions.</p>
|
||||
<p class="page-description">Technical reference for `@vyla-entertainment/sdk`: classes, methods, parameters, and TypeScript definitions.</p>
|
||||
|
||||
## Class: `VylaSDK`
|
||||
|
||||
The primary entry point of the package. Instantiated to manage scraper execution, health probing, subtitle retrieval, downloads, and manga discovery.
|
||||
The primary entry point for media scraping, subtitle retrieval, downloads, and manga discovery.
|
||||
|
||||
```typescript
|
||||
import VylaSDK from '@vyla-entertainment/sdk';
|
||||
@@ -18,15 +18,10 @@ import VylaSDK from '@vyla-entertainment/sdk';
|
||||
constructor(options?: VylaSDKOptions)
|
||||
```
|
||||
|
||||
Creates a new instance of `VylaSDK`.
|
||||
**Parameters:**
|
||||
- `options.tmdbApiKey` *(string, optional)* — TMDB v3 API Key for metadata lookups.
|
||||
- `options.penguManifest` *(any, optional)* — Custom manifest for the Pengu provider source.
|
||||
|
||||
#### Parameters
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `options.tmdbApiKey` | `string` | Optional | `null` | Your TMDB v3 API Key. Highly recommended; required by sources that query metadata by IMDb ID or episode name. |
|
||||
| `options.penguManifest` | `any` | Optional | `null` | Custom manifest definition for the Pengu provider source. |
|
||||
|
||||
#### Example
|
||||
```javascript
|
||||
const sdk = new VylaSDK({
|
||||
tmdbApiKey: '9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d'
|
||||
@@ -41,20 +36,16 @@ const sdk = new VylaSDK({
|
||||
getSources(excludeDisabled?: boolean): SourceConfig[]
|
||||
```
|
||||
|
||||
Returns the registered list of provider scraper configurations.
|
||||
Returns registered provider scraper configurations.
|
||||
|
||||
#### Parameters
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `excludeDisabled` | `boolean` | Optional | `false` | When `true`, filters out providers marked with `disabled: true`. |
|
||||
**Parameters:**
|
||||
- `excludeDisabled` *(boolean, optional)* — When `true`, filters out scrapers with `disabled: true`. Default: `false`.
|
||||
|
||||
#### Returns
|
||||
Array of [`SourceConfig`](#interface-sourceconfig) objects.
|
||||
**Returns:** Array of [`SourceConfig`](#interface-sourceconfig) objects.
|
||||
|
||||
#### Example
|
||||
```javascript
|
||||
const activeSources = sdk.getSources(true);
|
||||
console.log(`Available active providers: ${activeSources.map(s => s.key).join(', ')}`);
|
||||
console.log(activeSources.map(s => s.key).join(', '));
|
||||
```
|
||||
|
||||
---
|
||||
@@ -71,29 +62,19 @@ async getStream(
|
||||
): Promise<StreamResult | { allUrls: StreamResult[] }>
|
||||
```
|
||||
|
||||
Executes the scraper module for a specified provider and resolves streaming candidate URLs.
|
||||
Executes a provider scraper module to resolve candidate stream URLs.
|
||||
|
||||
#### Parameters
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `key` | `string` | Required | — | The source key identifier (e.g. `'vidlink'`, `'vixsrc'`). |
|
||||
| `id` | `string \| number` | Required | — | Numeric TMDB ID or string IMDb ID (for movies and TV shows). |
|
||||
| `s` | `number \| null` | Optional | `null` | Season number (required for TV episodes). |
|
||||
| `e` | `number \| null` | Optional | `null` | Episode number (required for TV episodes). |
|
||||
| `clientIP` | `string \| null` | Optional | `null` | Client IP address passed for upstream geo-token generation. |
|
||||
**Parameters:**
|
||||
- `key` *(string, required)* — Provider key (e.g. `'vidlink'`, `'vixsrc'`).
|
||||
- `id` *(string | number, required)* — TMDB ID or IMDb ID.
|
||||
- `s` *(number, optional)* — Season number (for TV series). Default: `null`.
|
||||
- `e` *(number, optional)* — Episode number (for TV series). Default: `null`.
|
||||
- `clientIP` *(string, optional)* — Client IP address passed for upstream geo-token generation. Default: `null`.
|
||||
|
||||
#### Returns
|
||||
A Promise resolving to a [`StreamResult`](#interface-streamresult) object, or `{ allUrls: StreamResult[] }` if the source supports multi-URL extraction.
|
||||
**Returns:** A Promise resolving to a [`StreamResult`](#interface-streamresult) object.
|
||||
|
||||
#### Throws
|
||||
- `Error('Source with key "..." not found')` if the key does not exist.
|
||||
- `Error('Source module for key "..." not found')` if the source module is disabled or failed to import.
|
||||
- Upstream network errors or scraper extraction errors if the title cannot be found.
|
||||
|
||||
#### Example
|
||||
```javascript
|
||||
const movieStream = await sdk.getStream('vidlink', 155);
|
||||
|
||||
const episodeStream = await sdk.getStream('vixsrc', 1396, 1, 1);
|
||||
```
|
||||
|
||||
@@ -109,17 +90,14 @@ async getSubtitles(
|
||||
): Promise<SubtitleResult[]>
|
||||
```
|
||||
|
||||
Discovers and parses all available subtitle tracks for a movie or TV episode.
|
||||
Retrieves parsed subtitle tracks for a movie or TV episode.
|
||||
|
||||
#### Parameters
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `id` | `string \| number` | Required | — | TMDB media identifier. |
|
||||
| `s` | `number \| null` | Optional | `null` | Season number (TV shows). |
|
||||
| `e` | `number \| null` | Optional | `null` | Episode number (TV shows). |
|
||||
**Parameters:**
|
||||
- `id` *(string | number, required)* — TMDB media ID.
|
||||
- `s` *(number, optional)* — Season number. Default: `null`.
|
||||
- `e` *(number, optional)* — Episode number. Default: `null`.
|
||||
|
||||
#### Returns
|
||||
A Promise resolving to an array of [`SubtitleResult`](#interface-subtitleresult) objects.
|
||||
**Returns:** Array of [`SubtitleResult`](#interface-subtitleresult) objects.
|
||||
|
||||
---
|
||||
|
||||
@@ -135,8 +113,7 @@ async getDownloads(
|
||||
|
||||
Resolves direct media download packages and torrent/debrid links.
|
||||
|
||||
#### Returns
|
||||
A Promise resolving to an array of [`DownloadResult`](#interface-downloadresult) objects.
|
||||
**Returns:** Array of [`DownloadResult`](#interface-downloadresult) objects.
|
||||
|
||||
---
|
||||
|
||||
@@ -146,15 +123,12 @@ A Promise resolving to an array of [`DownloadResult`](#interface-downloadresult)
|
||||
async probeSource(key: string): Promise<ProbeResult>
|
||||
```
|
||||
|
||||
Sends a lightweight probe request against the designated source to measure responsiveness and availability.
|
||||
Sends a probe request against a single provider to check responsiveness.
|
||||
|
||||
#### Parameters
|
||||
| Parameter | Type | Required | Description |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `key` | `string` | Required | The provider key to probe. |
|
||||
**Parameters:**
|
||||
- `key` *(string, required)* — Provider key to probe.
|
||||
|
||||
#### Returns
|
||||
A Promise resolving to a [`ProbeResult`](#interface-proberesult) object: `{ ok: boolean, ms: number | null }`.
|
||||
**Returns:** `{ ok: boolean, ms: number | null }`.
|
||||
|
||||
---
|
||||
|
||||
@@ -164,10 +138,7 @@ A Promise resolving to a [`ProbeResult`](#interface-proberesult) object: `{ ok:
|
||||
async probeAllSources(): Promise<ProbeAllResult>
|
||||
```
|
||||
|
||||
Concurrently probes all active (non-disabled) sources and compiles a live health map.
|
||||
|
||||
#### Returns
|
||||
A Promise resolving to a [`ProbeAllResult`](#type-probeallresult) dictionary mapping source keys to their probe results.
|
||||
Concurrently probes all active sources and returns a health map.
|
||||
|
||||
---
|
||||
|
||||
@@ -177,19 +148,19 @@ A Promise resolving to a [`ProbeAllResult`](#type-probeallresult) dictionary map
|
||||
```typescript
|
||||
async searchManga(query: string, page?: number, perPage?: number): Promise<any>
|
||||
```
|
||||
Queries the manga catalog via `atsu.moe` using Chrome 131 TLS fingerprinting. Returns paginated title listings.
|
||||
Queries the manga catalog via `atsu.moe` using Chrome 131 TLS fingerprinting.
|
||||
|
||||
#### `getManga(id)`
|
||||
```typescript
|
||||
async getManga(id: string): Promise<any>
|
||||
```
|
||||
Retrieves full manga details including description, genres, author, status, and chapter list.
|
||||
Retrieves full manga details, author, genres, and chapter list.
|
||||
|
||||
#### `getMangaChapter(mangaId, chapterId)`
|
||||
```typescript
|
||||
async getMangaChapter(mangaId: string, chapterId: string): Promise<any>
|
||||
```
|
||||
Resolves ordered image URLs, dimensions, and aspect ratios for all pages in a given chapter.
|
||||
Resolves ordered image URLs and dimensions for all pages in a chapter.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user