Cpt_mathix / MyAnimeList(MAL) - Last updates "Edit Button"

// ==UserScript==
// @name         MyAnimeList(MAL) - Last updates "Edit Button"
// @version      1.3.3
// @description  Brings the edit button back to your profile
// @author       Cpt_mathix
// @include      *://myanimelist.net/profile*
// @exclude      *://myanimelist.net/profile/*/reviews*
// @exclude      *://myanimelist.net/profile/*/recommendations*
// @exclude      *://myanimelist.net/profile/*/clubs*
// @exclude      *://myanimelist.net/profile/*/friends*
// @licence      GPL-2.0-or-later; http://www.gnu.org/licenses/gpl-2.0.txt
// @run-at       document-start
// @grant        GM_getValue
// @grant        GM_setValue
// @namespace https://greasyfork.org/users/16080
// ==/UserScript==

var version = '1.3.3';

window.addEventListener('load', function() {
    var you = document.getElementsByClassName('header-profile-link')[0].textContent;
    var user_profile = document.getElementsByTagName('title')[0].textContent.replace("\'s Profile - MyAnimeList.net", "");

    prepareLastUpdates();
    if (you.trim() == user_profile.trim()) {
        processLastUpdates(true);
    } else {
        loadRSS(you, "anime", "rw");
        loadRSS(you, "manga", "rm");

        console.log('Running script: Last updates "Edit Button"');
    }
}, false);

function prepareLastUpdates() {
    var data = document.getElementsByClassName("statistics-updates");
    for(var i = 0; i < data.length; i++) {
        var edit = document.createElement('div');
        edit.className = "add_edit_button";

        var title = data[i].getElementsByTagName('a')[1];
        title.parentNode.insertBefore(edit, title.parentNode.childNodes[2]);
        title.className += 'pr4';
    }
}

function processLastUpdates(isYourProfile, list, type) {
    var data = document.getElementsByClassName("statistics-updates");
    for(var i = 0; i < data.length; i++) {
        var itemUrl = data[i].getElementsByTagName('a');
        var id = itemUrl[0].href.match(/\d+/)[0];
        var edit = data[i].getElementsByClassName("add_edit_button")[0];

        if (isYourProfile) {
            createEditYourProfile(data[i], edit, id);
        } else {
            createEditOtherProfile(data[i], edit, id, list, type);
        }
    }

    if (typeof jQuery == 'undefined') $ = unsafeWindow.$;

    $('.lightbox').fancybox({
        'width'			: 700,
        'height'		: '85%',
        'overlayShow'	: false,
        'titleShow'     : false,
        'type'          : 'iframe'
    });
}

function createEditYourProfile(element, edit, id) {
    var url;
    if (element.parentNode.className.indexOf('manga') == -1) {
        url = "/ownlist/anime/" + id + "/edit?hideLayout=1";
        edit.outerHTML = '<a href=' + url + ' title="Edit this entry" class="lightbox button_edit">edit</a>';
    } else {
        url = "/ownlist/manga/" + id + "/edit?hideLayout=1";
        edit.outerHTML = '<a href=' + url + ' title="Edit this entry" class="lightbox button_edit">edit</a>';
    }
}

function createEditOtherProfile(element, edit, id, list, type) {
    var url;
    if (element.parentNode.className.indexOf('manga') == -1 && type === "anime") {
        if (haveListHit(list, id)) {
            url = "/ownlist/anime/" + id + "/edit?hideLayout=1";
            edit.outerHTML = '<a href=' + url + ' title="Edit this entry" class="lightbox button_edit">edit</a>';
        } else {
            url = "/ownlist/anime/add?hideLayout=1&selected_series_id=" + id;
            edit.outerHTML = '<a href=' + url + ' title="Add this entry" class="lightbox button_add">add</a>';
        }
    } else if (element.parentNode.className.indexOf('manga') > -1 && type === "manga") {
        if (haveListHit(list, id)) {
            url = "/ownlist/manga/" + id + "/edit?hideLayout=1";
            edit.outerHTML = '<a href=' + url + ' title="Edit this entry" class="lightbox button_edit">edit</a>';
        } else {
            url = "/ownlist/manga/add?hideLayout=1&selected_series_id=" + id;
            edit.outerHTML = '<a href=' + url + ' title="Add this entry" class="lightbox button_add">add</a>';
        }
    }
}

function haveListHit(list, id) {
    return list[id];
}

function loadRSS(user, type, query) {
    makeRequest('GET', '/rss.php?type=' + query + '&u=' + user).then(function(rss) {
        var lastUpdate = rss.getElementsByTagName('pubDate')[0].textContent;
        var cachedDate = getCacheDate(type + "rss");

        if (lastUpdate == cachedDate) {
            console.log('Processing cached ' + type + 'list...');
            processLastUpdates(false, getUserList(type), type);
        } else {
            console.log('Cached ' + type + ' data not up to date!');
            setCacheDate(type + "rss", lastUpdate);

            loadUserList(user, type);
        }
    }).catch(function(err) {
        console.log(err);
        console.log(type + ' RSS feed failed to load');
        var lastUpdate = new Date();
        var cachedDate = new Date(getCacheDate(type + "list"));

        if (lastUpdate - cachedDate < 86400000 && lastUpdate - cachedDate > 0) {
            console.log('Processing cached ' + type + 'list...');
            processLastUpdates(false, getUserList(type), type);
        } else {
            console.log('Cached ' + type + ' data not up to date!');

            loadUserList(user, type);
        }
    });
}

function loadUserList(user, type) {
    makeRequest('GET', '/malappinfo.php?u=' + user + '&status=all&type=' + type + '').then(function (data) {
        var xmlDocument = data;

        // create a list that I can cache
        var rawList = xmlDocument.getElementsByTagName('series_' + type + 'db_id');
        var statusList = xmlDocument.getElementsByTagName('my_status');
        var set = {};
        for (var i = 0; i < rawList.length; i++) {
            set[rawList[i].textContent] = true;
        }

        setCacheDate(type + "list", new Date());
        setUserList(type, set);

        processLastUpdates(false, set, type);
    }).catch(function (err) {
        console.log("failed to load list, trying to grab cached list");
        processLastUpdates(false, getUserList(type), type);
    });
}

function makeRequest(method, url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                resolve(xhr.responseXML);
            } else {
                reject();
            }
        };
        xhr.onerror = function () {
            reject();
        };
        xhr.send();
    });
}

function getUserList(type) {
    var object = GM_getValue('MAL' + type + 'list');
    if (object)
        return JSON.parse(object);
    else {
        console.log("failed to get lists");
        return false;
    }
}

function setUserList(type, list) {
    GM_setValue('MAL' + type + 'list', JSON.stringify(list));
}

function getCacheDate(type) {
    var object = GM_getValue('CacheDate' + type + version);
    if (object)
        return JSON.parse(object);
    else
        return null;
}

function setCacheDate(type, value) {
    GM_setValue('CacheDate' + type + version, JSON.stringify(value));
}