KissAnime Multi Downloader

This is a userscript that will download multi episodes form KissAnime. It also can create m3u8 playlist.

当前为 2017-07-02 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name KissAnime Multi Downloader
  3. // @namespace https://greasyfork.org/en/users/135934-anime-bro1
  4. // @version 0.1
  5. // @description This is a userscript that will download multi episodes form KissAnime. It also can create m3u8 playlist.
  6. // @author AnimeBro1
  7. // @homepage https://github.com/Eltion/Kissanime-Downloader
  8. // @match http://kissanime.ru/Anime/*
  9. // @exclude http://kissanime.ru/Anime/*/*
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_xmlhttpRequest
  13. // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
  14.  
  15. // @require https://cdn.rawgit.com/Eltion/Kissanime-Downloader/ee154d713ce5af9c031b4abdd20fae8bb7cc2dc5/css.js
  16. // @require https://cdn.rawgit.com/Eltion/Kissanime-Downloader/ee154d713ce5af9c031b4abdd20fae8bb7cc2dc5/vr.js
  17.  
  18. // ==/UserScript==
  19.  
  20.  
  21. var images = ["","","","",""];
  22. var words = [];
  23. var k = "";
  24. var eps = [];
  25. var epsName = [];
  26. var epsLinks = [];
  27. var failedLinks = [];
  28.  
  29. var count = 1;
  30. var failedCount = 0;
  31.  
  32. var start = "";
  33. var end = "";
  34. var isText = false;
  35. var isHTML = false;
  36. var isM3U8 = false;
  37. var quality = [];
  38. var failed = true;
  39.  
  40. var animebro;
  41. var max = 1;
  42.  
  43.  
  44. (function() {
  45. if(!isBasicJson()){
  46. getBasicJson();
  47. }
  48. max = $(".listing").find("a").toArray().length;
  49. createButton();
  50. $("#aend").attr('value',max+"");
  51. $("#startscript").on('click',function(){
  52. start = $("#astart").val();
  53. end = $("#aend").val();
  54. if($("#aquality").val().includes(",")){
  55. quality = $("#aquality").val().split(",");
  56. }else{
  57. alert("Wrong quality format, plese read the help");
  58. return;
  59. }
  60. isText = $("#atxt").get(0).checked;
  61. isHTML = $("#ahtml").get(0).checked;
  62. isM3U8 = $("#am3u8").get(0).checked;
  63. getAllEps();
  64. });
  65. //getEP();
  66. //getLinks(GM_getValue("html3"));
  67. })();
  68.  
  69. function createButton(){
  70. var imgSrc = "https://assets.ubuntu.com/v1/4cd0df1c-picto-download-orange.svg";
  71. var html = "<div id='adownloader' style='position:fixed; bottom:10px; left:10px'><img id='startscript' style='cursor:pointer;float:left;position: relative; top:5px;margin-right:10px;' width='70px' src='https://assets.ubuntu.com/v1/4cd0df1c-picto-download-orange.svg' /><div style='background:#dd4814; position: relative;height:70px;padding:10px; border-radius: 10px; text-align:center; color: white;float: left;'><div style='display: inline-block;float: left;'>Start: <input value='1' id='astart' style='color:white; text-align:center; width: 30px; background: transparent; border:0.3px solid white; border-radius:5px;' type='text'></input> End: <input id='aend' value='5' style='color:white; text-align:center; width: 30px; background: transparent; border:0.3px solid white; border-radius:5px;' type='text'></input><br /><br />Quality: <input id='aquality' value='720,480,360' style='color:white; text-align:center; width: 75px; background: transparent; border:0.3px solid white; border-radius:5px;' type='text'></input></div><div style='display:inline-block;float:left;'><input id='atxt' type='checkbox' />Text List <br /><input id='ahtml' type='checkbox' />html List<br /><input id='am3u8' type='checkbox' />m3u8 List</div><a style='display:block; text-align:center;' href='https://github.com/Eltion/Kissanime-Downloader' target='_blank' >Help?</a></div></div>";
  72. var html2 = "<div id='ainfo' style=' padding:10px; border-radius:20px;position:fixed; display: none; bottom:10px; right:10px; background:#dd4814;height:100px;width:400px;'><h3 style='text-align: center'>KissAnime Downloader</h3><p style='width:100%; word-wrap: break-word;' id='aoutput'></p><p id='aprogress'></p></div>";
  73. //var html3 = "<div id='ainfo2' style='background: red; padding: 10px; position: a'>"
  74. $('body').append(html);
  75. $('body').append(html2);
  76. }
  77.  
  78. function getAllEps(){
  79.  
  80. eps = [];
  81. epsName = [];
  82. epsLinks = [];
  83. var x = $(".listing").find("a").toArray();
  84. for(var i =0; i < x.length; i++){
  85. eps.push(x[i].href);
  86. epsName.push(x[i].innerText);
  87. }
  88. if(start < 0 || end < start || end > eps.length || !(isText || isHTML || isM3U8)){
  89. alert("Wrong Options. Max number:"+eps.length);
  90. return;
  91. }
  92. $("#adownloader").hide(500);
  93. $("#ainfo").show(500);
  94. eps.reverse();
  95. epsName.reverse();
  96. eps = eps.slice( parseInt(start)-1, parseInt(end));
  97. epsName = epsName.slice(parseInt(start)-1,parseInt(end));
  98. console.log(epsName);
  99. alert("Don't try to use the page until it's over!");
  100. getEP(eps[0]);
  101. }
  102.  
  103. function getEP(url){
  104. console.log(url);
  105. words = [];
  106. images=["","","","",""];
  107. k = url + "&s=default";
  108. $('#aoutput').html("Grabbing: "+url+"...");
  109. var msg = $.ajax({type: "GET", url: url, async: false}).responseText;
  110. $('#aoutput').append(" <b style='color:green'>Done</b>");
  111. if(isCapacha(msg)){
  112. GetWords(msg);
  113. getImages(msg);
  114. }else{
  115. //alert("x");
  116. noCapacha(msg);
  117. }
  118. // var persentage = (epsLinks.length/eps.length)*100;
  119. //$('#aprogress').html(persentage+"%");
  120. }
  121.  
  122. function isCapacha(html){
  123. return html.includes("formVerify");
  124. }
  125.  
  126. function noCapacha(html){
  127. getLinks(html);
  128. if(count < eps.length){
  129. getEP(eps[count]);
  130. count++;
  131. }
  132. }
  133.  
  134. function isBasicJson(){
  135. return GM_getValue("AnimeBro1",false);
  136. }
  137.  
  138. function Complete() {
  139. var jj = 0;
  140. var postData = "";
  141. for(var j = 0; j <2; j++){
  142. var w1 = GM_getValue( words[j], false );
  143. if(w1 !== false){
  144. if(w1.includes(" ")){
  145. w1 = w1.split(" ");
  146. }else{
  147. w1 = [w1];
  148. }
  149. for(var k =0; k < w1.length; k++){
  150. for(var i = 0; i < images.length; i++){
  151. if((images[i] === w1[k]) && postData.length < 4){
  152. postData += i+",";
  153. }
  154. }
  155. }
  156. }
  157. }
  158. if(postData.length == 4){
  159. postdata(postData);
  160. console.log("EP Grabed");
  161. }else{
  162. CaptachaNotCompleted(eps[count]);
  163. }
  164. }
  165.  
  166. function CaptachaNotCompleted(url){
  167. console.log("Eltioni: "+ url);
  168. var x = $.ajax({type: "POST", url:"http://kissanime.ru/Mobile/GetEpisode", data:{eID:2693},async: false}).responseText;
  169. x = x.split("|||")[0];
  170. epsLinks.push(x);
  171. }
  172.  
  173. function postdata(answer){
  174. var data = {reUrl: k, answerCap: answer};
  175. var msg = $.ajax({type: "POST", url: "http://kissanime.ru/Special/AreYouHuman2",data: data ,async: false}).responseText;
  176. //console.log(msg);
  177. getLinks(msg);
  178. }
  179.  
  180. function whatServer(html){
  181. re = /https:\/\/www.rapidvideo.com\/e\/[^"']*/g;
  182. if(html.includes("slcQualix")){
  183. return 1;
  184. }else if(re.exec(html)){
  185. return 3;
  186. }
  187. }
  188.  
  189. function getLinks(html){
  190. //console.log(html);
  191. server = whatServer(html);
  192. //GM_setValue("html3",html);
  193. if(server == 1){
  194. var b = [];
  195. var $rr = $($.parseHTML(html,document,true));
  196. if(animebro == null){
  197. //alert("xx");
  198. var script1 = $rr.find("script").toArray()[6].innerHTML;
  199. var script2 = $rr.find("script").toArray()[7].innerHTML;
  200. eval("animebro = 1;"+script1);
  201. eval("animebro = 1;"+script2);
  202. }
  203. var x = $rr.find("#slcQualix").find("option").toArray();
  204. for(var i = 0; i < x.length; i++){
  205. var c = {"file": ovelWrap(x[i].value), "label": x[i].innerText};
  206. b.push(c);
  207. }
  208. console.log(b);
  209. getLinkWithSetQuality(b);
  210. }else if(server == 2){
  211. var openload = html.match(/https:\/\/openload.co\/embed\/[^"']*/g);
  212. console.log(openload);
  213. }else if(server == 3){
  214. var url = html.match(/https:\/\/www.rapidvideo.com\/e\/[^"']*/g);
  215. rapidvideo(url);
  216. }
  217.  
  218. }
  219.  
  220. function rapidvideo(url){
  221.  
  222. GM_xmlhttpRequest({
  223. method: "GET",
  224. url: ""+url,
  225. synchronous: true,
  226. onload: function(response) {
  227. var e = JSON.parse(response.responseText.split('"sources": ')[1].split("]")[0]+"]");
  228. if (e === undefined || e === null) {
  229. console.log(response.responseText);
  230. }else{
  231. console.log(e);
  232. getLinkWithSetQuality(e);
  233. }
  234. }
  235. });
  236.  
  237. }
  238.  
  239. function getLinkWithSetQuality(ee){
  240. //console.log(e);
  241. for(var i =0; i < quality.length; i++){
  242. for(var j =0; j < ee.length; j++){
  243. if(ee[j].label.includes(quality[i])){
  244. //var b = {"link":ee[j].file,"name":epsName[count-1],"quality":quality[i]};
  245. epsLinks.push(ee[j].file);
  246. console.log(ee[j].file);
  247. return;
  248. }
  249. }
  250. }
  251. epsLinks.push("");
  252. console.log("Wrong quality");
  253. }
  254.  
  255. function getBasicJson(){
  256. var msg = $.ajax({type: "GET", url: "https://rawgit.com/Eltion/Kissanime-Chaptcha-Auto-Complete/master/BasicJson.json", async: false}).responseText;
  257. msg = JSON.parse(msg);
  258. for(var i = 0; i < msg.length; i++){
  259. GM_setValue(msg[i].n,msg[i].v);
  260. }
  261. location.reload();
  262. }
  263.  
  264. function getImages(html){
  265. //console.log(html);
  266. var items = html.match(/CapImg\?f=[^"']*/g);
  267. //console.log(items);
  268. loader(items, loadImage, function () {
  269. Complete();
  270. //alert(count);
  271. console.log(failedLinks);
  272. if(count < eps.length){
  273. getEP(eps[count]);
  274. count++;
  275. }else{
  276. $("#ainfo").html('Done, <a href="https://github.com/Eltion/Kissanime-Downloader" target="_blank">What to do now??</a>');
  277. console.log("DONE");
  278. console.log(epsLinks);
  279. if(isText){
  280. createTxtList();
  281. }
  282. if(isHTML){
  283. createHTMLlist();
  284. }if(isM3U8){
  285. createM3U8();
  286. }
  287. }
  288. });
  289. }
  290.  
  291. function GetWords(html){
  292. var form = html.split("formVerify")[1].split("</form")[0];
  293. var x = form.match(/(?:<span[^>]*>\s*)([^<]*)/g);
  294. var word1 = x[0].split(">")[1].replace(/\s\s/g,"");
  295. var word2 = x[1].split(">")[1].replace(/\s\s/g,"");
  296. words = [word1,word2];
  297. }
  298.  
  299. function createTxtList(){
  300. var list ="";
  301. for(var i = 0; i < epsLinks.length; i++){
  302. list += encodeURI(epsLinks[i]) + "[" + epsName[i].replace(/[\s:\|\[\]\{\}]+/g,"_") + ".mp4\n";
  303. }
  304. download("list.txt","text/plain",list);
  305. }
  306.  
  307. function createHTMLlist(){
  308. var list ="";
  309. for(var i = 0; i < epsLinks.length; i++){
  310. list += '<a href="' + epsLinks[i] + '" download="' + epsName[i] + '">' + epsName[i] + '</a><br>';
  311. }
  312. download("list.html","text/html",list);
  313. }
  314.  
  315. function createM3U8(){
  316. var list =" #EXTM3U\n\n";
  317. for(var i = 0; i < epsLinks.length; i++){
  318. list += '#EXTINF:-1,'+epsName[i]+"\n"+encodeURI(epsLinks[i])+"\n\n";
  319. }
  320. download("list.m3u8","text/plain",list);
  321. }
  322.  
  323. function download(filename, datatype, text) {
  324. var element = document.createElement('a');
  325. element.setAttribute('href', 'data:' + datatype + ';charset=utf-8,' + encodeURIComponent(text));
  326. element.setAttribute('download', filename);
  327. // element.setAttribute('target', '_blank');
  328. // ^^ problems with safari
  329.  
  330. element.style.display = 'none';
  331. document.body.appendChild(element);
  332.  
  333. element.click();
  334.  
  335. document.body.removeChild(element);
  336. }
  337.  
  338. function loader(items, thingToDo, allDone) {
  339. if (!items) {
  340. // nothing to do.
  341. return;
  342. }
  343.  
  344. if ("undefined" === items.length) {
  345. // convert single item to array.
  346. items = [items];
  347. }
  348.  
  349. var count = items.length;
  350.  
  351. // this callback counts down the things to do.
  352. var thingToDoCompleted = function (items, i) {
  353. count--;
  354. if (0 === count) {
  355. allDone(items);
  356. }
  357. };
  358.  
  359. for (var i = 0; i < items.length; i++) {
  360. // 'do' each thing, and await callback.
  361. thingToDo(items, i, thingToDoCompleted);
  362. }
  363. }
  364.  
  365. function loadImage(items, i, onComplete) {
  366. var img = new Image();
  367. var canvas = document.createElement("canvas");
  368. var ctx = canvas.getContext("2d");
  369. var dataURL ="";
  370. var onLoad = function (e) {
  371. canvas.width = img.naturalWidth;
  372. canvas.height = img.naturalHeight;
  373. ctx.drawImage(img, 0, 0);
  374. dataURL = canvas.toDataURL("image/jpeg");
  375. images[i] = dataURL;
  376. e.target.removeEventListener("load", onLoad);
  377. onComplete(items, i);
  378. };
  379. img.addEventListener("load", onLoad, false);
  380. img.src = "http://kissanime.ru/Special/"+items[i];
  381. }
  382.  
  383.  
  384.  
  385.