Better Rule34

A script to improve the use of rule34!

Ajankohdalta 1.6.2024. Katso uusin versio.

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 or Violentmonkey 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         Better Rule34
// @name:fr      Meilleure règle 34
// @namespace    http://tampermonkey.net/
// @version      0.80
// @description  A script to improve the use of rule34!
// @description:fr Un script pour améliorer l'utilisation de rule34!
// @author       You
// @match        https://rule34.xxx/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=rule34.xxx
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==

const defaultConfig = {
    imageResizeNotice: false,
    theme: "dark",
    undeletePosts: true,
    clickAnywhereToStart: false,
    htmlVideoPlayer: false,
    dynamicResizing: false,
    scrollPostsIntoView: false,
    downloadFullSizedImages: false,
    fitImageToScreen: false,
    hideAlerts: false
};

function initializeSettings(defaultConfig) {
    Object.keys(defaultConfig).forEach(key => {
        if (GM_getValue(key) === undefined) {
            GM_setValue(key, defaultConfig[key]);
        }
    });
}

initializeSettings(defaultConfig);

const dark = {
    "primary": "#121212",
    "secondary": "#000011",
    "contrast" : "#4a4a4a",
    "complementary" : "#666666",
    "tableBackground" : "transparent",
    "linkColor" : "#00f"
};

const themes = {
    "dark": dark
}


if(GM_getValue("dynamicResizing", "false") == "true"){
    const css2 = `
    div.sidebar {
        max-width: 30%;
    }
    div.sidebar li {
        font-size: 120%;
    }
    div.content {
        width: 100%;
    }
    .thumb {
        height: 20%;
        width: auto;
    }
    `
            GM_addStyle(css2);
}



const params = new URLSearchParams(window.location.search);

const settingsData = `{
        "settings": [
            {
                "name": "imageResizeNotice",
                "description": "Remove the image resize notice",
                "type": "dropdown",
                "options": ["resize", "no-resize"]
            },
            {
                "name": "theme",
                "description": "Theme selection",
                "type": "dropdown",
                "options": ["dark", "light", "auto"]
            },
            {
                "name": "undeletePosts",
                "description": "Display deleted posts",
                "type": "checkbox"
            },
            {
                "name": "clickAnywhereToStart",
                "description": "Click anywhere on the page to start the video",
                "type": "checkbox"
            },
            {
                "name": "htmlVideoPlayer",
                "description": "Use HTML video player instead of the Fluid Player",
                "type": "checkbox"
            },
            {
                "name": "dynamicResizing",
                "description": "Dynamically resize the page for odd aspect ratios or large screens",
                "type": "checkbox"
            },
            {
                "name": "scrollPostsIntoView",
                "description": "Scroll posts into view",
                "type": "checkbox"
            },
            {
                "name": "downloadFullSizedImages",
                "description": "Download the full resolution image when saving the image",
                "type": "checkbox"
            },
            {
                "name": "fitImageToScreen",
                "description": "Fit image to screen (buggy)",
                "type": "checkbox"
            },
            {
                "name": "hideAlerts",
                "description": "Hide script warnings",
                "type": "checkbox"
            }
        ]
    }`;

// Parse the settings JSON
const settingsObj = JSON.parse(settingsData);

