When2Meet CSV Exporter

Add a button to export When2Meet availability data as CSV

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         When2Meet CSV Exporter
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Add a button to export When2Meet availability data as CSV
// @author       Tyler Bletsch
// @match        https://www.when2meet.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

/* reverse engineering notes:

Here are the important global variables kept by when2meet:

The strings of people names:
  PeopleNames (Array): [ "Abdul", … ]

An array of slots, where each entry is an array of people IDs:
  AvailableAtSlot (Array): [ [ 115436591, 115438675, 115448517, … ], … ]

The actual time of each timeslot reffered to in AvailableAtSlot, as unix timestamps:
  TimeOfSlot (Array):  [ 1736780400, 1736781300, … ]

An array of the people ID numbers used in AvailableAtSlot, ordered in a manner correlated to PeopleNames:
  PeopleIDs (Array): [ 115660081, 115436591, … ]

The currently selected timezone:
  timezone (string): "America/New_York"

These are consumed by make_csv() below.
*/

(function () {
    'use strict';

    // Wait until the page is fully loaded
    window.addEventListener('load', () => {
        // Check if the make_csv function exists
        console.log("Export CSV button is being added...");
        function make_csv() {
            let csv = "time ("+timezone+")," + PeopleNames.join(",") + "\n";

            // Iterate through each time slot
            for (let i = 0; i < TimeOfSlot.length; i++) {
                //const time = new Date(TimeOfSlot[i] * 1000).toISOString(); // Convert UNIX timestamp to ISO string
                //const time = new Date(TimeOfSlot[i] * 1000).toISOString().replace("T", " ").split(".")[0];
                const time = new Date(TimeOfSlot[i] * 1000).toLocaleString("en-US", {
                    timeZone: timezone, // timezone is a global from when2meet
                    year: "numeric",
                    month: "2-digit",
                    day: "2-digit",
                    hour: "2-digit",
                    minute: "2-digit",
                    second: "2-digit",
                    hour12: false,
                }).replace(",", "");
                const availablePeople = new Set(AvailableAtSlot[i]); // Set of people IDs available at this time slot

                // Create a row with "o" for available people
                const row = [time];
                for (let personID of PeopleIDs) {
                    row.push(availablePeople.has(personID) ? "o" : "");
                }

                csv += row.join(",") + "\n";
            }
            return csv;
        }

        // Create the "Export CSV" button floating in the lower right of the screen
        const button = document.createElement('button');
        button.innerText = 'Tampermonkey: Export CSV';
        button.style.position = 'fixed';
        button.style.bottom = '20px';
        button.style.right = '20px';
        button.style.padding = '12px 24px';
        button.style.fontSize = '16px';
        button.style.fontWeight = 'bold';
        button.style.backgroundColor = '#007bff';
        button.style.color = '#fff';
        button.style.border = '2px solid #0056b3';
        button.style.borderRadius = '8px';
        button.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.5)';
        button.style.cursor = 'pointer';
        button.style.transition = 'all 0.2s ease';
        button.style.zIndex = '1000';

        // Add a click event to generate and download the CSV
        button.addEventListener('click', () => {
            try {
                const csv = make_csv(); // Call the make_csv() function
                const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
                const url = URL.createObjectURL(blob);

                // Create a temporary <a> element to trigger the download
                const link = document.createElement('a');
                link.href = url;
                link.download = 'when2meet_export.csv';
                link.style.display = 'none';
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);

                // Revoke the blob URL
                URL.revokeObjectURL(url);
            } catch (error) {
                console.error("Error generating CSV:", error);
                alert("Failed to generate CSV. Check the console for details.");
            }
        });

        // Add the button to the page
        document.body.appendChild(button);
    });
})();