· 5 years ago · Dec 19, 2020, 04:44 PM
1/** Container for music tracks */
2module.exports = class Song {
3 /**
4 * Creates a container to unify different API data
5 * @param {string} type The type of container to create
6 * @param {Object} data The data to be supplied to the container
7 */
8 constructor(type, data) {
9 /**
10 * The type of this container
11 * @type {string}
12 */
13 this.type = type
14
15 /**
16 * The title of this song
17 * @type {string}
18 */
19 this.title = `Unknown`
20
21 /**
22 * The URL to this song
23 * @type {string}
24 */
25 this.url = ''
26
27 /**
28 * The raw data for this container
29 * @type {Object}
30 */
31 this.data = data
32
33 switch(type) {
34 case('spotify'): {
35 this.title = `${data.title || data.name} - ${data.artist || data.artists.map(r => r.name)[0]}`;
36 this.url = this.data.link || ('https://open.spotify.com/track/' + this.data.id);
37 this._duration = this.data.duration_ms || 0;
38 break;
39 }
40 case('youtube'): {
41 this._youtube = data;
42 this.title = this.youtube.title;
43 this.url = 'https://youtu.be/' + this.youtube.id;
44 this._duration = this.youtube.duration || 0;
45 break;
46 }
47 case('soundcloud'): {
48 this.soundcloud = data;
49 this.title = `${data.title} - ${data.author.name}`;
50 this.url = 'https://soundcloud.com';
51 this._duration = 0;
52 break;
53 }
54 default: return null;
55 }
56 return this;
57 }
58
59 /**
60 * The duration of this song in milliseconds
61 * @type {number}
62 */
63 get duration() {
64 return !this._youtube ? this._duration : this._youtube.duration;
65 }
66
67 /**
68 * Searches the data of this song via the YouTube API
69 * @returns {Promise<Object|null>} API data or null
70 */
71 async fetchYoutube() {
72 return this._youtube = await _searchSong(this.title).catch(e => {return null});
73 }
74
75 /**
76 * Searches the lyrics for this song via the Melon API
77 * @returns {Promise<Object|null>} a promise with the API data or null
78 */
79 async fetchLyrics() {
80 return this._lyrics = await lyrics.get('melon', this.title).catch(e => {return null});
81 }
82
83 /**
84 * Queries YouTube or returns API data from the private key
85 * @returns {*}
86 */
87 get youtube() {
88 if (!(this._youtube === undefined)) return this._youtube;
89 return this.fetchYoutube();
90 }
91
92 /**
93 * Queries Melon or returns API data from the private key
94 * @returns {*}
95 */
96 get lyrics() {
97 if (!(this._lyrics === undefined)) return this._lyrics;
98 return this.fetchLyrics();
99 }
100}