MAL Voice Actor Filter

This script filters voice actor: "Voice Acting Roles" and anime staff: "Anime Staff Positions" by your anime list entries

目前為 2014-10-16 提交的版本,檢視 最新版本

// MAL Voice Actor Filter!
// version 1.2
// 2010-06-14
// Copyright (c) 2009, Bastvera <[email protected]>
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
//
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "MAL Voice Actor Filter", and click Uninstall.
//
// --------------------------------------------------------------------
//
// ==UserScript==
// @name           MAL Voice Actor Filter
// @namespace      http://thayanger.neostrada.pl
// @include        http://myanimelist.net/people/*
// @include        http://myanimelist.net/people.php?id=*
// @description    This script filters voice actor: "Voice Acting Roles" and anime staff: "Anime Staff Positions" by your anime list entries
// @author         Bastvera <[email protected]>
// @version        1.2.3
// ==/UserScript==
 
//All edit buttons in "Voice Acting Roles"
var allEdits = document.evaluate(
    "//td[@style='padding-left: 5px;']//table[1]//a[@class='Lightbox_AddEdit button_edit']",
    document,
    null,
    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
    null);
//All edit buttons in "Anime Staff Positions"
var allEditsStaff = document.evaluate(
    "//td[@style='padding-left: 5px;']//table[2]//a[@class='Lightbox_AddEdit button_edit']",
    document,
    null,
    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
    null);

//Correct Table check
var antyStaff = allEdits.snapshotItem(0);
antyStaff = antyStaff.parentNode.parentNode.parentNode.parentNode.parentNode.previousSibling;
var convert=antyStaff.innerHTML;
var finder = convert.search("Voice Acting Roles");
var finderStaff = convert.search("Anime Staff Positions");
	
if(finder!=-1 || finderStaff!=-1){
	
    //Elements placing
    var checkboxAnchor = allEdits.snapshotItem(0);
    checkboxAnchor = checkboxAnchor.parentNode.parentNode.parentNode.parentNode.parentNode.previousSibling;
		
    var newElement = document.createElement('BR');
    checkboxAnchor.appendChild(newElement);
	
    var checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.defaultChecked = false;
    checkboxAnchor.appendChild(checkbox);

    newElement = document.createElement('label');
    newElement.setAttribute('for','firstName');
    newElement.appendChild(document.createTextNode('Filter entries by your Anime List.'));
    checkboxAnchor.appendChild(newElement);
    newElement.style.fontWeight="normal";
    newElement.style.fontSize="10px";
	
    if (finder!=-1){
        //Arrays for storing elements
        var editdiv = [];	//Edit button Div
        var moe = [];		//Char Name
        var role = [];		//Main/Support Div
	
        //Edit Entries Segments
        for (var i = 0; i < allEdits.snapshotLength; i++){
            var AnchorLink = allEdits.snapshotItem(i);
            editdiv[i] = AnchorLink.parentNode;									//Edit button Div
            role[i] = editdiv[i].parentNode.nextSibling.nextSibling.lastChild;	//Main/Support Div
            moe[i] = editdiv[i].parentNode.nextSibling.nextSibling.firstChild;	//Char Name
        }
    } else {
        allEditsStaff = allEdits;
    }

    //Arrays for storing elements
    var editdivStaff = [];	//Edit button Div
    var moe2 = [];		//Anime Name
	
    //Edit Entries Segments
    for (var i = 0; i < allEditsStaff.snapshotLength; i++){
        var AnchorLink = allEditsStaff.snapshotItem(i);
        editdivStaff[i] = AnchorLink;									//Edit button Div
        moe2[i] = editdivStaff[i].parentNode.parentNode.firstChild;	//Anime Name
    }
	
    //All add buttons in "Voice Acting Roles"
    var	allElements = document.evaluate(
        "//td[@style='padding-left: 5px;']//a[@class='Lightbox_AddEdit button_add']", //"//td[@style='padding-left: 5px;']//table[1]//a[@class='Lightbox_AddEdit button_add']",
        document,
        null,
        XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
        null);

    //Array with add buttons div
    var addbutton = [];
    for (i = 0; i < allElements.snapshotLength; i++){
        AnchorLink = allElements.snapshotItem(i);
        addbutton[i] = AnchorLink.parentNode.parentNode.parentNode;		//Main Div with Add button
    }

    //Div backup
    var backup = [];
    var orginal = [];
    var backpos = 0;
	
    //Get or Set status of checkbox
    var checkboxmem = GM_getValue('checkboxmem'); //Get chceckbox status
    if(checkboxmem==null){
        checkboxmem=false;
        GM_setValue('checkboxmem', checkboxmem);
        checkbox.checked=checkboxmem;
    }
    else{
        checkbox.checked=checkboxmem;
        if(checkbox.checked==true){
            HideDivs(editdivStaff);
        }
    }

    //Collect Plan to Watch divs
    var editPlan = [];
    //editPlan = CollectPlan();
    CollectPlan();

    //Listener
    checkbox.addEventListener('change',function () {
			
        if(checkbox.checked==true){
            HideDivs(editdivStaff);
        }

        if(checkbox.checked==false){
            RestoreDivsStaff();
        }
		
		GM_setValue('checkboxmem', checkbox.checked);
		
    },false)
}

