Simgrid ICS export

Provided as-is, no future support :>

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Simgrid ICS export
// @version      2025-01-28
// @license      MIT
// @namespace    ap-simgrid-ics-export
// @description  Provided as-is, no future support :>
// @author       Arsen Petrosian
// @match        https://www.thesimgrid.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=thesimgrid.com
// @require      https://cdn.jsdelivr.net/npm/[email protected]/ics.deps.min.js
// @grant        GM_openInTab
// @run-at       document-end
// ==/UserScript==

(function() {
    let createdButton = null;

    Date.prototype.addMinutes = function(m) {
        this.setTime(this.getTime() + (m*60*1000));
        return this;
    }

    function exportIcs() {
        const url = document.location.href
        const title = document.querySelector('h1').textContent.trim()

        const cal = ics();
        const races = document.querySelectorAll('.event-block')
        for(const race of races) {
            const dataItems = race.querySelectorAll('[aria-labelledby="information-tab"] .list-group-item')

            const track = [...dataItems].find(item => item.querySelector('dt').innerText.trim().toLowerCase() === 'track')
            const trackName = track ? track.querySelector('dd').innerText.trim() : ''

            const duration = [...dataItems].find(item => item.querySelector('dt').innerText.trim().toLowerCase() === 'duration')
            const durationMins = duration ? duration.querySelector('dd').innerText.trim().split(' ')[0] : ''

            const raceName = race.querySelector('h4').textContent.trim().toUpperCase()
            const time = race.querySelector('time').attributes.datetime.value
            const endTime = (new Date(time)).addMinutes(durationMins ? (+durationMins + 60) : 180)
            cal.addEvent(`${trackName || raceName} | ${title}`, `${raceName} ${url}`, '', time, endTime.toISOString());
        }
        cal.download();
        GM_openInTab ('https://calendar.google.com/calendar/r/settings/export', { active: true });
    }

    function triggerRecheck() {
        console.log(document.querySelector('meta[property="og:url"]').attributes.content.value, window.location.href)
        if (window.location.href.includes('/races')) {
            if (!createdButton) {
                createdButton = document.createElement('li');
                createdButton.className = 'nav-item';
                createdButton.innerHTML = `<a class="nav-link " href="#">Export .ics</a>`
                setTimeout(() => {
                    document.querySelector('.nav').appendChild(createdButton);
                }, 1000) // Yes, I don't care


                createdButton.addEventListener('click', async (e) => {
                    e.preventDefault()
                    exportIcs();
                });
            }
        } else {
            if (createdButton) {
                createdButton.removeEventListener
                createdButton.remove();
                createdButton = null;
            }
        }
    }

    new MutationObserver(triggerRecheck)
        .observe(
        document.querySelector('head'), {
            attributes: true, childList: true, subtree: true
        }
    );

    triggerRecheck();
})()