Skip to content

Commit f4edac9

Browse files
authored
Create utils.gs
1 parent fd6c4aa commit f4edac9

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

utils.gs

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
3+
Resources:
4+
5+
- [Add a button on the sheet to run this script](https://www.benlcollins.com/apps-script/google-sheets-button/)
6+
- [Get client ID and client secret by creating an app in spotify dev dashboard](https://developer.spotify.com/dashboard/applications)
7+
- [Spotify API Explorer](https://developer.spotify.com/console/get-playlist-tracks/)
8+
9+
*/
10+
11+
var spotifyPlaylistUrl;
12+
var spotifyClientId;
13+
var spotifyClientSecret;
14+
15+
var youtubePlaylistUrl;
16+
17+
function importPlaylistContent(){
18+
spotifyPlaylistUrl = getCellText(5, 6); // hardcoded location in sheet: F5
19+
playlistMarket = getCellText(6, 6); // hardcoded location in sheet: F6
20+
spotifyClientId = getCellText(7, 6); // hardcoded location in sheet: F7
21+
spotifyClientSecret = getCellText(8, 6); // hardcoded location in sheet: F8
22+
23+
const playlistId = parseSpotifyPlaylistId(spotifyPlaylistUrl);
24+
const token = getToken();
25+
const songs = getSongs(token, playlistId, playlistMarket);
26+
const flattenedSongs = songs.map(song => ({"ARTIST": song.track.artists[0].name , "TRACK": song.track.name}))
27+
writeSongstoSheet(['ARTIST', 'TRACK'], flattenedSongs);
28+
}
29+
30+
function getCellText(row, col) {
31+
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
32+
var cellValue = sheet.getRange(row, col).getValue();
33+
return cellValue.toString();
34+
}
35+
36+
37+
function parseSpotifyPlaylistId(url) {
38+
var regex = /playlist\/(\w+)/;
39+
var match = url.match(regex);
40+
41+
if (match && match[1]) {
42+
return match[1];
43+
} else {
44+
throw new Error('Invalid Spotify playlist URL');
45+
}
46+
}
47+
48+
const getToken = function () {
49+
const authorization = "Basic "+ Utilities.base64Encode(`${spotifyClientId}:${spotifyClientSecret}`);
50+
const fetchParams = {
51+
method: 'post',
52+
payload: {'grant_type': 'client_credentials'},
53+
headers: {'Authorization': authorization},
54+
muteHttpExceptions: true
55+
}
56+
const replaceResponse = UrlFetchApp.fetch("https://accounts.spotify.com/api/token", fetchParams);
57+
return (JSON.parse(replaceResponse.getContentText())).access_token;
58+
}
59+
60+
const getSongs = function(_token, playlistId, playlistMarket){
61+
const requestOptions = {
62+
method: 'GET',
63+
headers: {"Authorization": `Bearer ${_token}`},
64+
redirect: 'follow',
65+
muteHttpExceptions: true
66+
};
67+
const response = UrlFetchApp.fetch(`https://api.spotify.com/v1/playlists/${playlistId}/tracks?market=${playlistMarket}&fields=items(track(name%2Cartists(name)))`, requestOptions)
68+
69+
return (JSON.parse(response)).items
70+
}
71+
72+
const writeSongstoSheet = function(_headings, _songs){
73+
var outputRows = [];
74+
75+
_songs.forEach(function(song) {
76+
outputRows.push(_headings.map(function(heading) {
77+
return song[heading] || '';
78+
}));
79+
});
80+
81+
if (outputRows.length) {
82+
// Add the headings - delete this next line if headings not required
83+
outputRows.unshift(_headings);
84+
// Clear any previous content (quick n dirty way)
85+
SpreadsheetApp.getActiveSheet().getRange(1, 1, 2*outputRows.length, outputRows[0].length).clearContent();
86+
// Write new stuff
87+
SpreadsheetApp.getActiveSheet().getRange(1, 1, outputRows.length, outputRows[0].length).setValues(outputRows);
88+
}
89+
}
90+
91+
function populateYoutubePlaylist() {
92+
youtubePlaylistUrl = getCellText(13,6) // hardcoded location in sheet: F13
93+
var playlistId = getPlaylistIdFromUrl(youtubePlaylistUrl);
94+
95+
var sheet = SpreadsheetApp.getActiveSpreadsheet();
96+
97+
var data = sheet.getRange('A:B').getValues();
98+
99+
for (var i = 1; i < data.length; i++) {
100+
var artist = data[i][0];
101+
var track = data[i][1];
102+
103+
if (!artist || !track){
104+
break
105+
}
106+
107+
addToPlaylist(playlistId, artist, track);
108+
Utilities.sleep(2000);
109+
}
110+
}
111+
112+
function getPlaylistIdFromUrl(url) {
113+
var regex = /list=([^&]+)/;
114+
var match = url.match(regex);
115+
if (match && match[1]) {
116+
return match[1];
117+
} else {
118+
throw new Error('Invalid playlist URL.');
119+
}
120+
}
121+
122+
function addToPlaylist(playlistId, artist, track) {
123+
var videoId = getVideoId(artist, track);
124+
125+
var youtubeService = YouTube;
126+
127+
var playlistItem = {
128+
snippet: {
129+
playlistId: playlistId,
130+
resourceId: {
131+
kind: 'youtube#video',
132+
videoId: videoId
133+
}
134+
}
135+
};
136+
137+
try {
138+
youtubeService.PlaylistItems.insert(playlistItem, 'snippet');
139+
Logger.log('Video added to playlist successfully.');
140+
} catch (error) {
141+
Logger.log('Error adding video to playlist: ' + error);
142+
}finally{
143+
Utilities.sleep(2000);
144+
}
145+
}
146+
147+
function getVideoId(artist, track) {
148+
var query = artist + ' ' + track;
149+
var youtubeService = YouTube;
150+
var searchResponse = youtubeService.Search.list('id', {
151+
q: query,
152+
type: 'video',
153+
maxResults: 1,
154+
});
155+
Utilities.sleep(2000);
156+
157+
if (searchResponse.items && searchResponse.items.length > 0) {
158+
var videoId = searchResponse.items[0].id.videoId;
159+
return videoId;
160+
} else {
161+
Logger.log('No video found for artist and track: ' + artist + ' - ' + track);
162+
}
163+
}

0 commit comments

Comments
 (0)