function CollectPlan(){
    //Get username
    var allNavs = document.evaluate(
        "//div[@id='menu_left']//ul[@id='nav']//a",
        document,
        null,
        XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
        null);

    var userName;
    for (var i = 0; i < allNavs.snapshotLength; i++){
        var linkNav = allNavs.snapshotItem(i);
        var userTest=/\/profile\/.*/;
        var getName = userTest.exec(linkNav);
        getName = "" + getName;
        getName = getName.replace(/\/profile\//,"");
        if(getName!='null')
            userName=getName;
    }

    var rssURL = "http://myanimelist.net/rss.php?type=rw&u=" + userName;
	
    //RSS change check
    GM_xmlhttpRequest({
        method: 'GET',
        url: rssURL,
        headers: {
            'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
            'Accept': 'application/atom+xml,application/xml,text/xml',
        },
        onload: function(responseDetails){
		
            //Cache test
            var cacheCheck = 0;
		
            var lastTime = /<pubDate>.*<\/pubDate>/;
            var modTime = lastTime.exec(responseDetails.responseText);
            var saveTime = GM_getValue('saveTime');
            modTime = "" + modTime;
            if(modTime!=saveTime){					//Cache time check
                GM_setValue('saveTime', modTime);
                checkboxText('Filter entries by your Anime List. (Downloading Plan to Watch entries...)');
    //newElement.appendChild(document.createTextNode('222'));
    //checkboxAnchor.appendChild(newElement);

            }
            else
                cacheCheck++;

            if(cacheCheck==0){
                //User list
				var animeURL = "http://myanimelist.net/malappinfo.php?u=" + userName + "&status=all";
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: animeURL,
                    headers: {
                        'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
                        'Accept': 'application/atom+xml,application/xml,text/xml',
                    },
                    onload: function(responseDetails){
                        var text = responseDetails.responseText;
	
                        var key = ";";									//Chaching string

                        //Edit Anime links formating
                        var tagcount = 5000;													//Max number of anime entries
                        var plancount = 0;														//Counter "Plan to Watch" entries
                        var ListLinks = [];														//Array for anime entries storing
                        var anireg=/<series_animedb_id>\d{1,}<\/series_animedb_id>/g;		//Anime entries links
                        var anistatus=/<my_status>\d{1}<\/my_status>/g;		//Anime entries status
                        var exactlink=/\d{1,}/;													//Anime exact link

                        for (var i = 0; i < tagcount; i++){
                            var linkGet = anireg.exec(text); 
							if(linkGet==null){
                                tagcount=i;
                                break;
                            } 
							else {			
								var planDetect = anistatus.exec(text);
								if(planDetect=="<my_status>6</my_status>"){
									ListLinks[plancount] = linkGet;
									ListLinks[plancount] = exactlink.exec(ListLinks[plancount]);
									key = key + ListLinks[plancount] + ";";
									ListLinks[plancount] = "http://myanimelist.net/anime/" + ListLinks[plancount] + "/";
									plancount++;
                                }
							}   
						}							
                        GM_setValue('list', key); //Store Cache string
                        CollectDivs(ListLinks);
                        checkboxText('Filter entries by your Anime List.');
                    }
                });
            }
			
            else{
                var ListLinks = [];								//Anime Links Array
                var key = GM_getValue('list');					//Fetch link from Cache
                var exactlink=/\d{1,}/g;
                var tagcount = 5000;
                for (var i = 0; i < tagcount; i++){
                    var linkGet = exactlink.exec(key);
                    if(linkGet==null){
                        tagcount=i;
                        break;
                    }
                    else{
                        ListLinks[i]=linkGet;
                        ListLinks[i] = "http://myanimelist.net/anime/" + ListLinks[i] + "/";
                    }
                }
                CollectDivs(ListLinks);
                checkboxText('Filter entries by your Anime List.');
            }
        }
    });

    function CollectDivs(ListLinks){

                /*
                var editParent = [];		//Main div
                var editSibling = [];		//Anime Link href for comparing
                //var editPlan = [];			//Plan to Watch div
            
                for (var i = 0; i < allEdits.snapshotLength; i++){
                    editParent[i] = editdiv[i].parentNode.parentNode;
                    editSibling[i] = editdiv[i].parentNode.firstChild;	//Anime Name;
            			
                    //Store "Plan to Watch" Divs
                    var convert = editSibling[i].href;
                    //for (var tcount in ListLinks){ <-------------------------------------------
                    //}
                }*/
    
        //var editParent = [];		//Main div
        var editSibling = [];		//Anime Link href for comparing
        //var editPlan = [];			//Plan to Watch div
    
        for (var i = 0; i < allEdits.snapshotLength; i++){
            //editParent[i] = editdiv[i].parentNode.parentNode;
            editSibling[i] = editdiv[i].parentNode.firstChild;	//Anime Name;

            StorePlan(i);
        }
    
        for (var i = 0; i < allEditsStaff.snapshotLength; i++){
            //editParent[i] = editdivStaff[i].parentNode.parentNode.parentNode;
            editSibling[i] = moe2[i];	//Anime Name;

            StorePlan(i);
        }

        function StorePlan(i){
            //Store "Plan to Watch" Divs
            var convert = editSibling[i].href;
            var exactlink=/\d{1,}/;
            convert = "http://myanimelist.net/anime/" + exactlink.exec(convert) + "/";	//Anime Link;


            for (var tcount in ListLinks){
                var finderPlan = convert.search(ListLinks[tcount]);
                if(finderPlan!=-1){
                    editPlan.push(editSibling[i]);
                    break;
                }
            }
        }
    }
    //return editPlan;
}

