f95zone tweaks

f95zone exclude tags and min like filter

Version au 24/04/2021. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name        f95zone tweaks
// @namespace   f95zone tweaks
// @description f95zone exclude tags and min like filter
// @match       https://f95zone.to/latest/
// @version     1.3.1
// @author      3xd_tango
// @require     https://cdn.jsdelivr.net/combine/npm/@violentmonkey/dom@1,npm/@violentmonkey/[email protected]
// @grant       GM_addStyle
// @grant       GM_getValue
// @grant       GM_setValue
// ==/UserScript==

(function () {
'use strict';

var css_248z = ".customTags{border-radius:2px;box-shadow:0 0 0 0 transparent,0 1px 1px 0 rgba(0,0,0,.15),0 1px 2px 0 rgba(0,0,0,.15);display:inline-block;font-size:.8em;line-height:1.8em;margin:4px 4px 0 0;padding:0 6px;text-shadow:1px 1px 2px rgba(0,0,0,.75)}.selected-tags-wrap span:hover{background-color:#ba4545}.selected-tags-wrap span{background-color:#181a1d;border-radius:3px;cursor:pointer;display:inline-block;font-size:.9em;line-height:24px;margin:4px 4px 0 0;padding:0 6.66667px;transition:.2s}";

let like_limit = GM_getValue('like_limit', 200);
let dislikes = GM_getValue('dislikes', ['female protagonist', 'text based', 'mind control']);
let likes = GM_getValue('likes', [['incest', '#ff0000'], ['harem', '#0011ff']]);
let totalTags = GM_getValue('tags', []);
function mainFilter() {
  init();
  return VM.createElement(VM.Fragment, null, VM.createElement("div", {
    className: "filter-block"
  }, VM.createElement("h4", {
    className: "filter-block_title"
  }, "Tags Like Limits"), VM.createElement("div", {
    className: "selectize-input"
  }, VM.createElement("input", {
    value: like_limit,
    autoComplete: "off",
    style: "width: 127px;",
    onChange: limitHandler
  }))), VM.createElement("div", {
    className: "filter-block"
  }, VM.createElement("h4", {
    className: "filter-block_title"
  }, "Like Tags"), VM.createElement("div", {
    className: "filter-block_content"
  }, VM.createElement("div", {
    className: "selectize-input"
  }, VM.createElement("input", {
    autoComplete: "off",
    placeholder: "Enter a tag to filter...",
    list: "totalTagName1",
    style: "width: 100%; opacity: 1; position: relative; left: 0px;",
    onChange: likeHandler
  }, VM.createElement("datalist", {
    id: "totalTagName1"
  }, totalTags.map(t => VM.createElement("option", {
    value: t
  }))))), VM.createElement("div", {
    className: "selected-tags-wrap"
  }, likes.map(dl => VM.createElement("span", {
    onClick: tagRemoveHandler1
  }, dl[0]))))), VM.createElement("div", {
    className: "filter-block"
  }, VM.createElement("h4", {
    className: "filter-block_title"
  }, "Dislike Tags"), VM.createElement("div", {
    className: "filter-block_content"
  }, VM.createElement("div", {
    className: "selectize-input"
  }, VM.createElement("input", {
    placeholder: "Enter a tag to filter...",
    list: "totalTagName",
    style: "width: 100%; opacity: 1; position: relative; left: 0px;",
    onChange: dislikeHandler
  }, VM.createElement("datalist", {
    id: "totalTagName"
  }, totalTags.map(t => VM.createElement("option", {
    value: t
  }))))), VM.createElement("div", {
    className: "selected-tags-wrap"
  }, dislikes.map(dl => VM.createElement("span", {
    onClick: tagRemoveHandler
  }, dl))))), VM.createElement("style", null, css_248z));
}
function init() {
  const element = document.querySelectorAll('.resource-tile');

  if (element[0]) {
    likeFilter();
    clickTotalTags();
    dislikeFilter();
    likeLimit();
    filterOut();
  } else {
    setTimeout(init, 100);
  }
}

function tagRemoveHandler(event) {
  dislikes = dislikes.filter(r => r !== event.target.textContent);
  event.target.remove();
  GM_setValue('dislikes', dislikes);
  dislikeFilter();
  filterOut();
}

function tagRemoveHandler1(event) {
  likes = likes.filter(r => r[0] !== event.target.textContent);
  event.target.remove();
  GM_setValue('likes', likes);
  likeFilter();
  likeLimit();
  filterOut();
}

function likeHandler(event) {
  const tagName = event.target.value;
  event.target.value = '';
  let x;

  do {
    x = prompt(`Please Enter the Color in Hex like '#FFFFFF'`);
  } while (!x.includes('#') && x === '' && x.length <= 1);

  if (x !== null) {
    const tag = [tagName, x];
    likes.push(tag);
    GM_setValue('likes', likes);
    let node = document.createElement("SPAN");
    node.onclick = tagRemoveHandler1;
    node.appendChild(document.createTextNode(tagName));
    event.target.parentNode.parentNode.childNodes[1].append(node);
    likeFilter();
    likeLimit();
    filterOut();
  }
}

function dislikeHandler(event) {
  const tagName = event.target.value;
  dislikes.push(tagName);
  GM_setValue('dislikes', dislikes);
  event.target.value = '';
  let node = document.createElement("SPAN");
  node.onclick = tagRemoveHandler;
  node.appendChild(document.createTextNode(tagName));
  event.target.parentNode.parentNode.childNodes[1].append(node);
  dislikeFilter();
  filterOut();
}

function limitHandler(event) {
  like_limit = event.target.value;
  GM_setValue('like_limit', like_limit);
  likeLimit();
  filterOut();
}

function clickTotalTags() {
  const y = document.querySelector('.selectize-control');

  if (y !== null) {
    y.addEventListener("click", function (e) {
      const x = document.querySelectorAll('div.option');
      console.log('clicked', x);

      if (x !== []) {
        totalTags = [];
        x.forEach(e => totalTags.push(e.innerHTML));
        GM_setValue('tags', totalTags);
      }
    });
  }
}

function likeFilter() {
  const element = document.querySelectorAll('.resource-tile');
  document.querySelectorAll('.customTags').forEach(e => e.parentNode.remove());

  for (let i = 0; i < element.length; i++) {
    // console.debug(element[i]);
    element[i].setAttribute('isDisplay', 'false');

    // if (element[i].style.display === 'none') {
    //   continue;
    // }

    let node = document.createElement("DIV");
    const dataTags = element[i].dataset.tags.split(',');
    node.style.padding = '.5rem 0';

    for (let j = likes.length - 1; j >= 0; j--) {
      if (dataTags.includes(likes[j][0])) {
        let node1 = document.createElement("SPAN");
        node1.classList.add('customTags');
        node1.style.backgroundColor = likes[j][1];
        element[i].style.boxShadow = `0px 0px 10px 1px ${likes[j][1]}`;
        node1.appendChild(document.createTextNode(likes[j][0]));
        node.appendChild(node1);
        element[i].setAttribute('isDisplay', 'true');
      } else if (element[i].getAttribute('isDisplay') === null) {
        element[i].setAttribute('isDisplay', 'false');
      }
    }

    if (element[i].getAttribute('isDisplay') === 'true') {
      try {
        element[i].childNodes[0].childNodes[1].childNodes[1].appendChild(node);
      } catch (e) {
        console.error(e);
        setTimeout(likeFilter, 200);
      }
    }
  }
}

function dislikeFilter() {
  const element = document.querySelectorAll('.resource-tile');

  for (let i = 0; i < element.length; i++) {

    const dataTags = element[i].dataset.tags.split(',');
    const isFP = checkTags(element[i], dataTags);

    if (isFP) {
      element[i].setAttribute('isDislike', 'true');
    } else {
      element[i].setAttribute('isDislike', 'false');
    }
  }
}

function likeLimit() {
  const element = document.querySelectorAll('.resource-tile');

  if (like_limit === '') {
    like_limit = -1;
  }

  for (let i = 0; i < element.length; i++) {
    const element_likes = element[i].childNodes[0].childNodes[1].childNodes[1].childNodes[1].childNodes[1].innerHTML;

    if (Number(element_likes) <= Number(like_limit)) {
      if (element[i].getAttribute('isDisplay') === 'false') {
        element[i].setAttribute('isLikeLimit', 'true');
      } else {
        element[i].setAttribute('isLikeLimit', 'false');
      }
    } else {
      element[i].setAttribute('isLikeLimit', 'false');
    }
  }
}

function filterOut() {
  const element = document.querySelectorAll('.resource-tile');

  for (let i = 0; i < element.length; i++) {
    if (element[i].getAttribute('isDislike') === 'true' || element[i].getAttribute('isLikeLimit') === 'true') {
      element[i].style.setProperty('display', 'none', 'important');
      element[i].style.setProperty('height', '0px', 'important');
      element[i].style.setProperty('margin', '0px', 'important');
    } else {
      element[i].style.setProperty("display", "block", "important");
      element[i].style.setProperty("height", "unset", "important");
      element[i].style.setProperty("margin", "unset", "important");
    }
  }
}

function checkTags(element, dataTags) {
  let tagProt = ['female protagonist', 'male protagonist', 'futa/trans protagonist'];
  const tagProtNames = dislikes.filter(e => e.includes('protagonist'));
  let b = [];
  let c = 0;
  dataTags.forEach(e => {
    if (tagProtNames.length >= 1) {
      if (tagProtNames.includes(e)) {
        return b.push(e);
      }
    }

    if (dislikes.includes(e)) {
      c += 1;
    }
  });
  console.debug(`b = ${b}`, c, element);

  if (c > 0) {
    return true;
  }

  if (b.length > 0) {
    b.forEach(e => {
      tagProt = tagProt.filter(r => r !== e);
    });

    for (let i = 0; i <= tagProt.length - 1; i++) {
      console.debug(`datatags includes? = ${dataTags.includes(tagProt[i])} for ${tagProt[i]} `);

      if (dataTags.includes(tagProt[i])) {
        return false;
      }

      if (i === tagProt.length - 1) {
        return true;
      }
    }
  }

  console.debug(`tagProt = ${tagProt}`);
  return false;
}

document.querySelector('.content-block_filter').append(mainFilter());

history.onpushstate = function (state) {
  setTimeout(init, 200);
};

(function (history) {
  var pushState = history.pushState;

  history.pushState = function (state) {
    if (typeof history.onpushstate == "function") {
      history.onpushstate({
        state: state
      });
    }

    return pushState.apply(history, arguments);
  };
})(window.history);

}());