import Fuse from 'fuse.js'; import FuseResult = Fuse.FuseResult; const Fuse = require('fuse.js') const fs = require('fs') const scraper = require('./playlist-scrape') const PLAYLIST_URL = 'https://nintendoradioplaylist2.000webhostapp.com/Livestream%20Playlist.html' const playlist: Track[] = require('./playlist.json') const albumValidCharacters = new Set() const trackValidCharacters = new Set() function buildAlbumValidCharacters() { albumValidCharacters.clear() new Set(playlist.map(entry => entry.album)) // Get set of albums .forEach(album => album.split('').forEach(letter => albumValidCharacters.add(letter))) } function buildTrackValidCharacters() { trackValidCharacters.clear() new Set(playlist.map(entry => entry.track)) .forEach(track => track.split('').forEach(letter => trackValidCharacters.add(letter))) } function getValidAlbumCharacters() { if (albumValidCharacters.size === 0) { buildAlbumValidCharacters() } return albumValidCharacters } function getValidTrackCharacters() { if (trackValidCharacters.size === 0) { console.log("Building index of valid track characters, this may take some time...") buildTrackValidCharacters() } return trackValidCharacters } const fuseByAlbum = new Fuse(playlist, { keys: ['album'] }) const fuseByTrack = new Fuse(playlist, { keys: ['track'] }) function searchAlbums(query): FuseResult[] { return fuseByAlbum.search(query) } function searchTracks(query): FuseResult[] { return fuseByTrack.search(query) } function fullSearch(album, track, duration): FuseResult { const inAlbumSearch = new Fuse(searchAlbums(album), {keys: ['item.track']}) const trackResults = inAlbumSearch.search(track).map(result => result.item) if (duration) { return filterResultsByDuration(trackResults, duration) } else { // No duration present, treat as album+track lookup return trackResults[0] } } function albumDurationSearch(album, duration): FuseResult { const albumResults = searchAlbums(album) return filterResultsByDuration(albumResults, duration, true) } function trackDurationSearch(track, duration): FuseResult { const trackResults = searchTracks(track) return filterResultsByDuration(trackResults, duration) } function filterResultsByDuration(results, duration, failSearch = false): FuseResult { const durationResults = results.filter(result => result.item.duration === duration) if (durationResults.length > 0) { return durationResults[0] } else { return failSearch ? null : results[0] } } export function search(albumQuery, trackQuery, duration): FuseResult { if (albumQuery && trackQuery) { return fullSearch(albumQuery, trackQuery, duration) } else if (albumQuery && duration) { return albumDurationSearch(albumQuery, duration) } else if (trackQuery && duration) { return trackDurationSearch(trackQuery, duration) } else { // Not enough info to perform a decent search // console.log("Skipping search for", albumQuery, trackQuery, duration) return null } } export function getAt(index): Track { return playlist[index] } function trySearch() { console.log(JSON.stringify(search("Final Fantasy VI", "Dancing Mad", "\f"))) } class Track { public album: string public track: string public duration: string } // These shouldn't be called asynchronously, manually call it ourselves buildTrackValidCharacters() buildAlbumValidCharacters() module.exports = { search, getAt, getValidAlbumCharacters, getValidTrackCharacters } if (require.main === module) { trySearch() }