Inject2Download

Simple media download script

当前为 2018-08-17 提交的版本,查看 最新版本

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