Skip to content

Instantly share code, notes, and snippets.

@azu
Created January 21, 2009 15:46
Show Gist options
  • Save azu/50007 to your computer and use it in GitHub Desktop.
Save azu/50007 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name NicoNicoPlaylist mod
// @namespace http://oamaxa2.u-abel.net/wordpress/
// @original d.hatena.ne.jp/Sore_0
// @description alterでは自動的に再生、コメント非表示、画面非表示にする。
// @include http://www.nicovideo.jp/*
// @include http://com.nicovideo.jp/*
// @exclude http://www.nicovideo.jp/thumb*
// @version 0.2.9.3
// @update 2009/01/21
// ==/UserScript==
(function(){
var w=(unsafeWindow||window),document=w.document;
var $=function(id){return document.getElementById(id);};
var SCROLL=GM_getValue("nico_scroll")||200;
const playerFocus=true; /* スクロール時のplayerへのfocus */
var NicoNicoPlaylist={
version:"0.2.9.3",
getUserAgent:function(){
return "Mozilla/5.0 (Greasemonkey) NicoNicoPlaylist mod/"+NicoNicoPlaylist.version;
}
};
var Util={
observe:function(elem, event, func, capture){
capture=!!capture;
if(elem.attachEvent){
elem.attachEvent("on"+event,func);
}
else if(elem.addEventListener){
elem.addEventListener(event,func,capture);
}
else{
elem["on"+event]=func;
}
}
};
var NicoNico={
WATCH_PAGE_REGEXP:/http:\/\/.*?\.nicovideo\.jp\/watch\/([^\/?<>\"\'#]+)/,
WATCH_URL:"http://www.nicovideo.jp/watch/",
GETRELATION_API_URL:"http://www.nicovideo.jp/api/getrelation?page=1&sort=p&order=d&video=",
WHATPAGE:function(){
if(/http:\/\/.*?\.nicovideo\.jp\/([^\/]*)\/?/.test(location.href))
return RegExp.$1;
}
};
var Video=function(){this.initialize.apply(this,arguments);};
Video.prototype={
initialize:function(){
this.id=arguments[0]||"";
this.title=arguments[1]||"";
},
serialize:function(){return [w.escape(this.id),w.escape(this.title)].join("&");},
unserialize:function(data){
var r=[];
if(data) r=data.split(/&/);
this.id=w.unescape(r[0]);
this.title=w.unescape(r[1]);
},
getPlayUri:function(){return NicoNico.WATCH_URL+this.id;},
play:function(){w.location.href=this.getPlayUri();},
getRelatedVideos:function(iterator,terminator){
if(typeof(iterator)!="function") return;
terminator=terminator||function(){};
GM_xmlhttpRequest({
method:"GET",
url:NicoNico.GETRELATION_API_URL+this.id,
headers:{"Content-type":"text/xml","User-Agent":NicoNicoPlaylist.getUserAgent()},
onload:function(r){
if(200<=r.status&&r.status<300){
var tags=r.responseText.match(/<video>((?:.|\r|\n)+?)<\/video>/gm);
if(!tags)return false;
for(var i=0,len=tags.length; i<len; i++){
var m=tags[i].match(NicoNico.WATCH_PAGE_REGEXP);
if(!m)continue;
var videoId=m[1];
m=tags[i].match(/<title>(.+?)<\/title>/);
if(!m)continue;
var title=m[1];
iterator(videoId,title);
}
}
terminator(r);
},
onerror:terminator
});
}
};
var PlayList=function(){this.initialize.apply(this,arguments);};
PlayList.all=function(){
var list=GM_getValue("all_playlist");
return list? list.split(/,/):[];
};
PlayList.add=function(playlist){
if(GM_getValue("all_playlist")&&GM_getValue("all_playlist").match(GM_getValue("current"))) return;
else{
var list=PlayList.all();
list.push(playlist.id||playlist);
GM_setValue("all_playlist",list.join(","));
}
};
PlayList.change=function(id){
if(!GM_getValue("playlist_"+id)){
GM_setValue("playlist_"+id,id+";");
PlayList.add(id);
}
GM_setValue("current",id);
};
PlayList.prototype={
initialize:function(){
this.id=arguments[0]||'default';
this.videos=[];
this.load();
},
serialize:function(){
var videos=[];
for(var i=0, len=this.videos.length; i<len; i++){
videos.push(this.videos[i].serialize());
}
return [
w.escape(this.id),
videos.join(":")
].join(";");
},
unserialize:function(data){
var r=[];
if(data) r=data.split(/;/);
this.id=w.unescape(r[0]);
this.videos=[];
if(r[1]){
var vids=r[1].split(/:/);
for(var i=0; i<vids.length; i++){
if(vids[i]){
var v=new Video();
v.unserialize(vids[i]);
this.videos.push(v);
}
}
}
},
save:function(){
var self=this;
setTimeout(function(){GM_setValue("playlist_"+self.id,self.serialize());},0);
},
load:function(){
var data=GM_getValue("playlist_"+(GM_getValue("current")||this.id));
if(data) this.unserialize(data);
},
push:function(video){this.videos.push(video);},
pop:function(){return this.videos.shift();},
popRandom:function(){
if(this.videos.length==0) return undefined;
var i=Math.floor(Math.random()*this.videos.length);
var v=this.videos[i];
this.videos.splice(i,1);
return v;
},
up:function(index){
if(index>=0&&index<this.videos.length){
this.videos.unshift(this.videos[index]);
return this.videos.splice(index+1,1);
}
return false;
},
down:function(index){
if(index>=0&&index<this.videos.length){
this.videos.push(this.videos[index]);
return this.videos.splice(index,1);
}
return false;
},
remove:function(index){
if(index>=0&&index<this.videos.length) return this.videos.splice(index,1);
return false;
},
clear:function(){this.videos=[];},
scroll:function(e){
var Target=$("flvplayer_container");
var scrollTop=document.documentElement.scrollTop;
w.scrollBy(0,(getElementPosition(Target)-scrollTop-e));
}
};
var PlayListController=function(){this.initialize.apply(this,arguments);};
PlayListController.prototype={
initialize:function(playlist){
this.playlist=playlist;
this.popmark=GM_getValue("popmark")||false;
this.random=GM_getValue("random_"+this.playlist.id)||false;
this.loop=GM_getValue("loop_"+this.playlist.id)||false;
this.state=GM_getValue("state_"+this.playlist.id)||false;
this.cache=GM_getValue("cache_"+this.playlist.id)||false;
this.mark="del";
this.update();
},
change:function(id){
PlayList.change(id);
this.playlist.clear();
this.playlist.load();
this.random=GM_getValue("random_"+id)||false;
this.loop=GM_getValue("loop_"+id)||false;
this.state=GM_getValue("state_"+id)||false;
this.cache=GM_getValue("cache_"+id)||false;
this.mark="del";
this.update();
},
getPageVideoId:function(){
var m;
if(m=location.href.match(NicoNico.WATCH_PAGE_REGEXP)) return m[1];
else return false;
},
isWatchPage:function(){return this.getPageVideoId()!=false;},
pushVideo:function(videoId,title){
var video=new Video(videoId,title);
this.playlist.push(video);
this.playlist.save();
this.update();
},
pushVideos:function(videos){
for(var i=0,len=videos.length; i<len; i++){
var video=new Video(videos[i].id,videos[i].title);
this.playlist.push(video);
}
this.playlist.save();
this.update();
},
pushThisVideo:function(){
var videoId=this.getPageVideoId();
if(videoId){
var title=unescape(w.Video.title);
var video=new Video(videoId,title);
this.playlist.push(video);
this.playlist.save();
this.update();
}
},
pushAllVideos:function(){
var as=$x("//a[contains(concat(' ',normalize-space(@class),' '),' video ')]",document);
for(var i=0, len=as.length; i<len; i++){
var a=as[i];
if(!a.href||a.className=="video noadd") continue;
var m;
if(m=a.href.match(NicoNico.WATCH_PAGE_REGEXP)){
var video=new Video(m[1],a.innerHTML);
this.playlist.push(video);
if(this.popmark) this.popVideoMark();
}
}
var self=this;
if(location.href.match(NicoNico.WATCH_PAGE_REGEXP)){
var thisVideo=new Video(w.Video.id);
thisVideo.getRelatedVideos(function(videoId,title){
var video=new Video(videoId,title);
self.playlist.push(video);
},function(){
self.playlist.save();
self.update();
});
}
else{
self.playlist.save();
self.update();
}
},
pushMarkedVideos:function(){
var $marked=$x("//a[contains(concat(' ',normalize-space(@class),' '),' video ')][./ancestor::*[contains(concat(' ',normalize-space(@class),' '), ' marked ')]]",document);
for(var i=0, len=$marked.length; i<len; i++)
if($marked&&$marked[i].href.match(NicoNico.WATCH_URL)&&!$marked[i].href.match($marked[i].textContent)){
var link=$marked[i].href.substring(30);
var video=new Video(link,$marked[i].textContent);
this.playlist.push(video);
if(this.popmark&&$marked)this.popVideoMark();
}
this.playlist.save();
this.update();
},
popVideoMark:function(){
var $marked=$x("//*[contains(concat(' ',normalize-space(@class),' '),' marked ')]",document);
if(!$marked) return;
var page=NicoNico.WHATPAGE();
if(page.match(/ranking|tag|search|newarrival|recent|myvideo|hotlist/g)||page==""){
for(var i=0; i<$marked.length; i++){
$marked[i].setAttribute("class","thumb_frm");
}
}
else{
for(var i=0; i<$marked.length; i++){
$marked[i].setAttribute("class","");
}
}
},
playNext:function(){
var video;
if(this.random) video=this.playlist.popRandom();
else video=this.playlist.pop();
if(video){
if(this.loop) this.playlist.push(video);
this.playlist.save();
video.play();
}
},
clearCache:function(){
if(this.cache&&!w.Video.isDeleted&&!w.Video.isMymemory&&!w.gm_CacheProtect){
var cacheDir="http://www.nicovideo.jp/cache/ajax_rm?"+w.Video.id;
GM_xmlhttpRequest({
method:"GET",
url:cacheDir,
onload:function(){
GM_xmlhttpRequest({
method:"GET",
url:cacheDir+"low",
onload:function(){
controller.playNext();
}
});
}
});
}
else{
this.playNext();
}
},
economy:function(){
if(this.cache){
var cacheDir="http://www.nicovideo.jp/cache/ajax_rm?"+w.Video.id;
GM_xmlhttpRequest({
method:"GET",
url:cacheDir+"low",
onload:function(){
controller.clearCache();
}
});
}
else{
this.playNext();
}
},
reload:function(e){
if(w.NicoCache){
var tmp="http://www.nicovideo.jp/cache/ajax_rmtmp?"+w.Video.id;
GM_xmlhttpRequest({
method:"GET",
url:tmp,
onload:function(){
GM_xmlhttpRequest({
method:"GET",
url:tmp+"low",
onload:function(){
w.location.reload(e);
}
});
}
});
}
else w.location.reload(e);
},
remove:function(video){
this.playlist.remove(video);
this.playlist.save();
this.update();
},
clear:function(){
this.playlist.clear();
this.playlist.save();
this.update();
},
up:function(video){
this.playlist.up(video);
this.playlist.save();
this.update();
},
down:function(video){
this.playlist.down(video);
this.playlist.save();
this.update();
},
setPopMark:function(popmark){
this.popmark=popmark;
GM_setValue("popmark",this.popmark);
},
setRandom:function(random){
this.random=random;
GM_setValue("random_"+this.playlist.id,this.random);
},
setLoop:function(loop){
this.loop=loop;
GM_setValue("loop_"+this.playlist.id,this.loop);
},
setState:function(state){
this.state=state;
GM_setValue("state_"+this.playlist.id,this.state);
},
setCache:function(cache){
this.cache=cache;
GM_setValue("cache_"+this.playlist.id,this.cache);
},
update:function(){
var self=this;
var listScrollTop=0;
var box=$("playlistcontroller");
if(!box){
box=document.createElement("div");
box.id="playlistcontroller";
box.style.position="fixed";
box.style.width="410px";
box.style.left="-406px";
box.style.top="40px";
box.style.border="1px solid #CCC";
box.style.backgroundColor="#FFF0FC";
box.style.zIndex="1000";
box.style.overflow="auto";
Util.observe(box,"click",function(){
box.style.left="0px";
});
Util.observe(box,"mouseout",function(e){
if(e.clientX<5||e.clientY<40||e.clientX>400||e.clientY>330)box.style.left="-406px";
});
document.body.appendChild(box);
}
else{
var ul=$("listbox").getElementsByTagName("ul")[0];
listScrollTop=ul.scrollTop;
box.innerHTML="";
}
var header=document.createElement("div");
header.style.margin="5px 0px 0px 10px";
header.style.cssFloat="left";
box.appendChild(header);
var title=document.createElement("p");
title.style.fontSize="90%";
title.style.fontWeight="bold";
title.innerHTML="NicoNicoPlaylist mod";
var del_mark=document.createElement("span");
del_mark.className="move_button";
del_mark.style.marginLeft="10px";
del_mark.innerHTML="\u2715";
del_mark.title="削除";
del_mark.style.color="#D00";
del_mark.style.cursor="pointer";
Util.observe(del_mark,"click",function(){
var dl=$x("//*[@class='del']",document);
var up=$x("//*[@class='up']",document);
var down=$x("//*[@class='down']",document);
for(var i=0; i<dl.length; i++){
up[i].style.display="none";
down[i].style.display="none";
dl[i].style.display="inline";
self.mark="del";
}
});
title.appendChild(del_mark);
var up_mark=document.createElement("span");
up_mark.className="move_button";
up_mark.innerHTML="\u25b2";
up_mark.title="上に移動";
up_mark.style.color="#063";
up_mark.style.cursor="pointer";
Util.observe(up_mark,"click",function(){
var dl=$x("//*[@class='del']",document);
var up=$x("//*[@class='up']",document);
var down=$x("//*[@class='down']",document);
for(var i=0; i<up.length; i++){
dl[i].style.display="none";
down[i].style.display="none";
up[i].style.display="inline";
self.mark="up";
}
});
title.appendChild(up_mark);
var down_mark=document.createElement("span");
down_mark.className="move_button";
down_mark.innerHTML="\u25bc";
down_mark.title="下に移動";
down_mark.style.color="gray";
down_mark.style.cursor="pointer";
Util.observe(down_mark,"click",function(){
var dl=$x("//*[@class='del']",document);
var up=$x("//*[@class='up']",document);
var down=$x("//*[@class='down']",document);
for(var i=0; i<down.length; i++){
dl[i].style.display="none";
up[i].style.display="none";
down[i].style.display="inline";
self.mark="down";
}
});
title.appendChild(down_mark);
header.appendChild(title);
var changerDiv=document.createElement("div");
changerDiv.style.margin="5px 10px 5px 0px";
changerDiv.style.cssFloat="right";
box.appendChild(changerDiv);
var changer=document.createElement("input");
changer.type="button";
changer.style.backgroundColor="white";
changer.style.border="1px solid black";
changer.style.padding="0px";
changer.style.fontWeight="bold";
changer.value=(this.playlist.id=="default") ? "main":this.playlist.id;
changer.title="change playlist";
Util.observe(changer,"mousedown",function(){
var id=(playlist.id=="default") ? "alter":"default";
self.change(id);
});
changerDiv.appendChild(changer);
var hr=document.createElement("hr");
hr.style.clear="both";
hr.style.margin="0px 10px 5px 10px";
box.appendChild(hr);
var buttons=document.createElement("div");
buttons.style.margin="5px 0px 6px 10px";
buttons.style.color="#000000";
var empty=(this.playlist.videos.length==0);
var buttonDefinition=[
{caption:"\u30de\u30fc\u30af\u3057\u305f\u52d5\u753b\u3092\u8ffd\u52a0",
click:function(){self.pushMarkedVideos();}},
{caption:"\u30da\u30fc\u30b8\u4e2d\u306e\u52d5\u753b\u3092\u8ffd\u52a0",
click:function(){self.pushAllVideos();}},
{caption:"\u518d\u751f",
click:function(){self.playNext();},disabled:empty},
{caption:"\u5168\u3066\u524a\u9664",
click:function(){self.clear();},disabled:empty}
];
if(this.isWatchPage()){
buttonDefinition.shift();
buttonDefinition.unshift(
{caption:"\u3053\u306e\u52d5\u753b\u3092\u8ffd\u52a0",
click:function(){self.pushThisVideo();}});
}
for(var i=0, len=buttonDefinition.length; i<len; i++){
var def=buttonDefinition[i];
var btn=document.createElement("input");
btn.type="button";
btn.value=def.caption;
btn.className="submit";
btn.style.marginRight="5px";
if(def.click) Util.observe(btn,"click",def.click);
if(def.disabled) btn.disabled=true;
buttons.appendChild(btn);
}
box.appendChild(buttons);
var listbox=document.createElement("div");
listbox.id="listbox";
listbox.style.margin="0px 10px";
listbox.style.padding="0px";
listbox.style.border="1px solid #999";
listbox.style.height="200px";
listbox.style.backgroundColor="#FFF";
box.appendChild(listbox);
var list=document.createElement("ul");
list.className="TXT12";
list.style.listStyleType="none";
list.style.margin="0px";
list.style.padding="0px";
list.style.width="100%";
list.style.height="100%";
list.style.overflow="auto";
listbox.appendChild(list);
for(var i=0, len=this.playlist.videos.length; i<len; i++){
var v=this.playlist.videos[i];
var item=document.createElement("li");
item.style.padding="2px 5px 2px 0px";
item.style.whiteSpace="nowrap";
if(i % 2) item.style.backgroundColor="#FFF9FD";
var del=document.createElement("a");
del.href="javascript:void(0);";
del.innerHTML="\u2715";
del.className="del";
del.style.color="#D00";
del.style.fontSize="92%";
del.style.display=(self.mark=="del")? "inline":"none";
Util.observe(del,"click",(function(index){
return function(){self.remove(index);};
})(i));
item.appendChild(del);
var up=document.createElement("a");
up.href="javascript:void(0);";
up.innerHTML="\u25b2";
up.className="up";
up.style.color="#063";
up.style.display=(self.mark=="up") ? "inline" :"none";
Util.observe(up,"click",(function(index){
return function(){self.up(index);};
})(i));
item.appendChild(up);
var down=document.createElement("a");
down.href="javascript:void(0);";
down.innerHTML="\u25bc";
down.className="down";
down.style.color="gray";
down.style.display=(self.mark=="down") ? "inline" :"none";
Util.observe(down,"click",(function(index){
return function(){self.down(index);};
})(i));
item.appendChild(down);
var anchor=document.createElement("a");
anchor.href=v.getPlayUri();
anchor.innerHTML=v.title;
anchor.className="video noadd";
anchor.style.marginLeft="5px";
anchor.style.textDecoration="none";
item.appendChild(anchor);
Util.observe(anchor,"click",(function(index){
return function(){self.remove(index);};
})(i));
list.appendChild(item);
}
if(listScrollTop>0) list.scrollTop=listScrollTop;
if(location.href.match(NicoNico.WATCH_PAGE_REGEXP)){
var scroll=document.createElement("span");
scroll.style.position="absolute";
scroll.style.margin="5px";
scroll.style.fontSize="70%";
scroll.style.paddingLeft="5px";
scroll.innerHTML="scroll\u3000";
var scrl_switch=document.createElement("a");
scrl_switch.id="scrl_switch";
scrl_switch.href="javascript:void(0);";
scrl_switch.innerHTML=SCROLL;
scroll.appendChild(scrl_switch);
box.appendChild(scroll);
var scrl_ctl=document.createElement("form");
scrl_ctl.style.position="absolute";
scrl_ctl.style.margin="3px";
scrl_ctl.id="scroll_form";
scrl_ctl.style.display="none";
var scrl_txt=document.createElement("input");
scrl_txt.style.fontSize="70%";
scrl_txt.style.marginLeft="40px";
scrl_txt.type="text";
scrl_txt.size="3";
scrl_txt.maxLength="4";
scrl_txt.name="scroll_value";
scrl_txt.value=SCROLL;
var scrl_but=document.createElement("input");
scrl_but.style.fontSize="70%";
scrl_but.type="button";
scrl_but.className="submit";
scrl_but.value="\u4fdd\u5b58";
scrl_ctl.appendChild(scrl_txt);
scrl_ctl.appendChild(scrl_but);
box.appendChild(scrl_ctl);
Util.observe(scrl_switch,"click",function(){
$("scrl_switch").style.display="none";
$("scroll_form").style.display="inline";
});
Util.observe(scrl_but,"click",function(){
var form=$("scroll_form");
var txt=$("scrl_switch");
SCROLL=(form.scroll_value.value.match(/-?\d+/))? form.scroll_value.value:SCROLL;
txt.innerHTML=SCROLL;
GM_setValue("nico_scroll",SCROLL);
self.playlist.scroll();
form.style.display="none";
txt.style.display="inline";
});
}
var checkboxes=document.createElement("div");
checkboxes.className="TXT12";
checkboxes.style.margin="3px 10px 5px 10px";
checkboxes.style.textAlign="right";
var checkboxDefinition=[
{caption:"Mark",
click:function(){self.setPopMark(this.checked);},checked:this.popmark,watch:0},
{caption:"Random",
click:function(){self.setRandom(this.checked);},checked:this.random},
{caption:"Loop",
click:function(){self.setLoop(this.checked);},checked:this.loop},
{caption:"Pause",
click:function(){self.setState(this.checked);},checked:this.state,watch:1},
{caption:"Cache",
click:function(){self.setCache(this.checked);},checked:this.cache,nl:1}
];
for(var i=0, len=checkboxDefinition.length; i<len; i++){
var def=checkboxDefinition[i];
if(((location.href.match(NicoNico.WATCH_PAGE_REGEXP)&&def.watch==0)
||!location.href.match(NicoNico.WATCH_PAGE_REGEXP)&&def.watch==1)
||(!w.NicoCache&&def.nl==1)) continue;
var chk=document.createElement("input");
chk.id="check_"+i;
chk.type="checkbox";
chk.style.marginLeft="6px";
chk.style.verticalAlign="middle";
if(def.click) Util.observe(chk,"click",(function(c,f){
return function(){f.apply(c);};
})(chk, def.click));
if(def.disabled) chk.disabled=true;
if(def.checked) chk.checked=true;
checkboxes.appendChild(chk);
var label=document.createElement("label");
label.htmlFor=chk.id;
label.innerHTML=def.caption;
label.style.verticalAlign="middle";
label.style.fontSize="95%";
label.style.fontWeight="bold";
checkboxes.appendChild(label);
}
box.appendChild(checkboxes);
}
};
var playlist=new PlayList();
var controller=new PlayListController(playlist);
w.gm_playlistController=controller;
if(location.href.match(NicoNico.WATCH_PAGE_REGEXP)){
var player=$("flvplayer");
(function(timer){
var t=setInterval(function(){
var status=player.ext_getStatus();
if(status=="connectionError"||document.title=="Error?"){
clearInterval(t);
player.style.display="none";
controller.reload(true);
}
if(status=="playing"){
clearInterval(t);
playlist.scroll(SCROLL);
if(unescape(w.Video.tags).match("ネタバレ")) player.ext_setCommentVisible();
if(playerFocus) player.focus();
timer();
}
if(status=="paused"||status=="stopped"){
if(playlist.id=="alter"){
player.ext_play(1);
player.ext_setCommentVisible();
player.ext_setVideoSize('normal');
player.SetVariable('nico.player._video._visible', 0);
}
}
},250);
})(function(){
var t=setInterval(function(){
var status=player.ext_getStatus();
if(document.title=="Error?"){
clearInterval(t);
player.style.display="none";
controller.reload(true);
}
else if(status=="end"){
if(controller.state) return;
else{
clearInterval(t);
if(playlist.videos.length>0){
player.style.display="none";
if(w.NicoCache){
if(w.gm_removeEconomy) controller.economy();
else controller.clearCache();
}
else controller.playNext();
}
}
}
},1000);
});
}
function $x(xpath,context){
var x=document.evaluate(xpath,context,null,7,null);
var array=[];
for(var i=0; i<x.snapshotLength; i++) array.push(x.snapshotItem(i));
return array;
}
function getElementPosition(elem){
var offsetTrail=elem;
var offsetTop=0;
while(offsetTrail){
offsetTop+=offsetTrail.offsetTop;
offsetTrail=offsetTrail.offsetParent;
}
offsetTop=offsetTop||null;
return offsetTop;
}
var PlayListStyle=[
".move_button,a.del,a.up,a.down{",
"margin-left:5px; font-weight:bold; text-decoration:none; outline:none;}"
].join('\n');
GM_addStyle(PlayListStyle);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment