What.CD Spotify

Add a Spotify link & embedded player to torrents on What.CD

  1. // ==UserScript==
  2. // @name What.CD Spotify
  3. // @namespace https://greasyfork.org/users/62518
  4. // @description Add a Spotify link & embedded player to torrents on What.CD
  5. // @version 0.32
  6. // @match https://what.cd/*
  7. // @grant GM_registerMenuCommand
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // ==/UserScript==
  11. // spacepandas edit hack thing, credits to orkyl and aphex80 for all the actual work
  12.  
  13. var maxSizeCache = 1000;
  14. var stringSimilarityThreshold = 0.6;
  15. localStorage.what = localStorage.what || JSON.stringify([]);
  16.  
  17. var curColor = GM_getValue("color", "black");
  18. var curPosition = GM_getValue("position", "above");
  19.  
  20. GM_registerMenuCommand("What.CD Spotify: Switch widget theme colors", function() {
  21. if (curColor === "black") {
  22. if(confirm("Switch to white Spotify widget theme?")) {
  23. GM_setValue("color", "white");
  24. location.reload();
  25. }
  26. } else if (curColor === "white") {
  27. if(confirm("Switch to black Spotify widget theme?")) {
  28. GM_setValue("color", "black");
  29. location.reload();
  30. }
  31. }
  32. });
  33.  
  34. GM_registerMenuCommand("What.CD Spotify: Switch widget position relative to artwork", function() {
  35. if (curPosition === "above") {
  36. if(confirm("Move the Spotify widget below Album/Artist artwork?")) {
  37. GM_setValue("position", "below");
  38. location.reload();
  39. }
  40. } else if (curPosition === "below") {
  41. if(confirm("Move the Spotify widget above Album/Artist artwork?")) {
  42. GM_setValue("position", "above");
  43. location.reload();
  44. }
  45. }
  46. });
  47.  
  48. function createSpotifyLink(link, imageSource) {
  49. var a = document.createElement('a');
  50. a.href = link;
  51. a.title = 'Listen in Spotify';
  52. var img = document.createElement('img');
  53. img.style.border = 'none';
  54. img.style.marginLeft = '3px';
  55. img.style.marginRight = '3px';
  56. img.src = imageSource;
  57. img.width = 15;
  58. a.appendChild(img);
  59. return a;
  60. }
  61.  
  62. function createSpotifyLinkGreen(link) {
  63. return createSpotifyLink(link, 'data:image/png;charset=utf-8;base64,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');
  64. }
  65.  
  66. function createSpotifyLinkBlue(link) {
  67. return createSpotifyLink(link, 'data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKnGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4zMDA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjY1NTM1PC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMDA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3BuZzwvZGM6Zm9ybWF0PgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6OTNkMzUxMGItNTUxNi00ZGVmLTlkZTEtODk4MzJhMDRjYTk1PC94bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpIaXN0b3J5PgogICAgICAgICAgICA8cmRmOlNlcT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IChNYWNpbnRvc2gpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA1LTA5VDAxOjM5OjQyKzAyOjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjkzZDM1MTBiLTU1MTYtNGRlZi05ZGUxLTg5ODMyYTA0Y2E5NTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IChNYWNpbnRvc2gpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA1LTA5VDAxOjQwOjQ0KzAyOjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjAwZTBhNmVhLWRjOWEtNGMxNi04NzM3LTJkNjYyZDQ0ODY3Mzwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6MDBlMGE2ZWEtZGM5YS00YzE2LTg3MzctMmQ2NjJkNDQ4NjczPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpwaG90b3Nob3A6MDgzODgzNGEtMzY2YS0xMTc4LWI3YTctZTczODljZjUxOTUzPC94bXBNTTpEb2N1bWVudElEPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxNS0wNS0wOFQyMjo1NToxMyswMjowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMTUtMDUtMDlUMDE6NDA6NDQrMDI6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE1LTA1LTA5VDAxOjQwOjQ0KzAyOjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNCAo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');
  68. }
  69.  
  70. function getCache(key) {
  71. var list = JSON.parse(localStorage.what);
  72. var res = null;
  73. $(list).each(function(i, el) {
  74. if (el.key === key) {
  75. res = el.value;
  76. return false;
  77. }
  78. });
  79. return res;
  80. }
  81.  
  82. function setCache(o) {
  83. var list = JSON.parse(localStorage.what);
  84. if (list.length == maxSizeCache) {
  85. list.shift();
  86. }
  87. list.push(o);
  88. localStorage.what = JSON.stringify(list);
  89. }
  90.  
  91. function getSpotifyArtistId(whatArtist, onSuccess) {
  92.  
  93. var cachedArtistId = getCache(whatArtist);
  94. if (cachedArtistId !== null && cachedArtistId !== '') {
  95. onSuccess(cachedArtistId);
  96. return;
  97. }
  98.  
  99. var encodedArtist = whatArtist.replace(" ", "+").replace("&", "");
  100. if (encodedArtist === '') {
  101. onSuccess('');
  102. return;
  103. }
  104.  
  105. $.get('https://api.spotify.com/v1/search?q=' + encodedArtist + '&type=artist', function(data) {
  106. var artists = data.artists.items;
  107. if (artists !== null && artists.length > 0) {
  108. var bestArtistId = null;
  109. var rank = 0;
  110. $(artists).each(function(i, artist) {
  111. if (rank < sSimilarity(artist.name.toUpperCase(), whatArtist.toUpperCase())) {
  112. rank = sSimilarity(artist.name.toUpperCase(), whatArtist.toUpperCase());
  113. bestArtistId = artist.id;
  114. }
  115. });
  116. setCache({ key: whatArtist, value: bestArtistId });
  117. onSuccess(bestArtistId);
  118. } else {
  119. onSuccess('');
  120. }
  121. });
  122. }
  123.  
  124. function getSpotifyArtistAlbums(artistId, onSuccess) {
  125.  
  126. $.get('https://api.spotify.com/v1/artists/' + artistId + '/albums?limit=50', function(data) {
  127. var albumItems = data.items;
  128. var albums = [];
  129. $(albumItems).each(function(i, albumItem) {
  130. albums.push({ name : albumItem.name, id : albumItem.id });
  131. });
  132. onSuccess(albums);
  133. });
  134. }
  135.  
  136. function getSpotifyArtistAlbumId(artistId, whatAlbum, onSuccess) {
  137.  
  138. var cachedAlbumId = getCache(whatAlbum);
  139. if (cachedAlbumId !== null && cachedAlbumId !== '') {
  140. onSuccess(cachedAlbumId);
  141. return;
  142. }
  143.  
  144. $.get('https://api.spotify.com/v1/artists/' + artistId + '/albums', function(data) {
  145. var albums = data.items;
  146. var albumId = "";
  147. if (albums !== null && albums.length > 0) {
  148. $(albums).each(function(j, album) {
  149. if (sSimilarity(album.name.toUpperCase(), whatAlbum.toUpperCase()) >= stringSimilarityThreshold) {
  150. albumId = album.id;
  151. return false;
  152. }
  153. });
  154. setCache({ key: whatAlbum, value: albumId });
  155. onSuccess(albumId);
  156. } else {
  157. onSuccess('');
  158. }
  159. });
  160. }
  161.  
  162. // DOM methods
  163.  
  164. var dom = {
  165. id: function (id) { return document.getElementById(id); },
  166. qs: function (s, p) { return (p || document).querySelector(s); },
  167. qsa: function (s, p) { return (p || document).querySelectorAll(s); },
  168. cl: function (cl, p) { return (p || document).getElementsByClassName(cl); },
  169. tag: function (tag, p) { return (p || document).getElementsByTagName(tag); },
  170. txt: function (txt) { return document.createTextNode(txt); },
  171. app: function (parent, var_args) {
  172. for (var i = 1, il = arguments.length; i < il; ++i) {
  173. var child = arguments[i];
  174. if (typeof child == 'string') child = this.txt(child);
  175. if (child) parent.appendChild(child);
  176. }
  177. },
  178. mk: function (tag, attr, var_args) {
  179. var elem = document.createElement(tag);
  180. if (attr) for (var a in attr) if (attr.hasOwnProperty(a)) elem[a] = attr[a];
  181. if (arguments.length > 2) {
  182. var args = Array.prototype.slice.call(arguments, 2);
  183. args.unshift(elem);
  184. this.app.apply(this, args);
  185. }
  186. return elem;
  187. },
  188. par: function (tag, el) {
  189. do el = el.parentNode;
  190. while (el && el.tagName != tag.toUpperCase());
  191. return el;
  192. }
  193. };
  194.  
  195. function embedSpotifyPlaylist(id) {
  196. var themecolor = GM_getValue("color", "black");
  197. var h = "320"; // height must be at least 80px more than width (minimum: 250px) or the compact player is rendered
  198. // frameborder & allowtransparency values required to render correctly!
  199.  
  200. var url = "https://embed.spotify.com/?uri=" + id + "&theme=" + themecolor;
  201.  
  202. var box = dom.mk('div', {className: 'box'},
  203. dom.mk('div', {className: 'head'},
  204. dom.mk('strong', null, 'Listen')),
  205. dom.mk('div', {className: 'player'},
  206. dom.mk('a', {position: "relative", left: "-16px"},
  207. dom.mk('p', null,
  208. dom.mk('iframe', {src: url, width: "240px", height: h, frameborder: "0", allowtransparency: "true", style: "border:none;"})))));
  209.  
  210. var elem = dom.cl('box')[0];
  211.  
  212. if(GM_getValue("position", "above") === "above") {
  213. elem.parentNode.insertBefore(box, elem);
  214. } else {
  215. if(dom.cl('box_image')[0] === null) {
  216. elem.parentNode.insertBefore(box, elem);
  217. }
  218. elem.appendChild(box);
  219. }
  220.  
  221. }
  222.  
  223.  
  224. /*************************************/
  225. /************* Top 10 ****************/
  226. /*************************************/
  227. if (window.location.href.indexOf('top10.php') > -1) {
  228. var processTable = function (table) {
  229. var groups = $('div.group_info', table);
  230. $(groups).each(function(i, group) {
  231. var whatArtist = $(group).find('a[href*="artist.php"]')[0];
  232. var whatAlbum = $(group).find('a[href*="torrents.php?id"]')[0];
  233. whatAlbum = $(whatAlbum).text();
  234. whatArtist = $(whatArtist).text();
  235.  
  236. getSpotifyArtistId(whatArtist, function(artistId) {
  237. if (artistId !== '' && artistId !== undefined) {
  238. getSpotifyArtistAlbumId(artistId, whatAlbum, function(albumId) {
  239. var a = null;
  240. if (albumId !== '') {
  241. a = createSpotifyLinkGreen('spotify:album:' + albumId);
  242. } else {
  243. a = createSpotifyLinkBlue('spotify:artist:' + artistId);
  244. }
  245. $(group).prepend(a);
  246. });
  247. }
  248. });
  249. });
  250. };
  251.  
  252. $('.torrent_table').each(function () { processTable(this); });
  253.  
  254. new MutationObserver(function (mutes) {
  255. mutes.forEach(function (m) {
  256. $(m.addedNodes).each(function () {
  257. if (this.nodeName == 'TABLE') processTable(this);
  258. });
  259. });
  260. }).observe(document.querySelector('.thin'), { childList: true });
  261. }
  262.  
  263. /*************************************/
  264. /*********** Artist page *************/
  265. /*************************************/
  266. if (window.location.href.indexOf('artist.php') > -1) {
  267. var whatArtist = $('h2').text();
  268. getSpotifyArtistId(whatArtist, function(artistId) {
  269. if (artistId !== '' && artistId !== undefined) {
  270. var a = createSpotifyLinkBlue('spotify:artist:' + artistId);
  271. $('h2').append(a);
  272. embedSpotifyPlaylist('spotify:artist:' + artistId);
  273. getSpotifyArtistAlbums(artistId, function(albums) {
  274. var groups = $('#torrents_album, #torrents_ep').find('div.group_info');
  275. $(groups).each(function(i, group) {
  276. var whatAlbum = $(group).find('a[href*="torrents.php?id"]')[0];
  277. whatAlbum = $(whatAlbum).text();
  278. var album = $.grep(albums, function(album) {
  279. return sSimilarity(album.name.toUpperCase(), whatAlbum.toUpperCase()) >= stringSimilarityThreshold;
  280. });
  281. if (album.length > 0) {
  282. setCache({ key: whatAlbum, value: album[0].id });
  283. var a = createSpotifyLinkGreen('spotify:album:' + album[0].id);
  284. $(group).prepend(a);
  285. }
  286. });
  287. });
  288. }
  289. });
  290. }
  291.  
  292. /*************************************/
  293. /*********** Torrent page ************/
  294. /*************************************/
  295. if (window.location.href.indexOf('torrents.php?id') > -1) {
  296. var whatArtist = $('h2 > a').text();
  297. var whatAlbum = $('h2 > span').text();
  298.  
  299. getSpotifyArtistId(whatArtist, function(artistId) {
  300. if (artistId !== '' && artistId !== undefined) {
  301. getSpotifyArtistAlbumId(artistId, whatAlbum, function(albumId) {
  302. var a = null;
  303. if (albumId !== '') {
  304. a = createSpotifyLinkGreen('spotify:album:' + albumId);
  305. embedSpotifyPlaylist('spotify:album:' + albumId);
  306. } else {
  307. a = createSpotifyLinkBlue('spotify:artist:' + artistId);
  308. }
  309. $('h2').append(a);
  310. });
  311. }
  312. });
  313. }
  314.  
  315. /*************************************/
  316. /******* Bookmark artist page ********/
  317. /*************************************/
  318. if (window.location.href.indexOf('bookmarks.php?type=artists') > -1) {
  319. var tds = $('.artist_table').find('.rowa, .rowb').find('td');
  320. var artists = $('.artist_table').find('a[href*="artist.php?id"]');
  321. $(artists).each(function(i, artistElement) {
  322. artist = $(artistElement).text();
  323. getSpotifyArtistId(artist, function(artistId) {
  324. if (artistId !== '') {
  325. var a = createSpotifyLinkGreen('spotify:artist:' + artistId);
  326. var x = $('div.group_info')[i];
  327. $(tds[i]).prepend(a);
  328. }
  329. });
  330. });
  331. }
  332.  
  333. /*************************************/
  334. /******* Bookmark torrent page *******/
  335. /*************************************/
  336. if (window.location.href.indexOf('bookmarks.php?type=torrents') > -1) {
  337. var groups = $('.group');
  338. $(groups).each(function(i, group) {
  339. var whatArtistElement = $(group).find('a[href*="artist.php"]')[0];
  340. var whatAlbumElement = $(group).find('a[href*="torrents.php?id"]')[0];
  341. whatAlbum = $(whatAlbumElement).text();
  342. whatArtist = $(whatArtistElement).text();
  343.  
  344. getSpotifyArtistId(whatArtist, function(artistId) {
  345. if (artistId !== '' && artistId !== undefined) {
  346. getSpotifyArtistAlbumId(artistId, whatAlbum, function(albumId) {
  347. var a = null;
  348. if (albumId !== '') {
  349. a = createSpotifyLinkGreen('spotify:album:' + albumId);
  350. } else {
  351. a = createSpotifyLinkBlue('spotify:artist:' + artistId);
  352. }
  353. $(whatArtistElement).before(a);
  354. });
  355. }
  356. });
  357. });
  358. }
  359.  
  360. var sSimilarity = function(sa1, sa2){
  361. // Compare two strings to see how similar they are.
  362. // Answer is returned as a value from 0 - 1
  363. // 1 indicates a perfect similarity (100%) while 0 indicates no similarity (0%)
  364. // Algorithm is set up to closely mimic the mathematical formula from
  365. // the article describing the algorithm, for clarity.
  366. // Algorithm source site: http://www.catalysoft.com/articles/StrikeAMatch.html
  367. // (Most specifically the slightly cryptic variable names were written as such
  368. // to mirror the mathematical implementation on the source site)
  369. //
  370. // 2014-04-03
  371. // Found out that the algorithm is an implementation of the Sørensen–Dice coefficient [1]
  372. // [1] http://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient
  373. //
  374. // The algorithm is an n-gram comparison of bigrams of characters in a string
  375.  
  376.  
  377. // for my purposes, comparison should not check case or whitespace
  378. var s1 = sa1.replace(/\s/g, "").toLowerCase();
  379. var s2 = sa2.replace(/\s/g, "").toLowerCase();
  380.  
  381. function intersect(arr1, arr2) {
  382. // I didn't write this. I'd like to come back sometime
  383. // and write my own intersection algorithm. This one seems
  384. // clean and fast, though. Going to try to find out where
  385. // I got it for attribution. Not sure right now.
  386. var r = [], o = {}, l = arr2.length, i, v;
  387. for (i = 0; i < l; i++) {
  388. o[arr2[i]] = true;
  389. }
  390. l = arr1.length;
  391. for (i = 0; i < l; i++) {
  392. v = arr1[i];
  393. if (v in o) {
  394. r.push(v);
  395. }
  396. }
  397. return r;
  398. }
  399.  
  400. var pairs = function(s){
  401. // Get an array of all pairs of adjacent letters in a string
  402. var pairs = [];
  403. for(var i = 0; i < s.length - 1; i++){
  404. pairs[i] = s.slice(i, i+2);
  405. }
  406. return pairs;
  407. };
  408.  
  409. //console.log(intersect(pairs(s1), pairs(s2)))
  410. var similarity_num = 2 * intersect(pairs(s1), pairs(s2)).length;
  411. var similarity_den = pairs(s1).length + pairs(s2).length;
  412. var similarity = similarity_num / similarity_den;
  413. return similarity;
  414. };