Skip to content

Commit

Permalink
Export utilities APIs to public and minor fixes (#32)
Browse files Browse the repository at this point in the history
These updates enhance the flexibility and reliability of the ytmp3 mod
ule by introducing new utility APIs and refining existing components.
The improved YouTube URL validation regex and corrected export stateme
nts ensure a smoother experience for developers integrating YouTube fu
nctionalities into their projects.

* df963ae - fix(error): Fix exports statement in `error` module
* d72fc89 - refactor(url-utils): Improve the YouTube URL regex
* 06903d1 - test(url-utils): Use `IDExtratorError` class
* 75c61bd - feat(ytmp3): Add new utilities APIs

Signed-off-by: Ryuu Mitsuki <[email protected]>
  • Loading branch information
mitsuki31 committed Aug 22, 2024
2 parents cc4d0e7 + 8b3e64e commit f6c0068
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 10 deletions.
90 changes: 87 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ A promise that resolves to an array of strings representing the successfully dow
### `getVideosInfo`
```ts
async function getVideosInfo(...urls: ...(string | URL)): Promise<import('@distube/ytdl-core').videoInfo[]>
async function getVideosInfo(
...urls: string | URL
): Promise<import('@distube/ytdl-core').videoInfo[]>
```
<details>
Expand All @@ -201,7 +203,7 @@ This function accepts multiple YouTube URLs and retrieves information for each v
| Name | Type | Description |
| ---- | ---- | ----------- |
| `urls` | `...(string \| URL)` | The YouTube video URLs to fetch information for. Each URL can be either a string or a URL object. |
| `...urls` | `string \| URL` | The YouTube video URLs to fetch information for. Each URL can be either a string or a URL object. |
#### Returns
Expand Down Expand Up @@ -232,7 +234,8 @@ First, it checks if the `FFMPEG_PATH` environment variable is set. If it is set,
#### Returns
A promise that resolves to a boolean value, `true` if the `ffmpeg` binary installed on system; otherwise, `false`.
A promise that resolves to a boolean value, `true` if the `ffmpeg` binary installed on system; otherwise, `false`.
**Type:** `boolean`
</details>
Expand Down Expand Up @@ -266,6 +269,87 @@ If the `ffmpeg` is not installed on the system, this function will aborts immedi
---
### `extractVideoId`
```ts
function extractVideoId(url: string | URL): string
```
<details>
<summary>API Details</summary>
Extracts the YouTube video ID from given YouTube URL.
The YouTube video ID have exactly 11 characters with allowed symbols are `A-Z`, `a-z`, `0-9`, `_`, and `-`.
Allowed YouTube domains to extract:
- `www.youtube.com`
- `m.youtube.com`
- `youtube.com`
- `youtu.be`
- `music.youtube.com`
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| `url` | `string \| URL` | The URL to evaluate. |
#### Returns
A string with 11 characters representing the video ID.
**Type:** `string`
</details>
---
### `validateUrl`
```ts
function validateUrl(url: string | URL, withId?: boolean = true): boolean
```
<details>
<summary>API Details</summary>
Validates the given YouTube URL and optionally validates its video ID.
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| `url` | `string \| URL` | The URL to validate. |
| `withId` | `boolean` | Whether to also validate the video ID within the URL. If `false`, the function will only validate the URL's domain name. Defaults to `true`. |
#### Returns
Returns `true` if the given URL is a valid YouTube URL; otherwise `false`.
**Type:** `boolean`
</details>
---
### `validateId`
```ts
function validateId(id: string): boolean
```
<details>
<summary>API Details</summary>
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| `id` | `string` | The video ID to validate. |
#### Returns
Returns `true` if the given ID correctly represents the YouTube video ID; otherwise `false`.
**Type:** `boolean`
---
### API Usage
Download audio from a single YouTube URL:
Expand Down
10 changes: 10 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const {
} = require('./lib/audioconv');
const { logger: log, dropNullAndUndefined } = require('./lib/utils');
const { importConfig } = require('./lib/config');
const URLUtils = require('./lib/url-utils');
const error = require('./lib/error');
const ytmp3 = require('./lib/ytmp3');
const pkg = require('./package.json');

Expand Down Expand Up @@ -456,10 +458,18 @@ module.exports = Object.freeze({
singleDownload: ytmp3.singleDownload,
batchDownload: ytmp3.batchDownload,
getVideosInfo: ytmp3.getVideosInfo,
// :: URLUtils
YTURLUtils: URLUtils, // aliased to `YTURLUtils` for readability
extractVideoId: URLUtils.extractVideoId,
validateUrl: URLUtils.validateUrl,
validateId: URLUtils.validateId,
// :: audioconv
defaultAudioConvOptions,
checkFfmpeg,
convertAudio,
// :: error
IDExtractorError: error.IDExtractorError,
UnknownOptionError: error.UnknownOptionError
});


Expand Down
4 changes: 2 additions & 2 deletions lib/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class IDExtractorError extends Error {}
*/
class UnknownOptionError extends Error {}

exports = {
module.exports = Object.freeze({
IDExtractorError,
UnknownOptionError
};
});
8 changes: 4 additions & 4 deletions lib/url-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ URLUtils.VIDEO_ID_STRICT_REGEX = new RegExp(`^[A-Za-z0-9_-]{${URLUtils.MAX_ID_LE
* @see {@link module:url-utils~URLUtils.YTURL_WITH_ID_REGEX URLUtils.YTURL_WITH_ID_REGEX}
* @see {@link module:url-utils~URLUtils.BASIC_YOUTUBE_DOMAINS URLUtils.BASIC_YOUTUBE_DOMAINS}
*/
URLUtils.YTURL_REGEX = new RegExp(`https?:\\/\\/(${
URLUtils.YTURL_REGEX = new RegExp(`^https?:\\/\\/(${
URLUtils.BASIC_YOUTUBE_DOMAINS.reduce((acc, val) => {
val = val.replace(/\./g, '\\.');
acc += !(acc.length || 0) ? val : `|${val}`;
acc += (val !== 'youtu\\.be') ? '\\/watch\\?v=' : '\\/';
acc += (val !== 'youtu\\.be') ? '\\/watch\\?v=' : '\\/?';
return acc;
}, '')
})`);
Expand All @@ -134,7 +134,7 @@ URLUtils.YTURL_REGEX = new RegExp(`https?:\\/\\/(${
* @see {@link module:url-utils~URLUtils.BASIC_YOUTUBE_DOMAINS URLUtils.BASIC_YOUTUBE_DOMAINS}
*/
URLUtils.YTURL_WITH_ID_REGEX = new RegExp(
`${URLUtils.YTURL_REGEX.source}${URLUtils.VIDEO_ID_REGEX.source}`
`${URLUtils.YTURL_REGEX.source.replace(/\?\)$/, ')')}${URLUtils.VIDEO_ID_REGEX.source}`
);

/**
Expand All @@ -150,7 +150,7 @@ URLUtils.YTURL_WITH_ID_REGEX = new RegExp(
* - `youtu.be`
* - `music.youtube.com`
*
* @param {string | URL} url - The URL to be evaluate.
* @param {string | URL} url - The URL to evaluate.
* @returns {string} A string with 11 characters representing the video ID.
*
* @throws {TypeError} If a given URL is not a string or `URL` object.
Expand Down
4 changes: 3 additions & 1 deletion test/unittest/url-utils.spec.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import assert from 'node:assert';

import URLUtils from '../../lib/url-utils.js';
import error from '../../lib/error.js';
const { IDExtractorError } = error;

describe('module:url-utils', function () {
describe('.URLUtils', function () {
Expand Down Expand Up @@ -53,7 +55,7 @@ describe('module:url-utils', function () {

it(testMessages.extractVideoId[2], function () {
assert.throws(() =>
URLUtils.extractVideoId('https://youtu.be/watch?v=abc'), 'IDExtractorError');
URLUtils.extractVideoId('https://youtu.be/watch?v=abc'), IDExtractorError);
});

it(testMessages.extractVideoId[3], function () {
Expand Down

0 comments on commit f6c0068

Please sign in to comment.