Rule34 Artist favorites

A simple script to add the possibility to favorite artists to rule34

Fra 15.10.2022. Se den seneste versjonen.

// ==UserScript==
// @name         Rule34 Artist favorites
// @description  A simple script to add the possibility to favorite artists to rule34
// @namespace    User_314159_AFav
// @version      1.0
// @author       User_314159
// @license      Creative Commons Attribution 2.5 Generic
// @match        https://rule34.xxx/index.php?page=account&s=home
// @match        https://rule34.xxx/index.php?page=post*
// @iconURL      https:///rule34.xxx/favicon.ico?v=2
// @grant        none
// ==/UserScript==

/* Functions used to interact with the local storage */
function getArtists() {// gets the localstorage array and parses it into an actual array, creates a new one if there is no key in localStorage
    let artists;
    if(localStorage.getItem('rule34FavArtists') === null){
        console.log('generated new artists array');
        artists = [];
    }else {
        artists = JSON.parse(localStorage.getItem('rule34FavArtists'));
    }
    return artists;
}
function deleteArtist(artist) { // deletes the specified artist out of the array and saves it
    let artists = getArtists();
    let target = artists.indexOf(artist);
    artists.splice(target, 1);
    saveArtists(artists);
    console.log('Deleted ' + artist);
}
function saveArtists(artists) { // saves an updated version of the artists to local storage
    localStorage.setItem('rule34FavArtists', JSON.stringify(artists));
}
function exportArtists(){ // gets the local storage and logs it to the console as a string
    let artists = localStorage.getItem('rule34FavArtists');
    console.log(JSON.stringify(artists));
}
function importArtists(){ // takes an inputted array string and overwrites the local storage with it
    let data = window.prompt("Enter the string here: ");
    localStorage.setItem('rule34FavArtists', JSON.parse(data));
}


/* These are the functions for the Favorites displaying */
function generateArtistEntry(artists, name) { // generates a container with a delete button calling the deleteArtist function and a link to the artist page
    let link = document.createElement('a');
    let deleteButton = document.createElement('button');
    let container = document.createElement('div');

    deleteButton.innerHTML = 'delete';
    deleteButton.setAttribute('id', 'artistFavDel');
    link.innerHTML = name;

    link.setAttribute('href', 'https://rule34.xxx/index.php?page=post&s=list&tags=' + name);
    deleteButton.setAttribute('name', name);

    deleteButton.addEventListener("click", function() {deleteArtist(name)}, false);

    container.appendChild(deleteButton);
    container.appendChild(link);

    return container;
}

/* Functions for the adding of artists to the favorites */
function generateAddButton(name){ // generates a button that is added to the bottom of the post to add an artist
    var button = document.createElement('button');
    button.innerHTML = ('Add ' + name + ' to favorites');
    button.addEventListener("click", function() {addArtist(name)}, false);
    return button;
}
function generateArtistAddable(){ // adds the artists as single buttons to the bottom of the page, the buttons are generated in the generateAddButton function
    let possibles = document.getElementsByClassName('tag-type-artist tag');
    let artists = document.getElementsByClassName('link-list')[0];
    for(let i = 0; i < possibles.length; i++){
        let artist = possibles[i].children[1].firstChild.data.split(' ').join('_'); // this hell of a selector is the name of the artist with the spaces replaced with underscores
        console.log(artist);
        artists.appendChild(generateAddButton(artist));
    }

}
function addArtist(artist) { // adds the name of the artist to the array and saves the array, cancels if the artist already is in the most recent save
    let artists = getArtists();
    if(artists.includes(artist)){
        console.log(artist + ' already in favorites.');
        return;
    }
    artists.push(artist);
    saveArtists(artists);
    console.log('Added ' + artist + ' to favorites');

}


/* Main Function */
(function() {
    'use strict';
    let artists = getArtists(); // gets the artists and parses them from a string to an iterable

    let url = window.location.href;
    if(url.includes('page=post&s=view')){
        generateArtistAddable();
    }; // this part checks if you are on a post and if so, the 'add to favorites' gets added

    let favoritesHeader = document.createElement('h4'); //header 4 element
    let favoritesCollapse = document.createElement('details'); // collapsible list of favorites
    let favoritesTitle = document.createElement('summary'); // title element of the collapsible
    let exp = document.createElement('button');
    let imp = document.createElement('button');
    // the two buttons are for import and export
    exp.addEventListener("click", function() {exportArtists()}, false);
    imp.addEventListener("click", function() {importArtists()}, false);
    imp.innerHTML = 'Import';
    exp.innerHTML = 'Export';
    // the buttons values get declared and the onclick functions get set to the export / import functions

    favoritesTitle.innerHTML = 'Favorite Artists'; //setting the title

    for(let i = 0; i < artists.length; i++){
        favoritesCollapse.appendChild(generateArtistEntry(artists, artists[i]));
    } // this adds one link for each favorite artist to the collapsible

    let desc = document.createElement('p'); //description, paragraph element
    desc.innerHTML = 'View all of your favorite artists and remove them if you wish.';

    favoritesCollapse.appendChild(favoritesTitle); // the title of the collapsible gets added

    favoritesHeader.appendChild(favoritesCollapse); // the collapsible gets added to the main container

    let mainPosts = document.getElementById("user-index").lastElementChild; // the last child of the user-index div is gotten, which is the "To main post page"
    let space = document.getElementById('user-index'); // the space variable is the container element for the whole thing

    space.insertBefore(favoritesHeader, mainPosts); // main container for the artist entries
    space.insertBefore(desc, mainPosts); // the description
    space.insertBefore(exp, mainPosts); // export button
    space.insertBefore(imp, mainPosts); // import button
    // this block just adds all the objects to the page before the "To main post page" link
})();