Advertisement
Amned92

YouTube subPlaylist Scirpt

Mar 29th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.34 KB | None | 0 0
  1. // TODO: Better exception handling for Youtube API calls
  2. // TODO: Deal with playlist limits (~ 200-218 videos)
  3. // TODO: Special keyword "ALLOTHER" for all other (unmentioned yet in the app) channel ids
  4.  
  5. function updatePlaylists() {
  6. var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  7. var data = sheet.getDataRange().getValues();
  8. var reservedTableRows = 3; // Start of the range of the PlaylistID+ChannelID data
  9. var reservedTableColumns = 2; // Start of the range of the ChannelID data
  10. var reservedTimestampCell = "F1";
  11. if (!sheet.getRange(reservedTimestampCell).getValue()) sheet.getRange(reservedTimestampCell).setValue(ISODateString(new Date()));
  12.  
  13. var debugFlag_dontUpdateTimestamp = false;
  14. var debugFlag_dontUpdatePlaylists = false;
  15.  
  16. /// For each playlist...
  17. for (var iRow = reservedTableRows; iRow < sheet.getLastRow(); iRow++) {
  18. var playlistId = data[iRow][0];
  19. if (!playlistId) continue;
  20.  
  21. /// ...get channels...
  22. var channelIds = [];
  23. for (var iColumn = reservedTableColumns; iColumn < sheet.getLastColumn(); iColumn++) {
  24. var channel = data[iRow][iColumn];
  25. if (!channel) continue;
  26. else if (channel == "ALL")
  27. channelIds.push.apply(channelIds, getAllChannelIds());
  28. else if (!(channel.substring(0,2) == "UC" && channel.length > 10)) // Check if it is not a channel ID (therefore a username). MaybeTODO: do a better validation, since might interpret a channel with a name "UC..." as a channel ID
  29. {
  30. try {
  31. channelIds.push(YouTube.Channels.list('id', {forUsername: channel, maxResults: 1}).items[0].id);
  32. } catch (e) {
  33. Logger.log("ERROR: " + e.message);
  34. continue;
  35. }
  36. }
  37. else
  38. channelIds.push(channel);
  39. }
  40.  
  41. /// ...get videos from the channels...
  42. var videoIds = [];
  43. var lastTimestamp = sheet.getRange(reservedTimestampCell).getValue();
  44. for (var i = 0; i < channelIds.length; i++) {
  45. videoIds.push.apply(videoIds, getVideoIds(channelIds[i], lastTimestamp)); // Append new videoIds array to the original one
  46. }
  47.  
  48. ///if (!debugFlag_dontUpdateTimestamp) sheet.getRange(reservedTimestampCell).setValue(ISODateString(new Date())); // Update timestamp
  49.  
  50. /// ...add videos to the playlist
  51. if (!debugFlag_dontUpdatePlaylists) {
  52. for (var i = 0; i < videoIds.length; i++) {
  53. try {
  54. YouTube.PlaylistItems.insert
  55. ( { snippet:
  56. { playlistId: playlistId,
  57. resourceId:
  58. { videoId: videoIds[i],
  59. kind: 'youtube#video'
  60. }
  61. }
  62. }, 'snippet,contentDetails'
  63. );
  64. } catch (e) {
  65. Logger.log("ERROR: " + e.message);
  66. continue;
  67. }
  68.  
  69. Utilities.sleep(1000);
  70. }
  71. }
  72. }
  73. if (!debugFlag_dontUpdateTimestamp) sheet.getRange(reservedTimestampCell).setValue(ISODateString(new Date()));
  74. }
  75.  
  76. function getVideoIds(channelId, lastTimestamp) {
  77. var videoIds = [];
  78.  
  79. // First call
  80. try {
  81.  
  82. var results = YouTube.Search.list('id', {
  83. channelId: channelId,
  84. maxResults: 50,
  85. order: "date",
  86. publishedAfter: lastTimestamp
  87. });
  88.  
  89. } catch (e) {
  90. Logger.log("ERROR: " + e.message);
  91. return;
  92. }
  93.  
  94. for (var j = 0; j < results.items.length; j++) {
  95. var item = results.items[j];
  96. videoIds.push(item.id.videoId);
  97. }
  98.  
  99. // Other calls
  100. var nextPageToken = results.nextPageToken;
  101. for (var pageNo = 0; pageNo < (-1+Math.ceil(results.pageInfo.totalResults / 50.0)); pageNo++) {
  102.  
  103. try {
  104. results = YouTube.Search.list('id', {
  105. channelId: channelId,
  106. maxResults: 50,
  107. order: "date",
  108. publishedAfter: lastTimestamp,
  109. pageToken: nextPageToken
  110. });
  111. } catch (e) {
  112. Logger.log("ERROR: " + e.message);
  113. continue;
  114. }
  115.  
  116. for (var j = 0; j < results.items.length; j++) {
  117. var item = results.items[j];
  118. videoIds.push(item.id.videoId);
  119. }
  120.  
  121. nextPageToken = results.nextPageToken;
  122. }
  123.  
  124. return videoIds;
  125. }
  126.  
  127. function getAllChannelIds() { // get YT Subscriptions-List, src: https://www.reddit.com/r/youtube/comments/3br98c/a_way_to_automatically_add_subscriptions_to/
  128. var AboResponse, AboList = [[],[]], nextPageToken = [], nptPage = 0, i, ix;
  129.  
  130. // Workaround: nextPageToken API-Bug (this Tokens are limited to 1000 Subscriptions... but you can add more Tokens.)
  131. nextPageToken = ['','CDIQAA','CGQQAA','CJYBEAA','CMgBEAA','CPoBEAA','CKwCEAA','CN4CEAA','CJADEAA','CMIDEAA','CPQDEAA','CKYEEAA','CNgEEAA','CIoFEAA','CLwFEAA','CO4FEAA','CKAGEAA','CNIGEAA','CIQHEAA','CLYHEAA'];
  132. try {
  133. do {
  134. AboResponse = YouTube.Subscriptions.list('snippet', {
  135. mine: true,
  136. maxResults: 50,
  137. order: 'alphabetical',
  138. pageToken: nextPageToken[nptPage],
  139. fields: 'items(snippet(title,resourceId(channelId)))'
  140. });
  141. for (i = 0, ix = AboResponse.items.length; i < ix; i++) {
  142. AboList[0][AboList[0].length] = AboResponse.items[i].snippet.title;
  143. AboList[1][AboList[1].length] = AboResponse.items[i].snippet.resourceId.channelId;
  144. }
  145. nptPage += 1;
  146. } while (AboResponse.items.length > 0 && nptPage < 20);
  147. if (AboList[0].length !== AboList[1].length) {
  148. return 'Length Title != ChannelId'; // returns a string === error
  149. }
  150. } catch (e) {
  151. return e;
  152. }
  153.  
  154. Logger.log('Acquired subscriptions %s', AboList[1].length);
  155. return AboList[1];
  156. }
  157.  
  158. function getAllChannelIds_OLD() { // Note: this function is not used. TODO: It seems to be leaking channels. Find out which ones and why?
  159. var channelIds = [];
  160.  
  161. // First call
  162. try {
  163. var results = YouTube.Subscriptions.list('snippet', {
  164. mine: true,
  165. maxResults: 50
  166. });
  167. } catch (e) {
  168. Logger.log("ERROR: " + e.message);
  169. return;
  170. }
  171. for (var i = 0; i < results.items.length; i++) {
  172. var item = results.items[i];
  173. channelIds.push(item.snippet.resourceId.channelId);
  174. }
  175.  
  176. // Other calls
  177. var nextPageToken = results.nextPageToken;
  178. for (var pageNo = 0; pageNo < (-1+Math.ceil(results.pageInfo.totalResults / 50.0)); pageNo++) {
  179.  
  180. try {
  181. results = YouTube.Subscriptions.list('snippet', {
  182. mine: true,
  183. maxResults: 50,
  184. pageToken: nextPageToken
  185. });
  186. } catch (e) {
  187. Logger.log("ERROR: " + e.message);
  188. continue;
  189. }
  190. for (var i = 0; i < results.items.length; i++) {
  191. var item = results.items[i];
  192. channelIds.push(item.snippet.resourceId.channelId);
  193. }
  194.  
  195. nextPageToken = results.nextPageToken;
  196. }
  197.  
  198. Logger.log('Acquired subscriptions %s, Actual subscriptions %s', channelIds.length, results.pageInfo.totalResults);
  199. return channelIds;
  200. }
  201.  
  202. function ISODateString(d) { // modified from src: http://stackoverflow.com/questions/7244246/generate-an-rfc-3339-timestamp-similar-to-google-tasks-api
  203. function pad(n){return n<10 ? '0'+n : n}
  204. return d.getUTCFullYear()+'-'
  205. + pad(d.getUTCMonth()+1)+'-'
  206. + pad(d.getUTCDate())+'T'
  207. + pad(d.getUTCHours())+':'
  208. + pad(d.getUTCMinutes())+':'
  209. + pad(d.getUTCSeconds())+'.000Z'
  210. }
  211.  
  212. function onOpen() {
  213. SpreadsheetApp.getActiveSpreadsheet().addMenu("Functions", [{name: "Update Playlists", functionName: "updatePlaylists"}]);
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement