Hides posts with specified tags, artists, or users and intelligently skips them in the post view based on your navigation direction.
// ==UserScript==
// @name Rule34 Custom Blocker (Tags & Users)
// @name:tr Rule34 Özel Engelleyici (Etiketler ve Kullanıcılar)
// @namespace https://greasyfork.org/en/users/1500762-kerimdemirkaynak
// @version 3.2
// @description Hides posts with specified tags, artists, or users and intelligently skips them in the post view based on your navigation direction.
// @description:tr Belirlenen etiketlere, çizerlere veya yükleyicilere sahip gönderileri gizler ve tekli gönderi görünümünde gezinme yönünüze göre otomatik olarak atlar.
// @author Kerim Demirkaynak
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=256&domain_url=https%3A%2F%2Frule34.xxx%2F
// @match https://rule34.xxx/index.php*
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// Engellenecek etiketleri, çizerleri veya kullanıcıları bu listeye ekleyebilirsiniz.
// İstenmeyen çizerleri etiket olarak (örn: "trash_artist") ekleyebilirsiniz.
// Kullanıcıları (yükleyicileri) engellemek için başına "user:" ekleyin (örn: "user:GokuYellow")
const blockList = [
'futanari',
'futa_on_male',
'futa_on_futa',
'dickgirl',
'shemale',
'gutanari',
'user:furreal99',
'user:GokuYellow'
// ve diğer istemediğiniz etiket/kullanıcılar...
];
const blockedTags = [];
const blockedUsers = [];
// Listeyi etiketler ve kullanıcılar olarak ikiye ayırıyoruz
blockList.forEach(item => {
const lowerItem = item.toLowerCase().trim();
if (lowerItem.startsWith('user:')) {
blockedUsers.push(lowerItem.replace('user:', '').trim());
} else {
blockedTags.push(lowerItem);
}
});
const urlParams = new URLSearchParams(window.location.search);
const pageType = urlParams.get('s');
// --- Izgara/Liste Görünümü İçin (Ana Sayfa) ---
if (pageType === 'list' || !pageType) {
const hideThumbnails = () => {
document.querySelectorAll('span.thumb').forEach(thumb => {
if (thumb.style.display === 'none') return;
const img = thumb.querySelector('img.preview');
// Not: Liste görünümünde sadece etiketleri kontrol edebiliriz
// Yükleyici (uploader) bilgisi Rule34 liste DOM yapısında varsayılan olarak bulunmaz.
if (img && img.title && blockedTags.some(tag => img.title.toLowerCase().includes(tag))) {
thumb.style.display = 'none';
}
});
};
const listObserver = new MutationObserver(hideThumbnails);
const imageList = document.getElementById('post-list');
if (imageList) {
listObserver.observe(imageList, { childList: true, subtree: true });
}
hideThumbnails();
}
// --- Tekli Gönderi/Görüntüleme Sayfası İçin (Akıllı Atlatma) ---
if (pageType === 'view') {
let lastKnownDirection = 'next'; // Varsayılan yön
const setupDirectionListeners = () => {
const nextButton = document.getElementById('next_search_link');
const prevButton = document.getElementById('prev_search_link');
if (nextButton) nextButton.addEventListener('mousedown', () => { lastKnownDirection = 'next'; }, true);
if (prevButton) prevButton.addEventListener('mousedown', () => { lastKnownDirection = 'prev'; }, true);
};
const checkAndSkip = () => {
const tagList = document.getElementById('tag-sidebar');
const image = document.getElementById('image');
if (!tagList || !image) return;
// Kontrol etmeden önce resmi görünür yap (bir önceki gizlenmiş olabilir)
image.style.visibility = 'visible';
// 1. Etiketleri / Çizerleri al
const currentTags = Array.from(tagList.querySelectorAll('li a')).map(a => a.innerText.toLowerCase().replace(/ /g, '_'));
// 2. Yükleyiciyi (Uploader / User) İstatistik sekmesinden al
const uploaderNode = document.querySelector('#stats a[href*="uname="]');
const currentUploader = uploaderNode ? uploaderNode.innerText.trim().toLowerCase() : '';
// Yasaklı kontrolü
const isForbiddenTag = currentTags.some(currentTag => blockedTags.some(blocked => currentTag.includes(blocked)));
const isForbiddenUser = blockedUsers.includes(currentUploader);
if (isForbiddenTag || isForbiddenUser) {
// 1. Resmi anında gizle
image.style.visibility = 'hidden';
console.log(`Engellenen içerik algılandı. Yön: ${lastKnownDirection}. Atlanıyor...`);
// 2. Doğru yöndeki butona tıkla
const buttonToClick = (lastKnownDirection === 'next')
? document.getElementById('next_search_link')
: document.getElementById('prev_search_link');
if (buttonToClick && buttonToClick.href && !buttonToClick.href.endsWith('#')) {
buttonToClick.click();
}
}
};
// Gözlemci: Sayfa içeriği (etiketler, resim) değiştiğinde tetiklenir
const viewObserver = new MutationObserver(() => {
checkAndSkip();
// Butonlar da yeniden yüklenebileceği için dinleyicileri tekrar kur
setupDirectionListeners();
});
const targetNode = document.getElementById('post-view');
if (targetNode) {
viewObserver.observe(targetNode, { childList: true, subtree: true });
}
// Sayfa ilk yüklendiğinde işlemleri başlat
setupDirectionListeners();
checkAndSkip(); // setTimeout olmadan daha hızlı çalışır
}
})();