您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a button to export When2Meet availability data as CSV
// ==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); }); })();