|
// ==/UserScript== |
|
// ==UserScript== |
|
// @name Premium Kissanime |
|
// @version 0.5 |
|
// @description Tampermonkey script for better kissanime usage. |
|
// @include /https?://(www\.|)kissanime\.(to|org|me|com)/*/ |
|
// @copyright 2012+, Yengas |
|
// ==/UserScript== |
|
|
|
// Disable Adblock Detection |
|
if(typeof DoDetect2 != 'undefined') DoDetect2 = null; |
|
// Hide Left/Right floats + floating hide links that adblock doesnt remove |
|
$(".divCloseBut a").click(); |
|
$("#divFloatLeft").remove(); |
|
$("#divFloatRight").remove(); |
|
$("a:contains('Click here to download all')").remove(); |
|
|
|
// Global Functions |
|
String.format = function() { |
|
var s = arguments[0]; |
|
for (var i = 0; i < arguments.length - 1; i++) { |
|
var reg = new RegExp("\\{" + i + "\\}", "gm"); |
|
s = s.replace(reg, arguments[i + 1]); |
|
} |
|
|
|
return s; |
|
} |
|
|
|
String.prototype.htmlEncode = function(){ |
|
return this.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>'); |
|
}; |
|
|
|
String.prototype.sanitize = function(){ |
|
return this.htmlEncode().replace(/(\r\n|\n|\r)/gm, "").trim(); |
|
}; |
|
|
|
// Download all feature |
|
var download_links = {}, titles = {}, downloadButton = document.createElement('div'); |
|
|
|
function getByQuality(quality){ |
|
var returnArray = [], titleArray = []; |
|
if( quality in download_links ){ |
|
var sorted = Object.keys(download_links[quality]).sort(function(x, y) { return x - y; }); |
|
sorted.forEach(function(key){ |
|
returnArray.push(download_links[quality][key]); |
|
titleArray.push(titles[key]); |
|
}); |
|
} |
|
return [returnArray, titleArray]; |
|
} |
|
function downloadByQuality(quality){ |
|
getByQuality(quality)[0].forEach(function(url){ |
|
$("body").append('<iframe width="1" height="1" frameborder="0" src="' + url + '"></iframe>'); |
|
}); |
|
} |
|
|
|
function downloadLinksToHTML(d){ |
|
return $(d).find("#divDownload")[0].innerHTML; |
|
} |
|
|
|
downloadButton.innerHTML = "<button>Download all</button>"; |
|
$(".listing").before(downloadButton); |
|
$(downloadButton).find("button").on('click', function(e){ |
|
e.preventDefault(); |
|
var downloader = $(this).parent().html('<span class="bigChar">Downloader</span><br />Quality: <select id="quality"></select><br />Total: <span id="count">0</span><br /><input type="button" id="playlist" value="XSPF Playlist" /><input type="button" id="iframe" value="Iframe All" /><input type="button" id="listButton" value="Get List of URLs"><br /><textarea id="list" wrap="off" style="display:none;resize:none;width:300px;height:200px;"></textarea>'); |
|
var select = downloader.find("select"), count = downloader.find('#count'), list = downloader.find("#list"); |
|
var playlistStrings = { main: '<?xml version="1.0" encoding="UTF-8"?><playlist xmlns="http://xspf.org/ns/0/" xmlns:vlc="http://www.videolan.org/vlc/playlist/ns/0/" version="1"><title>{0}</title><trackList>{1}</trackList><extension application="http://www.videolan.org/vlc/playlist/0">{2}</extension></playlist>', track: '<track><location>{0}</location><title>{1}</title><extension application="http://www.videolan.org/vlc/playlist/0"><vlc:id>{2}</vlc:id><vlc:option>network-caching=1000</vlc:option></extension></track>', extension: '<vlc:item tid="{0}"/>' } |
|
var anime_title = $("a.bigChar").text().sanitize(); |
|
|
|
function createPlaylist(){ |
|
var id = 0, trackList = [], extensionList = [], quality = select.val(), sortedEpisodes = Object.keys(download_links[quality]).sort(function(x, y) { return x - y; }); |
|
sortedEpisodes.forEach(function(key){ |
|
var title = titles[key].sanitize(), url = download_links[quality][key]; |
|
trackList.push(String.format(playlistStrings.track, url.htmlEncode(), title, id)); |
|
extensionList.push(String.format(playlistStrings.extension, id++)); |
|
}); |
|
|
|
return new Blob([String.format(playlistStrings.main, anime_title, trackList.join(''), extensionList.join(''))], { type: 'application/octet-stream' }); |
|
} |
|
|
|
downloader.find("#iframe").on('click', function(){ downloadByQuality(select.val()); }); |
|
downloader.find("#listButton").on('click', function(){ |
|
var text = ""; |
|
list.show(); |
|
var episodes = getByQuality(select.val()); |
|
for(var key in episodes[0]){ |
|
text += episodes[0][key] + "&=" + encodeURIComponent(episodes[1][key]) + "\r\n"; |
|
} |
|
list.val(text); |
|
}); |
|
downloader.find("#playlist").on('click', function(){ |
|
var a = document.createElement('a'); |
|
a.className = "bigChar"; |
|
a.href = window.URL.createObjectURL(createPlaylist()); |
|
a.download = anime_title.replace(/[\/:*?"<>|]+/g, "") + '.xspf'; |
|
a.textContent = 'Download file!'; |
|
document.body.appendChild(a); |
|
a.click(); |
|
document.body.removeChild(a); |
|
}); |
|
select.change(function(){ count.text( getByQuality(select.val())[0].length ); list.hide(); }); |
|
|
|
function updateDownloader(){ |
|
var keys = Object.keys(download_links); |
|
select.find('option').each(function(){ var index = keys.indexOf(this.innerText); if(index > -1) keys.splice(index, 1); }); |
|
keys.forEach(function(op){ select.append('<option value="' + op + '">' + op + '</option>'); }); |
|
select.trigger('change'); |
|
} |
|
|
|
var episodeLinks = $('table.listing a'); |
|
episodeLinks.each(function(){ |
|
var link = $(this), href = this.href; |
|
function request_page(){ |
|
$.get(href, function(data){ |
|
if(data.includes("Are You Human")){ |
|
return window.setTimeout(function(){ request_page(); }, 1000); |
|
} |
|
var d = document.createElement('div'); |
|
d.innerHTML = data; |
|
d.innerHTML = downloadLinksToHTML(d); |
|
var links = $(d).find('a'); |
|
console.log(links); |
|
|
|
if(links.length > 0){ |
|
var episode = episodeLinks.length - episodeLinks.index(link); |
|
titles[episode] = link[0].innerText; |
|
|
|
link.after("<br />" + $.map(links, function(l){ |
|
if(!(l.innerText in download_links)){ download_links[l.innerText] = {}; } |
|
download_links[l.innerText][episode] = l.href; |
|
return "--> " + l.outerHTML; |
|
}).join("<br />")) |
|
} |
|
updateDownloader(); |
|
}); |
|
} |
|
request_page(); |
|
}); |
|
}); |
|
|
|
// Skip to next when buffered and time save feature here |
|
|
|
var splitted = location.href.split("Anime/"), nextEpisode = $("img[title='Next episode']").parent(), animeName = splitted.length < 2 ? undefined : (splitted[1].split('/'))[0]; |
|
var last = localStorage[animeName + "-last"], current = new Date().getTime(), limit = 30 * 1000, goNext = true, paused = false; |
|
if(last == null){ |
|
localStorage[animeName + "-last"] = last = 0; |
|
}else{ |
|
last = window.parseInt(last); |
|
} |
|
|
|
var Player = function(){}; |
|
|
|
Player.prototype.getSelected = function(){ |
|
var el = document.querySelector("#selectPlayer"); |
|
return (el == null || el.offsetParent === null) ? "html5" : el.value/* == "flash" ? "html5" : "flash"*/; |
|
}; |
|
|
|
Player.prototype.video = function(){ |
|
var selected = this.getSelected(); |
|
if(Player[selected] != null) return Player[selected]; |
|
var video = selected == "html5" ? videojs("my_video_1_html5_api") : /*jwplayer()*/document.querySelector("#embedVideo"); |
|
video.type = selected; |
|
return Player[selected] = video; |
|
}; |
|
|
|
Player.prototype.getBuffered = function(){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return 0; |
|
else if(video.type == "html5"){ |
|
var end = this.video().buffered().end( this.video().buffered().length - 1 ), duration = this.video().duration(); |
|
return end > duration ? 1 : end / duration; |
|
}else if(video.type == "flash"){ |
|
//return this.video().getBuffer() / 100.0; |
|
return this.video().getVideoLoadedFraction(); |
|
}else{ |
|
return 0; |
|
} |
|
}; |
|
|
|
Player.prototype.getCurrentTime = function(){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return 0; |
|
else if(video.type == "html5"){ |
|
return this.video().currentTime(); |
|
}else if(video.type == "flash"){ |
|
//return this.video().getPosition(); |
|
return this.video().getCurrentTime(); |
|
}else{ |
|
return 0; |
|
} |
|
}; |
|
|
|
Player.prototype.pause = function(state){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return; |
|
else if(video.type == "html5"){ |
|
this.video().pause(); |
|
}else if(video.type == "flash"){ |
|
//this.video().pause(state == null ? true : state); |
|
this.video().pauseVideo(); |
|
}else{ |
|
return; |
|
} |
|
}; |
|
|
|
Player.prototype.paused = function(){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return 0; |
|
else if(video.type == "html5"){ |
|
return this.video().paused(); |
|
}else if(video.type == "flash"){ |
|
//return this.video().getState() == "PAUSED"; |
|
return this.video().getPlayerState() == 2; |
|
}else{ |
|
return ; |
|
} |
|
}; |
|
|
|
Player.prototype.seek = function(point){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return 0; |
|
else if(video.type == "html5"){ |
|
this.video().currentTime(point); |
|
}else if(video.type == "flash"){ |
|
//this.video().seek(point); |
|
this.video().seekTo(point, true); |
|
}else{ |
|
return ; |
|
} |
|
}; |
|
|
|
Player.prototype.getDuration = function(){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return 0; |
|
else if(video.type == "html5"){ |
|
return this.video().duration(); |
|
}else if(video.type == "flash"){ |
|
return this.video().getDuration(); |
|
}else{ |
|
return -1; |
|
} |
|
}; |
|
|
|
Player.prototype.getBufferedPercent = function(){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return 0; |
|
else if(video.type == "html5"){ |
|
return this.video().bufferedPercent(); |
|
}else if(video.type == "flash"){ |
|
return this.getBuffered(); |
|
}else{ |
|
return 0; |
|
} |
|
}; |
|
|
|
Player.prototype.ready = function(){ |
|
var video = this.video(); |
|
if(video == null || video.type == null) return false; |
|
if(video.type == "html5") |
|
return true; |
|
else if(video.type == "flash"){ |
|
//return true; |
|
return video.seekTo != undefined; |
|
} |
|
return false; |
|
}; |
|
var player = new Player(); |
|
|
|
function saveInterval(){ |
|
var time = player.getCurrentTime(); |
|
|
|
if(time != null && time > 0){ |
|
localStorage[splitted[1]] = time; |
|
|
|
if(!goNext){ if(!paused){ player.pause(); paused = true; } goNext = !player.paused(); } |
|
if(goNext && nextEpisode.length > 0 && (player.getBufferedPercent() >= 0.90 || ( player.getBuffered() >= 0.90 && player.getCurrentTime() > player.getDuration() * 9 / 10 ))){ |
|
localStorage[animeName + "-last"] = new Date().getTime(); |
|
nextEpisode.attr('target', '_blank'); |
|
nextEpisode[0].click(); |
|
nextEpisode.attr('target', '_self'); |
|
nextEpisode = []; |
|
} |
|
} |
|
} |
|
|
|
if(splitted.length > 1){ |
|
if(localStorage[splitted[1]] != null){ |
|
var setInterval = window.setInterval(function(){ |
|
var video = player.video(); |
|
|
|
if(player.ready()){ |
|
var save = parseFloat(localStorage[splitted[1]]), selected = player.getSelected(); |
|
window.clearInterval(setInterval); |
|
|
|
/*if(selected != "flash"){ |
|
$("#selectPlayer").val("flash").change(); |
|
}*/ |
|
/*if(save >= 15 && selected != "html5"){ |
|
$("#selectPlayer").val("html5").change(); |
|
}else if((save == NaN || save < 15) && selected != "flash"){ |
|
$("#selectPlayer").val("flash").change(); |
|
}*/ |
|
|
|
player.seek(save, true); |
|
if(current - last < limit){ player.pause(); goNext = false; } |
|
window.setInterval(saveInterval, 5000); |
|
} |
|
}, 3000); |
|
}else{ |
|
/*if(player.getSelected() != "flash"){ |
|
$("#selectPlayer").val("flash").change(); |
|
}*/ |
|
goNext = current - last >= limit; |
|
window.setInterval(saveInterval, 5000); |
|
} |
|
} |
|
|
|
// Show where we left off... |
|
$(".listing td a").each(function(){ |
|
var key = this.href.split("Anime/")[1]; |
|
var time = parseFloat(localStorage[key]) || 0; |
|
|
|
if(time > 10){ |
|
var mins = Math.floor(time / 60), seconds = Math.floor(time % 60); |
|
this.innerHTML += " [" + mins + ":" + seconds + "]"; |
|
} |
|
}); |
+1 does this still work?