// Function to create and display the settings overlay
function openSettings() {
    // Create the overlay div
    const overlay = document.createElement('div');
    overlay.style.position = 'fixed';
    overlay.style.top = '0';
    overlay.style.left = '0';
    overlay.style.width = '100%';
    overlay.style.height = '100%';
    overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
    overlay.style.display = 'flex';
    overlay.style.justifyContent = 'center';
    overlay.style.alignItems = 'center';
    overlay.style.zIndex = '1000'; // Ensures it overlays everything else

    // Create the centered div
    const centeredDiv = document.createElement('div');
    centeredDiv.style.width = '25vw';
    centeredDiv.style.backgroundColor = 'white';
    centeredDiv.style.padding = '20px';
    centeredDiv.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
    centeredDiv.style.textAlign = 'left';
    centeredDiv.style.display = 'flex';
    centeredDiv.style.flexDirection = 'column';
    centeredDiv.style.justifyContent = 'center';
    centeredDiv.style.alignItems = 'stretch';

    // Create form elements for each setting
    settingsObj.settings.forEach(setting => {
        const settingDiv = document.createElement('div');
        settingDiv.style.marginBottom = '10px';

        const label = document.createElement('label');
        label.innerText = setting.description;
        label.style.display = 'block';
        label.style.marginBottom = '5px';

        settingDiv.appendChild(label);

        if (setting.type === "checkbox") {
            // Create a checkbox for boolean values
            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.checked = GM_getValue(setting.name, "false") === "true";
            checkbox.addEventListener('change', () => {
                GM_setValue(setting.name, checkbox.checked.toString());
            });
            settingDiv.appendChild(checkbox);
        } else if (setting.type === "dropdown") {
            // Create a dropdown for other values
            const dropdown = document.createElement('select');
            const currentValue = GM_getValue(setting.name, setting.options[0]);
            setting.options.forEach(option => {
                const optionElement = document.createElement('option');
                optionElement.value = option;
                optionElement.innerText = option;
                if (option === currentValue) {
                    optionElement.selected = true;
                }
                dropdown.appendChild(optionElement);
            });
            dropdown.addEventListener('change', () => {
                GM_setValue(setting.name, dropdown.value);
            });
            settingDiv.appendChild(dropdown);
        }

        centeredDiv.appendChild(settingDiv);
    });

    // Append the centered div to the overlay
    overlay.appendChild(centeredDiv);

    // Append the overlay to the body
    document.body.appendChild(overlay);

    // Optionally, add a click event to close the overlay when clicking outside the centered div
    overlay.addEventListener('click', (e) => {
        if (e.target === overlay) {
            document.body.removeChild(overlay);
        }
    });
}

function setTheme(){
    let currentTheme = themes[GM_getValue("theme", "false")];
    if(currentTheme){
        const css = `

            table a:link {
                color: ${currentTheme.linkColor};
            }

            table a:visited {
                color: ${currentTheme.linkColor};
            }

            body {
                background-color: ${currentTheme.primary};
            }
            .flat-list{
                background-color: ${currentTheme.secondary};
            }
            div#header ul#subnavbar {
                background-color: ${currentTheme.secondary};
            }
            div#header ul#navbar li.current-page {
                background-image: url(https://imgs.search.brave.com/77L3MmxBu09NuN5WiX4HlbmWjjUe7eAsmBbakS7-DTo/rs:fit:120:120:1/g:ce/aHR0cHM6Ly91cGxv/YWQud2lraW1lZGlh/Lm9yZy93aWtpcGVk/aWEvY29tbW9ucy90/aHVtYi8wLzAyL1Ry/YW5zcGFyZW50X3Nx/dWFyZS5zdmcvMTIw/cHgtVHJhbnNwYXJl/bnRfc3F1YXJlLnN2/Zy5wbmc);;
            }
            .current-page {
                background-color: ${currentTheme.secondary};
                background-color: brightness(110%);
            }
            .manual-page-chooser>input[type=text]{
                background-color: ${currentTheme.secondary};
            }
            .manual-page-chooser>input[type=submit]{
                background-color: ${currentTheme.secondary};
                color: ${currentTheme.contrast};
            }
            div.tag-search input[type=text]{
                background-color: ${currentTheme.secondary};
                color: ${currentTheme.contrast};
            }
            div.tag-search input[type=submit]{
                background-color: ${currentTheme.secondary};
                color: ${currentTheme.contrast};
            }
            .col2 {
                color: ${currentTheme.contrast};
            }
            h6 {
                color: ${currentTheme.contrast};
            }
            h5 {
                color: ${currentTheme.contrast};
            }
            .tag-count {
                color: ${currentTheme.contrast};
            }
            b {
                color: ${currentTheme.contrast};
            }
            li {
                color: ${currentTheme.contrast};
            }
            ul {
                color: ${currentTheme.contrast};
            }
            button {
                background-color: ${currentTheme.secondary};
                color: ${currentTheme.contrast};
                box-sizing: border-box;
                border: 1px solid;
                margin-top: 3px;
                border-color: ${currentTheme.contrast};
            }
            table.highlightable td {
                color: ${currentTheme.contrast};
            }
            h2 {
                color: ${currentTheme.contrast};
            }
            table.form p {
                color: ${currentTheme.contrast};
            }
            table {
                color: ${currentTheme.contrast};
            }
            label {
                color: ${currentTheme.contrast};
            }
            table {
                background-color: ${currentTheme.tableBackground};
            }
            div {
                color: gray;
            }
        `;
        GM_addStyle(css);
        const thumbs = document.querySelectorAll(".thumb");
        thumbs.forEach(thumb => {
            const images = thumb.getElementsByTagName("img");
            for (let i = 0; i < images.length; i++) {
                images[i].style.border = `3px solid ${currentTheme.complementary}`;
            }
        });

        const e=document.getElementById("user-index");e&&[...e.getElementsByTagName("p")].map(e=>(e.style.color=currentTheme.contrast));


        if(GM_getValue("resizePosts", "false") == "true" && window.location.href.startsWith("https://rule34.xxx/index.php?page=post&s=view")){
            GM_addStyle(".content{max-height: 45%; max-width: 45%; overflow: auto;}");
            document.getElementById("image").style.maxHeight = "50%";
            document.getElementById("image").style.maxWidth = "fit-content";
            document.getElementById("image").style.overflow = "auto";
        }
    }
}

let randNum

function getFromRule34(tags, index, limit, useBlacklist = false) {
    if(tags=="all"){tags = ""}
    let pid = index
    if(useBlacklist){tags += (" -"+decodeURIComponent(getCookie("tag_blacklist")).replaceAll("%20", " -").replaceAll("%2F", "/"))}
    console.log(tags)
    const url = `https://api.rule34.xxx/index.php?page=dapi&s=post&q=index&tags=${encodeURIComponent(tags)}&limit=${limit}&pid=${pid}&json=1`;

    return fetch(url)
        .then(response => response.json())
        .then(data => {
        console.log(data)
        return data;
    });
}


function getFromRule34WithId(id) {

    const url = `https://api.rule34.xxx/index.php?page=dapi&s=post&q=index&id=${id}&json=1`;

    return fetch(url)
        .then(response => response.json())
        .then(data => {
        return data[0];
    });
}


function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

function getTagsFromUrl(currentUrl) {
    if(currentUrl.startsWith("https://rule34.xxx/index.php?page=post&s=list&tags=")) {
        return currentUrl.replace("https://rule34.xxx/index.php?page=post&s=list&tags=", "");
    }
}

function creatLinks() {
    try {
        if (window.location.href.startsWith("https://rule34.xxx/index.php?page=post&s=list&tags=")) {
            var anchors = document.getElementsByClassName("image-list")[0].getElementsByTagName("a");

            if (anchors.length > 0) {
                for (var i = 0; i < anchors.length; i++) {
                    const urlParams = new URLSearchParams(window.location.search);
                    let pageNum = parseInt(urlParams.get("pid"));
                    if(!pageNum){pageNum=0}
                    anchors[i].href = (anchors[i].href + "&srchTags=" + getTagsFromUrl(window.location.href) + "&index=" + (i + pageNum).toString()).replace(/[\?&]pid=\d*/g, '');;
                }
            } else {
                throw new Error("No elements found with class name 'image-list' or no anchor elements found within that class.");
            }
        } else {
            throw new Error("The current URL does not start with 'https://rule34.xxx/index.php?page=post&s=list&tags='.");
        }
    } catch (error) {
        console.error("An error occurred in creatLinks: " + error);
    }
}


var preloadedData; // Variable to store the preloaded JSON data

// Function to preload data for the next post
function preloadNextPost(srchTags, nextIndex, limit) {
    getFromRule34(srchTags, nextIndex, limit, true)
        .then(jsonInfo => {
        console.log(jsonInfo)
        preloadedData = jsonInfo;
        console.log(preloadedData)
    })
        .catch(error => {
        console.error("An error occurred during API request:", error);
    });
}

// Function to navigate to the next post using preloaded data
function navigateToNextPost(srchTags, nextIndex) {
    if (!preloadedData || !preloadedData.length) {
        console.error("No preloaded data available. Cannot proceed.");
        return;
    }

    const nextPostId = preloadedData[0].id;
    const newUrl = `https://rule34.xxx/index.php?page=post&s=view&id=${nextPostId}&srchTags=${encodeURIComponent(srchTags)}&index=${nextIndex}`;

    window.location.href = newUrl;
}

// Event listener for the "DOMContentLoaded" event
setTimeout(function(){
    const urlParams = new URLSearchParams(window.location.search);
    const srchTags = urlParams.get("srchTags");
    const currentIndex = parseInt(urlParams.get("index"));

    if (!srchTags || isNaN(currentIndex)) {
        console.error("Invalid URL parameters. Cannot proceed.");
        return;
    }

    const nextIndex = currentIndex + 1;
    console.log(nextIndex)
    const limit = 1000;

    // Preload data for the next post
    preloadNextPost(srchTags, nextIndex, 1);

    // Event listener for when the user tries to navigate to the next post
    document.getElementById("nextButton").addEventListener("click", () => {
        navigateToNextPost(srchTags, nextIndex);
    });
},1000);



function backPost() {
    const urlParams = new URLSearchParams(window.location.search);
    const srchTags = urlParams.get("srchTags");
    const currentIndex = parseInt(urlParams.get("index"), 10);

    if (!srchTags || isNaN(currentIndex)) {
        console.error("Invalid URL parameters. Cannot proceed.");
        return;
    }

    const nextIndex = currentIndex - 1;
    const limit = 1;

    getFromRule34(srchTags, nextIndex, limit)
        .then(jsonInfo => {
        if (!jsonInfo || !jsonInfo.length) {
            console.error("No data received from API. Cannot proceed.");
            return;
        }

        const nextPostId = jsonInfo[0].id;
        const newUrl = `https://rule34.xxx/index.php?page=post&s=view&id=${nextPostId}&srchTags=${encodeURIComponent(srchTags)}&index=${nextIndex}`;

        window.location.href = newUrl;
    })
        .catch(error => {
        console.error("An error occurred during API request:", error);
    });
}


async function randomVideo() {
    const urlParams = new URLSearchParams(window.location.search);
    let srchTags = urlParams.get("tags");

    if (!srchTags) {
        // If tags parameter is not found in the URL, get the value from the input element
        const tagsInput = document.querySelector("input[name='tags']");
        srchTags = tagsInput.value.replace(/ /g, "+");
    }

    const posts = await getFromRule34(srchTags, 1, 1000);

    if (posts.length === 0) {
        console.error("No posts found for the given tags. Cannot proceed.");
        return;
    }

    const randNum = Math.floor(Math.random() * posts.length);
    const postId = posts[randNum].id;

    const newUrl = `https://rule34.xxx/index.php?page=post&s=view&id=${postId}&tags=${encodeURIComponent(srchTags)}&index=${randNum}`;
    window.location.href = newUrl;
}

async function downloadAllPostFiles() {
    const urlParams = new URLSearchParams(window.location.search);
    let srchTags = urlParams.get("tags");

    if (!srchTags) {
        // If tags parameter is not found in the URL, get the value from the input element
        const tagsInput = document.querySelector("input[name='tags']");
        srchTags = tagsInput.value.replace(/ /g, "+");
    }

    const posts = await getFromRule34(srchTags, 0, 1000);

    if (posts.length === 0) {
        console.error("No posts found for the given tags. Cannot proceed.");
        return;
    }

    // Loop through each post and download the file
    for (const post of posts) {
        const postId = post.image;
        const fileUrl = post.file_url;

        try {
            const response = await fetch(fileUrl);
            const blob = await response.blob();

            // Create a temporary link element to trigger the download
            const link = document.createElement("a");
            link.href = URL.createObjectURL(blob);
            link.download = postId; // You can adjust the filename as needed
            link.click();

            // Clean up the temporary URL object
            URL.revokeObjectURL(link.href);
        } catch (error) {
            console.error(`Error downloading post ${postId}:`, error);
        }
    }
}



function makeButtons(){
    let btn = document.createElement("button");
    btn.innerHTML = "Random";
    btn.onclick = randomVideo;
    let btn4 = document.createElement("button");
    btn4.innerHTML = "↓";
    btn4.onclick = downloadAllPostFiles;
    if(document.getElementsByClassName("tag-search")[0]){document.getElementsByClassName("tag-search")[0].appendChild(btn); document.getElementsByClassName("tag-search")[0].appendChild(btn4)};
    if(document.getElementsByClassName("image-sublinks")[0]){
        let btn3 = document.createElement("button");
        btn3.innerHTML = "back";
        btn3.onclick = backPost;
        document.getElementsByClassName("image-sublinks")[0].appendChild(btn3);
        let btn2 = document.createElement("button");
        btn2.innerHTML = "next";
        btn2.id = "nextButton"
        document.getElementsByClassName("image-sublinks")[0].appendChild(btn2);
    }
}

