vdj 1.4.7 → 1.6.0
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.
- package/dist/core/iService.d.ts +8 -8
- package/dist/core/iService.js +2 -2
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +10 -10
- package/dist/core/playlist.d.ts +24 -24
- package/dist/core/playlist.js +126 -126
- package/dist/core/song.d.ts +18 -19
- package/dist/core/song.js +16 -16
- package/dist/core/types.d.ts +39 -40
- package/dist/core/types.js +2 -2
- package/dist/default_implementations/youtube/service.d.ts +13 -13
- package/dist/default_implementations/youtube/service.js +112 -112
- package/dist/default_implementations/youtube/song.d.ts +19 -20
- package/dist/default_implementations/youtube/song.js +73 -73
- package/dist/default_implementations/youtubedl/service.d.ts +11 -11
- package/dist/default_implementations/youtubedl/service.js +77 -64
- package/dist/default_implementations/youtubedl/song.d.ts +13 -14
- package/dist/default_implementations/youtubedl/song.js +46 -46
- package/dist/index.d.ts +6 -6
- package/dist/index.js +17 -17
- package/package.json +5 -5
- package/src/default_implementations/youtube/service.ts +1 -1
- package/src/default_implementations/youtubedl/service.ts +14 -1
- package/test/test.js +1 -1
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const API = require("simple-youtube-api");
|
|
16
|
-
const ytdl = require("ytdl-core");
|
|
17
|
-
const song_1 = __importDefault(require("./song"));
|
|
18
|
-
class YouTubeService {
|
|
19
|
-
constructor(key) {
|
|
20
|
-
this.canSearch = true;
|
|
21
|
-
this.type = 'youtube';
|
|
22
|
-
this.api = new API(key);
|
|
23
|
-
}
|
|
24
|
-
fetch(targets, logger) {
|
|
25
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const fetched = [];
|
|
27
|
-
for (const target of targets) {
|
|
28
|
-
var parsed = API.util.parseURL(target);
|
|
29
|
-
if (parsed.video) {
|
|
30
|
-
typeof (logger) == 'function' && logger(`[${this.type}] Fetching video from target ${target}.`);
|
|
31
|
-
const video = yield this.api.getVideoByID(parsed.video);
|
|
32
|
-
const seek = song_1.default.extractSeek(target);
|
|
33
|
-
if (video)
|
|
34
|
-
fetched.push(new song_1.default(this, video, undefined, logger, seek));
|
|
35
|
-
}
|
|
36
|
-
else if (parsed.playlist) {
|
|
37
|
-
typeof (logger) == 'function' && logger(`[${this.type}] Fetching playlist from target ${target}.`);
|
|
38
|
-
const playlist = yield this.api.getPlaylistByID(parsed.playlist);
|
|
39
|
-
if (!playlist)
|
|
40
|
-
continue;
|
|
41
|
-
yield playlist.getVideos();
|
|
42
|
-
fetched.push(...playlist.videos.map((v) => new song_1.default(this, v, parsed.playlist, logger)));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return fetched;
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
search(queries, searchType, logger) {
|
|
49
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
const fetched = [];
|
|
51
|
-
if (!this.canSearch)
|
|
52
|
-
return fetched;
|
|
53
|
-
for (const query of queries) {
|
|
54
|
-
if (searchType === 'playlist') {
|
|
55
|
-
typeof (logger) == 'function' && logger(`[${this.type}] Searching for a playlist with the input ${query}.`);
|
|
56
|
-
const results = yield this.api.searchPlaylists(query, 1);
|
|
57
|
-
if (results.length) {
|
|
58
|
-
const list = results[0];
|
|
59
|
-
const videos = yield list.getVideos();
|
|
60
|
-
fetched.push(...videos.map((v) => new song_1.default(this, v, list.id, logger)));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
typeof (logger) == 'function' && logger(`[${this.type}] Searching for a song with the input ${query}.`);
|
|
65
|
-
const results = yield this.api.searchVideos(query, 1);
|
|
66
|
-
if (results.length)
|
|
67
|
-
fetched.push(new song_1.default(this, results[0], undefined, logger));
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return fetched;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
canFetch(target, logger) {
|
|
74
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
-
const parsed = API.util.parseURL(target);
|
|
76
|
-
return parsed.video != undefined || parsed.playlist != undefined;
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
getSongInfo(url, logger) {
|
|
80
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
-
try {
|
|
82
|
-
const result = yield ytdl.getInfo(url);
|
|
83
|
-
return {
|
|
84
|
-
full: true,
|
|
85
|
-
metadataType: "youtube",
|
|
86
|
-
imgURL: result.player_response.videoDetails.thumbnail.thumbnails[0].url,
|
|
87
|
-
title: result.videoDetails.title,
|
|
88
|
-
duration: Number(result.videoDetails.lengthSeconds),
|
|
89
|
-
url: result.videoDetails.video_url,
|
|
90
|
-
artist: [result.videoDetails.author.name],
|
|
91
|
-
date: new Date(result.videoDetails.publishDate),
|
|
92
|
-
custom: result
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
catch (e) {
|
|
96
|
-
typeof (logger) == 'function' && logger(`Failed to get song info for url '${url}', error ${e}`);
|
|
97
|
-
return {
|
|
98
|
-
full: true,
|
|
99
|
-
metadataType: "youtube",
|
|
100
|
-
imgURL: "",
|
|
101
|
-
title: url,
|
|
102
|
-
duration: 0,
|
|
103
|
-
url: url,
|
|
104
|
-
artist: [],
|
|
105
|
-
date: new Date(),
|
|
106
|
-
custom: {}
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
exports.default = YouTubeService;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const API = require("simple-youtube-api");
|
|
16
|
+
const ytdl = require("@distube/ytdl-core");
|
|
17
|
+
const song_1 = __importDefault(require("./song"));
|
|
18
|
+
class YouTubeService {
|
|
19
|
+
constructor(key) {
|
|
20
|
+
this.canSearch = true;
|
|
21
|
+
this.type = 'youtube';
|
|
22
|
+
this.api = new API(key);
|
|
23
|
+
}
|
|
24
|
+
fetch(targets, logger) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const fetched = [];
|
|
27
|
+
for (const target of targets) {
|
|
28
|
+
var parsed = API.util.parseURL(target);
|
|
29
|
+
if (parsed.video) {
|
|
30
|
+
typeof (logger) == 'function' && logger(`[${this.type}] Fetching video from target ${target}.`);
|
|
31
|
+
const video = yield this.api.getVideoByID(parsed.video);
|
|
32
|
+
const seek = song_1.default.extractSeek(target);
|
|
33
|
+
if (video)
|
|
34
|
+
fetched.push(new song_1.default(this, video, undefined, logger, seek));
|
|
35
|
+
}
|
|
36
|
+
else if (parsed.playlist) {
|
|
37
|
+
typeof (logger) == 'function' && logger(`[${this.type}] Fetching playlist from target ${target}.`);
|
|
38
|
+
const playlist = yield this.api.getPlaylistByID(parsed.playlist);
|
|
39
|
+
if (!playlist)
|
|
40
|
+
continue;
|
|
41
|
+
yield playlist.getVideos();
|
|
42
|
+
fetched.push(...playlist.videos.map((v) => new song_1.default(this, v, parsed.playlist, logger)));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return fetched;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
search(queries, searchType, logger) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const fetched = [];
|
|
51
|
+
if (!this.canSearch)
|
|
52
|
+
return fetched;
|
|
53
|
+
for (const query of queries) {
|
|
54
|
+
if (searchType === 'playlist') {
|
|
55
|
+
typeof (logger) == 'function' && logger(`[${this.type}] Searching for a playlist with the input ${query}.`);
|
|
56
|
+
const results = yield this.api.searchPlaylists(query, 1);
|
|
57
|
+
if (results.length) {
|
|
58
|
+
const list = results[0];
|
|
59
|
+
const videos = yield list.getVideos();
|
|
60
|
+
fetched.push(...videos.map((v) => new song_1.default(this, v, list.id, logger)));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
typeof (logger) == 'function' && logger(`[${this.type}] Searching for a song with the input ${query}.`);
|
|
65
|
+
const results = yield this.api.searchVideos(query, 1);
|
|
66
|
+
if (results.length)
|
|
67
|
+
fetched.push(new song_1.default(this, results[0], undefined, logger));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return fetched;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
canFetch(target, logger) {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
const parsed = API.util.parseURL(target);
|
|
76
|
+
return parsed.video != undefined || parsed.playlist != undefined;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
getSongInfo(url, logger) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
try {
|
|
82
|
+
const result = yield ytdl.getInfo(url);
|
|
83
|
+
return {
|
|
84
|
+
full: true,
|
|
85
|
+
metadataType: "youtube",
|
|
86
|
+
imgURL: result.player_response.videoDetails.thumbnail.thumbnails[0].url,
|
|
87
|
+
title: result.videoDetails.title,
|
|
88
|
+
duration: Number(result.videoDetails.lengthSeconds),
|
|
89
|
+
url: result.videoDetails.video_url,
|
|
90
|
+
artist: [result.videoDetails.author.name],
|
|
91
|
+
date: new Date(result.videoDetails.publishDate),
|
|
92
|
+
custom: result
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
typeof (logger) == 'function' && logger(`Failed to get song info for url '${url}', error ${e}`);
|
|
97
|
+
return {
|
|
98
|
+
full: true,
|
|
99
|
+
metadataType: "youtube",
|
|
100
|
+
imgURL: "",
|
|
101
|
+
title: url,
|
|
102
|
+
duration: 0,
|
|
103
|
+
url: url,
|
|
104
|
+
artist: [],
|
|
105
|
+
date: new Date(),
|
|
106
|
+
custom: {}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.default = YouTubeService;
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
readonly
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
12
|
-
readonly
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
logger?: Logger;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
1
|
+
import { Readable as ReadableStream } from 'stream';
|
|
2
|
+
import { Video } from 'simple-youtube-api';
|
|
3
|
+
import { Song, SongInfo, Logger } from '../../core';
|
|
4
|
+
import YouTubeService from './service';
|
|
5
|
+
export default class YouTubeSong extends Song {
|
|
6
|
+
readonly type: string;
|
|
7
|
+
readonly title: string;
|
|
8
|
+
readonly playlistID?: string;
|
|
9
|
+
readonly trackID: string;
|
|
10
|
+
readonly streamURL: string;
|
|
11
|
+
readonly URL: string;
|
|
12
|
+
readonly live: boolean;
|
|
13
|
+
info: SongInfo;
|
|
14
|
+
logger?: Logger;
|
|
15
|
+
constructor(service: YouTubeService, video: Video, playlistID?: string, logger?: Logger, seek?: number);
|
|
16
|
+
getSongInfo(): Promise<SongInfo>;
|
|
17
|
+
static extractSeek(url: string): number;
|
|
18
|
+
stream(): ReadableStream | null;
|
|
19
|
+
}
|
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const youtube_dl_exec_1 = require("youtube-dl-exec");
|
|
13
|
-
const core_1 = require("../../core");
|
|
14
|
-
class YouTubeSong extends core_1.Song {
|
|
15
|
-
constructor(service, video, playlistID, logger, seek = 0) {
|
|
16
|
-
super(service);
|
|
17
|
-
this.type = 'youtube';
|
|
18
|
-
this.title = video.title;
|
|
19
|
-
this.trackID = video.id;
|
|
20
|
-
this.streamURL = video.url;
|
|
21
|
-
this.URL = video.url;
|
|
22
|
-
this.playlistID = playlistID;
|
|
23
|
-
this.live = video.raw.snippet.liveBroadcastContent == "live";
|
|
24
|
-
this.seek = seek;
|
|
25
|
-
this.info = {
|
|
26
|
-
full: false,
|
|
27
|
-
metadataType: this.type,
|
|
28
|
-
title: this.title,
|
|
29
|
-
url: this.URL,
|
|
30
|
-
duration: video.durationSeconds
|
|
31
|
-
};
|
|
32
|
-
this.logger = logger;
|
|
33
|
-
}
|
|
34
|
-
getSongInfo() {
|
|
35
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
if (this.info.full)
|
|
37
|
-
return this.info;
|
|
38
|
-
this.info = yield this.service.getSongInfo(this.URL);
|
|
39
|
-
return this.info;
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
static extractSeek(url) {
|
|
43
|
-
var lookFor = ["&t=", "?t="];
|
|
44
|
-
for (var i in lookFor) {
|
|
45
|
-
var key = lookFor[i];
|
|
46
|
-
var start = url.indexOf(key);
|
|
47
|
-
if (start === -1)
|
|
48
|
-
continue;
|
|
49
|
-
start += key.length;
|
|
50
|
-
var time = "";
|
|
51
|
-
var char = "";
|
|
52
|
-
for (var j = start; j < url.length; j++) {
|
|
53
|
-
char = url[j];
|
|
54
|
-
if (isNaN(Number(char)))
|
|
55
|
-
break;
|
|
56
|
-
time += char;
|
|
57
|
-
}
|
|
58
|
-
return Number(time);
|
|
59
|
-
}
|
|
60
|
-
return 0;
|
|
61
|
-
}
|
|
62
|
-
stream() {
|
|
63
|
-
const stream = youtube_dl_exec_1.exec(this.streamURL, {
|
|
64
|
-
output: '-',
|
|
65
|
-
format: 'bestaudio/best',
|
|
66
|
-
limitRate: '1M',
|
|
67
|
-
rmCacheDir: true,
|
|
68
|
-
verbose: true,
|
|
69
|
-
}, { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
70
|
-
return stream.stdout;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
exports.default = YouTubeSong;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const youtube_dl_exec_1 = require("youtube-dl-exec");
|
|
13
|
+
const core_1 = require("../../core");
|
|
14
|
+
class YouTubeSong extends core_1.Song {
|
|
15
|
+
constructor(service, video, playlistID, logger, seek = 0) {
|
|
16
|
+
super(service);
|
|
17
|
+
this.type = 'youtube';
|
|
18
|
+
this.title = video.title;
|
|
19
|
+
this.trackID = video.id;
|
|
20
|
+
this.streamURL = video.url;
|
|
21
|
+
this.URL = video.url;
|
|
22
|
+
this.playlistID = playlistID;
|
|
23
|
+
this.live = video.raw.snippet.liveBroadcastContent == "live";
|
|
24
|
+
this.seek = seek;
|
|
25
|
+
this.info = {
|
|
26
|
+
full: false,
|
|
27
|
+
metadataType: this.type,
|
|
28
|
+
title: this.title,
|
|
29
|
+
url: this.URL,
|
|
30
|
+
duration: video.durationSeconds
|
|
31
|
+
};
|
|
32
|
+
this.logger = logger;
|
|
33
|
+
}
|
|
34
|
+
getSongInfo() {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
if (this.info.full)
|
|
37
|
+
return this.info;
|
|
38
|
+
this.info = yield this.service.getSongInfo(this.URL);
|
|
39
|
+
return this.info;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
static extractSeek(url) {
|
|
43
|
+
var lookFor = ["&t=", "?t="];
|
|
44
|
+
for (var i in lookFor) {
|
|
45
|
+
var key = lookFor[i];
|
|
46
|
+
var start = url.indexOf(key);
|
|
47
|
+
if (start === -1)
|
|
48
|
+
continue;
|
|
49
|
+
start += key.length;
|
|
50
|
+
var time = "";
|
|
51
|
+
var char = "";
|
|
52
|
+
for (var j = start; j < url.length; j++) {
|
|
53
|
+
char = url[j];
|
|
54
|
+
if (isNaN(Number(char)))
|
|
55
|
+
break;
|
|
56
|
+
time += char;
|
|
57
|
+
}
|
|
58
|
+
return Number(time);
|
|
59
|
+
}
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
stream() {
|
|
63
|
+
const stream = (0, youtube_dl_exec_1.exec)(this.streamURL, {
|
|
64
|
+
output: '-',
|
|
65
|
+
format: 'bestaudio/best',
|
|
66
|
+
limitRate: '1M',
|
|
67
|
+
rmCacheDir: true,
|
|
68
|
+
verbose: true,
|
|
69
|
+
}, { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
70
|
+
return stream.stdout;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.default = YouTubeSong;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { IService, SongInfo, Logger } from '../../core/';
|
|
2
|
-
import YoutubedlSong from './song';
|
|
3
|
-
export default class YoutubedlService implements IService {
|
|
4
|
-
canSearch: boolean;
|
|
5
|
-
type: string;
|
|
6
|
-
fetch(targets: string[], logger?: Logger): Promise<YoutubedlSong[]>;
|
|
7
|
-
search(): Promise<YoutubedlSong[]>;
|
|
8
|
-
canFetch(target: string, logger?: Logger): Promise<boolean>;
|
|
9
|
-
getSongInfo(url: string, logger?: Logger): Promise<SongInfo>;
|
|
10
|
-
private parseDate;
|
|
11
|
-
}
|
|
1
|
+
import { IService, SongInfo, Logger } from '../../core/';
|
|
2
|
+
import YoutubedlSong from './song';
|
|
3
|
+
export default class YoutubedlService implements IService {
|
|
4
|
+
canSearch: boolean;
|
|
5
|
+
type: string;
|
|
6
|
+
fetch(targets: string[], logger?: Logger): Promise<YoutubedlSong[]>;
|
|
7
|
+
search(): Promise<YoutubedlSong[]>;
|
|
8
|
+
canFetch(target: string, logger?: Logger): Promise<boolean>;
|
|
9
|
+
getSongInfo(url: string, logger?: Logger): Promise<SongInfo>;
|
|
10
|
+
private parseDate;
|
|
11
|
+
}
|
|
@@ -1,64 +1,77 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const song_1 = __importDefault(require("./song"));
|
|
16
|
-
const youtube_dl_exec_1 = __importDefault(require("youtube-dl-exec"));
|
|
17
|
-
class YoutubedlService {
|
|
18
|
-
constructor() {
|
|
19
|
-
this.canSearch = false;
|
|
20
|
-
this.type = 'youtubedl';
|
|
21
|
-
}
|
|
22
|
-
fetch(targets, logger) {
|
|
23
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
-
return targets.map(x => new song_1.default(this, x, logger));
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
search() {
|
|
28
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
-
return [];
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
canFetch(target, logger) {
|
|
33
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
var res = yield youtube_dl_exec_1.default(target, { dumpSingleJson: true }, {});
|
|
35
|
-
return !!res;
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
getSongInfo(url, logger) {
|
|
39
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
-
var res = yield youtube_dl_exec_1.default(url, { dumpSingleJson: true, noCheckCertificates: true, addMetadata: true }, {});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const song_1 = __importDefault(require("./song"));
|
|
16
|
+
const youtube_dl_exec_1 = __importDefault(require("youtube-dl-exec"));
|
|
17
|
+
class YoutubedlService {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.canSearch = false;
|
|
20
|
+
this.type = 'youtubedl';
|
|
21
|
+
}
|
|
22
|
+
fetch(targets, logger) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
return targets.map(x => new song_1.default(this, x, logger));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
search() {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
return [];
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
canFetch(target, logger) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
var res = yield (0, youtube_dl_exec_1.default)(target, { dumpSingleJson: true }, {});
|
|
35
|
+
return !!res;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
getSongInfo(url, logger) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
var res = yield (0, youtube_dl_exec_1.default)(url, { dumpSingleJson: true, noCheckCertificates: true, addMetadata: true }, {});
|
|
41
|
+
if (typeof res === 'string') {
|
|
42
|
+
return {
|
|
43
|
+
full: false,
|
|
44
|
+
metadataType: "youtubedl",
|
|
45
|
+
imgURL: undefined,
|
|
46
|
+
title: url,
|
|
47
|
+
duration: undefined,
|
|
48
|
+
url: url,
|
|
49
|
+
artist: [],
|
|
50
|
+
date: undefined,
|
|
51
|
+
custom: {}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
full: true,
|
|
56
|
+
metadataType: "youtubedl",
|
|
57
|
+
imgURL: res.thumbnail,
|
|
58
|
+
title: res.title || url,
|
|
59
|
+
duration: res.duration,
|
|
60
|
+
url: url,
|
|
61
|
+
artist: [],
|
|
62
|
+
date: this.parseDate(res.upload_date),
|
|
63
|
+
custom: {}
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
parseDate(dateString) {
|
|
68
|
+
if (!dateString) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const year = dateString.slice(0, 4);
|
|
72
|
+
const month = dateString.slice(4, 6);
|
|
73
|
+
const day = dateString.slice(6, 8);
|
|
74
|
+
return new Date(`${year} ${month} ${day}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.default = YoutubedlService;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly
|
|
7
|
-
readonly
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
logger?: Logger;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
1
|
+
import { Readable as ReadableStream } from 'stream';
|
|
2
|
+
import { Song, SongInfo, Logger } from '../../core';
|
|
3
|
+
import YoutubedlService from './service';
|
|
4
|
+
export default class YoutubedlSong extends Song {
|
|
5
|
+
readonly type: string;
|
|
6
|
+
readonly streamURL: string;
|
|
7
|
+
readonly URL: string;
|
|
8
|
+
info: SongInfo;
|
|
9
|
+
logger?: Logger;
|
|
10
|
+
constructor(service: YoutubedlService, url: string, logger?: Logger);
|
|
11
|
+
getSongInfo(): Promise<SongInfo>;
|
|
12
|
+
stream(): ReadableStream | null;
|
|
13
|
+
}
|