Baraag Unspoiler NSFW Images

Remove sensitive content spoilers from images and videos on baraag

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Baraag Unspoiler NSFW Images
// @version      1.4
// @description  Remove sensitive content spoilers from images and videos on baraag
// @match        https://baraag.net/*
// @license      public domain
// @namespace    https://sleazyfork.org/users/1468364
// ==/UserScript==

(function() {
	'use strict';

	function hideHideButton() {
		const observer = new MutationObserver((mutations) => {
			document.querySelectorAll('.media-gallery__actions').forEach((el) => {
				if (el.style.display !== 'none') {
					el.style.display = 'none';
				}
			});
		});

		observer.observe(document.body, {
			childList: true,
			subtree: true,
		});
	}

	function isUserProfilePage() {
		return /^\/@[^\/]+(\/with_replies)?$/.test(window.location.pathname);
	}

	// Helper to verify poster image validity
	function verifyAndFixVideoPoster(video) {
		// Prevent double checking the specific video element
		if (video.dataset.posterChecked) return;

		const posterUrl = video.getAttribute('poster');

		if (posterUrl) {
			const img = new Image();

			img.onload = function() {
				// Check dimensions. 0x0 means a 0-byte or broken image
				if (this.naturalWidth === 0 || this.naturalHeight === 0) {
					video.removeAttribute('poster');
					video.setAttribute('preload', 'metadata');
				}
				video.dataset.posterChecked = 'true';
			};

			img.onerror = function() {
				video.removeAttribute('poster');
				video.setAttribute('preload', 'metadata');
				video.dataset.posterChecked = 'true';
			};

			img.src = posterUrl;
		} else {
			// No poster: Ensure we load metadata
			video.setAttribute('preload', 'metadata');
			video.dataset.posterChecked = 'true';
		}
	}

	// Process videos
	function processVideoPlayer(videoPlayer) {
		// Only stop if we have successfully found AND processed the video tag before.
		// If the video tag was missing on previous runs, we want to check again.
		if (videoPlayer.dataset.unspoilerComplete === 'fixed') {
			return;
		}

		// 1. Handle Spoiler Button
		const spoilerButtonDiv = videoPlayer.querySelector('.spoiler-button');
		if (spoilerButtonDiv && !spoilerButtonDiv.classList.contains('spoiler-button--hidden')) {
			const spoilerButton = videoPlayer.querySelector('.spoiler-button button');
			if (spoilerButton && !spoilerButton.dataset.unspoilerClicked) {
				spoilerButton.dataset.unspoilerClicked = 'true';
				spoilerButton.click();
			}
			// Hide canvas manually just in case
			const canvas = videoPlayer.querySelector('.media-gallery__preview');
			if (canvas) canvas.classList.add('media-gallery__preview--hidden');
		}

		// 2. Handle Video Tag (This might not exist yet due to lazy loading)
		const video = videoPlayer.querySelector('video');
		if (video) {
			verifyAndFixVideoPoster(video);
			// Only mark complete if we actually found and processed the video element
			videoPlayer.dataset.unspoilerComplete = 'fixed';
		} else {
			// Video tag is missing (lazy loaded).
			// Do NOT mark as complete. The MutationObserver will trigger again when
			// the site injects the video tag, allowing us to process it then.
		}
	}

	function processStatusCards() {
		document.querySelectorAll('.status-card__image-image').forEach(img => {
			if (img.style.visibility !== 'visible') {
				img.style.visibility = 'visible';
				const parentDiv = img.closest('.status-card__image');
				if (parentDiv) {
					parentDiv.parentNode.insertBefore(img, parentDiv);
				}
			}
		});
	}

	function processAllContent() {
		document.querySelectorAll('.video-player').forEach(videoPlayer => {
			processVideoPlayer(videoPlayer);
		});

		if (!window.location.pathname.includes('/media')) {
			document.querySelectorAll('.spoiler-button:not(.unspoiler-processed)').forEach(spoiler => {
				if (spoiler.closest('.video-player')) return;
				spoiler.classList.add('unspoiler-processed');
				const button = spoiler.querySelector('button');
				if (button && !button.dataset.unspoilerClicked) {
					button.dataset.unspoilerClicked = 'true';
					button.click();
				}
			});
		}

		if (window.location.pathname.includes('/media')) {
			document.querySelectorAll('.media-gallery__item').forEach(item => {
				const hasSpoilerOverlay = item.querySelector('.media-gallery__item__overlay .icon-eye-slash');
				if (!item.querySelector('img') && hasSpoilerOverlay) {
					const thumbnail = item.querySelector('.media-gallery__item-thumbnail');
					if (thumbnail && !thumbnail.dataset.unspoilerProcessed) {
						thumbnail.dataset.unspoilerProcessed = 'true';
						thumbnail.click();
					}
				}
			});
		}

		processStatusCards();
	}

	function initObserver() {
		const observer = new MutationObserver(mutations => {
			let needsProcessing = false;
			let hasNewVideos = false;

			mutations.forEach(mutation => {
				mutation.addedNodes.forEach(node => {
					if (node.nodeType === 1) {
						if (node.matches('.video-player')) hasNewVideos = true;
						else if (node.querySelector('.video-player')) hasNewVideos = true;
					}
				});
				if (mutation.addedNodes.length) needsProcessing = true;
			});

			if (needsProcessing) {
				if (hasNewVideos && isUserProfilePage()) {
					setTimeout(processAllContent, 100);
				} else {
					debouncedProcess();
				}
			}
		});

		observer.observe(document.body, { childList: true, subtree: true });
	}

	const debouncedProcess = debounce(processAllContent, 1);

	function debounce(func, wait) {
		let timeout;
		return function() {
			clearTimeout(timeout);
			timeout = setTimeout(func, wait);
		};
	}

	function init() {
		hideHideButton();
		processAllContent();
		initObserver();

		window.addEventListener('scroll', debounce(function() {
			const scrollThreshold = window.innerHeight * 2;
			if (document.documentElement.scrollHeight - window.scrollY - window.innerHeight < scrollThreshold) {
				var loadMoreButton = document.querySelector('.load-more');
				if (loadMoreButton) {
					loadMoreButton.click();
				}
			}
		}, 100));
	}

	if (document.readyState !== 'loading') {
		init();
	} else {
		document.addEventListener('DOMContentLoaded', init);
	}
})();