Created
August 6, 2019 14:32
-
-
Save jalamprea/6908ceebed3e2f1a61b77a7272da0e86 to your computer and use it in GitHub Desktop.
Implementation of Youtube Search API with Pure Javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var YoutubeSearcher = (function() { | |
function YoutubeSearcher() { | |
this.configuration = {}; | |
this.dependencies = {}; | |
} | |
YoutubeSearcher.prototype.searchSongs = function(query) { | |
var dependencies = this.dependencies; | |
var q = dependencies.q; | |
var rootScope = dependencies.rootScope; | |
var httpService = dependencies.httpService; | |
var defered = q.defer(); | |
var promise = defered.promise; | |
//-----------------First request----------------- | |
var apiKey = this.configuration.api_key; | |
var urlRequest = 'https://www.googleapis.com/youtube/v3/search?videoEmbeddable=true&order=relevance&part=id&q=' + query + '&type=video&maxResults=50&key=' + apiKey; | |
var errorCallback = function(data) { | |
var message = 'GENERAL_ERROR'; | |
if (data.status === 0) { | |
message = 'NETWORK_ERROR'; | |
} | |
rootScope.$broadcast('showSongsSearchResults', new RequestResponse('Error', message, {})); | |
}; | |
var successCallback = function(data) { | |
var songsId = YoutubeSearcher.prototype.getResourcesIdFromYoutubeResponse(data.data.items, 'searches-songs'); | |
if (songsId === '') { | |
rootScope.$broadcast('showSongsSearchResults', new RequestResponse('Error', 'SEARCH_SONGS_NOT_FOUND', { | |
results_not_found: true | |
})); | |
} else { | |
defered.resolve(songsId); | |
} | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
//-----------------Second request----------------- | |
var resolveCallback = function(songsId) { | |
urlRequest = 'https://www.googleapis.com/youtube/v3/videos?part=snippet%2C+contentDetails%2C+statistics&id=' + songsId + '&key=' + apiKey; | |
var successCallback = function(data) { | |
var songsList = YoutubeSearcher.prototype.getSongsListFromYoutubeResponse(data.data.items, dependencies, true); | |
songsList.toArray().sort(SongUtilities.sortByViews); | |
var response = { | |
songs: songsList, | |
query: query | |
}; | |
if (songsList.size() === 0) { | |
response = new RequestResponse('Error', 'SEARCH_SONGS_NOT_FOUND', response); | |
} else { | |
response = new RequestResponse('Success', '', response); | |
} | |
rootScope.$broadcast('showSongsSearchResults', response); | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
}; | |
promise.then(resolveCallback); | |
}; | |
YoutubeSearcher.prototype.getSuggestedSongs = function(songSourceId) { | |
var dependencies = this.dependencies; | |
var q = dependencies.q; | |
var rootScope = dependencies.rootScope; | |
var httpService = dependencies.httpService; | |
var defered = q.defer(); | |
var promise = defered.promise; | |
//-----------------First request----------------- | |
var apiKey = this.configuration.api_key; | |
var urlRequest = 'https://www.googleapis.com/youtube/v3/search?part=snippet&&maxResults=10&relatedToVideoId=' + songSourceId + '&type=video&key=' + apiKey; | |
var errorCallback = function(data) { | |
var message = 'GENERAL_ERROR'; | |
if (data.status === 0) { | |
message = 'NETWORK_ERROR'; | |
} | |
rootScope.$broadcast('updateSuggestedSongs', new RequestResponse('Error', message, {})); | |
}; | |
var successCallback = function(data) { | |
var songsId = YoutubeSearcher.prototype.getResourcesIdFromYoutubeResponse(data.data.items, 'suggested-songs'); | |
if (songsId === '') { | |
rootScope.$broadcast('updateSuggestedSongs', new RequestResponse('Error', 'RELATED_SONGS_NOT_FOUND', {})); | |
} else { | |
defered.resolve(songsId); | |
} | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
//-----------------Second request----------------- | |
var resolveCallback = function(songsId) { | |
urlRequest = 'https://www.googleapis.com/youtube/v3/videos?part=snippet%2C+contentDetails%2C+statistics&id=' + songsId + '&key=' + apiKey; | |
var successCallback = function(data) { | |
var songsList = YoutubeSearcher.prototype.getSongsListFromYoutubeResponse(data.data.items, dependencies, true); | |
songsList.toArray().sort(SongUtilities.sortByViews); | |
var response = { | |
songs: songsList | |
}; | |
if (songsList.size() === 0) { | |
response = new RequestResponse('Error', 'RELATED_SONGS_NOT_FOUND', response); | |
} else { | |
response = new RequestResponse('Success', '', response); | |
} | |
rootScope.$broadcast('updateSuggestedSongs', response); | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
}; | |
promise.then(resolveCallback); | |
}; | |
YoutubeSearcher.prototype.searchPlaylists = function(query) { | |
var dependencies = this.dependencies; | |
var q = dependencies.q; | |
var rootScope = dependencies.rootScope; | |
var httpService = dependencies.httpService; | |
var defered = q.defer(); | |
var promise = defered.promise; | |
//-----------------First request----------------- | |
var apiKey = this.configuration.api_key; | |
var urlRequest = 'https://www.googleapis.com/youtube/v3/search?part=snippet&q=' + query + '&type=playlist&fields=items%2Fid&maxResults=3&key=' + apiKey; | |
var errorCallback = function(data) { | |
var message = 'GENERAL_ERROR'; | |
if (data.status === 0) { | |
message = 'NETWORK_ERROR'; | |
} | |
rootScope.$broadcast('showPlaylistsSearchResults', new RequestResponse('Error', message, {})); | |
}; | |
var successCallback = function(data) { | |
var playlistsId = YoutubeSearcher.prototype.getResourcesIdFromYoutubeResponse(data.data.items, 'searches-playlists'); | |
if (playlistsId === '') { | |
rootScope.$broadcast('showPlaylistsSearchResults', new RequestResponse('Error', 'SEARCH_PLAYLISTS_NOT_FOUND', { | |
results_not_found: true | |
})); | |
} else { | |
defered.resolve(playlistsId); | |
} | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
//-----------------Second request----------------- | |
var resolveCallback = function(playlistsId) { | |
urlRequest = 'https://www.googleapis.com/youtube/v3/playlists?part=contentDetails%2C+snippet&fields=items(contentDetails%2Cid%2Csnippet)&id=' + playlistsId + '&key=' + apiKey; | |
var successCallback = function(data) { | |
var playlists = new List(); | |
var responseData = data.data.items; | |
var numberResults = responseData.length; | |
for (var i = 0; i < numberResults; i++) { | |
var item = responseData[i]; | |
var playlist = new Playlist(); | |
playlist.index = i; | |
playlist.source = 'Youtube'; | |
playlist.source_id = item.id; | |
playlist.thumbnail = item.snippet.thumbnails && item.snippet.thumbnails.default ? item.snippet.thumbnails.default.url : 'https://i.ytimg.com/vi/6F4BU6OakHY/mqdefault.jpg'; | |
playlist.title = item.snippet.title; | |
playlists.add(playlist); | |
} | |
var response = new RequestResponse('Success', '', { | |
playlists: playlists | |
}); | |
rootScope.$broadcast('showPlaylistsSearchResults', response); | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
}; | |
promise.then(resolveCallback); | |
}; | |
YoutubeSearcher.prototype.getPlaylistSongs = function(playlist) { | |
var dependencies = this.dependencies; | |
var q = dependencies.q; | |
var rootScope = dependencies.rootScope; | |
var httpService = dependencies.httpService; | |
var defered = q.defer(); | |
var promise = defered.promise; | |
//-----------------First request----------------- | |
var apiKey = this.configuration.api_key; | |
var urlRequest = 'https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails&playlistId=' + playlist.source_id + '&maxResults=50&key=' + apiKey; | |
var errorCallback = function(data) { | |
var message = 'GENERAL_ERROR'; | |
if (data.status === 0) { | |
message = 'NETWORK_ERROR'; | |
} | |
rootScope.$broadcast('getPlaylistSongs', new RequestResponse('Error', message, { | |
playlist: playlist | |
})); | |
}; | |
var successCallback = function(data) { | |
var songsId = YoutubeSearcher.prototype.getResourcesIdFromYoutubeResponse(data.data.items, 'get-playlist-songs'); | |
if (songsId === '') { | |
rootScope.$broadcast('getPlaylistSongs', new RequestResponse('Error', 'PLAYLIST_SONGS_NOT_FOUND', { | |
playlist: playlist | |
})); | |
} else { | |
defered.resolve(songsId); | |
} | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
//-----------------Second request----------------- | |
var resolveCallback = function(songsId) { | |
urlRequest = 'https://www.googleapis.com/youtube/v3/videos?videoEmbeddable=true&part=snippet%2C+contentDetails&id=' + songsId + '&key=' + apiKey; | |
var successCallback = function(data) { | |
var songsList = YoutubeSearcher.prototype.getSongsListFromYoutubeResponse(data.data.items, dependencies); | |
var response = { | |
playlist: playlist, | |
songs: songsList | |
}; | |
if (songsList.size() === 0) { | |
response = new RequestResponse('Error', 'PLAYLIST_SONGS_NOT_FOUND', response); | |
} else { | |
response = new RequestResponse('Success', '', response); | |
} | |
rootScope.$broadcast('getPlaylistSongs', response); | |
}; | |
httpService.get(urlRequest, {}, successCallback, errorCallback); | |
}; | |
promise.then(resolveCallback); | |
}; | |
YoutubeSearcher.prototype.getResourcesIdFromYoutubeResponse = function(items, source) { | |
var resourcesId = ''; | |
var numberSongs = items.length; | |
if (numberSongs > 0) { | |
var i; | |
if (source === 'suggested-songs') { | |
numberSongs = (numberSongs > 5 ? 5 : numberSongs); | |
} | |
if (source === 'searches-songs' || source === 'suggested-songs') { | |
for (i = 0; i < numberSongs; i++) { | |
resourcesId += items[i].id.videoId + ','; | |
} | |
} else if (source === 'searches-playlists') { | |
for (i = 0; i < numberSongs; i++) { | |
resourcesId += items[i].id.playlistId + ','; | |
} | |
} else if (source === 'get-playlist-songs') { | |
for (i = 0; i < numberSongs; i++) { | |
resourcesId += items[i].contentDetails.videoId + ','; | |
} | |
} | |
resourcesId = resourcesId.substring(0, resourcesId.length - 1); | |
} | |
return resourcesId; | |
}; | |
YoutubeSearcher.prototype.getSongsListFromYoutubeResponse = function(items, dependencies, getStatistics) { | |
var maxDurationSongs = dependencies.maxDurationSongs; | |
var blacklistConfig = {}; | |
var songsList = new List(); | |
var numberSongs = items.length; | |
if (dependencies.rootScope.blacklistConfig) { | |
blacklistConfig = dependencies.rootScope.blacklistConfig; | |
} | |
for (var i = 0; i < numberSongs; i++) { | |
var item = items[i]; | |
var song = new Song(); | |
song.source = 'Youtube'; | |
song.source_id = item.id; | |
song.thumbnail = item.snippet.thumbnails && item.snippet.thumbnails.medium ? item.snippet.thumbnails.medium.url : 'https://i.ytimg.com/vi/6F4BU6OakHY/mqdefault.jpg'; | |
song.title = item.snippet.title; | |
var blackListValidation = blacklistConfig.is_enabled && blacklistConfig.words !== '' ? SongUtilities.areKeywordsContainedInTitle(song.title, blacklistConfig.words) : false; | |
if (song.title.toLowerCase().indexOf('cover') !== -1 || song.title.toLowerCase().indexOf('tutorial') !== -1 || blackListValidation) { | |
continue; | |
} | |
if (item.snippet.categoryId === '10') { | |
var duration = item.contentDetails.duration; | |
duration = SongUtilities.normalizeDuration(duration, maxDurationSongs); | |
if (duration !== null) { | |
song.duration = duration; | |
if (getStatistics) { | |
if (item.statistics && item.statistics.viewCount) { | |
song.views = parseInt(item.statistics.viewCount); | |
} else { | |
song.views = numberSongs - i; | |
} | |
} | |
songsList.add(song); | |
} | |
} | |
} | |
return songsList; | |
}; | |
return YoutubeSearcher; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment