Iridium

YouTube with more freedom

// ==UserScript==
// @version         0.3.0a
// @name            Iridium
// @namespace       https://github.com/ParticleCore
// @description     YouTube with more freedom
// @compatible      firefox
// @compatible      opera
// @icon            https://raw.githubusercontent.com/ParticleCore/Iridium/gh-pages/images/i-icon.png
// @match           *://www.youtube.com/*
// @exclude         *://www.youtube.com/tv*
// @exclude         *://www.youtube.com/embed/*
// @exclude         *://www.youtube.com/live_chat*
// @run-at          document-start
// @homepageURL     https://github.com/ParticleCore/Iridium
// @supportURL      https://github.com/ParticleCore/Iridium/wiki
// @contributionURL https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UMVQJJFG4BFHW
// @grant           GM_getValue
// @grant           GM_setValue
// @noframes
// ==/UserScript==
(function () {
    "use strict";

    var iridium = {

        inject: function (is_userscript) {

            var i18n;
            var modules;
            var iridium_api;
            var user_settings;
            var default_language;

            default_language = {
                language: "English (US)",
                section_titles: {
                    about: "Information and useful links",
                    general: "General settings",
                    video: "Video settings",
                    settings: "Iridium settings"
                },
                sub_section_titles: {
                    channel: "Channel",
                    blacklist: "Blacklist",
                    general: "General",
                    language: "Language",
                    layout: "Layout",
                    player: "Player",
                    settings: "Settings",
                    thumbnails: "Thumbnails"
                },
                iridium_api: {
                    settings_button: "Iridium settings",
                    feature_link: "Find out what this does"
                }
            };

            modules = [
                {
                    options: {
                        default_logo_page: {
                            id: "default_logo_page",
                            section: "general",
                            sub_section: "general",
                            type: "dropdown",
                            value: "home",
                            i18n: {
                                label: "Default YouTube logo page:",
                                options: [
                                    "Home",
                                    "Trending",
                                    "Subscriptions"
                                ]
                            },
                            options: [
                                "home",
                                "trending",
                                "subscriptions"
                            ]
                        },
                        default_channel_tab: {
                            id: "default_channel_tab",
                            section: "general",
                            sub_section: "general",
                            type: "dropdown",
                            value: "home",
                            i18n: {
                                label: "Default channel tab:",
                                options: [
                                    "Home",
                                    "Videos",
                                    "Playlists",
                                    "Channels",
                                    "Discussion",
                                    "About"
                                ]
                            },
                            options: [
                                "home",
                                "videos",
                                "playlists",
                                "channels",
                                "discussion",
                                "about"
                            ]
                        }
                    },
                    setDestination: function (event) {

                        var url;
                        var data;

                        if ((data = event.target.data) && (url = data.webNavigationEndpointData && data.webNavigationEndpointData.url)) {

                            if (user_settings.default_channel_tab !== "home" && url.match(/^\/(?:channel|user)\/(?:[^\/])+$/)) {

                                data.webNavigationEndpointData.url += "/" + user_settings.default_channel_tab;
                                event.target.href = data.webNavigationEndpointData.url;

                            }

                            if (user_settings.default_logo_page !== "home" && url === "/" && event.target.tagName === "A" && event.target.id === "logo") {

                                data.browseEndpoint.browseId = "FE" + user_settings.default_logo_page;
                                data.webNavigationEndpointData.url += "feed/" + user_settings.default_logo_page;
                                event.target.href = data.webNavigationEndpointData.url;

                            }

                        }

                    },
                    ini: function () {

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        window.addEventListener("mouseup", this.setDestination.bind(this), true);

                    }
                },
                {
                    options: {
                        square_avatars: {
                            id: "square_avatars",
                            section: "general",
                            sub_section: "layout",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Make user images squared"
                            }
                        }
                    },
                    ini: function () {

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        if (user_settings.square_avatars) {

                            document.documentElement.classList.add("iri-square-avatars");

                        } else {

                            document.documentElement.classList.remove("iri-square-avatars");

                        }

                    }
                },
                {
                    options: {
                        thumbnail_preview: {
                            id: "thumbnail_preview",
                            section: "general",
                            sub_section: "thumbnails",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Preview videos by hovering the thumbnails"
                            }
                        },
                        thumbnail_preview_mute: {
                            id: "thumbnail_preview_mute",
                            section: "general",
                            sub_section: "thumbnails",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Shift key toggles audio on video preview"
                            }
                        }
                    },
                    togglePreviewMute: function (event) {

                        var player_api;

                        if (user_settings.thumbnail_preview_mute && event.which === 16 && (player_api = document.getElementById("iri-preview-player"))) {

                            player_api.handleGlobalKeyDown(77, false);

                        }

                    },
                    setPreviewArgs: function (args) {

                        args.autoplay = 1;
                        args.controls = "0";
                        args.enablecastapi = "0";
                        args.iv_load_policy = "3";
                        args.modestbranding = "1";
                        args.mute = "1";
                        args.player_wide = "0";
                        args.rel = "0";
                        args.showinfo = "0";
                        args.vq = "small";

                        args.ad3_module = null;
                        args.baseUrl = null;
                        args.eventid = null; // excludes from watch history
                        args.iv_endscreen_url = null;
                        args.ppv_remarketing_url = null;
                        args.probe_url = null;
                        args.remarketing_url = null;
                        args.videostats_playback_base_url = null;

                    },
                    iniPreview: function (context, event) {

                        var i;
                        var args;
                        var temp;
                        var config;
                        var data_list;
                        var player_api;

                        args = {};
                        data_list = event.target.responseText.split("&");

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

                            temp = data_list[i].split("=");
                            args[temp[0]] = window.decodeURIComponent(temp[1]);

                        }

                        context.setPreviewArgs(args);

                        config = JSON.parse(JSON.stringify(window.yt.config_.FILLER_DATA.player));
                        config.args = args;
                        config.attrs.id = "iri-preview-player";

                        window.yt.player.Application.create("iri-video-preview", config);

                        if ((player_api = document.getElementById("iri-preview-player"))) {

                            player_api.setVolume(50);

                        }

                    },
                    getPreviewArgs: function (video_id) {

                        var sts;
                        var xhr;
                        var params;
                        var context;

                        context = this;
                        sts = window.yt.config_.FILLER_DATA.player.sts;
                        params =
                            "video_id=" + video_id + "&" +
                            "sts=" + sts + "&" +
                            "ps=gaming" + "&" +
                            "el=detailpage" + "&" +
                            "c=WEB_GAMING" + "&" +
                            "cplayer=UNIPLAYER" + "&" +
                            "mute=true" + "&" +
                            "authuser=0";

                        xhr = new XMLHttpRequest();
                        xhr.addEventListener("load", function (event) {

                            context.iniPreview(context, event);

                        });
                        xhr.open("GET", "/get_video_info?" + params, true);
                        xhr.send();

                        return xhr;

                    },
                    endPreviewContainer: function (event, container, listener, xhr, timer, context, video_container, clicked) {

                        if (clicked || !container.parentNode.contains(event.toElement || event.relatedTarget)) {

                            document.removeEventListener("keydown", context.togglePreviewMute, false);

                            container.parentNode.removeEventListener("click", listener, false);
                            container.parentNode.removeEventListener("mouseleave", listener, false);

                            if (timer) {

                                window.clearInterval(timer);

                            }

                            if ((video_container = document.getElementById("iri-video-preview"))) {

                                if (xhr) {

                                    xhr.abort();

                                }

                                if (video_container.firstChild) {

                                    video_container.firstChild.destroy();

                                }
                            }

                            if (clicked && video_container) {

                                // video_container.remove();

                            }
                        }

                    },
                    iniPreviewContainer: function (event) {

                        var xhr;
                        var timer;
                        var context;
                        var video_id;
                        var container;
                        var video_container;

                        if (user_settings.thumbnail_preview) {

                            container = event.target;
                            video_id = container.dataHost && container.dataHost.data && container.dataHost.data.videoId;

                            if (container.tagName === "YT-IMG-SHADOW" && video_id && !container.querySelector("#iri-preview-player")) {

                                context = this;

                                if (!(video_container = document.getElementById("iri-video-preview"))) {

                                    video_container = document.createElement("iri-video-preview");
                                    video_container.id = "iri-video-preview";
                                    video_container.className = "ytp-small-mode";

                                }

                                if (video_container.parentNode !== container) {

                                    container.appendChild(video_container);

                                }

                                if (!window.yt || !window.yt.player || !window.yt.player.Application || !window.yt.player.Application.create) {

                                    timer = window.setInterval(function () {

                                        if (window.yt && window.yt.player && window.yt.player.Application && window.yt.player.Application.create) {

                                            window.clearInterval(timer);
                                            xhr = context.getPreviewArgs(video_id);

                                        }

                                    });

                                } else {

                                    xhr = this.getPreviewArgs(video_id);

                                }

                                document.addEventListener("keydown", this.togglePreviewMute, false);

                                container.parentNode.addEventListener("click", function listener(event) {

                                    context.endPreviewContainer(event, container, listener, xhr, timer, context, video_container, true);

                                }, false);

                                container.parentNode.addEventListener("mouseleave", function listener(event) {

                                    context.endPreviewContainer(event, container, listener, xhr, timer, context);

                                }, false);

                            }

                        }

                    },
                    ini: function () {

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        document.addEventListener("mouseenter", this.iniPreviewContainer.bind(this), true);

                    }
                },
                {
                    options: {
                        enable_blacklist: {
                            id: "enable_blacklist",
                            section: "general",
                            sub_section: "blacklist",
                            type: "checkbox",
                            value: "home",
                            i18n: {
                                label: "Enable blacklist"
                            }
                        },
                        blacklist_settings: {
                            id: "blacklist_settings",
                            section: "general",
                            sub_section: "blacklist",
                            type: "custom",
                            value: {},
                            i18n: {
                                button_add_title: "Block",
                                button_edit: "Edit",
                                button_import: "Import",
                                button_export: "Export",
                                button_reset: "Reset",
                                button_save: "Save",
                                button_close: "Close",
                                button_remove: "Remove from blacklist",
                                placeholder: "Paste your new blacklist here",
                                confirm_reset: "You are about to reset your blacklist. It is advised to backup your current blacklist before continuing.\n\nDo you wish to contiue?\n\n",
                                reset_success: "Blacklist has been reset.\n\nChanges will be applied after a page refresh.\n\n",
                                confirm_import: "You are about to override your current blacklist. It is advised to backup your current blacklist before continuing.\n\nDo you wish to contiue?\n\n",
                                import_success: "Your blacklist has been imported with success.\n\nChanges will be applied after a page refresh.\n\n",
                                import_error: "Your blacklist could not be imported because it appears to be invalid.\n\n"
                            },
                            custom: function () {

                                var element;
                                var element_list;

                                element_list = [];

                                element = document.createElement("button");
                                element.textContent = i18n.blacklist_settings.button_edit;
                                element.className = "setting iri-settings-button";
                                element.addEventListener("click", this.textEditor.bind(this, "edit"));

                                element_list.push(element);

                                element = document.createElement("button");
                                element.textContent = i18n.blacklist_settings.button_import;
                                element.className = "setting iri-settings-button";
                                element.addEventListener("click", this.textEditor.bind(this, "import"));

                                element_list.push(element);

                                element = document.createElement("button");
                                element.textContent = i18n.blacklist_settings.button_export;
                                element.className = "setting iri-settings-button";
                                element.addEventListener("click", this.textEditor.bind(this, "export"));

                                element_list.push(element);

                                element = document.createElement("button");
                                element.textContent = i18n.blacklist_settings.button_reset;
                                element.className = "setting iri-settings-button danger";
                                element.addEventListener("click", this.resetBlacklist.bind(this));

                                element_list.push(element);

                                return element_list;

                            },
                            resetBlacklist: function () {

                                if (window.confirm(i18n.blacklist_settings.confirm_reset)) {

                                    user_settings.blacklist_settings = [];

                                    iridium_api.initializeSettings();
                                    iridium_api.saveSettings();

                                    window.alert(i18n.blacklist_settings.reset_success);

                                }

                            },
                            importBlacklist: function () {

                                var editor;
                                var textarea;

                                if ((textarea = document.getElementById("iridium-textarea")) && window.confirm(i18n.blacklist_settings.confirm_import)) {

                                    try {

                                        user_settings.blacklist_settings = JSON.parse(textarea.value);

                                        iridium_api.saveSettings();

                                        window.alert(i18n.blacklist_settings.import_success);

                                        if ((editor = document.getElementById("iridium-text-editor"))) {

                                            editor.remove();

                                        }

                                    } catch (error) {

                                        window.alert(i18n.blacklist_settings.import_error + error.name + ": " + error.message);

                                    }

                                }

                            },
                            closeEditor: function (editor) {

                                editor.remove();

                            },
                            textEditor: function (type, event) {

                                var i;
                                var obj;
                                var temp;
                                var editor;
                                var button;
                                var channel;
                                var textarea;
                                var temp_list;
                                var blocked_list;
                                var close_button;
                                var channel_link;
                                var buttons_section;

                                if (!(editor = document.getElementById("iridium-text-editor"))) {

                                    editor = document.createElement("div");
                                    editor.id = "iridium-text-editor";

                                    document.body.appendChild(editor);

                                } else {

                                    editor.textContent = "";

                                }

                                buttons_section = document.createElement("div");
                                buttons_section.id = "buttons-section";

                                editor.appendChild(buttons_section);

                                if (type === "import" || type === "export") {

                                    textarea = document.createElement("textarea");
                                    textarea.id = "iridium-textarea";
                                    textarea.setAttribute("spellcheck", "false");

                                    if (type === "import") {

                                        textarea.setAttribute("placeholder", i18n.blacklist_settings.placeholder);

                                        button = document.createElement("button");
                                        button.textContent = i18n.blacklist_settings.button_save;
                                        button.className = "iri-settings-button";
                                        button.addEventListener("click", this.importBlacklist.bind(this));

                                        buttons_section.appendChild(button);

                                    } else {

                                        textarea.value = JSON.stringify(user_settings.blacklist_settings, null, 4);

                                    }

                                    editor.appendChild(textarea);

                                } else if (type === "edit") {

                                    blocked_list = document.createElement("div");
                                    blocked_list.id = "iridium-blacklist";

                                    temp = Object.keys(user_settings.blacklist_settings);
                                    temp_list = [];

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

                                        obj = {};
                                        obj[temp[i]] = user_settings.blacklist_settings[temp[i]];

                                        temp_list.push([
                                            temp[i],
                                            user_settings.blacklist_settings[temp[i]]
                                        ]);

                                    }

                                    temp_list = temp_list.sort(function (previous, next) {
                                        return previous[1].localeCompare(next[1]);
                                    });

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

                                        channel = document.createElement("template");
                                        channel.innerHTML =
                                            "<div class='iri-blacklist-channel'>" +
                                            "        <button class='close' title='" + i18n.blacklist_settings.button_remove + "'>" +
                                            "            <svg viewBox='0 0 10 10' height='10' width='10'>" +
                                            "                <polygon points='10 1.4 8.6 0 5 3.6 1.4 0 0 1.4 3.6 5 0 8.6 1.4 10 5 6.4 8.6 10 10 8.6 6.4 5'/>" +
                                            "            </svg>" +
                                            "        </button><a target='_blank'></a>" +
                                            "</div>";
                                        channel = channel.content;
                                        channel.firstChild.data = true;

                                        channel_link = channel.querySelector("a");
                                        channel_link.href = "/channel/" + temp_list[i][0];
                                        channel_link.textContent = temp_list[i][1];

                                        close_button = channel.querySelector(".close");
                                        close_button.container = channel.firstChild;
                                        close_button.ucid = temp_list[i][0];
                                        close_button.addEventListener("click", function (event) {

                                            event.target.container.remove();
                                            delete user_settings.blacklist_settings[event.target.ucid];

                                            iridium_api.saveSettings();

                                        });

                                        blocked_list.appendChild(channel);

                                    }

                                    editor.appendChild(blocked_list);

                                }

                                button = document.createElement("button");
                                button.textContent = i18n.blacklist_settings.button_close;
                                button.className = "iri-settings-button";
                                button.addEventListener("click", this.closeEditor.bind(this, editor));

                                buttons_section.appendChild(button);

                            }
                        }
                    },
                    tag_list: [
                        "YTD-COMPACT-LINK-RENDERER",
                        "YTD-COMPACT-PLAYLIST-RENDERER",
                        "YTD-COMPACT-PROMOTED-VIDEO-RENDERER",
                        "YTD-COMPACT-RADIO-RENDERER",
                        "YTD-COMPACT-VIDEO-RENDERER",
                        "YTD-GRID-CHANNEL-RENDERER",
                        "YTD-GRID-MOVIE-PLAYLIST-RENDERER",
                        "YTD-GRID-MOVIE-RENDERER",
                        "YTD-GRID-PLAYLIST-RENDERER",
                        "YTD-GRID-RADIO-RENDERER",
                        "YTD-GRID-RENDERER",
                        "YTD-GRID-SHOW-RENDERER",
                        "YTD-GRID-VIDEO-RENDERER",
                        "YTD-CHANNEL-RENDERER",
                        "YTD-MOVIE-RENDERER",
                        "YTD-PLAYLIST-RENDERER",
                        "YTD-RADIO-RENDERER",
                        "YTD-SHOW-RENDERER",
                        "YTD-VIDEO-RENDERER"
                    ],
                    allowedBlacklistPage: function () {

                        return /^\/($|feed\/(?!subscriptions)|watch|results|shared)/.test(window.location.pathname);

                    },
                    hasContainers: function () {

                        return window.location.pathname.match(/^\/(?:(?:|results)$|feed\/)/);

                    },
                    getObjectByKey: function (obj, keys, match, list, pos) {

                        var i;
                        var results;
                        var property;

                        results = [];

                        for (property in obj) {

                            if (obj.hasOwnProperty(property) && obj[property] !== null) {

                                if (keys.indexOf(property) > -1 && (!match || typeof obj[property] !== "object" && match(obj[property]))) {

                                    results.push({
                                        target: obj,
                                        property: property,
                                        list: list,
                                        pos: pos
                                    });

                                } else if (obj[property].constructor === Object) {

                                    results = results.concat(this.getObjectByKey(obj[property], keys, match, list, pos));

                                } else if (obj[property].constructor === Array) {

                                    for (i = 0; i < obj[property].length; i++) {

                                        results = results.concat(this.getObjectByKey(obj[property][i], keys, match, obj[property], i));

                                    }

                                }

                            }

                        }

                        return results;

                    },
                    clearList: function (obj) {

                        var i;
                        var ids;
                        var videos;
                        var shelves;
                        var sections;
                        var shelf_tag;
                        var video_tag;
                        var section_tag;

                        section_tag = [
                            "itemSectionRenderer",
                            "showingResultsForRenderer",
                            "includingResultsForRenderer",
                        ];
                        shelf_tag = [
                            "shelfRenderer",
                            "compactAutoplayRenderer"
                        ];
                        video_tag = [
                            "playlistRenderer",
                            "channelRenderer",
                            "radioRenderer",
                            "showRenderer",
                            "videoRenderer",
                            "gridChannelRenderer",
                            "gridMoviePlaylistRenderer",
                            "gridMovieRenderer",
                            "gridPlaylistRenderer",
                            "gridRadioRenderer",
                            "gridShowRenderer",
                            "gridVideoRenderer",
                            "compactVideoRenderer",
                            "compactPlaylistRenderer",
                            "compactPromotedVideoRenderer",
                            "playlistPanelVideoRenderer"
                        ];

                        videos = this.getObjectByKey(obj, video_tag);

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

                            ids = this.getObjectByKey(videos[i].target, ["browseId"], function (string) {
                                return string.indexOf("UC") === 0;
                            });

                            if (ids[0] && user_settings.blacklist_settings[ids[0].target["browseId"]]) {

                                videos[i].list.splice(videos[i].list.indexOf(videos[i].target), 1);

                            }

                        }

                        shelves = this.getObjectByKey(obj, shelf_tag);

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

                            videos = this.getObjectByKey(shelves[i].target, video_tag);

                            if (videos.length === 0) {

                                shelves[i].list.splice(shelves[i].list.indexOf(shelves[i].target), 1);

                            }

                        }

                        if (this.hasContainers()) {

                            sections = this.getObjectByKey(obj, section_tag);

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

                                if (sections[i].target[sections[i].property].contents.length === 0) {

                                    sections[i].list.splice(sections[i].list.indexOf(sections[i].target), 1);

                                }

                            }

                        }

                    },
                    checkParse: function (original) {

                        var context = this;

                        return function (text, reviver) {

                            var temp = original.apply(this, arguments);

                            if (context.allowedBlacklistPage()) {

                                context.clearList(temp);

                            }

                            return temp;

                        };

                    },
                    getEmptyContainers: function () {

                        var i;
                        var temp;
                        var shelf;
                        var container;
                        var container_nodes;

                        container_nodes = "#contents ytd-item-section-renderer, #contents ytd-shelf-renderer";
                        container = document.querySelectorAll(container_nodes);

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

                            shelf = container[i].querySelector("yt-horizontal-list-renderer");

                            if (shelf && (shelf.hasAttribute("at-start") || shelf.hasAttribute("at-end"))) {

                                shelf.fillRemainingListItems();

                            }

                            temp = container[i].querySelector(this.tag_list.join(","));

                            if (!temp) {

                                container[i].remove();

                            }

                        }

                        window.dispatchEvent(new Event("resize"));

                    },
                    getContainers: function () {

                        var i;
                        var ucid;
                        var container;
                        var container_nodes;

                        container_nodes = "#contents ytd-item-section-renderer, #contents ytd-shelf-renderer";
                        container = document.querySelectorAll(container_nodes);

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

                            ucid = this.getObjectByKey(container[i].data, ["browseId"], function (string) {
                                return string.indexOf("UC") === 0;
                            });

                            if (ucid[0] && ucid.length === 1 && ucid[0].target.browseId) {

                                if (user_settings.blacklist_settings[ucid]) {

                                    container[i].remove();

                                }

                            }

                        }

                    },
                    getVideos: function () {

                        var i;
                        var temp;
                        var ucid;
                        var child;
                        var parent;
                        var videos;
                        var remove;
                        var up_next;

                        remove = [];
                        up_next = document.querySelector("ytd-compact-autoplay-renderer");
                        videos = document.querySelectorAll(this.tag_list.join(","));

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

                            if (videos[i].data) {

                                temp = videos[i];

                            }

                            if (temp && temp.data) {

                                ucid = this.getObjectByKey(temp.data, ["browseId"], function (string) {
                                    return string.indexOf("UC") === 0;
                                });

                                if (ucid[0] && ucid[0].target.browseId) {

                                    ucid = ucid[0].target.browseId;

                                }

                            }

                            if (ucid) {

                                if (user_settings.blacklist_settings[ucid]) {

                                    if (up_next && up_next.contains(videos[i])) {

                                        if (up_next.tagName === "YTD-COMPACT-AUTOPLAY-RENDERER") {

                                            up_next.remove();

                                        } else {

                                            up_next.parentNode.remove();
                                            up_next = document.querySelector(".watch-sidebar-separation-line");

                                            if (up_next) {

                                                up_next.remove();

                                            }

                                        }

                                    } else {

                                        remove.push(videos[i]);

                                    }

                                }

                            }

                        }

                        if (remove.length) {

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

                                child = remove[i];

                                while (child) {

                                    parent = child.parentNode;

                                    if (parent.childElementCount > 1 || parent.id === "contents" || parent.id === "items") {

                                        child.remove();
                                        break;

                                    }

                                    child = parent;

                                }

                            }

                            if (this.hasContainers()) {

                                // ignore.containers = [];

                            } else {

                                window.dispatchEvent(new Event("resize"));
                            }

                        }

                    },
                    modImportNode: function (original) {

                        var blacklist_button;

                        blacklist_button = document.createElement("div");
                        blacklist_button.className = "iri-add-to-blacklist";
                        blacklist_button.innerHTML =
                            "<svg viewBox='0 0 24 24' height='16' width='16'>" +
                            "    <polygon points='24 2.1 21.9 0 12 9.9 2.1 0 0 2.1 9.9 12 0 21.9 2.1 24 12 14.1 21.9 24 24 21.9 14.1 12'/>" +
                            "</svg>" +
                            "<div class='iri-tooltip'>" + i18n.blacklist_settings.button_add_title + "</div>";

                        return function (externalNode, deep) {

                            var node;
                            var container;

                            node = externalNode.firstElementChild;

                            if (node && (node.id === "thumbnail" || node.id === "img")) {

                                container = node.id === "img" ? node.parentNode : node;

                                if (!container.querySelector(".iri-add-to-blacklist")) {

                                    container.appendChild(blacklist_button.cloneNode(true));

                                }
                            }

                            return original.apply(this, arguments);

                        };

                    },
                    applyBlacklist: function () {

                        var hasContainers;

                        if (!this.allowedBlacklistPage()) {

                            return;

                        }

                        hasContainers = this.hasContainers();

                        if (hasContainers) {

                            this.getContainers();

                        }

                        this.getVideos();

                        if (hasContainers) {

                            this.getEmptyContainers();

                        }

                    },
                    addToBlacklist: function (event) {

                        var ucid;
                        var brand;
                        var parent;

                        if (user_settings.enable_blacklist && event.target.className === "iri-add-to-blacklist") {

                            event.preventDefault();
                            event.stopPropagation();

                            parent = event.target.parentNode;

                            while (parent) {

                                if (this.tag_list.indexOf(parent.tagName) > -1) {

                                    if (parent.data) {

                                        ucid = this.getObjectByKey(parent.data, ["browseId"], function (string) {
                                            return string.indexOf("UC") === 0;
                                        });

                                        if (ucid[0] && ucid[0].target.browseId) {

                                            brand = ucid[0].list[0].text;

                                            ucid = ucid[0].target.browseId;

                                        }

                                    }

                                    break;

                                }

                                parent = parent.parentNode;

                            }

                            if (ucid && brand) {

                                user_settings.blacklist_settings[ucid] = brand;

                                iridium_api.saveSettings();

                                this.applyBlacklist();

                            }

                            return false;

                        }

                    },
                    iniBlacklist: function () {

                        if (this.allowedBlacklistPage()) {

                            document.documentElement.classList.add("iri-blacklist-allowed");

                        } else {

                            document.documentElement.classList.remove("iri-blacklist-allowed");

                        }

                    },
                    ini: function () {

                        var context;

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        if (user_settings.enable_blacklist) {

                            context = this;

                            JSON.parse = this.checkParse(JSON.parse);
                            HTMLDocument.prototype.importNode = this.modImportNode(HTMLDocument.prototype.importNode);

                            document.addEventListener("readystatechange", this.iniBlacklist.bind(this), false);
                            document.addEventListener("yt-page-data-fetched", this.iniBlacklist.bind(this), false);
                            document.addEventListener("click", this.addToBlacklist.bind(this), true);

                            Object.defineProperty(Object.prototype, "ytInitialData", {
                                set: function (data) {
                                    this._ytInitialData = data;
                                },
                                get: function () {

                                    if (context.allowedBlacklistPage()) {

                                        context.clearList(this._ytInitialData);

                                    }

                                    return this._ytInitialData;

                                }
                            });

                        }

                    }
                },
                {
                    options: {
                        channel_video_count: {
                            id: "channel_video_count",
                            section: "video",
                            sub_section: "general",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Display uploaded videos number"
                            }
                        },
                        channel_video_time: {
                            id: "channel_video_time",
                            section: "video",
                            sub_section: "general",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Display how long the video was uploaded"
                            }
                        }
                    },
                    removeVideoCount: function (listener) {

                        var xhr;
                        var video_count;
                        var video_count_dot;

                        delete this.addVideoCount.fetching;

                        document.removeEventListener("yt-navigate-finish", listener, false);

                        xhr = this.removeVideoCount.xhr;

                        if (xhr && xhr.abort) {

                            xhr.abort();

                            delete this.removeVideoCount.xhr;

                        }

                        if ((video_count_dot = document.querySelector("span.iri-video-count"))) {

                            video_count_dot.remove();

                        }

                        if ((video_count = document.getElementById("iri-video-count"))) {

                            video_count.remove();

                        }

                    },
                    addVideoCount: function (channel_url, event) {

                        var count_match;
                        var video_count;
                        var video_count_dot;
                        var owner_container;

                        delete this.addVideoCount.fetching;

                        count_match = event.target.response.match(/"(?:stats|briefStats)":\[{"runs":\[{"text":"([\w\W ]+?")}]}/);

                        if (count_match && (count_match = count_match[1].replace("\"", "")) && (owner_container = document.getElementById("owner-container"))) {

                            video_count_dot = document.createElement("span");
                            video_count_dot.textContent = " · ";
                            video_count_dot.className = "iri-video-count";

                            video_count = document.createElement("a");
                            video_count.id = "iri-video-count";
                            video_count.textContent = count_match;
                            video_count.className = "yt-simple-endpoint iri-video-count";
                            video_count.setAttribute("href", channel_url + "/videos");
                            video_count.data = {
                                webNavigationEndpointData: {
                                    url: channel_url + "/videos"
                                }
                            };

                            owner_container.appendChild(video_count_dot);
                            owner_container.appendChild(video_count);

                            owner_container.channel_url = channel_url;
                            owner_container.video_count = count_match;

                        }

                    },
                    removeVideoTime: function (listener) {

                        var xhr;
                        var time_container;

                        delete this.addVideoTime.fetching;

                        document.removeEventListener("yt-navigate-finish", listener, false);

                        xhr = this.removeVideoTime.xhr;

                        if (xhr && xhr.abort) {

                            xhr.abort();

                            delete this.removeVideoTime.xhr;

                        }

                        if ((time_container = document.getElementById("iri-video-time"))) {

                            time_container.remove();

                        }

                    },
                    addVideoTime: function (published_date, event) {

                        var time_match;
                        var time_container;

                        delete this.addVideoTime.fetching;

                        time_match = event.target.response.match(/"publishedTimeText":{"simpleText":"([\w\W ]+?")}/);

                        if (time_match && (time_match = time_match[1].replace("\"", ""))) {

                            time_container = document.createElement("span");
                            time_container.id = "iri-video-time";
                            time_container.textContent = " · " + time_match;

                            published_date.appendChild(time_container);

                        }

                    },
                    loadStart: function () {

                        var xhr;
                        var context;
                        var video_id;
                        var channel_id;
                        var channel_url;
                        var upload_info;
                        var watch_page_active;

                        watch_page_active = document.querySelector("ytd-watch:not([hidden])");

                        if (watch_page_active && (channel_url = document.querySelector("#owner-name a"))) {

                            channel_url = channel_url.getAttribute("href");
                            channel_id = channel_url.match(/UC([a-z0-9-_]{22})/i);

                            if (channel_id && (channel_id = channel_id[1])) {

                                if (user_settings.channel_video_count && !this.addVideoCount.fetching && document.getElementById("owner-container") && !document.getElementById("iri-video-count") && (channel_url = document.querySelector("#owner-name a"))) {

                                    if (this.removeVideoCount.xhr) {

                                        this.removeVideoCount.xhr.abort();

                                    }

                                    this.addVideoCount.fetching = true;
                                    channel_url = channel_url.getAttribute("href");

                                    xhr = new XMLHttpRequest();
                                    xhr.addEventListener("load", this.addVideoCount.bind(this, channel_url));
                                    xhr.open("GET", "/playlist?list=UU" + channel_id, true);
                                    xhr.send();

                                    this.removeVideoCount.xhr = xhr;

                                    context = this;

                                    document.addEventListener("yt-navigate-finish", function listener() {

                                        context.removeVideoCount(listener);

                                    }, false);

                                }

                                if (user_settings.channel_video_time && !this.addVideoTime.fetching && (upload_info = document.querySelector("#upload-info .date")) && upload_info.textContent.indexOf("·") === -1) {

                                    if ((video_id = window.location.href.match(/v=([\w-]+)/)) && (video_id = video_id[1])) {

                                        if (this.removeVideoTime.xhr) {

                                            this.removeVideoTime.xhr.abort();

                                        }

                                        this.addVideoTime.fetching = true;

                                        xhr = new XMLHttpRequest();
                                        xhr.addEventListener("load", this.addVideoTime.bind(this, upload_info));
                                        xhr.open("GET", "/channel/UC" + channel_id + "/search?query=%22com%2Fwatch%3Fv%3D" + video_id + "%22", true);
                                        xhr.send();

                                        this.removeVideoTime.xhr = xhr;

                                        context = this;

                                        document.addEventListener("yt-navigate-finish", function listener() {

                                            context.removeVideoTime(listener);

                                        }, false);

                                    }

                                }

                            }

                        }

                    },
                    ini: function () {

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        window.addEventListener("yt-page-data-updated", this.loadStart.bind(this), true);

                    }
                },
                {
                    options: {
                        player_quality: {
                            id: "player_quality",
                            section: "video",
                            sub_section: "player",
                            type: "dropdown",
                            value: "auto",
                            i18n: {
                                label: "Default video quality:",
                                options: [
                                    "Auto",
                                    "4320p (8k)",
                                    "2880p (5k)",
                                    "2160p (4k)",
                                    "1440p",
                                    "1080p",
                                    "720p",
                                    "480p",
                                    "360p",
                                    "240p",
                                    "144p"
                                ]
                            },
                            options: [
                                "auto",
                                "highres",
                                "hd2880",
                                "hd2160",
                                "hd1440",
                                "hd1080",
                                "hd720",
                                "large",
                                "medium",
                                "small",
                                "tiny"
                            ]
                        },
                        player_auto_play: {
                            id: "player_auto_play",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Play videos automatically"
                            }
                        },
                        channel_trailer_auto_play: {
                            id: "channel_trailer_auto_play",
                            section: "video",
                            sub_section: "channel",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Play channel trailers automatically"
                            }
                        },
                        player_annotations: {
                            id: "player_annotations",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Allow annotations on videos"
                            }
                        },
                        player_subtitles: {
                            id: "player_subtitles",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Allow subtitles on videos"
                            }
                        },
                        player_loudness: {
                            id: "player_loudness",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Allow loudness normalisation"
                            }
                        },
                        player_ads: {
                            id: "player_ads",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Allow ads on videos"
                            }
                        },
                        subscribed_channel_player_ads: {
                            id: "subscribed_channel_player_ads",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Allow ads only on videos of subscribed channels"
                            }
                        },
                        player_hfr: {
                            id: "player_hfr",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Allow HFR (60fps) streams"
                            }
                        },
                        player_memorize_size: {
                            id: "player_memorize_size",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Memorize player size"
                            }
                        },
                        player_memorize_volume: {
                            id: "player_memorize_volume",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Memorize player volume"
                            }
                        }
                    },
                    modArgs: function (args) {

                        var i;
                        var fps;
                        var list;
                        var key_type;

                        if (user_settings.subscribed_channel_player_ads ? args.subscribed !== "1" : !user_settings.player_ads) {

                            delete args.ad3_module;

                        }

                        if (!user_settings.player_annotations) {

                            args.iv_load_policy = "3";

                        }

                        if (user_settings.player_memorize_size) {

                            args.player_wide = user_settings.theaterMode ? "1" : "0";

                        }

                        if (!user_settings.player_loudness) {

                            args.loudness = null;
                            args.relative_loudness = null;

                            delete args.loudness;
                            delete args.relative_loudness;

                        }

                        if (!user_settings.player_subtitles) {

                            window.localStorage.setItem("yt-html5-player-modules::subtitlesModuleData::module-enabled", "false");

                            if (args.caption_audio_tracks) {

                                args.caption_audio_tracks = args.caption_audio_tracks.split(/&d=[0-9]|d=[0-9]&/).join("");

                            }

                        }

                        if (!user_settings.player_hfr && args.adaptive_fmts) {

                            key_type = args.adaptive_fmts.indexOf(",") > -1 ? "," : "%2C";
                            list = args.adaptive_fmts.split(key_type);

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

                                fps = list[i].split(/fps(?:=|%3D)([0-9]{2})/);
                                fps = fps && fps[1];

                                if (fps > 30) {

                                    list.splice(i--, 1);

                                }

                            }

                            args.adaptive_fmts = list.join(key_type);

                        }

                    },
                    modVideoByPlayerVars: function (original) {

                        var context = this;

                        return function (args) {

                            var temp;
                            var current_config;


                            if (!this.getUpdatedConfigurationData) {

                                return original.apply(this, arguments);

                            }

                            current_config = this.getUpdatedConfigurationData();

                            if (current_config && current_config.args && (current_config.args.eventid === args.eventid || current_config.args.loaderUrl === args.loaderUrl) && !document.querySelector(".ended-mode")) {

                                return;

                            }

                            context.modArgs(args);

                            temp = original.apply(this, arguments);

                            if (user_settings.player_quality !== "auto") {

                                this.setPlaybackQuality(user_settings.player_quality);

                            }

                            return temp;

                        };

                    },
                    modPlayerLoad: function (original) {

                        var context = this;

                        return function (text, reviver) {

                            var temp;
                            var player;

                            context.modArgs(this.config.args);

                            temp = original.apply(this, arguments);

                            if (user_settings.player_quality !== "auto" && (player = document.getElementById("movie_player"))) {

                                player.setPlaybackQuality(user_settings.player_quality);

                            }

                            return temp;

                        };

                    },
                    modJSONParse: function (original) {

                        var context = this;

                        return function (text, reviver) {

                            var temp = original.apply(this, arguments);

                            if (temp && temp.player && temp.player.args) {

                                context.modArgs(temp.player.args);

                            }

                            return temp;

                        };

                    },
                    patchXHR: function (event) {

                        var i;
                        var temp;
                        var temp_list;
                        var key_value;
                        var player_api;

                        if (event.target.readyState === 4 && event.target.responseText.match(/eventid=/)) {

                            temp_list = {};
                            temp = event.target.responseText.split("&");

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

                                key_value = temp[i].split("=");
                                temp_list[key_value[0]] = key_value[1] || "";

                            }

                            this.modArgs(temp_list);

                            Object.defineProperty(event.target, "responseText", {writable: true});

                            event.target.responseText = "";
                            temp = Object.keys(temp_list);

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

                                event.target.responseText += temp[i] + "=" + temp_list[temp[i]];

                                if (i + 1 < temp.length) {

                                    event.target.responseText += "&";

                                }

                            }

                            if (user_settings.player_quality !== "auto" && (player_api = document.getElementById("movie_player"))) {

                                player_api.setPlaybackQuality(user_settings.player_quality);

                            }

                        }

                    },
                    modOpen: function (original) {

                        var context = this;

                        return function (method, url) {

                            if (url.match("get_video_info")) {

                                this.addEventListener("readystatechange", context.patchXHR.bind(context));

                            }

                            return original.apply(this, arguments);

                        };

                    },
                    modParseFromString: function (original) {

                        return function () {

                            var i;
                            var fps;
                            var result;
                            var streams;

                            if (!user_settings.player_hfr) {

                                result = original.apply(this, arguments);
                                streams = result.getElementsByTagName("Representation");
                                i = streams.length;

                                while (i--) {

                                    fps = streams[i].getAttribute("frameRate");

                                    if (fps > 30) {

                                        streams[i].remove();

                                    }

                                }

                                return result;

                            }

                            return original.apply(this, arguments);

                        };

                    },
                    handleCustoms: function (event) {

                        if (typeof event === "object") {

                            user_settings.userVolume = event.volume;

                        } else {

                            user_settings.theaterMode = event;

                        }

                        iridium_api.saveSettings();

                    },
                    playerReady: function (api) {

                        var watch_page_api;

                        if (api) {

                            if (user_settings.player_memorize_size) {

                                api.addEventListener("SIZE_CLICKED", this.handleCustoms);

                            }

                            if (user_settings.player_memorize_volume) {

                                api.setVolume(user_settings.userVolume);
                                api.addEventListener("onVolumeChange", this.handleCustoms);

                            }

                            if (user_settings.player_memorize_size && (watch_page_api = document.querySelector("ytd-watch"))) {

                                watch_page_api.playerApiReady_(api);
                                watch_page_api.theaterModeChanged_(user_settings.theaterMode);

                            }

                        }

                    },
                    shareApi: function (original) {

                        var context = this;

                        return function (api) {

                            context.playerReady(api);

                            if (original) {

                                return original.apply(this, arguments);

                            }

                        };
                    },
                    isChannel: function () {

                        return /^\/(user|channel)\//.test(window.location.pathname);

                    },
                    ini: function () {

                        var context;

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        context = this;

                        JSON.parse = this.modJSONParse(JSON.parse);
                        XMLHttpRequest.prototype.open = this.modOpen(XMLHttpRequest.prototype.open);
                        DOMParser.prototype.parseFromString = this.modParseFromString(DOMParser.prototype.parseFromString);
                        window.onYouTubePlayerReady = this.shareApi(window.onYouTubePlayerReady);

                        Object.defineProperties(Object.prototype, {
                            cueVideoByPlayerVars: {
                                set: function (data) {
                                    this._cueVideoByPlayerVars = data;
                                },
                                get: function () {
                                    return context.modVideoByPlayerVars(this._cueVideoByPlayerVars);
                                }
                            },
                            loadVideoByPlayerVars: {
                                set: function (data) {
                                    this._loadVideoByPlayerVars = data;
                                },
                                get: function () {

                                    if (context.isChannel() ? !user_settings.channel_trailer_auto_play : !user_settings.player_auto_play) {

                                        return this.cueVideoByPlayerVars;

                                    }

                                    return context.modVideoByPlayerVars(this._loadVideoByPlayerVars);

                                }
                            },
                            TIMING_AFT_KEYS: {
                                set: function (data) {
                                    this._TIMING_AFT_KEYS = data;
                                },
                                get: function () {

                                    var key;

                                    if (context.isChannel() ? !user_settings.channel_trailer_auto_play : !user_settings.player_auto_play) {

                                        if (window.ytcsi && window.ytcsi.data_ && window.ytcsi.data_.tick) {

                                            for (key in window.ytcsi.data_.tick) {

                                                if (window.ytcsi.data_.tick.hasOwnProperty(key)) {

                                                    return [key];

                                                }

                                            }

                                        } else {

                                            return ["srt"];

                                        }

                                    }

                                    return this._TIMING_AFT_KEYS;

                                }
                            },
                            loaded: {
                                set: function (data) {
                                    this._loaded = data;
                                },
                                get: function () {

                                    if (this.args && (context.isChannel() ? !user_settings.channel_trailer_auto_play : !user_settings.player_auto_play)) {

                                        return false;

                                    }

                                    return this._loaded;

                                }

                            },
                            load: {
                                set: function (data) {
                                    this._load = data;
                                },
                                get: function () {

                                    var temp = this._load && this._load.toString();

                                    if (temp && temp.match("Application.create")) {

                                        return context.modPlayerLoad(this._load);

                                    }

                                    return this._load;

                                }

                            },
                            autoplay: {
                                set: function (data) {
                                    this._autoplay = data;
                                },
                                get: function () {

                                    if (this.ucid && this._autoplay === "1" && (context.isChannel() ? !user_settings.channel_trailer_auto_play : !user_settings.player_auto_play)) {

                                        return "0";

                                    }

                                    return this._autoplay;

                                }

                            },
                            fflags: {
                                set: function (data) {
                                    this._fflags = data;
                                },
                                get: function () {

                                    if (this.ucid && (!this.autoplay || this.autoplay === "1") && (context.isChannel() ? !user_settings.channel_trailer_auto_play : !user_settings.player_auto_play)) {

                                        if (this._fflags && this._fflags.replace) {

                                            return this._fflags
                                                .replace(
                                                    "legacy_autoplay_flag=true",
                                                    "legacy_autoplay_flag=false"
                                                ).replace(
                                                    "disable_new_pause_state3=true",
                                                    "disable_new_pause_state3=false"
                                                );

                                        }

                                    }

                                    return this._fflags;

                                }

                            }
                        });

                    }
                },
                {
                    options: {
                        shortcuts_always_active: {
                            id: "shortcuts_always_active",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Player shortcuts always active"
                            }
                        }
                    },
                    alwaysActive: function (event) {

                        var i;
                        var api;
                        var list;
                        var clear;
                        var length;
                        var event_clone;

                        if (user_settings.shortcuts_always_active && (api = document.getElementById("movie_player"))) {

                            clear = window.location.pathname === "/watch" && api && api !== event.target && !api.contains(event.target);

                            clear = clear && !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey && !event.target.isContentEditable;

                            clear = clear && (event.which > 47 && event.which < 58 || event.which > 95 && event.which < 106 || [27, 32, 35, 36, 37, 38, 39, 40, 66, 67, 79, 87, 187, 189].indexOf(event.which) > -1);

                            if (clear && ["EMBED", "INPUT", "OBJECT", "TEXTAREA", "IFRAME"].indexOf(document.activeElement.tagName) === -1) {

                                event_clone = new Event("keydown");
                                list = Object.keys(Object.getPrototypeOf(event));
                                length = list.length;

                                for (i = 0; i < length; i++) {

                                    event_clone[list[i]] = event[list[i]];

                                }

                                event.preventDefault();
                                api.dispatchEvent(event_clone);

                            }

                        }

                    },
                    ini: function () {

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        document.addEventListener("keydown", this.alwaysActive.bind(this));

                    }
                },
                {
                    options: {
                        player_volume_wheel: {
                            id: "player_volume_wheel",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Change volume using the mouse wheel"
                            }
                        }
                    },
                    changeVolume: function (event) {

                        var api;
                        var player;
                        var direction;
                        var timestamp;
                        var can_scroll;
                        var new_volume;
                        var player_state;
                        var chrome_bottom;
                        var invideo_drawer;
                        var player_settings;
                        var fullscreen_playlist;

                        api = document.getElementById("movie_player");
                        player = document.querySelector("video");
                        invideo_drawer = document.querySelector(".iv-drawer");
                        player_settings = document.querySelector(".ytp-settings-menu");
                        fullscreen_playlist = document.querySelector(".ytp-playlist-menu");
                        can_scroll = (!fullscreen_playlist || !fullscreen_playlist.contains(event.target)) && (!invideo_drawer || !invideo_drawer.contains(event.target)) && (!player_settings || !player_settings.contains(event.target));

                        if (can_scroll && player && api && api.contains(event.target)) {

                            player_state = api.getPlayerState();

                            if (player_state > 0 && player_state < 5) {

                                event.preventDefault();
                                chrome_bottom = document.querySelector(".ytp-chrome-bottom");

                                if (chrome_bottom) {

                                    if (!chrome_bottom.classList.contains("ytp-volume-slider-active")) {

                                        chrome_bottom.classList.add("ytp-volume-slider-active");

                                    }

                                    if (chrome_bottom.timer) {

                                        window.clearTimeout(chrome_bottom.timer);

                                    }

                                    api.dispatchEvent(new Event("mousemove"));

                                    chrome_bottom.timer = window.setTimeout(function () {

                                        if (chrome_bottom && chrome_bottom.classList.contains("ytp-volume-slider-active")) {

                                            chrome_bottom.classList.remove("ytp-volume-slider-active");
                                            delete chrome_bottom.timer;

                                        }

                                    }, 4000);

                                }

                                direction = event.deltaY || event.wheelDeltaY;
                                new_volume = api.getVolume() - (Math.sign(direction) * 5);

                                if (new_volume < 0) {

                                    new_volume = 0;

                                } else if (new_volume > 100) {

                                    new_volume = 100;

                                }

                                api.setVolume(new_volume);

                                timestamp = Date.now();

                                window.localStorage.setItem(
                                    "yt-player-volume",
                                    JSON.stringify({
                                        data: JSON.stringify({
                                            volume: new_volume,
                                            muted: false
                                        }),
                                        creation: timestamp,
                                        expiration: timestamp + 2592E6
                                    })
                                );

                                return false;

                            }

                        }

                    },
                    ini: function () {

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        if (user_settings.player_volume_wheel) {

                            document.addEventListener("wheel", this.changeVolume.bind(this));

                        }

                    }
                },
                {
                    options: {
                        player_always_visible: {
                            id: "player_always_visible",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Video stays always visible while scrolling"
                            }
                        },
                        player_always_playing: {
                            id: "player_always_playing",
                            section: "video",
                            sub_section: "player",
                            type: "checkbox",
                            value: true,
                            i18n: {
                                label: "Video keeps playing when changing pages",
                                button_restore: "Restore",
                                button_close: "Close"
                            }
                        }
                    },
                    endMiniPlayer: function (class_name) {

                        var player_api;
                        var is_in_theater_mode;

                        document.documentElement.classList.remove(class_name);

                        if ((player_api = document.getElementById("movie_player"))) {

                            is_in_theater_mode = document.querySelector("ytd-watch[theater]");

                            player_api.setSizeStyle(true, is_in_theater_mode);

                        }

                    },
                    iniMiniPlayer: function (class_name) {

                        var player_api;

                        document.documentElement.classList.add(class_name);

                        if ((player_api = document.getElementById("movie_player"))) {

                            player_api.setSizeStyle(false, true);

                            this.iniMiniPlayerControls(player_api);

                        }

                    },
                    iniAlwaysVisible: function (event) {

                        var player;
                        var player_bounds;
                        var is_out_of_sight;
                        var player_container;
                        var is_already_floating;

                        if (user_settings.player_always_visible) {

                            is_already_floating = document.documentElement.classList.contains("iri-always-visible");

                            if (event.detail && event.detail.pageType !== "watch" && is_already_floating) {

                                this.endMiniPlayer("iri-always-visible");

                            } else if (window.location.pathname === "/watch") {

                                if ((player_container = document.getElementById("player-container")) && (player_bounds = player_container.getBoundingClientRect())) {

                                    is_out_of_sight = player_bounds.bottom < ((player_bounds.height / 2) + 50);

                                    if (is_out_of_sight && !is_already_floating) {

                                        this.iniMiniPlayer("iri-always-visible");

                                    } else if (!is_out_of_sight && is_already_floating) {

                                        this.endMiniPlayer("iri-always-visible");

                                    }

                                }

                            }

                        }

                    },
                    iniAlwaysPlaying: function (event) {

                        if (user_settings.player_always_playing) {

                            if (event.detail && event.detail.pageType === "watch") {

                                this.endMiniPlayer("iri-always-playing");

                            } else if (!document.querySelector(".ended-mode")) {

                                this.iniMiniPlayer("iri-always-playing");

                            }

                        }

                    },
                    restorePlayer: function () {

                        var player_api;
                        var current_data;
                        var original_url;
                        var history_state;
                        var watch_page_api;
                        var page_manager_api;

                        if ((watch_page_api = document.querySelector("ytd-watch"))) {

                            if ((player_api = document.getElementById("movie_player"))) {

                                current_data = player_api.getUpdatedConfigurationData();
                                original_url = current_data.args.loaderUrl.replace(window.location.origin, "");
                                document.title = current_data.args.title + " - YouTube";

                                history_state = {
                                    endpoint: {
                                        clickTrackingParams: "",
                                        watchEndpoint: {
                                            videoId: current_data.args.video_id
                                        },
                                        webNavigationEndpointData: {
                                            url: original_url,
                                            webPageType: "WATCH"
                                        }
                                    },
                                    entryTime: window.performance.now(),
                                    savedComponentState: null
                                };

                                window.history.pushState(history_state, document.title, original_url);

                            }

                            this.endMiniPlayer("iri-always-playing");

                            if ((page_manager_api = document.querySelector("ytd-page-manager"))) {

                                page_manager_api.setActivePage_(watch_page_api);

                            }

                            watch_page_api.initComments_();

                            document.dispatchEvent(new Event("yt-page-data-fetched"));
                            document.dispatchEvent(new Event("yt-page-data-updated"));

                        }

                    },
                    closePlayer: function () {

                        var player_api;

                        this.endMiniPlayer("iri-always-playing");

                        if ((player_api = document.getElementById("movie_player"))) {

                            player_api.stopVideo(true);

                        }

                    },
                    iniMiniPlayerControls: function (player_api) {

                        var restore_page;
                        var close_mini_player;
                        var mini_player_controls;

                        if (!(mini_player_controls = document.getElementById("iri-mini-player-controls")) && player_api) {

                            mini_player_controls = document.createElement("div");
                            mini_player_controls.id = "iri-mini-player-controls";

                            restore_page = document.createElement("div");
                            restore_page.id = "iri-mini-player-restore";
                            restore_page.className = "iri-mini-player-control iri-mini-player-left-control";
                            restore_page.innerHTML =
                                "<svg height='24' width='24' fill='#FFF'>" +
                                "    <use xlink:href='#iri-svg-restore' class='iri-svg-shadow'/>" +
                                "    <path id='iri-svg-restore' d='M21 4H1v16h22V4h-2zm0 14H3v-6h10V6h8v12z'/>" +
                                "</svg>" +
                                "<div class='iri-mini-player-tooltip'>" + i18n.player_always_playing.button_restore + "</div>";
                            restore_page.addEventListener("click", this.restorePlayer.bind(this), false);

                            close_mini_player = document.createElement("div");
                            close_mini_player.id = "iri-mini-player-close";
                            close_mini_player.className = "iri-mini-player-control iri-mini-player-right-control";
                            close_mini_player.innerHTML =
                                "<svg height='24' width='24' fill='#FFF'>" +
                                "    <use xlink:href='#iri-svg-close' class='iri-svg-shadow'/>" +
                                "    <path id='iri-svg-close' d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/>" +
                                "</svg>" +
                                "<div class='iri-mini-player-tooltip'>" + i18n.player_always_playing.button_close + "</div>";
                            close_mini_player.addEventListener("click", this.closePlayer.bind(this), false);

                            mini_player_controls.appendChild(restore_page);
                            mini_player_controls.appendChild(close_mini_player);

                            player_api.appendChild(mini_player_controls);

                        }

                    },
                    modStopVideo: function (original) {

                        return function (bypass) {

                            if (user_settings.player_always_playing && !bypass) {

                                return;

                            }

                            return original.apply(this, arguments);

                        };

                    },
                    ini: function () {

                        var context;

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                        window.addEventListener("scroll", this.iniAlwaysVisible.bind(this), false);
                        window.addEventListener("yt-navigate-start", this.iniAlwaysVisible.bind(this), false);
                        window.addEventListener("yt-navigate-finish", this.iniAlwaysVisible.bind(this), false);
                        window.addEventListener("yt-navigate-start", this.iniAlwaysPlaying.bind(this), false);
                        window.addEventListener("yt-navigate-finish", this.iniAlwaysPlaying.bind(this), false);

                        context = this;

                        Object.defineProperty(Object.prototype, "stopVideo", {
                            set: function (data) {
                                this._stopVideo = data;
                            },
                            get: function () {
                                return context.modStopVideo(this._stopVideo);
                            }
                        })

                    }
                },
                {
                    options: {
                        iridium_dark_mode: {
                            id: "iridium_dark_mode",
                            section: "settings",
                            sub_section: "settings",
                            type: "checkbox",
                            value: false,
                            i18n: {
                                label: "Use dark theme"
                            },
                            callback: function () {

                                if (user_settings.iridium_dark_mode) {

                                    document.documentElement.classList.add("iri-dark-mode-settings");

                                } else {

                                    document.documentElement.classList.remove("iri-dark-mode-settings");

                                }

                            }
                        }
                    }
                },
                {
                    options: {
                        iridium_user_settings: {
                            id: "iridium_user_settings",
                            section: "settings",
                            sub_section: "settings",
                            type: "custom",
                            i18n: {
                                button_save: "Save",
                                button_close: "Close",
                                button_export: "Export",
                                button_import: "Import",
                                button_reset: "Reset",
                                placeholder: "Paste your new settings here",
                                confirm_reset: "You are about to reset your settings. It is advised to backup your current settings before continuing.\n\nDo you wish to contiue?\n\n",
                                reset_success: "Settings have been reset.\n\nChanges will be applied after a page refresh.\n\n",
                                confirm_import: "You are about to override your current settings. It is advised to backup your current settings before continuing.\n\nDo you wish to contiue?\n\n",
                                import_success: "Your settings have been imported with success.\n\nChanges will be applied after a page refresh.\n\n",
                                import_error: "Your settings could not be imported because they appear to be invalid.\n\n"
                            },
                            custom: function () {

                                var element;
                                var element_list;

                                element_list = [];

                                element = document.createElement("button");
                                element.textContent = i18n.iridium_user_settings.button_export;
                                element.className = "setting iri-settings-button";
                                element.addEventListener("click", this.textEditor.bind(this, "export"));

                                element_list.push(element);

                                element = document.createElement("button");
                                element.textContent = i18n.iridium_user_settings.button_import;
                                element.className = "setting iri-settings-button";
                                element.addEventListener("click", this.textEditor.bind(this, "import"));

                                element_list.push(element);

                                element = document.createElement("button");
                                element.textContent = i18n.iridium_user_settings.button_reset;
                                element.className = "setting iri-settings-button danger";
                                element.addEventListener("click", this.resetSettings.bind(this));

                                element_list.push(element);

                                return element_list;

                            },
                            resetSettings: function () {

                                if (window.confirm(i18n.iridium_user_settings.confirm_reset)) {

                                    user_settings = null;

                                    iridium_api.initializeSettings();
                                    iridium_api.saveSettings();

                                    window.alert(i18n.iridium_user_settings.reset_success);

                                }

                            },
                            importSettings: function () {

                                var editor;
                                var textarea;

                                if ((textarea = document.getElementById("iridium-textarea")) && window.confirm(i18n.iridium_user_settings.confirm_import)) {

                                    try {

                                        user_settings = JSON.parse(textarea.value);

                                        iridium_api.saveSettings();

                                        window.alert(i18n.iridium_user_settings.import_success);

                                        if ((editor = document.getElementById("iridium-text-editor"))) {

                                            editor.remove();

                                        }

                                    } catch (error) {

                                        window.alert(i18n.iridium_user_settings.import_error + error.name + ": " + error.message);

                                    }

                                }

                            },
                            closeEditor: function (editor) {

                                editor.remove();

                            },
                            textEditor: function (type, event) {

                                var editor;
                                var button;
                                var textarea;
                                var buttons_section;

                                if (!(editor = document.getElementById("iridium-text-editor"))) {

                                    editor = document.createElement("div");
                                    editor.id = "iridium-text-editor";

                                    document.body.appendChild(editor);

                                } else {

                                    editor.textContent = "";

                                }

                                buttons_section = document.createElement("div");
                                buttons_section.id = "buttons-section";
                                textarea = document.createElement("textarea");
                                textarea.id = "iridium-textarea";
                                textarea.setAttribute("spellcheck", "false");

                                if (type === "import") {

                                    textarea.setAttribute("placeholder", i18n.iridium_user_settings.placeholder);

                                    button = document.createElement("button");
                                    button.textContent = i18n.iridium_user_settings.button_save;
                                    button.className = "iri-settings-button";
                                    button.addEventListener("click", this.importSettings.bind(this));

                                    buttons_section.appendChild(button);

                                }

                                button = document.createElement("button");
                                button.textContent = i18n.iridium_user_settings.button_close;
                                button.className = "iri-settings-button";
                                button.addEventListener("click", this.closeEditor.bind(this, editor));

                                buttons_section.appendChild(button);

                                if (type === "export") {

                                    textarea.value = JSON.stringify(user_settings, null, 4);

                                }

                                editor.appendChild(buttons_section);
                                editor.appendChild(textarea);

                            }
                        },
                        iridium_language: {
                            id: "iridium_language",
                            section: "settings",
                            sub_section: "language",
                            type: "custom",
                            i18n: {
                                button_save: "Save",
                                button_close: "Close",
                                confirm_save: "You are about to replace your extension language settings.\n\nDo you wish to continue?\n\n",
                                save_success: "New language saved successfully.\n\nChanges will be applied after a page refresh.\n\n",
                                save_error: "The new language could not be saved because it appears to be invalid.\n\n"
                            },
                            custom: function () {

                                var element;
                                var element_list;

                                element_list = [];

                                element = document.createElement("button");
                                element.textContent = i18n.language;
                                element.className = "setting iri-settings-button";
                                element.addEventListener("click", this.textEditor.bind(this));

                                element_list.push(element);

                                return element_list;

                            },
                            closeEditor: function (editor) {

                                editor.remove();

                            },
                            saveLanguage: function (textarea) {

                                var editor;

                                if ((textarea = document.getElementById("iridium-textarea")) && window.confirm(i18n.iridium_language.confirm_save)) {

                                    try {

                                        user_settings.custom_language = JSON.parse(textarea.value);

                                        iridium_api.setCustomLanguage(user_settings.custom_language);
                                        iridium_api.saveSettings();

                                        window.alert(i18n.iridium_language.save_success);

                                        if ((editor = document.getElementById("iridium-text-editor"))) {

                                            editor.remove();

                                        }

                                    } catch (error) {

                                        window.alert(i18n.iridium_language.save_error + error.name + ": " + error.message);

                                    }
                                }

                            },
                            textEditor: function (event) {

                                var editor;
                                var button;
                                var textarea;
                                var buttons_section;

                                if (!(editor = document.getElementById("iridium-text-editor"))) {

                                    editor = document.createElement("div");
                                    editor.id = "iridium-text-editor";

                                    document.body.appendChild(editor);

                                } else {

                                    editor.textContent = "";

                                }

                                buttons_section = document.createElement("div");
                                buttons_section.id = "buttons-section";

                                button = document.createElement("button");
                                button.textContent = i18n.iridium_language.button_save;
                                button.className = "iri-settings-button";
                                button.addEventListener("click", this.saveLanguage.bind(this));

                                buttons_section.appendChild(button);

                                button = document.createElement("button");
                                button.textContent = i18n.iridium_language.button_close;
                                button.className = "iri-settings-button";
                                button.addEventListener("click", this.closeEditor.bind(this, editor));

                                buttons_section.appendChild(button);

                                textarea = document.createElement("textarea");
                                textarea.id = "iridium-textarea";
                                textarea.value = JSON.stringify(i18n, null, 4);
                                textarea.setAttribute("spellcheck", "false");

                                editor.appendChild(buttons_section);
                                editor.appendChild(textarea);

                            }
                        }
                    },
                    ini: function () {

                        if (iridium_api.initializeOption.call(this)) {

                            return;

                        }

                    }
                },
                {
                    options: {
                        about: {
                            id: "about",
                            section: "about",
                            type: "custom"
                        }
                    }
                }
            ];

            iridium_api = {

                setCustomLanguage: function (custom_language) {

                    var i;
                    var j;
                    var key;
                    var sub_key;

                    key = Object.keys(custom_language);

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

                        sub_key = Object.keys(custom_language[key[i]]);

                        if (!(key[i] in i18n)) {

                            i18n[key[i]] = custom_language[key[i]];

                        } else {

                            for (j = 0; j < sub_key.length; j++) {

                                i18n[key[i]][sub_key[j]] = custom_language[key[i]][sub_key[j]];

                            }

                        }

                    }

                },
                fillSettingsContainer: function (options_list) {

                    var i;
                    var j;
                    var temp;
                    var input;
                    var label;
                    var select;
                    var header;
                    var option;
                    var options;
                    var section;
                    var setting;
                    var help_link;
                    var sub_section;

                    if (!(section = document.getElementById("settings_sub_section"))) {

                        return;

                    }

                    section.textContent = "";

                    if ((header = document.getElementById("settings_section_header"))) {

                        header.textContent = i18n.section_titles[options_list[0].section];

                    }

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

                        option = options_list[i];

                        if (!(sub_section = document.getElementById(i18n.sub_section_titles[option.sub_section]))) {

                            sub_section = document.createElement("div");
                            sub_section.id = i18n.sub_section_titles[option.sub_section];

                            header = document.createElement("h3");
                            header.textContent = i18n.sub_section_titles[option.sub_section];

                            sub_section.appendChild(header);
                            section.appendChild(sub_section);

                        }

                        setting = document.createElement("div");
                        setting.className = "settings_setting";

                        switch (option.type) {

                            case "checkbox":

                                input = document.createElement("input");
                                input.className = "setting";
                                input.id = option.id;
                                input.type = option.type;
                                input.checked = user_settings[option.id];

                                label = document.createElement("label");
                                label.textContent = i18n[option.id].label;
                                label.className = "setting";
                                label.setAttribute("for", option.id);

                                setting.appendChild(input);
                                setting.appendChild(label);

                                if (option.callback) {

                                    input.callback = option.callback;

                                }

                                break;

                            case "dropdown":

                                label = document.createElement("label");
                                label.textContent = i18n[option.id].label;
                                label.className = "setting";
                                label.setAttribute("for", option.id);

                                select = document.createElement("select");
                                select.id = option.id;
                                select.className = "iri-settings-button";

                                for (j = 0; j < option.options.length; j++) {

                                    options = document.createElement("option");
                                    options.value = option.options[j];
                                    options.textContent = i18n[option.id].options[j];

                                    if (user_settings[option.id] === options.value) {

                                        options.setAttribute("selected", "true");

                                    }

                                    select.appendChild(options);
                                }

                                setting.appendChild(label);
                                setting.appendChild(select);

                                break;

                            case "custom":

                                if (option.custom) {

                                    temp = option.custom();

                                    for (j = 0; j < temp.length; j++) {

                                        setting.appendChild(temp[j]);

                                    }

                                }

                                break;

                        }

                        if (option.type !== "custom") {

                            help_link = document.createElement("a");
                            help_link.textContent = "?";
                            help_link.href = "https://github.com/ParticleCore/Iridium/wiki/Features#" + option.id;
                            help_link.setAttribute("title", i18n.iridium_api.feature_link);
                            help_link.className = "feature-link";
                            help_link.setAttribute("target", "features");

                            setting.appendChild(help_link);

                        }

                        sub_section.appendChild(setting);

                    }

                },
                loadSelectedSection: function () {

                    var name;
                    var option;
                    var active_id;
                    var options_list;
                    var active_sidebar;

                    if (!(active_sidebar = document.querySelector(".sidebar_section.active_sidebar"))) {

                        return;

                    }

                    active_id = active_sidebar.dataset.section;
                    options_list = [];

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

                        if (modules[i].options) {

                            for (name in modules[i].options) {

                                if (modules[i].options.hasOwnProperty(name)) {

                                    option = modules[i].options[name];

                                    if (option.section === active_id) {

                                        options_list.push(option);

                                    }

                                }

                            }

                        }

                    }

                    iridium_api.fillSettingsContainer(options_list);

                },
                updateSidebarSelection: function (event) {

                    var next;
                    var current;
                    var sidebar_current;

                    if (event.target.dataset.section) {

                        current = document.querySelector(".active_sidebar");
                        next = document.getElementById("sidebar_" + event.target.dataset.section);

                        if (next !== current) {

                            if ((sidebar_current = document.querySelector(".active_sidebar"))) {

                                sidebar_current.classList.remove("active_sidebar");

                            }

                            event.target.classList.add("active_sidebar");

                            iridium_api.loadSelectedSection();

                        }

                    }

                },
                settingsBuilder: function (option) {

                    var header;
                    var divider;
                    var section;
                    var sub_section;
                    var sidebar_section;
                    var settings_sidebar;
                    var settings_container;

                    if (!(settings_sidebar = document.getElementById("iridium_settings_sidebar"))) {

                        settings_sidebar = document.createElement("div");
                        settings_sidebar.id = "iridium_settings_sidebar";

                        document.body.appendChild(settings_sidebar);

                    }

                    if (!(sidebar_section = document.getElementById("sidebar_" + option.section))) {

                        sidebar_section = document.createElement("div");
                        sidebar_section.id = "sidebar_" + option.section;
                        sidebar_section.textContent = option.section;
                        sidebar_section.dataset.section = option.section;

                        sidebar_section.className = "sidebar_section";
                        settings_sidebar.appendChild(sidebar_section);

                    }

                    if (!(settings_container = document.getElementById("iridium_settings_container"))) {

                        settings_container = document.createElement("div");
                        settings_container.id = "iridium_settings_container";

                        if (!(section = document.getElementById("settings_section"))) {

                            header = document.createElement("h2");
                            header.id = "settings_section_header";

                            divider = document.createElement("div");
                            divider.className = "settings_divider";

                            section = document.createElement("div");
                            section.id = "settings_section";

                            section.addEventListener("change", iridium_api.autoSaveSettings, true);
                            section.appendChild(header);
                            section.appendChild(divider);

                            settings_container.appendChild(section);

                        }

                        if (!(sub_section = document.getElementById("settings_sub_section"))) {

                            sub_section = document.createElement("div");
                            sub_section.id = "settings_sub_section";

                            section.appendChild(sub_section);

                        }

                        document.body.appendChild(settings_container);

                    }

                    if (!document.querySelector(".active_sidebar")) {

                        sidebar_section.classList.add("active_sidebar");

                    }

                },
                loadSettingsMenu: function () {

                    var i;
                    var name;
                    var title;
                    var option;

                    if (document.head) {

                        document.head.textContent = "";

                    } else {

                        document.documentElement.appendChild(document.createElement("head"));

                    }

                    if (document.body) {

                        document.body.textContent = "";

                    } else {

                        document.documentElement.appendChild(document.createElement("body"));

                    }

                    if (!(title = document.querySelector("title"))) {

                        title = document.createElement("title");

                        document.head.appendChild(title);

                    }

                    title.textContent = i18n.iridium_api.settings_button;
                    document.body.id = "iridium_settings";
                    document.body.style.display = "none";

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

                        if (modules[i].options) {

                            for (name in modules[i].options) {

                                if (modules[i].options.hasOwnProperty(name)) {

                                    option = modules[i].options[name];
                                    iridium_api.settingsBuilder(option);

                                }

                            }

                        }

                    }

                    document.addEventListener("click", iridium_api.updateSidebarSelection);

                    iridium_api.loadSelectedSection();

                },
                autoSaveSettings: function (event) {

                    switch (event.target.type) {

                        case "checkbox":

                            user_settings[event.target.id] = event.target.checked;

                            break;

                        case "select-one":

                            user_settings[event.target.id] = event.target.value;

                            break;

                    }

                    if (event.target.callback) {

                        event.target.callback();

                    }

                    iridium_api.saveSettings();

                },
                saveSettings: function () {

                    document.documentElement.dataset.iridium_save_settings = JSON.stringify(user_settings);

                },
                initializeSettings: function () {

                    var i;
                    var option;
                    var options;

                    user_settings = JSON.parse(document.documentElement.dataset.iridium_user_settings || "{}");

                    if (document.documentElement.dataset.iridium_user_settings) {

                        document.documentElement.removeAttribute("data-iridium_user_settings");

                    }

                    i18n = default_language;

                    if (user_settings.custom_language) {

                        iridium_api.setCustomLanguage(user_settings.custom_language);

                    }

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

                        for (options in modules[i].options) {

                            if (modules[i].options.hasOwnProperty(options)) {

                                option = modules[i].options[options];

                                if (!(option.id in user_settings) && "value" in option) {

                                    user_settings[option.id] = option.value;

                                }

                                if (option.i18n) {

                                    i18n[option.id] = option.i18n;

                                }

                            }

                        }

                    }

                },
                initializeSettingsButton: function () {

                    var buttons;
                    var iridium_settings_button;

                    buttons = document.querySelector("#end #buttons");

                    if (buttons && !(iridium_settings_button = document.getElementById("iridium_settings_button"))) {

                        iridium_settings_button = document.createElement("a");
                        iridium_settings_button.id = "iridium_settings_button";
                        iridium_settings_button.href = "/iridium-settings";
                        iridium_settings_button.target = "_blank";
                        iridium_settings_button.innerHTML =
                            "<svg viewBox='0 0 24 24' style='height:24px;'>" +
                            "    <radialGradient id='iri-gradient' gradientUnits='userSpaceOnUse' cx='6' cy='22' r='18.5'>" +
                            "        <stop class='iri-start-gradient' offset='0'/>" +
                            "        <stop class='iri-stop-gradient' offset='1'/>" +
                            "    </radialGradient>" +
                            "    <polygon points='24,11.8 6,1.6 6,22'/>" +
                            "    <path d='M6 1.6V22l18-10.2L6 1.6z M9 6.8l9 5.1L9 17V6.8z'/>" +
                            "</svg>" +
                            "<div class='iri-tooltip' style='opacity: 0'>" + i18n.iridium_api.settings_button + "</div>";
                        buttons.parentNode.insertBefore(iridium_settings_button, buttons);

                        document.documentElement.removeEventListener("load", iridium_api.initializeSettingsButton, true);

                    }

                },
                initializeModules: function () {

                    var i;
                    var timestamp;

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

                        if (modules[i].ini) {

                            modules[i].ini();

                        }

                    }

                    if (user_settings.player_quality !== "auto") {

                        timestamp = Date.now();

                        window.localStorage.setItem(
                            "yt-player-quality",
                            JSON.stringify({
                                data: user_settings.player_quality,
                                creation: timestamp,
                                expiration: timestamp + 2592E6
                            })
                        );

                    }

                },
                initializeOption: function () {

                    var key;

                    if (this.started) {

                        return true;

                    }

                    this.started = true;

                    for (key in this.options) {

                        if (this.options.hasOwnProperty(key)) {

                            if (!(key in user_settings) && this.options[key].value) {

                                user_settings[key] = this.options[key].value;

                            }

                        }

                    }

                    return false;

                },
                ini: function () {

                    iridium_api.initializeSettings();

                    if (window.location.pathname === "/iridium-settings") {

                        iridium_api.loadSettingsMenu();

                        if (user_settings.iridium_dark_mode) {

                            document.documentElement.classList.add("iri-dark-mode-settings");

                        }

                    } else {

                        iridium_api.initializeModules();

                    }

                    document.documentElement.addEventListener("load", iridium_api.initializeSettingsButton, true);

                }

            };

            iridium_api.ini();

        },
        contentScriptMessages: function () {

            var key1;
            var key2;
            var gate;
            var sets;
            var locs;
            var observer;

            key1 = "iridium_save_settings";
            key2 = "getlocale";
            gate = document.documentElement;
            sets = JSON.parse(gate.dataset[key1] || null);
            locs = gate.dataset[key2] || null;

            if (!gate.contentscript) {

                gate.contentscript = true;
                observer = new MutationObserver(iridium.contentScriptMessages);

                return observer.observe(gate, {
                    attributes: true,
                    attributeFilter: ["data-" + key1, "data-" + key2]
                });

            }

            if (sets) {

                if (iridium.is_userscript) {

                    iridium.GM_setValue(iridium.id, JSON.stringify(sets));

                } else {

                    chrome.storage.local.set({iridiumSettings: sets});

                }

                document.documentElement.removeAttribute("data-iridium_save_settings");

            } else if (locs) {

                document.documentElement.dataset.setlocale = chrome.i18n.getMessage(locs);

            }

        },
        filterChromeKeys: function (keys) {

            if (keys[iridium.id] && keys[iridium.id].new_value) {

                document.documentElement.dataset.iridium_load_settings = JSON.stringify(
                    (keys[iridium.id].new_value && keys[iridium.id].new_value[iridium.id]) || keys[iridium.id].new_value || {}
                );

            }

        },
        main: function (event) {

            var holder;

            if (!event && iridium.is_userscript) {

                event = JSON.parse(iridium.GM_getValue(iridium.id, "{}"));

            }

            if (event) {

                event = JSON.stringify(event[iridium.id] || event);
                document.documentElement.dataset.iridium_user_settings = event;

                if (iridium.is_userscript) {

                    holder = document.createElement("link");
                    holder.rel = "stylesheet";
                    holder.type = "text/css";
                    holder.href = "https://particlecore.github.io/Iridium/css/Iridium.css?v=0.3.0a";
                    document.documentElement.appendChild(holder);

                }

                holder = document.createElement("script");
                holder.textContent = "(" + iridium.inject + "(" + iridium.is_userscript + "))";
                document.documentElement.appendChild(holder);
                holder.remove();

                if (!iridium.is_userscript) {

                    chrome.storage.onChanged.addListener(iridium.filterChromeKeys);

                }

            }

        },
        ini: function () {

            if (window.location.pathname === "/iridium-settings") {

                window.stop();

            }

            iridium.id = "iridiumSettings";
            iridium.is_userscript = typeof GM_info === "object";

            if (iridium.is_userscript) {

                iridium.GM_getValue = GM_getValue;
                iridium.GM_setValue = GM_setValue;
                iridium.main();

            } else {

                chrome.storage.local.get(iridium.id, iridium.main);

            }

            iridium.contentScriptMessages();

        }

    };

    iridium.ini();

}());