Schedule to ICS

Convert schedule to ICS

// ==UserScript==
// @license MIT
// @name         Schedule to ICS
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Convert schedule to ICS
// @author       Nwakey
// @match        https://dutgs.dlut.edu.cn/pyxx/pygl/kbcx_xs.aspx?xh=*
// @match        https://dutgs.dlut.edu.cn/pyxx/default.aspx?u=cas
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const startDate = new Date('2025-02-24'); // 第一周的开始日期

    const timeMap = {
        '1': { start: '08:00', end: '08:45' },
        '2': { start: '08:50', end: '09:35' },
        '3': { start: '10:05', end: '10:50' },
        '4': { start: '10:55', end: '11:40' },
        '5': { start: '13:30', end: '14:15' },
        '6': { start: '14:20', end: '15:05' },
        '7': { start: '15:35', end: '16:20' },
        '8': { start: '16:25', end: '17:10' },
        '9': { start: '18:00', end: '18:45' },
        '10': { start: '18:55', end: '19:40' },
        '11': { start: '19:50', end: '20:35' },
        '12': { start: '20:45', end: '21:30' }
    };

    function getWeekdayOffset(day) {
        const dayMap = {
            '星期一': 0,
            '星期二': 1,
            '星期三': 2,
            '星期四': 3,
            '星期五': 4,
            '星期六': 5,
            '星期日': 6
        };
        return dayMap[day];
    }

    function getEventDate(week, day) {
        const offset = (week - 1) * 7 + getWeekdayOffset(day);
        const eventDate = new Date(startDate);
        eventDate.setDate(startDate.getDate() + offset);
        return eventDate;
    }

    function formatDate(date, time) {
        return `${date.getFullYear()}${(date.getMonth() + 1).toString().padStart(2, '0')}${date.getDate().toString().padStart(2, '0')}T${time.replace(':', '')}00`;
    }

    function extractSchedule() {
        console.log('Extracting schedule...');
        const schedule = [];
        const courseSet = new Set(); // 用于存储已添加的课程信息
        const rows = document.querySelectorAll('#MainWork_DataGrid1 tr');
        rows.forEach((row, rowIndex) => {
            if (rowIndex === 0) return; // 跳过表头行
            const cells = row.querySelectorAll('td');
            cells.forEach((cell, cellIndex) => {
                if (cellIndex < 2 || !cell.innerHTML.trim()) return; // 跳过非课表单元格
                const courseInfos = cell.innerHTML.split('<br><br>'); // 分割多个课程信息
                courseInfos.forEach(courseInfoStr => {
                    const courseInfo = courseInfoStr.split('<br>');
                    if (courseInfo.length < 5) return; // 确保包含足够的课程信息
                    const weeks = courseInfo[3].match(/(\d+)-(\d+)周/);
                    const dayTimeMatches = courseInfo[3].match(/星期(.) (上|下)(\d+),(\d+)/g);
                    const locationMatch = courseInfo[2].match(/\((.*)\)/);
                    if (!weeks || !dayTimeMatches || !locationMatch) return;
                    const startWeek = parseInt(weeks[1]);
                    const endWeek = parseInt(weeks[2]);
                    dayTimeMatches.forEach(dayTime => {
                        const dayTimeMatch = dayTime.match(/星期(.) (上|下)(\d+),(\d+)/);
                        const day = `星期${dayTimeMatch[1]}`;
                        const times = [dayTimeMatch[3], dayTimeMatch[4]];
                        const course = {
                            name: courseInfo[0].replace('课程:', '').trim(),
                            class: courseInfo[1].replace('班级:', '').trim(),
                            location: locationMatch[1].trim(),
                            teacher: courseInfo[4].replace('主讲教师:', '').trim(),
                            startWeek,
                            endWeek,
                            day,
                            times
                        };
                        const courseKey = `${course.name}-${course.class}-${course.location}-${course.teacher}-${course.startWeek}-${course.endWeek}-${course.day}-${course.times.join(',')}`;
                        if (!courseSet.has(courseKey)) {
                            console.log('Extracted course:', course);
                            schedule.push(course);
                            courseSet.add(courseKey);
                        }
                    });
                });
            });
        });
        console.log('Schedule extraction complete:', schedule);
        return schedule;
    }
    function convertToICS(schedule) {
        console.log('Converting schedule to ICS...');
        let icsContent = 'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//Nwakey//Schedule to ICS//EN\n';
        schedule.forEach(event => {
            let replacedLocation = event.location.replace(/研教楼/g, '研究生教育大楼');
            for (let week = event.startWeek; week <= event.endWeek; week++) {
                const eventDate = getEventDate(week, event.day);
                const startTime = timeMap[event.times[0]].start;
                const endTime = timeMap[event.times[event.times.length - 1]].end;
                icsContent += 'BEGIN:VEVENT\n';
                icsContent += `SUMMARY:${event.name}\n`;
                icsContent += `LOCATION:大连理工大学\\,${replacedLocation}\n`;
                icsContent += `DESCRIPTION:Class ${event.class} Teacher: ${event.teacher}\n`;
                icsContent += `DTSTART:${formatDate(eventDate, startTime)}\n`;
                icsContent += `DTEND:${formatDate(eventDate, endTime)}\n`;
                icsContent += 'END:VEVENT\n';
                console.log('Added event to ICS:', event);
            }
        });
        icsContent += 'END:VCALENDAR';
        console.log('ICS conversion complete.');
        return icsContent;
    }

    function downloadICS(icsContent) {
        console.log('Downloading ICS file...');
        const blob = new Blob([icsContent], { type: 'text/calendar' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'schedule.ics';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        console.log('ICS file downloaded.');
    }

    function addButton() {
        const button = document.createElement('button');
        button.innerText = '下载 ICS 文件';
        button.style.position = 'fixed';
        button.style.top = '10px';
        button.style.right = '10px';
        button.style.zIndex = 1000;
        button.onclick = () => {
            console.log('Button clicked. Extracting schedule...');
            const schedule = extractSchedule();
            console.log('Converting schedule to ICS...');
            const icsContent = convertToICS(schedule);
            console.log('Downloading ICS file...');
            downloadICS(icsContent);
        };
        document.body.appendChild(button);
        console.log('Button added to the page.');
    }

    addButton();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址