function allowInputResize(){
    const awesompleteElement = document.getElementsByClassName("awesomplete")[0].childNodes[0];

    // Add input event listener
    awesompleteElement.addEventListener('input', resizeInput.bind(awesompleteElement));

    // Add click event listener
    awesompleteElement.addEventListener('click', resizeInput.bind(awesompleteElement));

    // Add blur (focus loss) event listener
    awesompleteElement.addEventListener('blur', restoreNormalSize.bind(awesompleteElement));

    awesompleteElement.style.position = "relative"
    awesompleteElement.style.zIndex = 99

    // The resizeInput function
    function resizeInput() {
        this.style.minWidth = "100%"
        this.style.width = this.value.length + "ch";
    }

    // Function to restore normal size
    function restoreNormalSize() {
        this.style.width = "100%"; // Clear the inline width style
    }
}

const imageSublinks = document.getElementsByClassName("image-sublinks")[0];
if (imageSublinks) {
    document.addEventListener("keydown", function(event) {
        // Check if the active element is an input element
        const activeElement = document.activeElement;
        const isInputElement = activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA";

        // If it's an input element, don't execute the functions
        if (isInputElement) {
            return;
        }

        // If it's not an input element, execute the functions based on the key press
        if (event.keyCode === 39) {
            const urlParams = new URLSearchParams(window.location.search);
            const srchTags = urlParams.get("srchTags");
            const currentIndex = parseInt(urlParams.get("index"));
            const nextIndex = currentIndex + 1;
            navigateToNextPost(srchTags, nextIndex);
        } else if (event.keyCode === 37) {
            backPost();
        }
    });
}


async function addDeletedPosts(id) {
    if (document.getElementById("status-notices")) {
        if (document.getElementsByClassName("status-notice")[0].firstChild.data.startsWith("This post was")) {
            let notices = document.getElementById("status-notices");
            try {
                const mediaJson = await getFromRule34WithId(id);
                const mediaUrl = mediaJson.file_url;
                const mediaType = mediaUrl.split('.').pop().toLowerCase();

                const videoExtensions = [
                    "mp4", "webm", "ogg", "mov", "avi", "wmv", "flv", "mkv",
                    "3gp", "m4v", "mpg", "mpeg", "swf", "vob", "m2ts"
                ];
                const imageExtensions = [
                    "jpg", "jpeg", "png", "gif", "bmp", "tiff", "tif", "svg",
                    "webp", "heic", "heif", "ico", "raw", "psd", "ai", "eps"
                ];

                if (videoExtensions.includes(mediaType)) {
                    let video = document.createElement("video");
                    video.src = mediaUrl;
                    video.controls = true;
                    video.style = "max-height: 70%; max-width: 70%; overflow: auto;";
                    document.getElementById("fit-to-screen").appendChild(video);
                } else if (imageExtensions.includes(mediaType)) {
                    let image = document.createElement("img");
                    image.src = mediaUrl;
                    image.style = "max-height: 70%; max-width: 70%; overflow: auto;";
                    document.getElementById("fit-to-screen").appendChild(image);
                }

                document.getElementById("status-notices").remove();
            } catch (e) {
                console.error(e);
            }
        } else {
            console.log("This post is not deleted.");
        }
    } else {
        console.log("The status-notices element is not present on this page.");
    }
}


function getLinksInDiv(element) {
    var elements = element.parentNode.querySelectorAll("a");
    return(elements[elements.length - 1])
}

function resizePostPopup(){
    try {
        if(GM_getValue("imageResizeNotice", "false") == "resize"){$('resized_notice').hide()}
        if(GM_getValue("imageResizeNotice", "false") == "orignal"){Post.highres(); $('resized_notice').hide();}
    } catch (e) {
        console.error(e);
    }
}

function startVideo(){
    if (document.getElementById("gelcomVideoPlayer_fluid_initial_play")) {
        document.getElementById("gelcomVideoPlayer").autoplay = true;
    }
}

