Genshin Impact daily check-in rewards

A script to collect Genshin Impact daily check-in rewards at startup and on an open tab at a random interval after reward reset. As long as you leave a tab with the page in the on startup and in the background, it will be collected.

// ==UserScript==
// @name         Genshin Impact daily check-in rewards
// @namespace    Genshin Impact daily check-in rewards
// @version      1.9
// @description  A script to collect Genshin Impact daily check-in rewards at startup and on an open tab at a random interval after reward reset. As long as you leave a tab with the page in the on startup and in the background, it will be collected.
// @author       NoxPi
// @license      MIT
// @match        https://webstatic-sea.mihoyo.com/ys/event/signin-sea/*
// @match        https://act.hoyolab.com/ys/event/signin-sea-v3/*
// @grant        none
// @require  	 https://code.jquery.com/jquery-3.6.0.min.js#sha256=/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=
// @require      https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js#sha512=qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==

// ==/UserScript==

// Default settings
/* The time zone of when the daily rewards are refreshing */
const RESET_TIMEZONE = "+0800"; // UTC+8
/* A random second interval to make the request semi-random */
const MAX_RANDOM_SEC_SCEW = 900; // 15 minutes
/* For how long will the script will try to listen for changes this round, before waiting until next refresh interval */
const LOOK_TIME_SEC = 60; // 1 minute
/* Seconds of delay between near complete loading of the site and click */
const DELAY_CLICK_SEC = 10; // 10 seconds


// Reload the page after reward reset (Based on RESET_TIMEZONE) has passed, at random number of seconds (Based on MAX_RANDOM_SEC_SCEW).
var time_to_refresh = moment.duration(moment().utcOffset(RESET_TIMEZONE).add(1, 'day').startOf('day').diff(moment())).asMilliseconds();
setTimeout(function(){ location.reload(); }, time_to_refresh+Math.floor(Math.random() * (MAX_RANDOM_SEC_SCEW*1000)));


// On page load
$(window).on('load', function() {
    // Ensure that we have at least loaded to a certain point before proceeding
    // To be sure that the true active box is getting correctly marked
    console.log("GIDCR: Onload event triggered");

    // Options for mutationObserver
    let observer_options = {
        childList: true,
        subtree: true,
        attributes: true
    },
    // Look for elements that indicate that things are mostly loaded
    load_observer = new MutationObserver(look_for_loaded);
    load_observer.observe(document, observer_options);
    console.log("GIDCR: Starting observation")

    // Stop the MutationObserver from runnning after a set period of time
    // The refresh code below this section will refresh the page, re-running the script from the beginning.
    window.setTimeout(function(){
        console.log("GIDCR: Timeout reached. Disconnecting the observer")
        load_observer.disconnect();
    }, LOOK_TIME_SEC*1000);
});


// Callback looking for elements indicating loading (near) completion
function look_for_loaded(mutations, observer) {
    // Fetch all mutations on the whole list of rewards
    for (let mutation of mutations) {
        // Look for the the avatar icon class, which loads last and thus indicate succesful load of the contents.
        var pattern = /components\-home\-assets\-\_\_sign\-content\-test\_\-\-\-miss\-info\-\-\-/;
        if (pattern.test(mutation.target.className)) {
            // Last class have been mutated and is assumed to be loaded in
            console.log("GIDCR: Page loaded")

            // Look for an active rewards button and click it if it exist
            window.setTimeout(function(){
                // Get the "Reward history" button
                var reward = $('[class*="components-home-assets-__sign-content-test_---actived-day---"]');

                // Found an active reward button
                if (reward.length > 0) {
                    console.log("GIDCR: Clicking the reward button")

                    // Click it
                    setTimeout(function(){
                        reward.mouseover();
                        reward.click();
                    }, 2000);
                }
            }, DELAY_CLICK_SEC*1000);
        }
    }
}