UNPKG

cody-music

Version:

mac osx spotify and itunes music player controller, spotify audio features, itunes and spotify genre, and playlist control

364 lines (318 loc) 10.2 kB
import { PlayerName, Track, TrackStatus, PlayerType, CodyResponse, } from "./models"; const cp = require("child_process"); export class MusicUtil { isLinux() { return this.isWindows() || this.isMac() ? false : true; } // process.platform return the following... // -> 'darwin', 'freebsd', 'linux', 'sunos' or 'win32' isWindows() { return process.platform.indexOf("win32") !== -1; } isMac() { return process.platform.indexOf("darwin") !== -1; } isEmptyObj(obj: any) { return Object.keys(obj).length === 0 && obj.constructor === Object; } isResponseOk(resp: any) { if (resp && resp.status === 200) { return true; } return false; } isItemsResponseOk(codyResp: CodyResponse) { if ( codyResp && codyResp.status === 200 && codyResp.data && codyResp.data.items ) { return true; } return false; } isResponseOkWithData(resp: any) { if (resp && resp.status === 200 && resp.data) { return true; } return false; } isBooleanString(val: string) { if ( (val && val.toLowerCase() === "true") || val.toLowerCase() === "false" ) { return true; } return false; } async execCmd(cmd: string, projectDir: any = null) { let result: any = null; try { let opts = projectDir !== undefined && projectDir !== null ? { cwd: projectDir } : {}; result = await this.execPromise(cmd, opts); } catch (e: any) { result = { error: e.message }; } return result; } async execPromise(command: string, opts: {}) { return new Promise((resolve, reject) => { cp.exec( command, opts, (error: any, stdout: string, stderr: any) => { if (error) { reject(error); return; } resolve(stdout.trim()); } ); }); } // Sleep for the designated milliseconds. // It should not be used in prod but only in the test. // It has a max of 5 seconds as this is resource intensive sleep(delayInMillis: number) { delayInMillis = Math.min(delayInMillis, 5000); var start = new Date().getTime(); while (new Date().getTime() < start + delayInMillis); } getPlayerName(player: string) { if (!player || player.trim().length === 0) { return PlayerName.SpotifyDesktop; } player = player.trim().toLowerCase(); if (player === "itunes") { return PlayerName.ItunesDesktop; } else if (player === "spotify-web") { return PlayerName.SpotifyWeb; } return PlayerName.SpotifyDesktop; } formatString(source: string, params: any) { let formatted = source; if (params && params.length > 0) { for (let i = 0; i < params.length; i++) { let regexp = new RegExp("\\{" + i + "\\}", "gi"); formatted = formatted.replace(regexp, params[i]); } } return formatted; } isTrackRunning(track: Track) { if (!track || !track.id) { return false; } if ( track.state === TrackStatus.Paused || track.state === TrackStatus.Playing ) { return true; } return false; } isTrackPlaying(track: Track) { if (!track || !track.id) { return false; } if (track.state === TrackStatus.Playing) { return true; } return false; } createPlaylistUriFromPlaylistId(playlist_id: string) { if (!playlist_id.includes("spotify:playlist:")) { playlist_id = `spotify:playlist:${playlist_id}`; } return playlist_id; } createSpotifyAlbumIdFromUri(uri: string) { // "spotify:album:6ZG5lRT77aJ3btmArcykra" if (uri && uri.indexOf("spotify:") === 0) { return uri.substring(uri.lastIndexOf(":") + 1); } return uri; } createTrackIdsFromUris(uris: string[]) { let trackIds = []; for (let i = 0; i < uris.length; i++) { trackIds.push(this.createSpotifyIdFromUri(uris[i])); } return trackIds; } createUriFromTrackId(track_id: string) { if (track_id && !track_id.includes("spotify:track:")) { track_id = `spotify:track:${track_id}`; } return track_id; } createUrisFromTrackIds(track_ids: string[], useUriObj: boolean = false) { let tracks = []; for (let i = 0; i < track_ids.length; i++) { let uri = track_ids[i]; if (!uri) { continue; } uri = this.createUriFromTrackId(uri); if (useUriObj) { const urlObj = { uri, }; tracks.push(urlObj); } else { tracks.push(uri); } } return tracks; } createSpotifyUserUriFromId(id: string) { if (id && !id.includes("spotify:user:")) { id = `spotify:user:${id}`; } return id; } createSpotifyIdFromUri(uri: string) { if (uri && uri.indexOf("spotify:") === 0) { return uri.substring(uri.lastIndexOf(":") + 1); } return uri; } createSpotifyIdsFromUris(uris: string[]) { const ids: string[] = []; if (uris && uris.length) { uris.forEach((uri) => { ids.push(this.createSpotifyIdFromUri(uri)); }); } return ids; } extractAristFromSpotifyTrack(track: any) { if (!track) { return; } if (track["artists"]) { const len = track["artists"].length; let artistNames = []; let artists = []; for (let y = 0; y < len; y++) { const artist = track["artists"][y]; artistNames.push(artist.name); artists.push({ name: artist.name, uri: artist.uri, id: artist.id, }); } delete track.artists; track.artists = artists; track["artist"] = artistNames.join(", "); track["artist_names"] = artistNames; } } launchWebUrl(url: string): Promise<any> { let open = "open"; let args = [url]; if (this.isWindows()) { open = "cmd"; // adds the following args to the beginning of the array args.unshift("/c", "start", '""'); } else if (!this.isMac()) { open = "xdg-open"; } args.unshift(open); const cmd = args.join(" "); return this.execCmd(cmd); } copySpotifyTrackToCodyTrack(spotifyTrack: any): Track { let track: Track; if (spotifyTrack) { // delete some attributes that are currently not needed if (spotifyTrack.album) { delete spotifyTrack.album.available_markets; delete spotifyTrack.album.external_urls; } if (spotifyTrack.external_urls) { delete spotifyTrack.external_urls; } if (spotifyTrack.external_ids) { delete spotifyTrack.external_ids; } // pull out the artist info into a more readable set of attributes this.extractAristFromSpotifyTrack(spotifyTrack); // assign the track track = { ...spotifyTrack }; if (spotifyTrack.duration_ms) { track.duration = spotifyTrack.duration_ms; } } else { track = new Track(); } track.type = "spotify"; track.playerType = PlayerType.WebSpotify; return track; } buildQueryString(obj: any, encodeVals: boolean = true) { let params = []; if (obj) { let keys = Object.keys(obj); if (keys) { for (let i = 0; i < keys.length; i++) { let key = keys[i]; let val = obj[key]; if (val && val !== undefined) { if (encodeVals) { let encodedVal = encodeURIComponent(val); params.push(`${key}=${encodedVal}`); } else { params.push(`${key}=${val}`); } } } } } if (params.length > 0) { return "?" + params.join("&"); } else { return ""; } } buildTrack(spotifyTrack: any) { let artists: string[] = []; if (spotifyTrack.artists) { artists = spotifyTrack.artists.map((artist: any) => { return artist.name; }); } let track: Track = new Track(); track.playerType = PlayerType.WebSpotify; track.type = spotifyTrack.type; track.artist = artists.join(", "); track.artist_names = artists; track.artists = spotifyTrack.artists; track.uri = spotifyTrack.uri; track.id = spotifyTrack.id; track.name = spotifyTrack.name; track.popularity = spotifyTrack.popularity; track.duration_ms = spotifyTrack.duration_ms; track.duration = spotifyTrack.duration_ms; track.disc_number = spotifyTrack.disc_number; track.explicit = spotifyTrack.explicit; track.href = spotifyTrack.href; track.album = spotifyTrack.album; return track; } }