> For the complete documentation index, see [llms.txt](https://soradocs.gitbook.io/sora-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://soradocs.gitbook.io/sora-documentation/streamasync-javascript-mode.md).

# StreamAsync Javascript mode

{% hint style="info" %}
For more examples, head over to [my repo](https://github.com/50n50/sources)
{% endhint %}

In the streamAsyncJS mode you extract the stream URL asynchronously instead of regular scraping. The function will still be provided with an HTML code.&#x20;

**Functions:**&#x20;

{% tabs %}
{% tab title="searchResults" %}
Extracts the search results from the provided HTML.

| Input | Output |
| ----- | ------ |
| HTML  | JSON   |

{% code title="Output JSON format" lineNumbers="true" %}

```json
{
   "title": "Example Title",
   "image": "https://example.com/image.jpg",
   "href": "https://grani.me/example"
}
```

{% endcode %}
{% endtab %}

{% tab title="extractDetails" %}
Extracts the details from the provided HTML.

| Input | Output |
| ----- | ------ |
| HTML  | JSON   |

{% code title="Output JSON format" lineNumbers="true" %}

```json
{
   "description": "An exciting anime series about adventures.",
   "aliases": "Alternate Name",
   "airdate": "2022"
}
```

{% endcode %}
{% endtab %}

{% tab title="extractEpisodes" %}
Extracts the episodes from the provided HTML.

| Input | Output |
| ----- | ------ |
| HTML  | JSON   |

{% code title="Output JSON format" lineNumbers="true" %}

```json
{
   "href": "https://grani.me/episode/123",
   "number": "1"
}
```

{% endcode %}
{% endtab %}

{% tab title="extractStreamUrl" %}
Extracts the stream from the provided URL.

| Input | Output |
| ----- | ------ |
| HTML  | URL    |

{% code title="Output format" lineNumbers="true" %}

```url
https://example.com/stream/video.mp4
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Example:**

{% code lineNumbers="true" %}

```javascript
function searchResults(html) {
    const results = [];


    const titleRegex = /<h2[^>]*>(.*?)<\/h2>/;
    const hrefRegex = /<a\s+href="([^"]+)"\s*[^>]*>/;
    const imgRegex = /<img[^>]*src="([^"]+)"[^>]*>/;

    const itemRegex = /<div class="my-2 w-64[^"]*"[^>]*>[\s\S]*?<\/div>\s*<\/div>\s*<\/div>/g;
    const items = html.match(itemRegex) || [];

    items.forEach((itemHtml) => {
        const titleMatch = itemHtml.match(titleRegex);
        const title = titleMatch ? titleMatch[1].trim() : '';

        const hrefMatch = itemHtml.match(hrefRegex);
        const href = hrefMatch ? hrefMatch[1].trim() : '';

        const imgMatch = itemHtml.match(imgRegex);
        const imageUrl = imgMatch ? imgMatch[1].trim() : '';

        if (title && href) {
            results.push({
                title: title,
                image: imageUrl,
                href: href
            });
        }
    });
    return results;
}

function extractDetails(html) {
    const details = [];

    const descriptionMatch = html.match(/<p class="sm:text-\[1\.05rem\] leading-loose text-justify">([\s\S]*?)<\/p>/);
    let description = descriptionMatch ? descriptionMatch[1].trim() : '';

    const airdateMatch = html.match(/<td[^>]*title="([^"]+)">[^<]+<\/td>/);
    let airdate = airdateMatch ? airdateMatch[1].trim() : '';

    if (description && airdate) {
        details.push({
            description: description,
            aliases: 'N/A',
            airdate: airdate
        });
    }
    console.log(details);
    return details;
}

function extractEpisodes(html) {
    const episodes = [];
    const htmlRegex = /<a\s+[^>]*href="([^"]*?\/episode\/[^"]*?)"[^>]*>[\s\S]*?الحلقة\s+(\d+)[\s\S]*?<\/a>/gi;
    const plainTextRegex = /الحلقة\s+(\d+)/g;

    let matches;

    if ((matches = html.match(htmlRegex))) {
        matches.forEach(link => {
            const hrefMatch = link.match(/href="([^"]+)"/);
            const numberMatch = link.match(/الحلقة\s+(\d+)/);
            if (hrefMatch && numberMatch) {
                const href = hrefMatch[1];
                const number = numberMatch[1];
                episodes.push({
                    href: href,
                    number: number
                });
            }
        });
    } else if ((matches = html.match(plainTextRegex))) {
        matches.forEach(match => {
            const numberMatch = match.match(/\d+/);
            if (numberMatch) {
                episodes.push({
                    href: null,
                    number: numberMatch[0]
                });
            }
        });
    }

    console.log(episodes);
    return episodes;
}

async function extractStreamUrl(html) {
    try {
        const sourceMatch = html.match(/data-source="([^"]+)"/);
        const embedUrl = sourceMatch?.[1]?.replace(/&amp;/g, '&');
        if (!embedUrl) return null;

        const response = await fetch(embedUrl);
        const data = await response;
        const videoUrl = data.match(/src:\s*'(https:\/\/[^']+\.mp4[^']*)'/)?.[1];
        console.log(videoUrl);
        return videoUrl || null;
    } catch (error) {
        return null;
    }
}
```

{% endcode %}
