Last active
April 2, 2019 07:47
-
-
Save erjiaqing/f1049583108196310f9b4dcec58d95f7 to your computer and use it in GitHub Desktop.
丢掉乱七八糟的课程表吧!No Time Table,将课表导出为日历文件!(Tampermonkey脚本)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name No Time Table | |
// @namespace http://app.ejq.me/ | |
// @version 0.0.4.1 | |
// @description Export time table as ICS file. | |
// @author EJQ | |
// @include http://210.42.121.132/servlet/Svlt_QueryStuLsn* | |
// @include http://210.42.121.133/servlet/Svlt_QueryStuLsn* | |
// @include http://210.42.121.134/servlet/Svlt_QueryStuLsn* | |
// @include http://210.42.121.241/servlet/Svlt_QueryStuLsn* | |
// @grant none | |
// @require http://code.jquery.com/jquery-1.12.4.min.js | |
// @updateURL https://gist.githubusercontent.com/erjiaqing/f1049583108196310f9b4dcec58d95f7/raw/nott.js | |
// ==/UserScript== | |
/** | |
* Copyright (C) 2017 Guo Song (Aka. erjiaqing) | |
* | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
/*/ | |
Update log: | |
0.0.4 -> 0.0.4.1: | |
[HotFix] 格式修复 | |
0.0.3 -> 0.0.4: | |
[Fix] 将上课地点存在Location域中 | |
0.0.2 -> 0.0.3: | |
[Fix] 修复部分已安排时间的课程无法显示的问题 | |
0.0.1 -> 0.0.2: | |
[Fix] 在没填写教学周的时候拒绝导出,同时导出自带update属性 | |
/*/ | |
function calcClassTime(str) | |
{ | |
var ret = []; | |
var weekDay = '日一二三四五六'; | |
var regexp1 = /周(.):(\d+)-(\d+)周,每(\d+)周;\s+(\d+)-(\d+)节(,(\d+)区,([^\s]+)){0,1}/g; | |
var regexp2 = /周(.):(\d+)-(\d+)周,每(\d+)周;\s+(\d+)-(\d+)节(,(\d+)区,([^\s]+)){0,1}/; | |
function p(hour, minute) | |
{ | |
return (hour * 3600 + minute * 60) * 1000; | |
} | |
var classStart = [p(8, 0),p(8, 50),p(9, 50),p(10, 40), | |
p(11, 30),p(14, 5),p(14, 55),p(15, 45), | |
p(16, 40),p(17, 30),p(18, 30),p(19, 20),p(20, 10)]; | |
var classEnd = [p(8, 45),p(9, 35),p(10, 35),p(11, 25), | |
p(12, 15),p(14, 50),p(15, 40),p(16, 30), | |
p(17, 25),p(18, 15),p(19, 15),p(20, 05),p(20, 55)]; | |
var m = str.match(regexp1); | |
if (m) | |
m.forEach(function (e){ | |
console.log(e); | |
var res = e.match(regexp2); | |
console.log(res); | |
ret.push({ | |
weekday: weekDay.search(res[1]), | |
start_week: Number(res[2]), | |
end_week: Number(res[3]), | |
interval: Number(res[4]), | |
class_begin: classStart[Number(res[5]) - 1], | |
class_end: classEnd[Number(res[6]) - 1], | |
area: res[8] ? Number(res[8]) : "", | |
classroom: res[9] ? res[9] : "" | |
}); | |
}); | |
return ret; | |
} | |
function processRow(r) | |
{ | |
console.log(r); | |
var ret = calcClassTime(r.children[9].children[0].innerText); | |
if (ret.length === 0) return undefined; | |
return { | |
name: r.children[1].innerText, | |
id: r.children[0].innerText, | |
note: r.children[10].innerText + "/" + r.children[5].innerText + "/" + r.children[2].innerText, | |
time: ret}; | |
} | |
function processTable() | |
{ | |
var r = $("tr"); | |
var ret = []; | |
for (var $i = 1; $i < r.length; $i++) | |
{ | |
var tmp = processRow(r[$i]); | |
if (tmp) | |
ret.push(tmp); | |
} | |
return ret; | |
} | |
function toTimeStamp(date) | |
{ | |
return date.toISOString().replace(/[\-:]/g, '').replace(/\.\d{3}/, ''); | |
} | |
function saveICS(str) | |
{ | |
function saveAs(blob, filename) { | |
var type = blob.type; | |
var force_saveable_type = 'application/octet-stream'; | |
if (type && type != force_saveable_type) { // 强制下载,而非在浏览器中打开 | |
var slice = blob.slice || blob.webkitSlice || blob.mozSlice; | |
blob = slice.call(blob, 0, blob.size, force_saveable_type); | |
} | |
var url = URL.createObjectURL(blob); | |
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a'); | |
save_link.href = url; | |
save_link.download = filename; | |
var event = document.createEvent('MouseEvents'); | |
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); | |
save_link.dispatchEvent(event); | |
URL.revokeObjectURL(url); | |
} | |
// console.log(str); | |
var bb = new Blob([str], {type: "text/plain;charset=utf-8"}); | |
saveAs(bb, 'TimeTable.ics'); | |
} | |
function processFull(currentWeek) | |
{ | |
var ret = ""; | |
var header = "BEGIN:VCALENDAR\r\n"+ | |
"VERSION:2.0\r\n"+ | |
"PRODID:-//hacksw/handcal//NONSGML v1.0//EN\r\n"; | |
var uuid_suffix = "whu_noTT@ejq.me"; | |
var res = processTable(); | |
var startWeek = new Date(); | |
// | |
var thisDay = startWeek.getDay(); | |
if (currentWeek > 0) currentWeek -= 1; | |
var shift = currentWeek * 7 * 24 * 3600 + thisDay * 24 * 3600 + startWeek.getHours() * 3600 + startWeek.getMinutes() * 60 + startWeek.getSeconds(); | |
shift *= 1000; | |
startWeek = new Date(startWeek.valueOf() - shift); | |
res.forEach(function (e) { | |
e.time.forEach(function (ti) { | |
for (var $i = ti.start_week - 1; $i < ti.end_week; $i += ti.interval) { | |
var ts = new Date(startWeek.valueOf() + ($i * 7 * 24 * 3600 + ti.weekday * 24 * 3600) * 1000 + ti.class_begin); | |
var te = new Date(ts.valueOf() + ti.class_end - ti.class_begin); | |
// console.log(ts); | |
// console.log(te); | |
ret += "BEGIN:VEVENT\r\n" + | |
"METHOD:UPDATE\r\n"+ | |
"UID:" + e.id + "_wk" + ($i + 1) + "_" + ti.weekday + "_" + ti.class_begin + "_" + ti.class_end + "@nott.ejq.me\r\n" + | |
"DTSTAMP:" + toTimeStamp(ts) + "\r\n" + | |
"DTSTART:" + toTimeStamp(ts) + "\r\n" + | |
"DTEND:" + toTimeStamp(te) + "\r\n" + | |
"SUMMARY:" + e.name + "\r\n" + | |
"LOCATION:" + ti.area + "区" + ti.classroom + "\r\n" + | |
"DESCRIPTION:" + e.note + "\r\n" + | |
"END:VEVENT\r\n"; | |
} | |
}); | |
}); | |
saveICS(header + ret + "END:VCALENDAR\r\n"); | |
return header + ret + "END:VCALENDAR\r\n"; | |
} | |
function finallyProcess() | |
{ | |
processFull(Number($("#__school_week").val())); | |
} | |
function init() | |
{ | |
$("#search").append('<input type="text" id="__school_week" placeholder="教学周">'); | |
$("#search").append('<input type="button" id="exportICS" class="searchBtb" name="export" value="导出ics">'); | |
$("#exportICS").on("click", finallyProcess); | |
} | |
init(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
function finallyProcess()
{
var tmp = Number($("#__school_week").val());
if(tmp > 0){
processFull(tmp);
}else{
alert("请输入正确的当前的教学周");
}
}