function addTagButtons(){
    const classList = ["tag-type-copyright", "tag-type-general", "tag-type-character", "tag-type-artist","tag-type-metadata"]
    for (const curClass of classList) {
        const elements = document.getElementsByClassName(curClass);

        for (const element of elements) {
            const button = document.createElement("button");
            button.innerHTML = "+";
            button.onclick = function() {console.log(" " + getLinksInDiv(this).innerText); document.getElementsByName("tags")[0].value += " " + (getLinksInDiv(this).innerText.trim()).replaceAll(" ","_")}
            element.insertBefore(button, element.firstChild);
        }
    }
}

function stretchyDiv(isImage){
    let div;
    if(isImage == 0){div = document.getElementById("fluid_video_wrapper_gelcomVideoPlayer")} else {div = document.getElementById("image")}
    if(isImage == 1){
        let newDiv = document.createElement("div");
        newDiv.style.position = "relative";
        div.parentNode.insertBefore(newDiv, div);
        newDiv.appendChild(div);
        div = newDiv;
        document.getElementById("image").maxHeight = 9999
    }
    const resizer = document.createElement("div");
    resizer.style.width = "10px";
    resizer.style.height = "10px";
    resizer.style.backgroundColor = "white";
    resizer.style.position = "absolute";
    resizer.style.bottom = "0";
    resizer.style.right = "0";
    resizer.style.cursor = "se-resize";
    resizer.style.zIndex = "10";


    let isResizing = false;
    let currentX;
    let currentY;
    let initialWidth;
    let initialHeight;

    resizer.addEventListener("mousedown", function(e) {
        document.body.style.userSelect = 'none';
        isResizing = true;
        currentX = e.clientX;
        currentY = e.clientY;
        initialWidth = parseFloat(getComputedStyle(div, null).getPropertyValue("width").replace("px", ""));
        initialHeight = parseFloat(getComputedStyle(div, null).getPropertyValue("height").replace("px", ""));
    });

    document.addEventListener("mouseup", function() {
        document.body.style.userSelect = '';
        isResizing = false;
    });

    document.addEventListener("mousemove", function(e) {
        if (isResizing) {
            let inner = div.getElementsByTagName("img")[0];
            let newWidth = initialWidth + (e.clientX - currentX);
            let newHeight = initialHeight + (e.clientY - currentY);
            if (!e.shiftKey) {
                // Resize both width and height at the same rate
                let ratio = initialWidth / initialHeight;
                newHeight = newWidth / ratio;
            }
            if(isImage == 1){inner.style.width = newWidth + "px"; inner.style.height = newHeight + "px";}
            div.style.width = newWidth + "px";
            div.style.height = newHeight + "px";
            if(document.getElementById("image")){
                document.getElementById("image").style.width = newWidth + "px";
                document.getElementById("image").style.height = newHeight + "px";
            }
        }
    });

    let strechySquare = div.appendChild(resizer);
}

function addInputBox(){
    let inputBox = document.createElement("input");
    let tagsElement = document.querySelector("[name='tags']");
    inputBox.type = "text"
    tagsElement.after(inputBox);
}

setTimeout(function(){
    if (document.getElementById("fluid_video_wrapper_gelcomVideoPlayer")) {
        stretchyDiv(0);
    } else if (document.getElementById("image")) {
        stretchyDiv(1);
    }
}, 300);

function setTags(tags){
    document.getElementsByName("tags")[0].value = tags
}

async function htmlVideoPlayer(id){
    const urlParts = window.location.href.split("&");
    let notices = document.getElementById("status-notices");
    let video = document.createElement("video");
    try {
        const videoUrl = await getFromRule34(id, 0 ,1);
        video.src = videoUrl;
        video.controls = true;
        video.style = "max-height: 70%; max-width: 70%; overflow: auto;";
        document.getElementById("fit-to-screen").appendChild(video);
        document.getElementById("status-notices").remove()
    } catch (e) {
        console.error(e);
    }
}

