// ==UserScript== // @name givee.club & giveaway.su improvements // @name:de givee.club & giveaway.su Verbesserungen // @namespace https://kurotaku.de // @version 1.0.1 // @description A script for some improvements for givee.club & giveaway.su // @description:de Ein Skript für einige Verbesserungen für givee.club & giveaway.su // @author Kurotaku // @license CC BY-NC-SA 4.0 // @match https://givee.club/* // @match https://giveaway.su/* // @icon https://givee.club/favicon.ico // @updateURL https://raw.githubusercontent.com/Kurotaku-sama/Userscripts/main/userscripts/givee.club_&_giveaway.su_improvements/script.user.js // @downloadURL https://raw.githubusercontent.com/Kurotaku-sama/Userscripts/main/userscripts/givee.club_&_giveaway.su_improvements/script.user.js // @require https://raw.githubusercontent.com/Kurotaku-sama/Userscripts/main/libraries/kuros_library.js // @require https://cdn.jsdelivr.net/npm/sweetalert2 // @require https://openuserjs.org/src/libs/sizzle/GM_config.js // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_registerMenuCommand // @run-at document-body // ==/UserScript== const SITE_DATA = { "givee.club": { sele_menu: `.user button[data-action="account-rewards"]`, sele_giveaways_container: "#event-active", sele_giveaway_container: "#event-active .col-md-4.col-sm-6", sele_giveaway_card: ".event-card", sele_giveaway_title: ".event-title .vertical-align-middle", sele_ads: ".definetelynotanad", sele_task_button_destination: ".actions-submit", sele_task_buttons: ".event-actions tr button.btn-default", html_button_toggle_visibility_open: ` `, html_button_toggle_visibility_close: ` `, html_button_config: ` `, menu_insert: "afterend" }, "giveaway.su": { sele_menu: "ul.menu", sele_giveaways_container: "#giveaways", sele_giveaway_container: "#giveaways .col-md-4.col-sm-6", sele_giveaway_card: ".giveaway-item", sele_giveaway_title: ".giveaway-title .vertical-align-middle", sele_ads: ".definetelynotanad", sele_task_button_destination: "#getKey", sele_task_buttons: "#actions tr button.btn-default", html_button_toggle_visibility_open: `
  • Show hidden
  • `, html_button_toggle_visibility_close: `
  • Hide hidden
  • `, html_button_config: `
  • Config
  • `, menu_insert: "afterbegin" } }; const CURRENT_DOMAIN = window.location.hostname; const DATA = SITE_DATA[CURRENT_DOMAIN]; const LOC = window.location.href; let gicl, gisu; (async function() { await init_gm_config(); if(get_field("script_enabled")) { insert_buttons(); if(gicl.get("hide_ads")) hide_ads(); wait_for_element(DATA.sele_giveaways_container).then(async () => { hide_items(); if(get_field("hide_item_buttons")) hide_item_buttons(); }); if(LOC.includes("/event/")) insert_giveaway_draw_time(); if(LOC.includes("/event/") || LOC.includes("/giveaway/view/")) insert_task_button(); } })(); async function init_gm_config() { const config_id_gicl = "configuration_gicl"; const config_id_gisu = "configuration_gisu"; gicl = new GM_config({ id: config_id_gicl, title: "givee.club improvements", fields: { companion: { type: "button", size: 100, label: "Install Giveaway Companion (Recommended)", click: () => window.open("https://raw.githubusercontent.com/longnull/GiveawayCompanion/master/GiveawayCompanion.user.js", "_blank"), }, script_enabled: { type: "checkbox", default: true, label: "Enable/Disable all improvements", }, hide_ads: { type: "checkbox", default: true, label: "Hide sponsored content", }, hide_item_buttons: { type: "checkbox", default: true, label: "Button in top right corner for quick hide", }, hide_items_from_list_by_default: { type: "checkbox", default: true, label: "Hide items by default", }, instant_hide: { type: "checkbox", default: false, label: "Instant hide", }, items_to_hide: { label: "Hide items by name
    (each item name must be written in a new line)", type: "textarea", }, }, frame: create_configuration_container(), }) gisu = new GM_config({ id: config_id_gisu, title: "giveaway.su improvements", fields: { companion: { type: "button", size: 100, label: "Install Giveaway Companion (Recommended)", click: () => window.open("https://raw.githubusercontent.com/longnull/GiveawayCompanion/master/GiveawayCompanion.user.js", "_blank"), }, script_enabled: { type: "checkbox", default: true, label: "Enable/Disable all improvements", }, hide_item_buttons: { type: "checkbox", default: true, label: "Button in top right corner for quick hide", }, hide_items_from_list_by_default: { type: "checkbox", default: true, label: "Hide items by default", }, instant_hide: { type: "checkbox", default: false, label: "Instant hide", }, items_to_hide: { label: "Hide items by name
    (each item name must be written in a new line)", type: "textarea", }, }, frame: create_configuration_container(), }) GM_registerMenuCommand("Settings givee.club", () => gicl.open()); GM_registerMenuCommand("Settings giveaway.su", () => gisu.open()); await wait_for_gm_config(); } function get_config() { if (CURRENT_DOMAIN === "givee.club") return gicl; else if (CURRENT_DOMAIN === "giveaway.su") return gisu; return null; } function get_field(field_name) { const config = get_config(); return config ? config.get(field_name) : false; } async function insert_buttons() { // Wait for menu element based on current domain wait_for_element(DATA.sele_menu).then((menu_element) => { let html = ""; // Check if we're on homepage (for toggle button) const home = document.querySelector(DATA.sele_giveaways_container); if (home) html += get_field("hide_items_from_list_by_default") ? DATA.html_button_toggle_visibility_open : DATA.html_button_toggle_visibility_close; // Always add config button html += DATA.html_button_config; // Insert buttons using domain-specific method menu_element.insertAdjacentHTML(DATA.menu_insert, html); // Add event listeners document.getElementById("button_config")?.addEventListener("click", () => get_config()?.open()); document.getElementById("button_toggle_visibility")?.addEventListener("click", toggle_visibility); // Remove empty
    tags (giveaway.su specific) if (CURRENT_DOMAIN === "giveaway.su") { const empty_links = menu_element.querySelectorAll('a'); empty_links.forEach(a => { if (!a.textContent.trim()) a.remove(); }); } }); } function toggle_visibility() { const btn = document.getElementById("button_toggle_visibility"); const icon = btn.querySelector("i"); const text = btn.querySelector("span"); icon.classList.toggle("glyphicon-eye-open"); icon.classList.toggle("glyphicon-eye-close"); text.textContent = text.textContent == "Show hidden" ? "Hide hidden" : "Show hidden"; let hidden = document.querySelectorAll(".gray-out-item"); hidden.forEach(el => el.classList.toggle("hide-item")); } function hide_ads() { const elements = document.querySelectorAll(DATA.sele_ads); elements.forEach(ad => { const parent = ad.closest('.col-md-4.col-sm-6'); parent ? parent.remove() : ad.remove(); }); } function hide_item_buttons() { const items = document.querySelectorAll(DATA.sele_giveaway_card); const eye_button = `
    `; items.forEach((item) => { if (!item.parentNode.classList.contains("gray-out-item")) { item.parentNode.insertAdjacentHTML('afterbegin', eye_button); item.parentNode.querySelector(".eye-container").addEventListener("click", add_to_hidden, false); } }); } function add_to_hidden(event) { let item = event.target; // Get the item while(item.classList.value !== "col-md-4 col-sm-6") // Go up till you reach the item item = item.parentNode; item.querySelector(".eye-container")?.remove(); let href_and_title = get_event_href_and_title(item); get_config().set("items_to_hide", get_prepared_items_to_hide(href_and_title)); // Override old list if(get_field("hide_items_from_list_by_default")) item.classList.add("gray-out-item"); if(get_field("instant_hide")) item.classList.add("hide-item"); get_config().save(); } function get_event_href_and_title(event) { return `${event.querySelector(DATA.sele_giveaway_card).pathname} - ${event.querySelector(DATA.sele_giveaway_title).innerText}`; } function get_event_href(event) { return `${event.querySelector(DATA.sele_giveaway_card).pathname}`; } function get_prepared_items_to_hide(new_title = null) { let items_to_hide = get_field("items_to_hide") || ""; // Add new title if provided if (new_title) items_to_hide += `\n${new_title.trim()}`; // Process the items string items_to_hide = items_to_hide .replace(/^\s*$(?:\r\n?|\n)/gm, "") // Remove blank lines .split('\n') // Split into array .map(line => trim_spaces(line)) // Trim each line .filter(line => line !== "") // Remove empty lines .filter((line, index, self) => // Remove duplicates self.indexOf(line) === index ) .sort(sort_alphabetically) // Sort alphabetically .join('\n'); // Join back to string return items_to_hide; } function hide_items() { let hidden_items = get_hidden_items_array(); let events = document.querySelectorAll(DATA.sele_giveaway_container); // Get all items in store events.forEach(function(event) { if(event.querySelector(DATA.sele_ads) === null) { let href = get_event_href(event); if(hidden_items.includes(href)) { event.classList.add("gray-out-item"); if(get_field("hide_items_from_list_by_default")) event.classList.add("hide-item"); } } }) } function get_hidden_items_array() { let hidden_items = get_field("items_to_hide").split("\n"); hidden_items = hidden_items.map(function (el) {return el.split(" - ")[0].trim();}); // Trim away the spaces hidden_items = hidden_items.filter((el) => el !== ""); // Remove all empty lines (shouldn't happen anymore, but safe is safe) return hidden_items; } function insert_task_button() { wait_for_element(DATA.sele_task_button_destination).then(async (destination) => { const button = ""; destination.innerHTML = button + destination.innerHTML; document.getElementById("k-check-tasks").addEventListener ("click", check_tasks, false); }); } function check_tasks() { let buttons = document.querySelectorAll(DATA.sele_task_buttons); buttons.forEach(button => button.click()); } function insert_giveaway_draw_time() { let countdown = document.querySelector(".event-countdown"); if(countdown) { let time = new Date(); let time_left = parseInt(countdown.getAttribute("data-timeleft")); time.setSeconds(time.getSeconds() + time_left); countdown.insertAdjacentHTML('afterend', `
    Giveaway will be drawn on: ${format_date_time(time)}
    `); } } function format_date_time(time) { let date = time.getDate() >= 10 ? time.getDate() : '0'+time.getDate(); let month = time.getMonth() >= 10 ? time.getMonth() : '0'+time.getMonth(); let full_year = time.getFullYear(); let hours = time.getHours() >= 10 ? time.getHours() : '0'+time.getHours(); let minutes = time.getMinutes() >= 10 ? time.getMinutes() : '0'+time.getMinutes(); let formated_date = `${date}.${month}.${full_year} - ${hours}:${(minutes)}`; return formated_date } GM_addStyle(` .event_countdown { text-align: center; font-size: 18px; margin-top: 20px; } .event_countdown > span { font-weight: bold; } .eye-container { position: absolute; right: 0; padding: 10px; height: 40px; width: 40px; } .gray-out-item {filter: saturate(0%)} .hide-item {display: none !important} `);