Inject2Download

Simple media download script

当前为 2018-07-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Inject2Download
  3. // @namespace http://lkubuntu.wordpress.com/
  4. // @version 0.4.4
  5. // @description Simple media download script
  6. // @author Anonymous Meerkat
  7. // @include *
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @grant GM.getValue
  11. // @grant GM.setValue
  12. // @grant none
  13. // @license MIT License
  14. // @run-at document-start
  15. // ==/UserScript==
  16.  
  17. // NOTE: This script now requires GM_setValue/getValue for storing preferences
  18.  
  19. (function() {
  20. "use strict";
  21.  
  22. var injected_set = {};
  23. var did_prefs = false;
  24.  
  25. function get_window() {
  26. var win = window;
  27. if (typeof unsafeWindow !== "undefined")
  28. win = unsafeWindow;
  29. return win;
  30. }
  31.  
  32. var win = get_window();
  33.  
  34. // Most of these are disabled by default in order to avoid modifying the user experience in unexpected ways
  35. var config_template = {
  36. simpleplayers: {
  37. name: "Replace with native players if possible",
  38. options: {
  39. "yes": "Yes",
  40. "flash": "Only if Flash is used",
  41. "no": "No"
  42. },
  43. default: "no"
  44. },
  45. noads: {
  46. name: "Block ads if possible (using a proper adblocker is highly recommended)",
  47. default: false
  48. },
  49. // TODO: Implement
  50. /*download: {
  51. name: "Enable downloading via the player itself if possible",
  52. default: false
  53. },*/
  54. blacklist: {
  55. name: "Blacklisted domains (one per line)",
  56. type: "textarea",
  57. default: "translate.google.com"
  58. }
  59. };
  60.  
  61. var config = {};
  62.  
  63. for (var key in config_template) {
  64. config[key] = config_template[key].default;
  65. /*(function(key) {
  66. GM.getValue(key).then(
  67. function (data) {
  68. if (data !== undefined)
  69. config[key] = data;
  70. },
  71. function () {}
  72. );
  73. })(key);*/
  74.  
  75.  
  76. // Having both work as callbacks is possible, but introduces delay
  77. // in cases where it's not necessary
  78. if (typeof GM_getValue !== "undefined") {
  79. var data = GM_getValue(key);
  80. if (data !== undefined)
  81. config[key] = data;
  82. } else if (typeof GM !== "undefined" && GM.getValue) {
  83. GM.getValue(key).then(function (data) {
  84. if (data !== undefined) {
  85. config[key] = data;
  86. }
  87. }, function() {});
  88. }
  89. }
  90.  
  91. function check_host(host) {
  92. var ourhost = window.location.hostname.toLowerCase();
  93. host = host.replace(/^ */, "").replace(/ *$/, "");
  94. if (ourhost === host.toLowerCase() ||
  95. (ourhost.indexOf("." + host) >= 0 &&
  96. ourhost.indexOf("." + host) === (ourhost.length - host.length - 1))) {
  97. return true;
  98. }
  99.  
  100. return false;
  101. }
  102.  
  103. function normalize_url(url) {
  104. if (!url)
  105. return url;
  106.  
  107. return url.replace(/^[a-z]+:\/\//, "//");
  108. }
  109.  
  110. function check_similar_url(url1, url2) {
  111. return normalize_url(url1) === normalize_url(url2);
  112. }
  113.  
  114. var blacklisted = false;
  115. var verified_blacklisted = false;
  116. function check_blacklisted() {
  117. var blacklist = config.blacklist.split("\n");
  118. blacklisted = false;
  119. var host = window.location.hostname.toLowerCase();
  120. for (var i = 0; i < blacklist.length; i++) {
  121. var normalized = blacklist[i].replace(/^ */, "").replace(/ *$/, "");
  122. if (host === normalized.toLowerCase() ||
  123. (host.indexOf("." + normalized) >= 0 &&
  124. host.indexOf("." + normalized) === (host.length - normalized.length - 1))) {
  125. console.log("[i2d] Blacklisted: " + normalized);
  126. blacklisted = true;
  127. break;
  128. }
  129. }
  130. return blacklisted;
  131. }
  132.  
  133. // Preferences
  134. if (window.location.hostname.toLowerCase() == "anonymousmeerkat.github.io" &&
  135. window.location.href.indexOf("anonymousmeerkat.github.io/inject2download/prefs.html") >= 0 &&
  136. !did_prefs) {
  137. run_on_load(function() {
  138. var text = [
  139. "<html><head><title>Inject2Download Preferences</title></head><body style='margin:0;padding:1em'>",
  140. "<div style='width:100%'><h2>Inject2Download</h2></div>",
  141. "<div id='prefs'></div>",
  142. "<div id='save'><button id='savebtn'>Save</button><br /><span id='savetxt'></span></div>",
  143. "</body></html>"
  144. ].join("");
  145. document.documentElement.innerHTML = text;
  146.  
  147. var prefs = document.getElementById("prefs");
  148. prefs.appendChild(document.createElement("hr"));
  149. for (var key in config_template) {
  150. var template = config_template[key];
  151.  
  152. var prefdiv = document.createElement("div");
  153. prefdiv.id = "pref-" + key;
  154. prefdiv.style.paddingBottom = "1em";
  155. var title = document.createElement("div");
  156. title.style.paddingBottom = ".5em";
  157. title.innerHTML = template.name;
  158. prefdiv.appendChild(title);
  159.  
  160. if (typeof template.default === "boolean" ||
  161. "options" in template) {
  162. var options = template.options;
  163. if (typeof template.default === "boolean") {
  164. options = {
  165. "true": "Yes",
  166. "false": "No"
  167. };
  168. }
  169.  
  170. for (var option in options) {
  171. var input = document.createElement("input");
  172. input.name = key;
  173. input.value = option;
  174. input.type = "radio";
  175. input.id = key + "-" + option;
  176.  
  177. if (config[key].toString() === option)
  178. input.setAttribute("checked", true);
  179.  
  180. var label = document.createElement("label");
  181. label.setAttribute("for", input.id);
  182. label.innerHTML = options[option];
  183.  
  184. prefdiv.appendChild(input);
  185. prefdiv.appendChild(label);
  186. prefdiv.appendChild(document.createElement("br"));
  187. }
  188. } else if (template.type === "textarea") {
  189. var input = document.createElement("textarea");
  190. input.name = key;
  191. input.style.width = "30em";
  192. input.style.height = "10em";
  193. input.innerHTML = config[key];
  194.  
  195. prefdiv.appendChild(input);
  196. } else {
  197. var input = document.createElement("input");
  198. input.name = key;
  199. input.value = config[key];
  200. input.style.width = "50em";
  201.  
  202. prefdiv.appendChild(input);
  203. }
  204.  
  205. prefs.appendChild(prefdiv);
  206. prefs.appendChild(document.createElement("hr"));
  207. }
  208.  
  209. document.getElementById("savebtn").onclick = function() {
  210. for (var key in config_template) {
  211. var els = document.getElementsByName(key);
  212. var value = undefined;
  213. if (els.length > 1) {
  214. // radio
  215. for (var i = 0; i < els.length; i++) {
  216. if (els[i].checked) {
  217. value = els[i].value;
  218. if (value === "true")
  219. value = true;
  220. if (value === "false")
  221. value = false;
  222. break;
  223. }
  224. }
  225. } else {
  226. if (els[0].tagName === "INPUT") {
  227. value = els[0].value;
  228. } else if (els[0].tagName === "TEXTAREA") {
  229. value = els[0].value;
  230. }
  231. }
  232. console.log("[i2d] " + key + " = " + value);
  233.  
  234. if (typeof GM_setValue !== "undefined")
  235. GM_setValue(key, value);
  236. else if (typeof GM !== "undefined" && GM.setValue)
  237. GM.setValue(key, value);
  238. }
  239. document.getElementById("savetxt").innerHTML = "Saved!";
  240. setTimeout(function() {
  241. document.getElementById("savetxt").innerHTML = "";
  242. }, 3000);
  243. };
  244.  
  245. console.log("[i2d] Finished rendering preferences page");
  246. });
  247. did_prefs = true;
  248. }
  249.  
  250. // Helper functions
  251. function run_on_load(f) {
  252. if (document.readyState === "complete" ||
  253. document.readyState === "interactive") {
  254. f();
  255. } else {
  256. var listener = function() {
  257. if (document.readyState === "complete" ||
  258. document.readyState === "interactive") {
  259. f();
  260.  
  261. document.removeEventListener("readystatechange", listener);
  262. }
  263. };
  264.  
  265. document.addEventListener("readystatechange", listener);
  266. //document.addEventListener('DOMContentLoaded', f, false);
  267. //window.addEventListener('load', f, false);
  268. }
  269. }
  270.  
  271. var i2d_url_list = [];
  272. function i2d_show_url(namespace, url, description) {
  273. if (!blacklisted && !verified_blacklisted) {
  274. if (check_blacklisted()) {
  275. verified_blacklisted = true;
  276. }
  277. }
  278.  
  279. if (blacklisted)
  280. return;
  281.  
  282. function get_absolute_url(url) {
  283. var a = document.createElement('a');
  284. a.href = url;
  285. return a.href;
  286. }
  287.  
  288. function run_on_load(f) {
  289. if (document.readyState === "complete" ||
  290. document.readyState === "interactive") {
  291. f();
  292. } else {
  293. var listener = function() {
  294. if (document.readyState === "complete" ||
  295. document.readyState === "interactive") {
  296. f();
  297.  
  298. document.removeEventListener("readystatechange", listener);
  299. }
  300. };
  301.  
  302. document.addEventListener("readystatechange", listener);
  303. //document.addEventListener('DOMContentLoaded', f, false);
  304. //window.addEventListener('load', f, false);
  305. }
  306. }
  307.  
  308. if (!description)
  309. description = "";
  310.  
  311. if (typeof url !== "string" || url.replace("\s", "").length === 0)
  312. return;
  313.  
  314. if (url.match(/^mediasource:/) || url.match(/^blob:/) || url.match(/^data:/))
  315. return;
  316.  
  317. url = get_absolute_url(url);
  318.  
  319. for (var i = 0; i < i2d_url_list.length; i++) {
  320. if (i2d_url_list[i][0] === namespace &&
  321. i2d_url_list[i][1] === url &&
  322. i2d_url_list[i][2] === description)
  323. return;
  324. }
  325.  
  326.  
  327. i2d_url_list.push([namespace, url, description]);
  328.  
  329. var newurl = decodeURIComponent(url);
  330.  
  331. var text = "[" + namespace + "] " + description + ": ";
  332.  
  333. console.log("[i2d] " + text + newurl);
  334.  
  335. run_on_load(function() {
  336. var el = document.getElementById("i2d-popup");
  337. var elspan = document.getElementById("i2d-popup-x");
  338. var elspan1 = document.getElementById("i2d-popup-close");
  339. var elspan2 = document.getElementById("i2d-popup-prefs");
  340. var eldiv = document.getElementById("i2d-popup-div");
  341. var eldivhold = document.getElementById("i2d-popup-div-holder");
  342. if (!el) {
  343. el = document.createElement("div");
  344. el.style.all = "initial";
  345. //el.style.position = "absolute";
  346. el.style.width = "max(60%, 100em)";
  347. el.style.height = "max(60%, 100em)";
  348. el.style.maxWidth = "100%";
  349. el.style.maxHeight = "100%";
  350. el.style.height = "auto";
  351. el.style.width = "auto";
  352. el.style.background = "white";
  353. el.style.top = "0px";
  354. el.style.left = "0px";
  355. el.style.zIndex = Number.MAX_SAFE_INTEGER - 1;
  356. el.style.color = "black";
  357. el.style.fontFamily = "sans-serif";
  358. el.style.fontSize = "16px";
  359. el.style.lineHeight = "normal";
  360. el.style.textAlign = "left";
  361. el.style.overflow = "scroll";
  362. el.style.position = "absolute";
  363.  
  364. /*el.ondblclick = function() {
  365. el.parentElement.removeChild(el);
  366. };*/
  367. eldivhold = document.createElement("div");
  368. eldivhold.id = "i2d-popup-span-holder";
  369. eldivhold.style.all = "initial";
  370. eldivhold.style.width = "100%";
  371. eldivhold.style.display = "block";
  372. eldivhold.style.overflow = "auto";
  373. eldivhold.style.paddingBottom = ".5em";
  374.  
  375. elspan = document.createElement("span");
  376. elspan.style.all = "initial";
  377. elspan.style.fontSize = "130%";
  378. elspan.style.cursor = "pointer";
  379. elspan.style.color = "#900";
  380. elspan.style.padding = ".1em";
  381. elspan.style.float = "left";
  382. elspan.style.display = "inline";
  383. elspan.id = "i2d-popup-x";
  384. elspan.innerHTML = '[hide]';
  385. elspan.style.textDecoration = "underline";
  386. eldivhold.appendChild(elspan);
  387.  
  388. elspan1 = document.createElement("span");
  389. elspan1.style.all = "initial";
  390. elspan1.style.fontSize = "130%";
  391. elspan1.style.cursor = "pointer";
  392. elspan1.style.color = "#900";
  393. elspan1.style.padding = ".1em";
  394. elspan1.style.float = "right";
  395. //elspan1.style.display = "none";
  396. elspan1.style.display = "inline";
  397. elspan1.id = "i2d-popup-close";
  398. elspan1.innerHTML = '[close]';
  399. elspan1.style.textDecoration = "underline";
  400. eldivhold.appendChild(elspan1);
  401.  
  402. elspan2 = document.createElement("a");
  403. elspan2.style.all = "initial";
  404. elspan2.style.fontSize = "130%";
  405. elspan2.style.cursor = "pointer";
  406. elspan2.style.color = "#900";
  407. elspan2.style.padding = ".1em";
  408. elspan2.style.float = "left";
  409. //elspan1.style.display = "none";
  410. elspan2.style.display = "inline";
  411. elspan2.id = "i2d-popup-prefs";
  412. elspan2.innerHTML = '[options]';
  413. elspan2.href = "https://anonymousmeerkat.github.io/inject2download/prefs.html";
  414. elspan2.setAttribute("target", "_blank");
  415. elspan2.style.textDecoration = "underline";
  416. eldivhold.appendChild(elspan2);
  417.  
  418. //el.innerHTML = "<br style='line-height:150%' />";
  419. el.id = "i2d-popup";
  420. eldiv = document.createElement("div");
  421. eldiv.style.all = "initial";
  422. eldiv.id = "i2d-popup-div";
  423. //eldiv.style.display = "none";
  424. eldiv.style.display = "block";
  425. el.appendChild(eldiv);
  426. el.insertBefore(eldivhold, el.firstChild);
  427. document.documentElement.appendChild(el);
  428.  
  429. elspan.onclick = function() {
  430. /*var el = document.getElementById("i2d-popup");
  431. el.parentElement.removeChild(el);*/
  432. var eldiv = document.getElementById("i2d-popup-div");
  433. var elspan = document.getElementById("i2d-popup-x");
  434. if (eldiv.style.display === "none") {
  435. elspan.innerHTML = '[hide]';
  436. eldiv.style.display = "block";
  437. elspan1.style.display = "inline";
  438. } else {
  439. elspan.innerHTML = '[show]';
  440. eldiv.style.display = "none";
  441. elspan1.style.display = "none";
  442. }
  443. };
  444.  
  445. elspan1.onclick = function() {
  446. var el = document.getElementById("i2d-popup");
  447. el.parentElement.removeChild(el);
  448. };
  449. }
  450. var shorturl = newurl;
  451. if (shorturl.length > 100) {
  452. shorturl = shorturl.substring(0, 99) + "&hellip;";
  453. }
  454. var el_divspan = document.createElement("span");
  455. el_divspan.style.all = "initial";
  456. el_divspan.innerHTML = text;
  457. eldiv.appendChild(el_divspan);
  458. var el_a = document.createElement("a");
  459. el_a.href = newurl;
  460. el_a.style.all = "initial";
  461. el_a.style.color = "blue";
  462. el_a.style.textDecoration = "underline";
  463. el_a.style.cursor = "pointer";
  464. el_a.title = newurl;
  465. el_a.innerHTML = shorturl;
  466. eldiv.appendChild(el_a);
  467. var el_br = document.createElement("br");
  468. el_br.style.all = "initial";
  469. eldiv.appendChild(el_br);
  470. //eldiv.innerHTML += text + "<a href='" + newurl + "' style='color:blue' title='" + newurl + "'>" + shorturl + "</a><br />";
  471.  
  472. // XXX: why is this needed? test: http://playbb.me/embed.php?w=718&h=438&vid=at/nw/flying_witch_-_01.mp4, animeplus.tv
  473. /*document.body.removeChild(el);
  474. el.style.position = "absolute";
  475. document.body.appendChild(el);*/
  476.  
  477. /*if (document.getElementById("i2d-popup-x"))
  478. document.getElementById("i2d-popup-x").parentElement.removeChild(document.getElementById("i2d-popup-x"));*/
  479.  
  480. /*el.insertBefore(elspan, el.firstChild);
  481. el.insertBefore(elspan1, el.firstChild);*/
  482. //el.insertBefore(eldivhold, el.firstChild);
  483. });
  484. }
  485.  
  486. function i2d_add_player(options) {
  487. var playlist = [];
  488. var elements = [];
  489. var ret = {};
  490.  
  491. /*var videoel = document.createElement("video");
  492. videoel.setAttribute("controls", "");
  493. options.element.appendChild(videoel);*/
  494.  
  495. if (!(options.elements instanceof Array) && !(options.elements instanceof NodeList)) {
  496. if (typeof options.elements === "string") {
  497. options.elements = document.querySelectorAll(options.elements);
  498. } else {
  499. options.elements = [options.elements];
  500. }
  501. }
  502. for (var i = 0; i < options.elements.length; i++) {
  503. (function(x) {
  504. if (!x)
  505. return;
  506. var videoel = document.createElement("video");
  507. videoel.setAttribute("controls", "");
  508. videoel.style.maxWidth = "100%";
  509. videoel.style.maxHeight = "100%";
  510. videoel.addEventListener("ended", function() {
  511. ret.next_playlist_item();
  512. });
  513. videoel.addEventListener("error", function() {
  514. ret.next_playlist_item();
  515. });
  516. /*var stylestr = "";
  517. for (var key in options.css) {
  518. stylestr += key + ":" + options.css[key] + ";"
  519. }*/
  520. for (var key in options.css) {
  521. videoel.style[key] = options.css[key];
  522. }
  523. //videoel.setAttribute("style", stylestr);
  524. if (options.replaceChildren) {
  525. x.innerHTML = "";
  526. }
  527. if (options.replace) {
  528. x.parentElement.replaceChild(videoel, x);
  529. } else {
  530. x.appendChild(videoel);
  531. }
  532. elements.push(videoel);
  533. })(options.elements[i]);
  534. }
  535. ret.add_urls = function(urls) {
  536. if (urls instanceof Array) {
  537. for (var i = 0; i < urls.length; i++) {
  538. ret.add_urls(urls[i]);
  539. }
  540. return;
  541. }
  542.  
  543. playlist.push(urls);
  544. if (playlist.length === 1) {
  545. ret.set_url(playlist[0]);
  546. }
  547. };
  548. ret.replace_urls = function(urls) {
  549. playlist = [];
  550. return ret.add_urls(urls);
  551. };
  552. var getext = function(url) {
  553. if (!url)
  554. return url;
  555.  
  556. return url.replace(/.*\.([^/.?]*)(?:\?.*)?$/, "$1").toLowerCase();
  557. };
  558. var loadscript = function(variable, url, cb) {
  559. if (!(variable in window)) {
  560. var script = document.createElement("script");
  561. script.src = url;
  562. script.onload = cb;
  563. document.head.insertBefore(script, document.head.lastChild);
  564. } else {
  565. cb();
  566. }
  567. };
  568. ret.set_url = function(url) {
  569. if (!url || typeof url !== "string")
  570. return;
  571. switch(getext(url)) {
  572. case "flv":
  573. loadscript("flvjs", "https://cdn.jsdelivr.net/npm/flv.js@latest", function() {
  574. var flvPlayer = flvjs.createPlayer({
  575. type: 'flv',
  576. url: url
  577. });
  578. for (var i = 0; i < elements.length; i++) {
  579. flvPlayer.attachMediaElement(elements[i]);
  580. }
  581. flvPlayer.load();
  582. });
  583. break;
  584. case "m3u8":
  585. loadscript("Hls", "https://cdn.jsdelivr.net/npm/hls.js@latest", function() {
  586. var hls = new Hls();
  587. hls.loadSource(url);
  588. for (var i = 0; i < elements.length; i++) {
  589. hls.attachMedia(elements[i]);
  590. }
  591. });
  592. break;
  593. default:
  594. for (var i = 0; i < elements.length; i++) {
  595. elements[i].src = url;
  596. }
  597. break;
  598. }
  599. };
  600. ret.next_playlist_item = function() {
  601. playlist = playlist.slice(1);
  602. if (playlist[0])
  603. ret.set_url(playlist[0]);
  604. };
  605. ret.setPlaying = function(playing) {
  606. for (var i = 0; i < elements.length; i++) {
  607. if (playing)
  608. elements[i].play();
  609. else
  610. elements[i].pause();
  611. }
  612. };
  613.  
  614. if (options.urls)
  615. ret.add_urls(options.urls);
  616.  
  617. return ret;
  618. }
  619.  
  620.  
  621. // Injecting functions
  622. var get_script_str = function(f) {
  623. return f.toString().replace(/^function.*{|}$/g, '');
  624. };
  625.  
  626. function add_script(s, el) {
  627. var script_body = "(function() {\n" + s + "\n})();";
  628. var myscript = document.createElement('script');
  629. myscript.className = "i2d";
  630. myscript.innerHTML = script_body;
  631. if (el) {
  632. el.appendChild(myscript);
  633. } else {
  634. document.head.appendChild(myscript);
  635. }
  636. }
  637.  
  638. function inject(variable, newvalue, aliases) {
  639. if (variable instanceof Array) {
  640. for (var i = 0; i < variable.length; i++) {
  641. inject(variable[i], newvalue, aliases);
  642. }
  643. return;
  644. }
  645.  
  646. console.log("[i2d] injecting " + variable);
  647. if (!aliases)
  648. aliases = [];
  649.  
  650. var initobjects = "";
  651. var subvariable = variable;
  652. var subindex = 0;
  653. while (true) {
  654. var index = subvariable.indexOf(".");
  655. var breakme = false;
  656. if (index < 0) {
  657. index = subvariable.length;
  658. breakme = true;
  659. }
  660. subvariable = subvariable.substr(index + 1);
  661. subindex += index + 1;
  662. var subname = variable.substr(0, subindex - 1);
  663. initobjects += "if (!" + subname + ") {" + subname + " = {};}\n";
  664. if (breakme)
  665. break;
  666. }
  667.  
  668. add_script("var config = " + JSON.stringify(config) + ";\n" +
  669. i2d_show_url.toString() + "\n" + i2d_add_player.toString() + "\n" +
  670. initobjects + "\n" +
  671. "if ((window." + variable + " !== undefined) && !(window." + variable + ".INJECTED)) {\n" +
  672. "var oldvariable = window." + variable + ";\n" +
  673. "var oldvariable_keys = Object.keys(oldvariable);\n" +
  674. "window." + variable + " = " + newvalue.toString() + ";\n" +
  675. "for (var i = 0; i < oldvariable_keys.length; i++) {\n" +
  676. " window." + variable + "[oldvariable_keys[i]] = oldvariable[oldvariable_keys[i]];\n" +
  677. "}\n" +
  678. "window." + variable + ".INJECTED = true;\n" +
  679. "var aliases = " + JSON.stringify(aliases) + ";\n" +
  680. "for (var i = 0; i < aliases.length; i++) {\n" +
  681. " if (aliases[i] in window && window[aliases[i]] == oldvariable)" +
  682. " window[aliases[i]] = window." + variable + "\n" +
  683. "}\n" +
  684. "}");
  685. }
  686.  
  687. function jquery_plugin_exists(name) {
  688. if (!("jQuery" in window) ||
  689. typeof window.jQuery !== "function" ||
  690. !("fn" in window.jQuery) ||
  691. !(name in window.jQuery.fn))
  692. return false;
  693.  
  694.  
  695. return true;
  696. }
  697.  
  698. function inject_jquery_plugin(name, value) {
  699. if (!jquery_plugin_exists(name) ||
  700. window.jQuery.fn[name].INJECTED)
  701. return;
  702.  
  703. inject("jQuery.fn." + name, value);
  704. }
  705.  
  706. var injected_urls = [];
  707.  
  708. (function(open) {
  709. window.XMLHttpRequest.prototype.open = function() {
  710. if (arguments[1]) {
  711. var src = arguments[1];
  712.  
  713. var url = null;
  714. for (var i = 0; i < injected_urls.length; i++) {
  715. if (injected_urls[i].url &&
  716. check_similar_url(injected_urls[i].url, src)) {
  717. url = injected_urls[i];
  718. break;
  719. }
  720.  
  721. if (injected_urls[i].pattern &&
  722. src.match(injected_urls[i].pattern)) {
  723. url = injected_urls[i];
  724. break;
  725. }
  726. }
  727.  
  728. if (url) {
  729. this.addEventListener("readystatechange", function() {
  730. if (this.readyState === 4) {
  731. url.func.bind(this)(src);
  732. }
  733. });
  734. }
  735. }
  736.  
  737. open.apply(this, arguments);
  738. };
  739. })(window.XMLHttpRequest.prototype.open);
  740.  
  741. function inject_url(pattern, func) {
  742. var obj = {func: func};
  743.  
  744. if (pattern instanceof RegExp) {
  745. obj.pattern = pattern;
  746. } else {
  747. obj.url = pattern;
  748. }
  749.  
  750. for (var i = 0; i < injected_urls.length; i++) {
  751. if (injected_urls[i].url === obj.url ||
  752. injected_urls[i].pattern === obj.pattern)
  753. return;
  754. }
  755.  
  756. injected_urls.push(obj);
  757. }
  758.  
  759. function can_inject(name) {
  760. if (name in window && (typeof window[name] === "object" || typeof window[name] === "function") && !window[name].INJECTED)
  761. return true;
  762. return false;
  763. }
  764.  
  765. function i2d_onload(f) {
  766. if (document.readyState === "loading") {
  767. document.addEventListener("DOMContentLoaded", f);
  768. } else {
  769. f();
  770. }
  771. }
  772.  
  773.  
  774. if (blacklisted)
  775. return;
  776.  
  777.  
  778. var injections = [
  779. // soundManager
  780. {
  781. variables: {
  782. window: "soundManager.createSound"
  783. },
  784. replace: function(context, args) {
  785. var arg1 = args[0];
  786. var arg2 = args[1];
  787.  
  788. if (typeof arg1 === "string")
  789. i2d_show_url("soundManager", arg2);
  790. else
  791. i2d_show_url("soundManager", arg1.url);
  792.  
  793. return context.oldvariable.apply(this, args);
  794. }
  795. },
  796. // jwplayer
  797. {
  798. variables: {
  799. window: "jwplayer"
  800. },
  801. replace: function(context, args) {
  802. var result = context.oldvariable.apply(this, args);
  803.  
  804. var check_sources = function(x, options) {
  805. if (!options)
  806. options = {};
  807.  
  808. if (typeof x === "object") {
  809. if (x instanceof Array) {
  810. for (var i = 0; i < x.length; i++) {
  811. check_sources(x[i]);
  812. }
  813. return;
  814. }
  815.  
  816. var label = "";
  817.  
  818. if ("title" in x)
  819. label += "[" + x.title + "]";
  820.  
  821. if ("label" in x)
  822. label += "[" + x.label + "]";
  823.  
  824. if ("kind" in x)
  825. label += "(" + x.kind + ")";
  826.  
  827. if ("streamer" in x) {
  828. i2d_show_url("jwplayer", x.streamer, "[stream]" + label);
  829. }
  830.  
  831. if ("file" in x) {
  832. i2d_show_url("jwplayer", x.file, label);
  833. }
  834.  
  835. if ("sources" in x) {
  836. check_sources(x.sources);
  837. }
  838.  
  839. if ("playlist" in x) {
  840. check_sources(x.playlist, {playlist: true});
  841. }
  842.  
  843. if ("tracks" in x) {
  844. check_sources(x.tracks, {playlist: true});
  845. }
  846. } else if (typeof x === "string") {
  847. i2d_show_url("jwplayer", x);
  848.  
  849. if (options.playlist) {
  850. inject_url(x, function() {
  851. check_sources(JSON.parse(this.responseText), {playlist: true});
  852. });
  853. }
  854. }
  855. };
  856.  
  857. if ("setup" in result) {
  858. var old_jwplayer_setup = result.setup;
  859. result.setup = function() {
  860. if (typeof arguments[0] === "object") {
  861. var x = arguments[0];
  862.  
  863. if ("modes" in x) {
  864. for (var i = 0; i < x.modes.length; i++) {
  865. // TODO: support more?
  866. if ("type" in x.modes[i] && x.modes[i].type === "html5") {
  867. if ("config" in x.modes[i] && "file" in x.modes[i].config) {
  868. check_sources(x.modes[i].config);
  869. }
  870. }
  871. }
  872. }
  873.  
  874. check_sources(x);
  875. }
  876.  
  877. if (config.noads && "advertising" in arguments[0])
  878. delete arguments[0].advertising;
  879.  
  880. return old_jwplayer_setup.apply(this, arguments);
  881. };
  882. }
  883.  
  884. if ("load" in result) {
  885. var old_jwplayer_load = result.load;
  886. result.load = function() {
  887. check_sources(arguments[0]);
  888. return old_jwplayer_load.apply(this, arguments);
  889. };
  890. }
  891.  
  892. if ("on" in result) {
  893. result.on('playlistItem', function(item) {
  894. check_sources(item.item);
  895. });
  896.  
  897. var old_jwplayer_on = result.on;
  898. result.on = function() {
  899. if (arguments[0] === "adBlock")
  900. return;
  901.  
  902. return old_jwplayer_on.apply(this, arguments);
  903. };
  904. }
  905.  
  906. return result;
  907. }
  908. },
  909. // flowplayer
  910. {
  911. variables: {
  912. window: ["flowplayer", "$f"]
  913. },
  914. replace: function(context, args) {
  915. var obj_baseurl = null;
  916. var els = [];
  917.  
  918. var urls = [];
  919. var url_pairs = {};
  920. var players = {};
  921. var add_url = function() {
  922. if (Object.keys(players).length === 0) {
  923. urls.push(arguments[1]);
  924. } else {
  925. for (var key in players) {
  926. players[key].add_urls(arguments[1]);
  927. }
  928. }
  929.  
  930. return i2d_show_url.apply(this, args);
  931. };
  932. var add_url_pair = function(el) {
  933. var newargs = Array.prototype.slice.call(arguments, 1);
  934. if (!(el in players)) {
  935. if (!url_pairs[el])
  936. url_pairs[el] = [];
  937. url_pairs[el].push(newargs[1]);
  938. } else {
  939. players[el].add_urls(newargs[1]);
  940. }
  941.  
  942. return i2d_show_url.apply(this, newargs);
  943. };
  944.  
  945. function get_url(x) {
  946. x = decodeURIComponent(x);
  947.  
  948. if (obj_baseurl) {
  949. if (x.match(/^[a-z]*:\/\//)) {
  950. return x;
  951. } else {
  952. return obj_baseurl + "/" + x;
  953. }
  954. } else {
  955. return x;
  956. }
  957. }
  958.  
  959. function check_sources(x, els, label) {
  960. if (typeof x === "string") {
  961. if (!x.match(/\.xml$/))
  962. add_url("flowplayer", get_url(x), label);
  963.  
  964. return;
  965. }
  966.  
  967. if (x instanceof Array) {
  968. for (var i = 0; i < x.length; i++) {
  969. check_sources(x[i], els, label);
  970. }
  971. return;
  972. }
  973.  
  974. if (typeof x !== "object")
  975. return;
  976.  
  977. // test: https://flowplayer.com/docs/player/standalone/vast/overlay.html
  978. if (config.noads && "ima" in x)
  979. delete x.ima;
  980.  
  981. label = "";
  982.  
  983. if ("title" in x)
  984. label += "[" + x.title + "]";
  985.  
  986. if ("clip" in x) {
  987. if ("baseUrl" in x.clip) {
  988. obj_baseurl = x.clip.baseUrl;
  989.  
  990. for (var i = 0; i < els.length; i++) {
  991. els[i].i2d_baseurl = obj_baseurl;
  992. }
  993. }
  994.  
  995. check_sources(x.clip, els, label);
  996. }
  997.  
  998. if ("sources" in x) {
  999. check_sources(x.sources, els, label);
  1000. }
  1001.  
  1002. if ("playlist" in x) {
  1003. check_sources(x.playlist, els, label);
  1004. }
  1005.  
  1006. if ("url" in x) {
  1007. check_sources(x.url, els, label);
  1008. }
  1009.  
  1010. if ("src" in x) {
  1011. check_sources(x.src, els. label);
  1012. }
  1013.  
  1014. if ("bitrates" in x) {
  1015. for (var j = 0; j < x.bitrates.length; j++) {
  1016. if ("url" in x.bitrates[j]) {
  1017. var description = "";
  1018. if (x.bitrates[j].isDefault)
  1019. description += "default:";
  1020. if (x.bitrates[j].sd)
  1021. description += "sd:";
  1022. if (x.bitrates[j].hd)
  1023. description += "hd:";
  1024. if (x.bitrates[j].bitrate)
  1025. description += x.bitrates[j].bitrate;
  1026.  
  1027. add_url("flowplayer", get_url(x.bitrates[j].url), description);
  1028. }
  1029. }
  1030. }
  1031. }
  1032.  
  1033. if (args.length >= 1) {
  1034. els = [null];
  1035.  
  1036. if (typeof args[0] === "string") {
  1037. try {
  1038. els[0] = document.getElementById(args[0]);
  1039. } catch(e) {
  1040. }
  1041.  
  1042. try {
  1043. if (!els[0])
  1044. els = document.querySelectorAll(args[0]);
  1045. } catch(e) {
  1046. els = [];
  1047. }
  1048. } else if (args[0] instanceof HTMLElement) {
  1049. els = [args[0]];
  1050. }
  1051. }
  1052.  
  1053. for (var i = 0; i < els.length; i++) {
  1054. if (!els[i] || !(els[i] instanceof HTMLElement))
  1055. continue;
  1056.  
  1057. if ("i2d_baseurl" in els[i])
  1058. obj_baseurl = els[i].i2d_baseurl;
  1059. }
  1060.  
  1061. var options = {};
  1062.  
  1063. if (args.length >= 3 && typeof args[2] === "object") {
  1064. check_sources(args[2], els);
  1065. options = args[2];
  1066. } else if (args.length >= 3 && typeof args[2] === "string") {
  1067. add_url("flowplayer", get_url(args[2]));
  1068. } else if (args.length === 2 && typeof args[1] === "object") {
  1069. check_sources(args[1], els);
  1070. options = args[1];
  1071. } else if (args.length === 2 && typeof args[1] === "string") {
  1072. add_url("flowplayer", get_url(args[1]));
  1073. }
  1074.  
  1075. var isflash = false;
  1076. if (args.length >= 2 && typeof args[1] === "string" && args[1].toLowerCase().match(/\.swf$/)) {
  1077. isflash = true;
  1078. }
  1079.  
  1080. for (var i = 0; i < els.length; i++) {
  1081. if (!els[i] || !(els[i] instanceof HTMLElement))
  1082. continue;
  1083.  
  1084. var href = els[i].getAttribute("href");
  1085. if (href) {
  1086. add_url_pair(els[i], "flowplayer", get_url(href), "href");
  1087. }
  1088. }
  1089.  
  1090. var oldvariable = context.oldvariable;
  1091. if (config.simpleplayers === "yes" ||
  1092. (config.simpleplayers === "flash" && isflash)) {
  1093. oldvariable = function() {
  1094. var css = {width: "100%", height: "100%"};
  1095. for (var key in options.screen) {
  1096. var val = options.screen[key];
  1097. switch(key) {
  1098. case "height":
  1099. case "width":
  1100. case "bottom":
  1101. case "top":
  1102. case "left":
  1103. case "right":
  1104. if (typeof val === "number") {
  1105. css[key] = val + "px";
  1106. } else {
  1107. css[key] = val;
  1108. }
  1109. break;
  1110. default:
  1111. css[key] = val;
  1112. break;
  1113. }
  1114. }
  1115. for (var i = 0; i < els.length; i++) {
  1116. var player_urls = url_pairs[els[i]] || [];
  1117. for (var x = 0; x < urls.length; x++) {
  1118. player_urls.push(urls[x]);
  1119. }
  1120. players[els[i]] = i2d_add_player({
  1121. elements: els[i],
  1122. replaceChildren: true,
  1123. urls: player_urls,
  1124. css: css
  1125. });
  1126. }
  1127.  
  1128. var allp = function(name) {
  1129. for (var key in players) {
  1130. players[key][name].apply(this, Array.prototype.slice.apply(args, 1));
  1131. }
  1132. };
  1133.  
  1134. var res = {};
  1135. var fns = [
  1136. "addClip",
  1137. "setPlaylist",
  1138. "load",
  1139. "playlist",
  1140. "play",
  1141. "ipad"
  1142. ];
  1143. for (var i = 0; i < fns.length; i++) {
  1144. res[fns[i]] = function(){};
  1145. }
  1146.  
  1147. return res;
  1148. };
  1149. }
  1150.  
  1151. var result = oldvariable.apply(this, args);
  1152.  
  1153. if (!result || typeof result !== "object")
  1154. return result;
  1155.  
  1156. if ("addClip" in result) {
  1157. var old_fplayer_addclip = result.addClip;
  1158. result.addClip = function() {
  1159. if (arguments.length > 0)
  1160. check_sources(arguments[0], els);
  1161.  
  1162. return old_fplayer_addclip.apply(this, arguments);
  1163. };
  1164. }
  1165.  
  1166. if ("setPlaylist" in result) {
  1167. var old_fplayer_setplaylist = result.setPlaylist;
  1168. result.setPlaylist = function() {
  1169. if (arguments.length > 0)
  1170. check_sources(arguments[0], els);
  1171.  
  1172. return old_fplayer_setplaylist.apply(this, arguments);
  1173. };
  1174. }
  1175.  
  1176. if ("load" in result) {
  1177. var old_fplayer_load = result.load;
  1178. result.load = function() {
  1179. if (arguments.length > 0)
  1180. check_sources(arguments[0], els);
  1181.  
  1182. return old_fplayer_load.apply(this, arguments);
  1183. };
  1184. }
  1185.  
  1186. if ("play" in result) {
  1187. var old_fplayer_play = result.play;
  1188. result.play = function() {
  1189. if (arguments.length > 0)
  1190. check_sources(arguments[0], els);
  1191.  
  1192. return old_fplayer_play.apply(this, arguments);
  1193. };
  1194. }
  1195.  
  1196. /*if ("on" in result) {
  1197. result.on("load", function(e, api, video) {
  1198. console.log(e);
  1199. check_sources(video || api.video, els);
  1200. });
  1201. }*/
  1202.  
  1203. return result;
  1204. },
  1205. after_inject: function(context) {
  1206. context.win.flowplayer(function(api, root) {
  1207. api.on("load", function(e, api, video) {
  1208. context.win.flowplayer().load(video || api.video);
  1209. });
  1210. });
  1211. }
  1212. },
  1213. // flowplayer (jQuery)
  1214. {
  1215. variables: {
  1216. jquery: "flowplayer"
  1217. },
  1218. replace: function(context, args) {
  1219. var newargs = Array.from(args);
  1220. newargs.unshift(jQuery(this)[0]);
  1221. return context.win.flowplayer.apply(this, newargs);
  1222. }
  1223. },
  1224. // video.js
  1225. {
  1226. variables: {
  1227. window: "videojs"
  1228. },
  1229. replace: function(context, args) {
  1230. if (args.length > 0 && typeof args[0] === "string") {
  1231. var my_el = document.getElementById(args[0]);
  1232. if (!my_el)
  1233. my_el = document.querySelector(args[0]);
  1234.  
  1235. if (my_el) {
  1236. if (my_el.src) {
  1237. i2d_show_url("videojs", my_el.src);
  1238. }
  1239.  
  1240. for (var i = 0; i < my_el.children.length; i++) {
  1241. if (my_el.children[i].tagName.toLowerCase() === "source") {
  1242. if (my_el.children[i].src) {
  1243. i2d_show_url("videojs", my_el.children[i].src, my_el.children[i].getAttribute("label"));
  1244. }
  1245. }
  1246. }
  1247. }
  1248. }
  1249.  
  1250. var result = context.oldvariable.apply(this, args);
  1251.  
  1252. var old_videojs_src = result.src;
  1253. result.src = function() {
  1254. if (arguments.length > 0 && typeof arguments[0] === "object") {
  1255. if ("src" in arguments[0]) {
  1256. i2d_show_url("videojs", arguments[0].src);
  1257. }
  1258. }
  1259.  
  1260. return old_videojs_src.apply(this, arguments);
  1261. };
  1262.  
  1263. return result;
  1264. }
  1265. },
  1266. // amp
  1267. {
  1268. variables: {
  1269. window: "amp"
  1270. },
  1271. replace: function(context, args) {
  1272. function show_amp_source(sourceobj) {
  1273. if ("protectionInfo" in sourceobj) {
  1274. console.log("[amp] Cannot decode protection info");
  1275. }
  1276. if ("src" in sourceobj)
  1277. i2d_show_url("amp", sourceobj.src);
  1278. }
  1279.  
  1280. if (args.length >= 2 && typeof args[1] === "object") {
  1281. if ("sourceList" in args[1]) {
  1282. for (var i = 0; i < args[1].sourceList.length; i++) {
  1283. show_amp_source(args[1].sourceList[i]);
  1284. }
  1285. }
  1286. }
  1287.  
  1288. var result = context.oldvariable.apply(this, args);
  1289.  
  1290. if (!result)
  1291. return result;
  1292.  
  1293. var old_amp_src = result.src;
  1294. result.src = function() {
  1295. for (var i = 0; i < args[0].length; i++) {
  1296. show_amp_source(args[0][i]);
  1297. }
  1298.  
  1299. return old_amp_src.apply(this, args);
  1300. };
  1301.  
  1302. return result;
  1303. }
  1304. },
  1305. // DJPlayer
  1306. {
  1307. variables: {
  1308. window: "DJPlayer"
  1309. },
  1310. proto: {
  1311. setMedia: function(context, args) {
  1312. if (args.length > 0 && typeof args[0] === 'string') {
  1313. i2d_show_url('DJPlayer', args[0]);
  1314. }
  1315.  
  1316. return context.oldvariable.apply(this, args);
  1317. }
  1318. }
  1319. },
  1320. // Bitmovin
  1321. {
  1322. variables: {
  1323. window: ["bitmovin.player", "bitdash", "bitmovinPlayer"]
  1324. },
  1325. replace: function(context, args) {
  1326. var result = context.oldvariable.apply(this, args);
  1327.  
  1328. var check_progressive = function(progressive) {
  1329. if (typeof progressive === "string") {
  1330. i2d_show_url("bitmovin", progressive, "progressive");
  1331. } else if (progressive instanceof Array) {
  1332. for (var i = 0; i < progressive.length; i++) {
  1333. check_progressive(progressive[i]);
  1334. }
  1335. } else if (typeof progressive === "object") {
  1336. var str = "";
  1337. if (progressive.label)
  1338. str += "[" + progressive.label + "] ";
  1339. if (progressive.bitrate)
  1340. str += progressive.bitrate;
  1341.  
  1342. i2d_show_url("bitmovin", progressive.url, str);
  1343. }
  1344. };
  1345.  
  1346. var check_sources = function(x) {
  1347. if (typeof x === "object") {
  1348. if ("source" in x) {
  1349. var sourceobj = x.source;
  1350.  
  1351. if (sourceobj.progressive) {
  1352. check_progressive(sourceobj.progressive);
  1353. }
  1354.  
  1355. if (sourceobj.dash) {
  1356. i2d_show_url("bitmovin", sourceobj.dash, "dash");
  1357. }
  1358.  
  1359. if (sourceobj.hls) {
  1360. i2d_show_url("bitmovin", sourceobj.hls, "hls");
  1361. }
  1362. }
  1363. }
  1364. };
  1365.  
  1366. if ("setup" in result) {
  1367. var old_bitmovin_setup = result.setup;
  1368. result.setup = function() {
  1369. check_sources(arguments[0]);
  1370.  
  1371. return old_bitmovin_setup.apply(this, arguments);
  1372. };
  1373. }
  1374.  
  1375. if ("load" in result) {
  1376. var old_bitmovin_load = result.load;
  1377. result.load = function() {
  1378. check_sources({source: arguments[0]});
  1379.  
  1380. return old_bitmovin_load.apply(this, arguments);
  1381. };
  1382. }
  1383.  
  1384. return result;
  1385. }
  1386. },
  1387. // DASH.js
  1388. {
  1389. variables: {
  1390. window: "dashjs.MediaPlayer"
  1391. },
  1392. replace: function(context, args) {
  1393. var outer_result = context.oldvariable.apply(this, args);
  1394.  
  1395. var oldcreate = outer_result.create;
  1396. outer_result.create = function() {
  1397. var result = oldcreate.apply(this, arguments);
  1398.  
  1399. var old_attachsource = result.attachSource;
  1400. result.attachSource = function(url) {
  1401. i2d_show_url("dash.js", url);
  1402. return old_attachsource.apply(this, arguments);
  1403. };
  1404.  
  1405. return result;
  1406. };
  1407.  
  1408. return outer_result;
  1409. }
  1410. },
  1411. // hls.js
  1412. {
  1413. variables: {
  1414. window: "Hls"
  1415. },
  1416. proto: {
  1417. loadSource: function(context, args) {
  1418. var url = args[0];
  1419. i2d_show_url("hls.js", url);
  1420. return context.oldvariable.apply(this, args);
  1421. }
  1422. }
  1423. },
  1424. // flv.js
  1425. {
  1426. variables: {
  1427. window: "flvjs.createPlayer"
  1428. },
  1429. replace: function(context, args) {
  1430. var options = args[0];
  1431. if (options) {
  1432. if ("url" in options) {
  1433. i2d_show_url("flv.js", options.url);
  1434. }
  1435. }
  1436. return context.oldvariable.apply(this, args);
  1437. }
  1438. },
  1439. // Kollus
  1440. {
  1441. variables: {
  1442. window: "KollusMediaContainer.createInstance"
  1443. },
  1444. replace: function(context, args) {
  1445. var options = args[0];
  1446.  
  1447. if (options) {
  1448. if ("mediaurl" in options) {
  1449. var types = [];
  1450. if (options.isencrypted)
  1451. types.push("encrypted");
  1452. if (options.isaudiofiles)
  1453. types.push("audio");
  1454. else
  1455. types.push("video");
  1456. i2d_show_url("kollus", options.mediaurl, types.join(":"));
  1457. }
  1458. }
  1459.  
  1460. // Replace flash with HTML5, but it doesn't work for HLS
  1461. if (config.simpleplayers === "yes" ||
  1462. config.simpleplayers === "flash") {
  1463. var value = (new KollusMediaContainer(options));
  1464. var old_launchFlashPlayer = value.launchFlashPlayer;
  1465. value.launchFlashPlayer = function() {
  1466. if (options.isencrypted) {
  1467. return old_launchflashplayer.apply(this, arguments);
  1468. } else if (options.isaudiofile) {
  1469. return value.launchHTML5AudioPlayer();
  1470. } else {
  1471. return value.launchHTML5Player();
  1472. }
  1473. };
  1474. value.isURLHasM3U8 = function(){return false;};
  1475. value = value.initialize();
  1476.  
  1477. return value;
  1478. } else {
  1479. return context.oldvariable.apply(this, args);
  1480. }
  1481. }
  1482. },
  1483. // Soundcloud
  1484. {
  1485. run_when: [{
  1486. host: "soundcloud.com"
  1487. }],
  1488. urls: [
  1489. {
  1490. regex: /api\.soundcloud\.com\/.*?\/tracks\/[0-9]*\/streams/,
  1491. callback: function(url) {
  1492. var track = url.match(/\/tracks\/([0-9]*)\//);
  1493. var parsed = JSON.parse(this.responseText);
  1494. for (var item in parsed) {
  1495. i2d_show_url("soundcloud", parsed[item], "[" + item + "] " + track[1]);
  1496. }
  1497. }
  1498. }
  1499. ]
  1500. },
  1501. // Mixcloud
  1502. {
  1503. run_when: [{
  1504. host: "mixcloud.com"
  1505. }],
  1506. urls: [
  1507. {
  1508. regex: /^(?:https?:\/\/www\.mixcloud\.com)?\/graphql(?:\?.*)?$/,
  1509. callback: function(url) {
  1510. var mixcloud_key = atob("SUZZT1VXQU5UVEhFQVJUSVNUU1RPR0VUUEFJRERPTk9URE9XTkxPQURGUk9NTUlYQ0xPVUQ=");
  1511. var key_length = mixcloud_key.length;
  1512.  
  1513. try {
  1514. var parsed = this.response;
  1515. var viewer = parsed.data.viewer;
  1516. if (!viewer)
  1517. viewer = parsed.data.changePlayerQueue.viewer;
  1518. var queue = viewer.playerQueue;
  1519.  
  1520. var cloudcast;
  1521. if (queue.queue) {
  1522. var currentIndex = 0;
  1523. if (queue.currentIndex)
  1524. currentIndex = queue.currentIndex;
  1525. cloudcast = queue.queue[currentIndex].cloudcast;
  1526. }
  1527.  
  1528. var info = cloudcast.streamInfo;
  1529. for (var key in info) {
  1530. var value = atob(info[key]);
  1531. var newval = [];
  1532. for (var i = 0; i < value.length; i++) {
  1533. newval[i] = value.charCodeAt(i) ^ mixcloud_key.charCodeAt(i % mixcloud_key.length);
  1534. }
  1535. var newvalue = String.fromCharCode.apply(String, newval);
  1536. if (newvalue.match(/^https?:\/\//)) {
  1537. i2d_show_url("mixcloud", newvalue, "[" + key + "] " + cloudcast.slug);
  1538. }
  1539. }
  1540. } catch (e) {
  1541. }
  1542. }
  1543. }
  1544. ]
  1545. },
  1546. // Forvo
  1547. {
  1548. run_when: [{
  1549. host: "forvo.com"
  1550. }],
  1551. variables: {
  1552. window: "createAudioObject"
  1553. },
  1554. replace: function(context, args) {
  1555. var id = args[0];
  1556. var mp3 = args[1];
  1557. var ogg = args[2];
  1558.  
  1559. i2d_show_url("forvo", mp3, "mp3");
  1560. i2d_show_url("forvo", ogg, "ogg");
  1561.  
  1562. return context.oldvariable.apply(this, args);
  1563. }
  1564. },
  1565. // Twitter
  1566. {
  1567. run_when: [{
  1568. host: "twitter.com",
  1569. url_regex: /:\/\/[^/]*\/i\/videos/
  1570. }],
  1571. onload: function() {
  1572. var pc = document.getElementById('playerContainer');
  1573. if (!pc) {
  1574. return;
  1575. }
  1576.  
  1577. var config = pc.getAttribute('data-config');
  1578. if (!config) {
  1579. return;
  1580. }
  1581.  
  1582. var config_parsed = JSON.parse(config);
  1583.  
  1584. if ("video_url" in config_parsed) {
  1585. i2d_show_url('twitter', config_parsed.video_url);
  1586. }
  1587. }
  1588. },
  1589. // TODO: Reimplement vine
  1590.  
  1591. // jPlayer
  1592. {
  1593. variables: {
  1594. jquery: "jPlayer"
  1595. },
  1596. replace: function(context, args) {
  1597. if (args.length > 0 && args[0] === "setMedia") {
  1598. if (args.length > 1) {
  1599. if (typeof args[1] === "object") {
  1600. for (var i in args[1]) {
  1601. if (i === "title" ||
  1602. i === "duration" ||
  1603. i === "track" /* for now */ ||
  1604. i === "artist" ||
  1605. i === "free")
  1606. continue;
  1607.  
  1608. i2d_show_url("jPlayer", args[1][i], i);
  1609. }
  1610. } else if (typeof args[1] === "string") {
  1611. i2d_show_url("jPlayer", args[1]);
  1612. }
  1613. }
  1614. }
  1615.  
  1616. return context.oldvariable.apply(this, args);
  1617. }
  1618. },
  1619. // amazingaudioplayer
  1620. {
  1621. variables: {
  1622. jquery: "amazingaudioplayer"
  1623. },
  1624. replace: function(context, args) {
  1625. var result = context.oldvariable.apply(this, args);
  1626.  
  1627. function add_source_obj(x) {
  1628. type = "";
  1629. if ("type" in x) {
  1630. type = x.type;
  1631. }
  1632.  
  1633. i2d_show_url("amazingaudioplayer", x.src, type);
  1634. }
  1635.  
  1636. function add_source(x) {
  1637. if (x instanceof Array) {
  1638. for (var i = 0; i < x.length; i++) {
  1639. add_source_obj(x[i]);
  1640. }
  1641. } else {
  1642. add_source_obj(x);
  1643. }
  1644. }
  1645.  
  1646. var audioplayer = jQuery(this).data("object").audioPlayer;
  1647. if (audioplayer.audioItem) {
  1648. add_source(audioplayer.audioItem.source);
  1649. }
  1650.  
  1651. var oldload = audioplayer.load;
  1652. audioplayer.load = function(item) {
  1653. if ("source" in item) {
  1654. add_source(item.source);
  1655. }
  1656.  
  1657. return oldload.apply(this, arguments);
  1658. };
  1659.  
  1660. return result;
  1661. }
  1662. },
  1663. // jPlayer{Audio,Video}
  1664. {
  1665. variables: {
  1666. jquery: ["jPlayerAudio", "jPlayerVideo"]
  1667. },
  1668. proto: {
  1669. setMedia: function(context, args) {
  1670. var e = args[0];
  1671. var label = "cleanaudioplayer";
  1672. if (oldvariablename === "jPlayerVideo")
  1673. label = "cleanvideoplayer";
  1674.  
  1675. var absolute = this._absoluteMediaUrls(e);
  1676. jQuery.each(this.formats, function(a, o) {
  1677. i2d_show_url(label, absolute[o]);
  1678. });
  1679. return context.oldvariable.apply(this, args);
  1680. }
  1681. }
  1682. }
  1683. ];
  1684.  
  1685. var props = {};
  1686.  
  1687. function defineprop(lastobj_win, lastobj_props, oursplit) {
  1688. if (!lastobj_win || !lastobj_props) {
  1689. console.log("lastobj_win === null || lastobj_props === null");
  1690. return;
  1691. }
  1692.  
  1693. if (!(oursplit in lastobj_props)) {
  1694. console.log(oursplit + " not in lastobj_props");
  1695. return;
  1696. }
  1697.  
  1698. var our_obj = lastobj_win[oursplit] || undefined;
  1699. var our_prop = lastobj_props[oursplit];
  1700.  
  1701. var recurse = function() {
  1702. for (var key in our_prop) {
  1703. if (!key.match(/^\$\$[A-Z]+$/)) {
  1704. defineprop(our_obj, our_prop, key);
  1705. }
  1706. }
  1707. };
  1708.  
  1709. if (!our_prop.$$INJECTED) {
  1710. if (our_obj !== undefined) {
  1711. if (our_prop.$$PROCESS) {
  1712. lastobj_win[oursplit] = our_prop.$$PROCESS(our_obj);
  1713. our_obj = lastobj_win[oursplit];
  1714. }
  1715.  
  1716. recurse();
  1717. }
  1718.  
  1719. try {
  1720. Object.defineProperty(lastobj_win, oursplit, {
  1721. get: function() {
  1722. return our_obj;
  1723. },
  1724. set: function(n) {
  1725. if (n === our_obj)
  1726. return;
  1727.  
  1728. //console.log(oursplit + " = ", n);
  1729.  
  1730. if (our_prop.$$PROCESS)
  1731. our_obj = our_prop.$$PROCESS(n);
  1732. else
  1733. our_obj = n;
  1734.  
  1735. recurse();
  1736. }
  1737. });
  1738. our_prop.$$INJECTED = true;
  1739. } catch (e) {
  1740. console.error(e);
  1741. }
  1742. }
  1743. }
  1744.  
  1745. function apply_injection(injection, variable, variablename, win) {
  1746. console.log("[i2d] Injecting " + variablename);
  1747.  
  1748. if ("replace" in injection) {
  1749. var context = {
  1750. oldvariable: variable,
  1751. oldvariablename: variablename,
  1752. win: win
  1753. };
  1754.  
  1755. var result = function() {
  1756. return injection.replace.bind(this)(context, arguments);
  1757. };
  1758.  
  1759. for (var key in variable) {
  1760. result[key] = variable[key];
  1761. }
  1762.  
  1763. return result;
  1764. } else if ("proto" in injection) {
  1765. for (var proto in injection.proto) {
  1766. (function(proto) {
  1767. var context = {
  1768. oldvariable: variable.prototype[proto],
  1769. oldvariablename: proto,
  1770. win: win
  1771. };
  1772.  
  1773. variable.prototype[proto] = function() {
  1774. return injection.proto[proto].bind(this)(context, arguments);
  1775. };
  1776. })(proto);
  1777. }
  1778. }
  1779.  
  1780. return variable;
  1781. }
  1782.  
  1783. function do_injection(injection) {
  1784. if ("run_when" in injection) {
  1785. var run_when = injection.run_when;
  1786. if (!(run_when instanceof Array)) {
  1787. run_when = [run_when];
  1788. }
  1789.  
  1790. for (var i = 0; i < run_when.length; i++) {
  1791. if ("host" in run_when[i]) {
  1792. if (!check_host(run_when[i].host))
  1793. return false;
  1794. }
  1795.  
  1796. if ("url_regex" in run_when[i]) {
  1797. if (!window.location.href.match(run_when[i].url_regex))
  1798. return false;
  1799. }
  1800. }
  1801. }
  1802.  
  1803. var win = get_window();
  1804.  
  1805. function do_window_injection(winvar) {
  1806. if (!(winvar instanceof Array))
  1807. winvar = [winvar];
  1808.  
  1809. for (var i = 0; i < winvar.length; i++) {
  1810. (function() {
  1811. var varname = winvar[i];
  1812. var dotsplit = varname.split(".");
  1813. var lastobj = win;
  1814.  
  1815. var process = function(v) {
  1816. return apply_injection(injection, v, dotsplit[dotsplit.length - 1], win);
  1817. };
  1818.  
  1819. var lastprop = props;
  1820. for (var x = 0; x < dotsplit.length; x++) {
  1821. var oursplit = dotsplit[x];
  1822. if (!lastprop[oursplit])
  1823. lastprop[oursplit] = {};
  1824.  
  1825. lastprop[oursplit].$$INJECTED = false;
  1826.  
  1827. if (x === dotsplit.length - 1) {
  1828. lastprop[oursplit].$$PROCESS = process;
  1829. }
  1830.  
  1831. lastprop = lastprop[oursplit];
  1832. }
  1833.  
  1834. /*defineprop(lastobj, dotsplit, 0, function(v) {
  1835. return apply_injection(injection, v, dotsplit[dotsplit.length - 1], win);
  1836. });*/
  1837. })();
  1838. }
  1839. }
  1840.  
  1841. if ("variables" in injection) {
  1842. if ("window" in injection.variables) {
  1843. var winvar = injection.variables.window;
  1844.  
  1845. do_window_injection(winvar);
  1846.  
  1847. /*if (!(winvar instanceof Array))
  1848. winvar = [winvar];
  1849.  
  1850. for (var i = 0; i < winvar.length; i++) {
  1851. var varname = winvar[i];
  1852. var dotsplit = varname.split(".");
  1853. var lastobj = win;
  1854.  
  1855. defineprop(lastobj, dotsplit, 0, function(v) {
  1856. return apply_injection(injection, v, dotsplit[dotsplit.length - 1], win);
  1857. });
  1858. }*/
  1859. }
  1860.  
  1861. if ("jquery" in injection.variables) {
  1862. var jqvar = injection.variables.jquery;
  1863. if (!(jqvar instanceof Array))
  1864. jqvar = [jqvar];
  1865.  
  1866. var winvar = [];
  1867. for (var i = 0; i < jqvar.length; i++) {
  1868. winvar.push("jQuery.fn." + jqvar[i]);
  1869. }
  1870.  
  1871. do_window_injection(winvar);
  1872. }
  1873. }
  1874.  
  1875. if ("onload" in injection) {
  1876. i2d_onload(injection.onload);
  1877. }
  1878.  
  1879. if ("urls" in injection) {
  1880. for (var i = 0; i < injection.urls.length; i++) {
  1881. inject_url(injection.urls[i].regex, injection.urls[i].callback);
  1882. }
  1883. }
  1884. }
  1885.  
  1886. function do_all_injections() {
  1887. for (var i = 0; i < injections.length; i++) {
  1888. do_injection(injections[i]);
  1889. }
  1890.  
  1891. var win = get_window();
  1892. for (var key in props) {
  1893. defineprop(win, props, key);
  1894. }
  1895. }
  1896. do_all_injections();
  1897.  
  1898.  
  1899. /*window.addEventListener("afterscriptexecute", function(e) {
  1900. i2d_main(e.target);
  1901. });*/
  1902.  
  1903. var process_raw_tag = function(el) {
  1904. var basename = "raw ";
  1905.  
  1906. if (el.tagName.toLowerCase() === "video") {
  1907. basename += "video";
  1908. } else {
  1909. basename += "audio";
  1910. }
  1911.  
  1912. if (el.id)
  1913. basename += ": #" + el.id;
  1914.  
  1915. var show_updates = function() {
  1916. if (el.src)
  1917. i2d_show_url(basename, el.src);
  1918.  
  1919. for (var x = 0; x < el.children.length; x++) {
  1920. if (el.children[x].tagName.toLowerCase() !== "source" &&
  1921. el.children[x].tagName.toLowerCase() !== "track") {
  1922. continue;
  1923. }
  1924.  
  1925. var type = "";
  1926. if (el.children[x].type)
  1927. type += "[" + el.children[x].type + "]";
  1928.  
  1929. if (el.children[x].label)
  1930. type += "[" + el.children[x].label + "]";
  1931.  
  1932. if (el.children[x].srclang)
  1933. type += "[" + el.children[x].srclang + "]";
  1934.  
  1935. if (el.children[x].kind)
  1936. type += "(" + el.children[x].kind + ")";
  1937.  
  1938. if (el.children[x].src)
  1939. i2d_show_url(basename, el.children[x].src, type);
  1940. }
  1941. };
  1942.  
  1943. var observer = new MutationObserver(show_updates);
  1944. observer.observe(el, { attributes: true, childList: true });
  1945.  
  1946. show_updates();
  1947. };
  1948.  
  1949. var process_el = function(el) {
  1950. if (el.nodeName === "SCRIPT") {
  1951. //i2d_main(el);
  1952. } else if (el.nodeName === "VIDEO" ||
  1953. el.nodeName === "AUDIO") {
  1954. process_raw_tag(el);
  1955. }
  1956.  
  1957. if (el.children) {
  1958. for (var i = 0; i < el.children.length; i++) {
  1959. process_el(el.children[i]);
  1960. }
  1961. }
  1962. };
  1963.  
  1964. var script_observer_cb = function(mutations, observer) {
  1965. for (var i = 0; i < mutations.length; i++) {
  1966. if (mutations[i].addedNodes) {
  1967. for (var x = 0; x < mutations[i].addedNodes.length; x++) {
  1968. var addednode = mutations[i].addedNodes[x];
  1969. process_el(addednode);
  1970. }
  1971. }
  1972. if (mutations[i].removedNodes) {
  1973. for (var x = 0; x < mutations[i].removedNodes.length; x++) {
  1974. if (mutations[i].removedNodes[x].nodeName === "SCRIPT") {
  1975. //i2d_main(mutations[i].removedNodes[x]);
  1976. }
  1977. }
  1978. }
  1979. }
  1980. };
  1981.  
  1982. var script_observer = new MutationObserver(script_observer_cb);
  1983.  
  1984. script_observer.observe(document, {childList: true, subtree: true});
  1985.  
  1986. i2d_onload(function() {
  1987. var get_raws = function() {
  1988. var audios = [].slice.call(document.getElementsByTagName("audio"));
  1989. var videos = [].slice.call(document.getElementsByTagName("video"));
  1990. var els = Array.prototype.concat(audios, videos);
  1991.  
  1992. for (var i = 0; i < els.length; i++) {
  1993. var basename = "raw ";
  1994. var el = els[i];
  1995.  
  1996. if (el.tagName.toLowerCase() === "video") {
  1997. basename += "video";
  1998. } else {
  1999. basename += "audio";
  2000. }
  2001.  
  2002. if (el.id)
  2003. basename += ": #" + el.id;
  2004.  
  2005. var show_updates = function() {
  2006. if (el.src)
  2007. i2d_show_url(basename, el.src);
  2008.  
  2009. for (var x = 0; x < el.children.length; x++) {
  2010. if (els[i].children[x].tagName.toLowerCase() !== "source" &&
  2011. els[i].children[x].tagName.toLowerCase() !== "track") {
  2012. continue;
  2013. }
  2014.  
  2015. var type = "";
  2016. if (el.children[x].type)
  2017. type += "[" + el.children[x].type + "]";
  2018.  
  2019. if (el.children[x].label)
  2020. type += "[" + el.children[x].label + "]";
  2021.  
  2022. if (el.children[x].srclang)
  2023. type += "[" + el.children[x].srclang + "]";
  2024.  
  2025. if (el.children[x].kind)
  2026. type += "(" + el.children[x].kind + ")";
  2027.  
  2028. if (el.children[x].src)
  2029. i2d_show_url(basename, el.children[x].src, type);
  2030. }
  2031. };
  2032.  
  2033. var observer = new MutationObserver(show_updates);
  2034. observer.observe(el, { attributes: true, childList: true });
  2035.  
  2036. show_updates();
  2037. }
  2038. };
  2039.  
  2040. //get_raws();
  2041.  
  2042. //i2d_main();
  2043. });
  2044. })();