function addCloseButtonToStatusNotice() {
    const statusNoticeElements = document.querySelectorAll('.status-notice');

    statusNoticeElements.forEach(element => {
        const closeButton = document.createElement('button');
        closeButton.textContent = 'x';
        closeButton.addEventListener('click', () => {
            element.parentNode.removeChild(element);
        });
        closeButton.style.background = 'none';
        closeButton.style.border = 'none';
        closeButton.style.cursor = 'pointer';
        element.appendChild(closeButton);
    });
}

async function overlayFullSizeImage(){
    const urlParams = new URLSearchParams(window.location.search);
    let id = urlParams.get("id");
    const postJson = await getFromRule34WithId(id);

    // Get the element with id "image"
    const originalImage = document.getElementById("image");

    // Create a new transparent image element
    const newImage = document.createElement("img");
    newImage.src = postJson.file_url;
    newImage.style.opacity = "0"; // Set opacity to 0 for transparency

    // Set the size of the new image to match the size of the original image
    newImage.style.width = originalImage.width + "px";
    newImage.style.height = originalImage.height + "px";

    // Position the new image on top of the original image
    newImage.style.position = "absolute";
    newImage.style.top = originalImage.offsetTop + "px";
    newImage.style.left = originalImage.offsetLeft + "px";
    newImage.style.zIndex = "1"; // Set a higher z-index to overlay on top

    // Insert the new transparent image before the original image
    originalImage.parentNode.insertBefore(newImage, originalImage);

}

function convertSearchToLink(){
    document.getElementsByName("commit")[0].innerHTML = `<a href="https://rule34.xxx/index.php?page=post&s=list&tags=all">${document.getElementsByName("commit")[0].innerHTML}</a>`
}

function fitPostToScreen(){
    if(GM_getValue("downloadFullSizedImages", "false") == "true" && GM_getValue("hideAlerts", "false") == "false"){window.alert(`downloadFullSizedImage and fitImageToScreen often cause bugs when used together.  To disable this alert turn hide alerts on in settings.`)}
    let postElement
    if(document.getElementById("fluid_video_wrapper_gelcomVideoPlayer")){postElement = document.getElementById("fluid_video_wrapper_gelcomVideoPlayer")} else {postElement = document.getElementById("image")}
    postElement.style.maxHeight = "85vh"
    postElement.style.width = "auto"
}

if(window.location.href.startsWith("https://rule34.xxx/index.php?page=post&s=view")){
    setTags(params.get("srchTags"))
} else if(window.location.href.startsWith("https://rule34.xxx/index.php?page=post&s=list")){
    setTags(params.get("tags"))
}

let isFirstClick = true;

document.addEventListener("click", function() {
    if (isFirstClick) {
        startVideo()
        isFirstClick = false;
    }
});

if(GM_getValue("scrollPostsIntoView", "false")){
    // Function to scroll an element into view
    function scrollIntoView(element) {
        if (element) {
            setTimeout(function(){element.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' })},250);
        }
    }

    // Try to find the element with id "image"
    var imageElement = document.querySelector('#image');

    // If not found, try to find the element with id "gelcomVideoPlayer"
    if (!imageElement) {
        var videoPlayerElement = document.querySelector('#gelcomVideoPlayer');
        scrollIntoView(videoPlayerElement);
    } else {
        scrollIntoView(imageElement);
    }
}

GM_registerMenuCommand('Click me!', openSettings);
makeButtons();
creatLinks()
addCloseButtonToStatusNotice()
setTheme()
setTimeout(resizePostPopup, 100)
setTimeout(addTagButtons, 100)
setTimeout(allowInputResize, 100)

if (GM_getValue("undeletePosts", "false") === "true") {
    setTimeout(() => addDeletedPosts(window.location.href.split("&").find(part => part.startsWith("id=")).replace("id=", "")), 500);
}
if (GM_getValue("htmlVideoPlayer", "false") === "true") {
    setTimeout(() => htmlVideoPlayer(window.location.href.split("&").find(part => part.startsWith("id=")).replace("id=", "")), 500);
}
if (GM_getValue("downloadFullSizedImages", "false") === "true") {
    setTimeout(overlayFullSizeImage, 500);
}
if (GM_getValue("fitImageToScreen", "false") === "true") {
    setTimeout(fitPostToScreen, 500);
}



let noteBoxes = document.querySelectorAll(".note-box");
noteBoxes.forEach(function(noteBox) {
    noteBox.style.zIndex = "999";
});