f95zone tweaks

f95zone exclude tags and min like filter.

Устаревшая версия за 23.08.2021. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name        f95zone tweaks
// @namespace   f95zone tweaks
// @description f95zone exclude tags and min like filter.
// @match       https://f95zone.to/latest/
// @version     1.3.4
// @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}.input-tag{width:127px;opacity:1;position:relative;left:0}.border-gradient{border:3px solid;border-image-slice:1}";

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'], ['futa/trans', '#EE82EE'], ['loli', '#00f5ffff'], ['futa/trans protagonist', '#EE82EE']]);
const 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: "on",
    placeholder: "Enter a tag to filter...",
    className: "input-tag",
    onChange: likeHandler,
    list: "totalTagName"
  })), VM.createElement("datalist", {
    id: "totalTagName"
  }, totalTags.map(item => {
    return VM.createElement("option", {
      value: item
    });
  })), 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", {
    autoComplete: "off",
    placeholder: "Enter a tag to filter...",
    className: "input-tag",
    onChange: dislikeHandler
  })), 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);
    const 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 = '';
  const 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', 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;
    // }

    const colors = [];
    const 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--) {
      // element[i].style.boxShadow = `0px 0px 10px 1px ${likes[j][1]}`;
      if (dataTags.includes(likes[j][0])) {
        if (!element[i].classList.contains('border-gradient')) {
          element[i].classList.add('border-gradient');
        }

        const node1 = document.createElement('SPAN');
        colors.push(likes[j][1]);
        node1.classList.add('customTags');
        node1.style.backgroundColor = 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 (colors.length > 1) {
      element[i].style.borderImageSource = `linear-gradient(to bottom right, ${colors.toString()})`;
    } else {
      element[i].style.color = colors[0];
    }

    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'));
  const 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()); // eslint-disable-next-line no-restricted-globals

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

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

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

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

}());