SteamGifts.com Giveaway Entry

Easily enter all visible giveaways. Pairs well with ESGST (https://github.com/rafaelgssa/esgst)

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name            SteamGifts.com Giveaway Entry
// @version         1.0.4
// @author          Dillon Regimbal
// @namespace       https://dillonr.com
// @description     Easily enter all visible giveaways. Pairs well with ESGST (https://github.com/rafaelgssa/esgst)
// @match           *://www.steamgifts.com/*
// @match           *://steamgifts.com/*
// @run-at          document-idle
// @grant           GM_addStyle
// @grant           GM_xmlhttpRequest
// @icon            https://store.steampowered.com/favicon.ico
// @noframes
// ==/UserScript==
// Since 2020-05-21
// https://greasyfork.org/en/scripts/403895-steamgifts-com-giveaway-entry
// https://github.com/dregimbal/UserScripts/blob/master/SteamGiveawayEntry.user.js

(function () {
    'use strict'

    // #region Config

    let giveaway_selector = 'div.giveaway__row-outer-wrap:not(.esgst-hidden) a.giveaway__heading__name'
    let no_giveaways_text = 'Find Giveaways!'
    let button_background_colour = '#4F7A26'
    let button_foreground_colour = '#FFFFFF'
    let button_font_size = '18px'

    // The delay in milliseconds between each giveaway entry
    // Setting it too low may cause SteamGifts to give you a soft-ban of a few days
    let entry_submission_delay_ms = 200

    // Whether the script should click the ESGST "Enter" buttons to enter the giveaways
    let esgst_entry_style = false

    // If the script should click the ESGST "Refresh all pages" button after entering the giveaways
    let esgst_refresh_pages_after_entry = false

    // If the script should attempt to close the ESGST modals after entering the giveaways
    let esgst_close_modals_after_entry = false

    let esgst_submit_button_selector = '.esgst-elgb-button .form__submit-button'
    let esgst_refresh_button_id = 'esgst-esRefreshAll'
    let esgst_modal_close_button_selector = '.esgst-popup-close'

    // #endregion

    // #region Styles

    let fira_code = window.document.createElement('link')
    fira_code.rel = 'stylesheet'
    fira_code.type = 'text/css'
    fira_code.href = 'https://cdn.jsdelivr.net/gh/tonsky/FiraCode@4/distr/fira_code.css'
    document.getElementsByTagName('HEAD')[0].appendChild(fira_code)

    GM_addStyle(`
        code { font-family: 'Fira Code', monospace; }
        @supports (font-variation-settings: normal) {
            code { font-family: 'Fira Code VF', monospace; }
        }
        @keyframes show {
            from {opacity: 0;}
            to {opacity: 1;}
        }
        @keyframes hide {
            from {opacity: 1;}
            to {opacity: 0;}
        }
        #enterAllBtn {
            background-color: ${button_background_colour};
            position: fixed;
            left: 20px;
            bottom: 20px;
            z-index: 69;
            border-radius: 2px;
            padding: 5px 10px;
            display: inline-block;
            cursor: pointer;
            text-align: center;
            visibility: hidden;
            opacity: 0;
        }
        #enterAllBtn a {
            font-family: 'Fira Code';
            text-decoration: none !important;
            cursor: pointer;
            color: ${button_foreground_colour} !important;
            font-size: ${button_font_size};
            font-weight: 400;
        }
        #enterAllBtn.visible {
            visibility: visible !important;
            animation-name: show;
            animation-delay: 1s;
            animation-duration: 2s;
            animation-iteration-count: 1;
            animation-timing-function: ease-in-out;
            animation-fill-mode: forwards;
        }
        `)

    // #endregion

    // #region Global variables

    // ESGST "Enter" buttons
    let esgst_Giveaways = []

    // Giveaway IDS to enter
    let giveawayIDs = []

    // Points that can be used to enter giveaways
    // Updates when a request to SteamGifts is made
    let entryPoints = 400

    // #endregion

    function enterGiveaway() {
        if (giveawayIDs.length > 0) {
            GM_xmlhttpRequest(
                {
                    method: 'POST',
                    url: 'https://www.steamgifts.com/ajax.php',
                    data: `xsrf_token=${document.getElementsByName('xsrf_token')[0].value}&do=entry_insert&code=${giveawayIDs.pop()}`,
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    },
                    onload: function (response) {
                        let e = JSON.parse(response.responseText)
                        if (typeof e.points !== 'undefined') {
                            entryPoints = e.points
                        }
                        if (e.type === 'success') {
                            enterBtnA.textContent = `Entry Count: ${e.entry_count}, Points: ${e.points}`
                        } else {
                            console.warn(e)
                        }

                        if (giveawayIDs.length <= 0) {
                            // All giveaways entered
                            enterBtnA.textContent = no_giveaways_text
                            finishedEnteringGiveaways()
                        } else if (entryPoints <= 0) {
                            // No more points
                            enterBtnA.textContent = `You have ${entryPoints} points`
                            finishedEnteringGiveaways()
                        } else {
                            // Continue entering giveaways
                            setTimeout(enterGiveaway, entry_submission_delay_ms)
                        }
                    }
                })
        } else {
            console.warn('Trying to enter a giveaway, but there are none to enter')
        }
    }

    function finishedEnteringGiveaways() {
        if (esgst_refresh_pages_after_entry) {
            document.getElementById(esgst_refresh_button_id).click()
        }
        if (esgst_close_modals_after_entry) {
            setTimeout(esgst_ClearModal, 300)
        }
    }

    function esgst_FindGiveaways() {
        esgst_Giveaways = []
        document.querySelectorAll(esgst_submit_button_selector)
            .forEach(giveaway => {
                esgst_Giveaways.push(giveaway)
            })

        enterBtnA.textContent = `Enter ${esgst_Giveaways.length} Giveaways!`
    }

    function esgst_SubmitGiveaway() {
        if (esgst_Giveaways.length > 0) {
            enterBtnA.textContent = `${esgst_Giveaways.length} Giveaways Remaining!`
            let giveaway = esgst_Giveaways.pop()
            giveaway.click()
            // Continue entering giveaways
            setTimeout(esgst_SubmitGiveaway, entry_submission_delay_ms)
        } else {
            enterBtnA.textContent = no_giveaways_text
            finishedEnteringGiveaways()
        }
    }

    function esgst_ClearModal() {
        document.querySelectorAll(esgst_modal_close_button_selector)
            .forEach(closeButton => {
                closeButton.click()
            })
    }

    function submitGiveaways() {
        divButton.removeEventListener('click', submitGiveaways)
        divButton.addEventListener('click', findGiveaways)
        if (esgst_entry_style) {
            enterBtnA.textContent = `Entering ${esgst_Giveaways.length} Giveaways!`
            esgst_SubmitGiveaway()
        } else {
            enterBtnA.textContent = `Entering ${giveawayIDs.length} Giveaways!`
            enterGiveaway()
        }
    }

    function findGiveaways() {
        if (esgst_entry_style) {
            esgst_FindGiveaways()
        } else {
            giveawayIDs = []
            document.querySelectorAll(giveaway_selector)
                .forEach(giveaway => {
                    let id = giveaway.href.replace('https://www.steamgifts.com', '').replace('/giveaway/', '').split('/')[0]
                    if (!giveawayIDs.includes(id)) {
                        giveawayIDs.push(id)
                    }
                })

            enterBtnA.textContent = `Enter ${giveawayIDs.length} Giveaways!`
        }
        divButton.removeEventListener('click', findGiveaways)
        divButton.addEventListener('click', submitGiveaways)
    }

    let divButton = document.createElement('div')
    divButton.id = 'enterAllBtn'

    let enterBtnA = document.createElement('a')
    enterBtnA.setAttribute('onclick', 'return false;')
    enterBtnA.textContent = no_giveaways_text

    divButton.appendChild(enterBtnA)
    document.body.appendChild(divButton)
    divButton.addEventListener('click', findGiveaways)
    setTimeout(() => {
        divButton.classList.add('visible')
    }, 3000)
}())