Inject2Download

Simple media download script

目前为 2018-07-18 提交的版本。查看 最新版本

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