Inject2Download

Simple media download script

当前为 2016-08-15 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Inject2Download
  3. // @namespace http://lkubuntu.wordpress.com/
  4. // @version 0.2.3
  5. // @description Simple media download script
  6. // @author Anonymous Meerkat
  7. // @include *
  8. // @grant none
  9. // @run-at document-start
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. "use strict";
  14.  
  15. // Helper functions
  16. function i2d_show_url(namespace, url, description) {
  17. function get_absolute_url(url) {
  18. var a = document.createElement('a');
  19. a.href = url;
  20. return a.href;
  21. }
  22.  
  23. if (!description)
  24. description = "";
  25.  
  26. if (typeof url !== "string" || url.replace("\s", "").length === 0)
  27. return;
  28.  
  29. if (url.match(/^mediasource:/))
  30. return;
  31.  
  32. url = get_absolute_url(url);
  33.  
  34. if (!("i2d_url_list" in window))
  35. window.i2d_url_list = [];
  36.  
  37. for (var i = 0; i < i2d_url_list.length; i++) {
  38. if (i2d_url_list[i][0] === namespace &&
  39. i2d_url_list[i][1] === url &&
  40. i2d_url_list[i][2] === description)
  41. return;
  42. }
  43.  
  44.  
  45. i2d_url_list.push([namespace, url, description]);
  46.  
  47. var newurl = decodeURIComponent(url);
  48.  
  49. var text = "[" + namespace + "] " + description + ": ";
  50.  
  51. console.log("[i2d] " + text + newurl);
  52.  
  53. var el = document.getElementById("i2d-popup");
  54. if (!el) {
  55. el = document.createElement("div");
  56. //el.style.position = "absolute";
  57. el.style.width = "max(60%, 100em)";
  58. el.style.height = "max(60%, 100em)";
  59. el.style.maxWidth = "100%";
  60. el.style.maxHeight = "100%";
  61. el.style.background = "white";
  62. el.style.top = "0px";
  63. el.style.left = "0px";
  64. el.style.zIndex = 999999;
  65. el.style.color = "black";
  66. el.style.overflow = "scroll";
  67. el.ondblclick = function() {
  68. el.parentElement.removeChild(el);
  69. };
  70. el.innerHTML = "Double click to close<br />";
  71. el.id = "i2d-popup";
  72. document.body.appendChild(el);
  73. }
  74. el.innerHTML += text + "<a href='" + newurl + "' style='color:blue'>" + newurl + "</a><br />";
  75.  
  76. // XXX: why is this needed? test: http://playbb.me/embed.php?w=718&h=438&vid=at/nw/flying_witch_-_01.mp4, animeplus.tv
  77. document.body.removeChild(el);
  78. el.style.position = "absolute";
  79. document.body.appendChild(el);
  80. }
  81.  
  82.  
  83. // Injecting functions
  84. var get_script_str = function(f) {
  85. return f.toString().replace(/^function.*{|}$/g, '');
  86. };
  87.  
  88. function add_script(s, el) {
  89. var script_body = "(function() {\n" + s + "\n})();";
  90. var myscript = document.createElement('script');
  91. myscript.className = "i2d";
  92. myscript.innerHTML = script_body;
  93. if (el) {
  94. el.appendChild(myscript);
  95. } else {
  96. document.head.appendChild(myscript);
  97. }
  98. }
  99.  
  100. function inject(variable, newvalue, aliases) {
  101. console.log("[i2d] injecting " + variable);
  102. if (!aliases)
  103. aliases = [];
  104.  
  105. add_script(i2d_show_url.toString() + "\n" +
  106. "if (!(window." + variable + ".INJECTED)) {\n" +
  107. "var oldvariable = window." + variable + ";\n" +
  108. "var oldvariable_keys = Object.keys(oldvariable);\n" +
  109. "window." + variable + " = " + newvalue.toString() + ";\n" +
  110. "for (var i = 0; i < oldvariable_keys.length; i++) {\n" +
  111. " window." + variable + "[oldvariable_keys[i]] = oldvariable[oldvariable_keys[i]];\n" +
  112. "}\n" +
  113. "window." + variable + ".INJECTED = true;\n" +
  114. "var aliases = " + JSON.stringify(aliases) + ";\n" +
  115. "for (var i = 0; i < aliases.length; i++) {\n" +
  116. " if (aliases[i] in window && window[aliases[i]] == oldvariable)" +
  117. " window[aliases[i]] = window." + variable + "\n" +
  118. "}\n" +
  119. "}");
  120. }
  121.  
  122. function inject_jquery_plugin(name, value) {
  123. if (!("jQuery" in window) ||
  124. !("fn" in window.jQuery) ||
  125. !(name in window.jQuery.fn) ||
  126. window.jQuery.fn[name].INJECTED)
  127. return;
  128.  
  129. inject("jQuery.fn." + name, value);
  130. }
  131.  
  132.  
  133. // Main code
  134. function i2d_main(e) {
  135. if (e) {
  136. if (!e.tagName || e.tagName.toLowerCase() !== "script")
  137. return;
  138. if ((e.className === "i2d")) {
  139. return;
  140. }
  141. }
  142.  
  143. if ("soundManager" in window && !window.soundManager.INJECTED) {
  144. inject("soundManager.createSound", function(arg1, arg2) {
  145. if (typeof arg1 === "string")
  146. i2d_show_url("soundManager", arg2);
  147. else
  148. i2d_show_url("soundManager", arg1.url);
  149.  
  150. return oldvariable.apply(this, arguments);
  151. });
  152. }
  153.  
  154. if ("jwplayer" in window && !window.jwplayer.INJECTED) {
  155. inject("jwplayer", function() {
  156. var result = oldvariable.apply(this, arguments);
  157.  
  158. var check_sources = function(x) {
  159. if (typeof x === "object") {
  160. if (x instanceof Array) {
  161. for (var i = 0; i < x.length; i++) {
  162. check_sources(x[i]);
  163. }
  164. return;
  165. }
  166.  
  167. var label = "";
  168.  
  169. if ("title" in x)
  170. label += "[" + x.title + "]";
  171.  
  172. if ("label" in x)
  173. label += "[" + x.label + "]";
  174.  
  175. if ("streamer" in x) {
  176. i2d_show_url("jwplayer", x.streamer, "[stream]" + label);
  177. }
  178.  
  179. if ("file" in x) {
  180. i2d_show_url("jwplayer", x.file, label);
  181. }
  182.  
  183. if ("sources" in x) {
  184. check_sources(x.sources);
  185. }
  186.  
  187. if ("playlist" in x) {
  188. check_sources(x.playlist);
  189. }
  190. } else if (typeof x === "string") {
  191. i2d_show_url("jwplayer", x);
  192. }
  193. };
  194.  
  195. if ("setup" in result) {
  196. var old_jwplayer_setup = result.setup;
  197. result.setup = function() {
  198. if (typeof arguments[0] === "object") {
  199. var x = arguments[0];
  200.  
  201. if ("modes" in x) {
  202. for (var i = 0; i < x.modes.length; i++) {
  203. // TODO: support more?
  204. if ("type" in x.modes[i] && x.modes[i].type === "html5") {
  205. if ("config" in x.modes[i] && "file" in x.modes[i].config) {
  206. check_sources(x.modes[i].config);
  207. }
  208. }
  209. }
  210. }
  211.  
  212. check_sources(x);
  213. }
  214.  
  215. return old_jwplayer_setup.apply(this, arguments);
  216. };
  217. }
  218.  
  219. if ("load" in result) {
  220. var old_jwplayer_load = result.load;
  221. result.load = function() {
  222. check_sources(arguments[0]);
  223. return old_jwplayer_load.apply(this, arguments);
  224. };
  225. }
  226.  
  227. if ("on" in result) {
  228. result.on('playlistItem', function(item) {
  229. check_sources(item.item);
  230. });
  231.  
  232. var old_jwplayer_on = result.on;
  233. result.on = function() {
  234. if (arguments[0] === "adBlock")
  235. return;
  236.  
  237. return old_jwplayer_on.apply(this, arguments);
  238. }
  239. }
  240.  
  241. return result;
  242. });
  243. }
  244.  
  245. if ("flowplayer" in window && !window.flowplayer.INJECTED) {
  246. inject("flowplayer", function() {
  247. var obj_baseurl = null;
  248. var els = [];
  249.  
  250. function get_url(x) {
  251. x = decodeURIComponent(x);
  252.  
  253. if (obj_baseurl) {
  254. if (x.match(/^[a-z]*:\/\//)) {
  255. return x;
  256. } else {
  257. return obj_baseurl + "/" + x;
  258. }
  259. } else {
  260. return x;
  261. }
  262. };
  263.  
  264. function check_sources(x, els, label) {
  265. if (typeof x === "string") {
  266. if (!x.match(/\.xml$/))
  267. i2d_show_url("flowplayer", get_url(x), label);
  268.  
  269. return;
  270. }
  271.  
  272. if (x instanceof Array) {
  273. for (var i = 0; i < x.length; i++) {
  274. check_sources(x[i], els, label);
  275. }
  276. return;
  277. }
  278.  
  279. if (typeof x !== "object")
  280. return;
  281.  
  282. label = "";
  283.  
  284. if ("title" in x)
  285. label += "[" + x.title + "]";
  286.  
  287. if ("clip" in x) {
  288. if ("baseUrl" in x.clip) {
  289. obj_baseurl = x.clip.baseUrl;
  290.  
  291. for (var i = 0; i < els.length; i++) {
  292. els[i].i2d_baseurl = obj_baseurl;
  293. }
  294. }
  295.  
  296. check_sources(x.clip, els, label);
  297. }
  298.  
  299. if ("sources" in x) {
  300. check_sources(x.sources, els, label);
  301. }
  302.  
  303. if ("playlist" in x) {
  304. check_sources(x.playlist, els, label);
  305. }
  306.  
  307. if ("url" in x) {
  308. check_sources(x.url, els, label);
  309. }
  310.  
  311. if ("src" in x) {
  312. check_sources(x.src, els. label);
  313. }
  314.  
  315. if ("bitrates" in x) {
  316. for (var j = 0; j < x.bitrates.length; j++) {
  317. if ("url" in x.bitrates[j]) {
  318. var description = "";
  319. if (x.bitrates[j].isDefault)
  320. description += "default:";
  321. if (x.bitrates[j].sd)
  322. description += "sd:";
  323. if (x.bitrates[j].hd)
  324. description += "hd:";
  325. if (x.bitrates[j].bitrate)
  326. description += x.bitrates[j].bitrate;
  327.  
  328. i2d_show_url("flowplayer", get_url(x.bitrates[j].url), description);
  329. }
  330. }
  331. }
  332. }
  333.  
  334. if (arguments.length >= 1) {
  335. els = [null];
  336.  
  337. if (typeof arguments[0] === "string") {
  338. try {
  339. els[0] = document.getElementById(arguments[0]);
  340. } catch(e) {
  341. }
  342.  
  343. try {
  344. if (!els[0])
  345. els = document.querySelectorAll(arguments[0]);
  346. } catch(e) {
  347. els = [];
  348. }
  349. } else if (arguments[0] instanceof HTMLElement) {
  350. els = [arguments[0]];
  351. }
  352. }
  353.  
  354. for (var i = 0; i < els.length; i++) {
  355. if (!els[i] || !(els[i] instanceof HTMLElement))
  356. continue;
  357.  
  358. if ("i2d_baseurl" in els[i])
  359. obj_baseurl = els[i].i2d_baseurl;
  360. }
  361.  
  362. if (arguments.length >= 3 && typeof arguments[2] === "object") {
  363. check_sources(arguments[2], els);
  364. } else if (arguments.length >= 3 && typeof arguments[2] === "string") {
  365. i2d_show_url("flowplayer", get_url(arguments[2]));
  366. } else if (arguments.length === 2 && typeof arguments[1] === "object") {
  367. check_sources(arguments[1], els);
  368. } else if (arguments.length === 2 && typeof arguments[1] === "string") {
  369. i2d_show_url("flowplayer", get_url(arguments[1]));
  370. }
  371.  
  372. for (var i = 0; i < els.length; i++) {
  373. if (!els[i] || !(els[i] instanceof HTMLElement))
  374. continue;
  375.  
  376. var href = els[i].getAttribute("href");
  377. if (href) {
  378. i2d_show_url("flowplayer", get_url(href), "href");
  379. }
  380. }
  381.  
  382. var result = oldvariable.apply(this, arguments);
  383.  
  384. if (!result || typeof result !== "object")
  385. return result;
  386.  
  387. if ("addClip" in result) {
  388. var old_fplayer_addclip = result.addClip;
  389. result.addClip = function() {
  390. if (arguments.length > 0)
  391. check_sources(arguments[0], els);
  392.  
  393. return old_fplayer_addclip.apply(this, arguments);
  394. };
  395. }
  396.  
  397. if ("setPlaylist" in result) {
  398. var old_fplayer_setplaylist = result.setPlaylist;
  399. result.setPlaylist = function() {
  400. if (arguments.length > 0)
  401. check_sources(arguments[0], els);
  402.  
  403. return old_fplayer_setplaylist.apply(this, arguments);
  404. };
  405. }
  406.  
  407. if ("load" in result) {
  408. var old_fplayer_load = result.load;
  409. result.load = function() {
  410. if (arguments.length > 0)
  411. check_sources(arguments[0], els);
  412.  
  413. return old_fplayer_load.apply(this, arguments);
  414. }
  415. }
  416.  
  417. /*if ("on" in result) {
  418. result.on("load", function(e, api, video) {
  419. console.log(e);
  420. check_sources(video || api.video, els);
  421. });
  422. }*/
  423.  
  424. return result;
  425. }, ["$f"]);
  426.  
  427. add_script(get_script_str(function() {
  428. flowplayer(function(api, root) {
  429. api.on("load", function(e, api, video) {
  430. flowplayer().load(video || api.video);
  431. });
  432. });
  433. }));
  434. }
  435.  
  436. if ("videojs" in window && !window.videojs.INJECTED) {
  437. inject("videojs", function() {
  438. if (arguments.length > 0 && typeof arguments[0] === "string") {
  439. var my_el = document.getElementById(arguments[0]);
  440. if (!my_el)
  441. my_el = document.querySelector(arguments[0]);
  442.  
  443. if (my_el) {
  444. if (my_el.src) {
  445. i2d_show_url("videojs", my_el.src);
  446. }
  447.  
  448. for (var i = 0; i < my_el.children.length; i++) {
  449. if (my_el.children[i].tagName.toLowerCase() === "source") {
  450. if (my_el.children[i].src) {
  451. i2d_show_url("videojs", my_el.children[i].src, my_el.children[i].getAttribute("label"));
  452. }
  453. }
  454. }
  455. }
  456. }
  457.  
  458. var result = oldvariable.apply(this, arguments);
  459.  
  460. var old_videojs_src = result.src;
  461. result.src = function() {
  462. if (arguments.length > 0 && typeof arguments[0] === "object") {
  463. if ("src" in arguments[0]) {
  464. i2d_show_url("videojs", arguments[0].src);
  465. }
  466. }
  467.  
  468. return old_videojs_src.apply(this, arguments);
  469. };
  470.  
  471. return result;
  472. });
  473.  
  474. add_script(i2d_show_url.toString() +
  475. get_script_str(function() {
  476. document.addEventListener("DOMContentLoaded", function() {
  477. var els = document.getElementsByClassName("video-js");
  478. for (var i = 0; i < els.length; i++) {
  479. var my_el = els[i];
  480. if (my_el.tagName.toLowerCase() === "video") {
  481. if (!my_el.getAttribute('data-setup')) {
  482. continue;
  483. }
  484. if (my_el.src) {
  485. i2d_show_url("videojs", my_el.src);
  486. }
  487.  
  488. for (var i = 0; i < my_el.children.length; i++) {
  489. if (my_el.children[i].tagName.toLowerCase() === "source") {
  490. if (my_el.children[i].src) {
  491. i2d_show_url("videojs", my_el.children[i].src, my_el.children[i].getAttribute("label"));
  492. }
  493. }
  494. }
  495. }
  496. }
  497. });
  498. }));
  499. }
  500.  
  501. if ("amp" in window && !window.amp.INJECTED) {
  502. inject("amp", function() {
  503. function show_amp_source(sourceobj) {
  504. if ("protectionInfo" in sourceobj) {
  505. console.log("[amp] Cannot decode protection info");
  506. }
  507. if ("src" in sourceobj)
  508. i2d_show_url("amp", sourceobj.src);
  509. }
  510.  
  511. if (arguments.length >= 2 && typeof arguments[1] === "object") {
  512. if ("sourceList" in arguments[1]) {
  513. for (var i = 0; i < arguments[1].sourceList.length; i++) {
  514. show_amp_source(arguments[1].sourceList[i]);
  515. }
  516. }
  517. }
  518.  
  519. var result = oldvariable.apply(this, arguments);
  520.  
  521. if (!result)
  522. return result;
  523.  
  524. var old_amp_src = result.src;
  525. result.src = function() {
  526. for (var i = 0; i < arguments[0].length; i++) {
  527. show_amp_source(arguments[0][i]);
  528. }
  529.  
  530. return old_amp_src.apply(this, arguments);
  531. };
  532.  
  533. return result;
  534. });
  535. }
  536.  
  537. if (window.location.host.search("forvo") >= 0 && "createAudioObject" in window && !window.createAudioObject.INJECTED) {
  538. inject("createAudioObject", function(id, mp3, ogg) {
  539. i2d_show_url("forvo", mp3, "mp3");
  540. i2d_show_url("forvo", ogg, "ogg");
  541.  
  542. return oldvariable.apply(this, arguments);
  543. });
  544. }
  545.  
  546. if ("jQuery" in window) {
  547. inject_jquery_plugin("jPlayer", function() {
  548. if (arguments.length > 0 && arguments[0] === "setMedia") {
  549. if (arguments.length > 1) {
  550. if (typeof arguments[1] === "object") {
  551. for (var i in arguments[1]) {
  552. if (i === "title" ||
  553. i === "duration" ||
  554. i === "track" /* for now */ ||
  555. i === "artist" ||
  556. i === "free")
  557. continue;
  558.  
  559. i2d_show_url("jPlayer", arguments[1][i], i);
  560. }
  561. } else if (typeof arguments[1] === "string") {
  562. i2d_show_url("jPlayer", arguments[1]);
  563. }
  564. }
  565. }
  566.  
  567. return oldvariable.apply(this, arguments);
  568. });
  569. }
  570. }
  571.  
  572. i2d_main();
  573.  
  574. window.addEventListener("afterscriptexecute", function(e) {
  575. i2d_main(e.target);
  576. });
  577.  
  578. document.addEventListener("DOMContentLoaded", function() {
  579. var get_raws = function() {
  580. var audios = [].slice.call(document.getElementsByTagName("audio"));
  581. var videos = [].slice.call(document.getElementsByTagName("video"));
  582. var els = Array.concat(audios, videos);
  583.  
  584. for (var i = 0; i < els.length; i++) {
  585. var basename = "raw ";
  586. var el = els[i];
  587.  
  588. if (el.tagName.toLowerCase() === "video") {
  589. basename += "video";
  590. } else {
  591. basename += "audio";
  592. }
  593.  
  594. if (el.id)
  595. basename += ": #" + el.id;
  596.  
  597. var show_updates = function() {
  598. if (el.src)
  599. i2d_show_url(basename, el.src);
  600.  
  601. for (var x = 0; x < el.children.length; x++) {
  602. if (els[i].children[x].tagName.toLowerCase() !== "source") {
  603. continue;
  604. }
  605.  
  606. var type = null;
  607. if (el.children[x].type)
  608. type = el.children[x].type;
  609.  
  610. if (el.children[x].src)
  611. i2d_show_url(basename, el.children[x].src, type);
  612. }
  613. };
  614.  
  615. var observer = new MutationObserver(show_updates);
  616. observer.observe(el, { attributes: true, childList: true });
  617.  
  618. show_updates();
  619. }
  620. };
  621. add_script(i2d_show_url.toString() + "\n" +
  622. "(" + get_raws.toString() + ")();");
  623.  
  624. i2d_main();
  625. });
  626. })();