function checkboxText(text){
    newElement.style.display="none"; 				//Please wait off
    newElement = document.createElement('label');
    newElement.appendChild(document.createTextNode(text));
    checkboxAnchor.appendChild(newElement);
    newElement.style.fontWeight="normal";
    newElement.style.fontSize="10px";
}

function HideDivs(){
    //Hide all div with add
    for (var current in addbutton){
        addbutton[current].style.display="none";
    }

    //Hide edit Div
    var current;
    for (current in editdivStaff){
        editdivStaff[current].style.display="none";
    }
			
    for(current in moe){
                     
        var curpos = current;
        curpos++;
	
        if(editdiv[current].parentNode.parentNode.getAttribute('style')!="display: none;"){ //Modify root entries only
					
            //Div backup storage
            backup[backpos] = editdiv[current].parentNode.parentNode.cloneNode(true);
            orginal[backpos] = editdiv[current].parentNode.parentNode;
            backpos++;
					
            //Root /Main/Support text add
            var temp = role[current].innerHTML;										//Main/Support text
            temp = temp.replace(/&nbsp;/,"");										//Main/Support clear
            var line = document.createTextNode('\n'+ temp);
            editdiv[current].parentNode.appendChild(line);
					
            //Root hide elements
            role[current].style.display="none";										//Hide Main/Support Div
            editdiv[current].style.display="none";									//Hide edit and airing Div
					
            for( curpos ; curpos < allEdits.snapshotLength; curpos++){
                if(moe[curpos].href==moe[current].href){ //Compare entries by moe name ^_^
		 
                    var br = document.createElement('br');
							
                    //Add Similar anime name
                    editdiv[current].parentNode.appendChild(br);
                    var newNode=editdiv[curpos].parentNode.firstChild.cloneNode(true);
                    editdiv[current].parentNode.appendChild(newNode);
							
                    //Similar /Main/Support text add
                    temp = role[curpos].innerHTML;
                    temp = temp.replace(/&nbsp;/,"");
                    line = document.createTextNode('\n'+temp);
                    editdiv[current].parentNode.appendChild(line);
							
                    //Hide Similar Div
                    editdiv[curpos].parentNode.parentNode.style.display="none";
                }
            }

            for (var i in editPlan){        
                if(editPlan[i] == editdiv[current].parentNode.firstChild.href){
                    editdiv[current].parentNode.parentNode.style.display="none";
                }
            }
        }
    }

    for(current in moe2){

        var curpos = current;
        curpos++;

        if(editdivStaff[current].parentNode.parentNode.parentNode.getAttribute('style')!="display: none;"){ //Modify root entries only

            //Div backup storage
            backup[backpos] = editdivStaff[current].parentNode.parentNode.parentNode.cloneNode(true);
            orginal[backpos] = editdivStaff[current].parentNode.parentNode.parentNode;
            backpos++;

            for( curpos ; curpos < allEditsStaff.snapshotLength; curpos++){
                if(moe2[curpos].href==moe2[current].href){ //Compare entries by anime name ^_^
	
                    var br = document.createElement('br');
							
                    //Add Similar anime name
                    editdivStaff[current].parentNode.appendChild(br);
                    var newNode=editdivStaff[curpos].parentNode.cloneNode(true);
                    editdivStaff[current].parentNode.parentNode.appendChild(newNode);

                    //Hide Similar Div
                    editdivStaff[curpos].parentNode.parentNode.parentNode.style.display="none";
                }
            }

            for (var i in editPlan){        
                if(editPlan[i] == moe2[current].href){
                    editdivStaff[current].parentNode.parentNode.parentNode.style.display="none";
                }
            }
        }
    }
}

function RestoreDivsStaff(){

    //Restore Modified Divs
    for(var current in  backup){
        orginal[current].parentNode.replaceChild(backup[current],orginal[current]);
    }

    //Unhide Similar Voice Actor
    for(current in  editdiv){
        editdiv[current].parentNode.parentNode.removeAttribute('style');
    }

    //Unhide Similar Staff
    for(current in  editdivStaff){
        editdivStaff[current].parentNode.parentNode.parentNode.removeAttribute('style');
    }

    //Unhide Plan to Watch
    //for (var i in editPlan){
    //    editPlan[i].removeAttribute('style');
    //}

    //Unhide add entries
    for(current in addbutton){
        addbutton[current].removeAttribute('style');
    }

    if (finder!=-1){
        //Rescan all edit entries
        allEdits = document.evaluate(
            "//td[@style='padding-left: 5px;']//table[1]//a[@class='Lightbox_AddEdit button_edit']",
            document,
            null,
            XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
            null);

        for (var i = 0; i < allEdits.snapshotLength; i++){
            AnchorLink = allEdits.snapshotItem(i);
            editdiv[i] = AnchorLink.parentNode;									//Edit button Div
            role[i] = editdiv[i].parentNode.nextSibling.nextSibling.lastChild;	//Main/Support Div
            moe[i] = editdiv[i].parentNode.nextSibling.nextSibling.firstChild;	//Char Name
        }
    
        //Rescan all edit entries
        allEditsStaff = document.evaluate(
            "//td[@style='padding-left: 5px;']//table[2]//a[@class='Lightbox_AddEdit button_edit']",
            document,
            null,
            XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
            null);
    }

    if (finderStaff!=-1) {
        //Rescan all edit entries
        allEditsStaff = document.evaluate(
            "//td[@style='padding-left: 5px;']//table[1]//a[@class='Lightbox_AddEdit button_edit']",
            document,
            null,
            XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
            null);
    }
			
    for (var i = 0; i < allEditsStaff.snapshotLength; i++){
        AnchorLink = allEditsStaff.snapshotItem(i);
        editdivStaff[i] = AnchorLink;									//Edit button Div
    }

    //Unhide edit entries
    for(current in editdivStaff){
        editdivStaff[current].removeAttribute('style');
    }

    //Reset backups
    backup = [];
    orginal = [];
    backpos = 0;
}