Created
September 22, 2019 04:24
-
-
Save getjump/a9864aef2f6ae9b309e5997e2c9c878f to your computer and use it in GitHub Desktop.
Экспортирует расписание с личного кабинета ДВФУ в iCal для дальнейшего импорта например в Google Calendar
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
// ЗАПУСКАТЬ ОТСЮДА: https://univer.dvfu.ru/schedule | |
// Проверено на работоспособность в Firefox | |
// Копировать в консоль, сохранить файл, импортировать например в Google Calendar | |
(async function() { | |
var semesterStart = '2019-09-23'; | |
var semesterEnd = '2020-01-03'; | |
// Function to download data to a file | |
function download(data, filename, type) { | |
var file = new Blob([data], {type: type}); | |
if (window.navigator.msSaveOrOpenBlob) // IE10+ | |
window.navigator.msSaveOrOpenBlob(file, filename); | |
else { // Others | |
var a = document.createElement("a"), | |
url = URL.createObjectURL(file); | |
a.href = url; | |
a.download = filename; | |
document.body.appendChild(a); | |
a.click(); | |
setTimeout(function() { | |
document.body.removeChild(a); | |
window.URL.revokeObjectURL(url); | |
}, 0); | |
} | |
} | |
function getWeekNumber(d) { | |
// Copy date so don't modify original | |
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate())); | |
// Set to nearest Thursday: current date + 4 - current day number | |
// Make Sunday's day number 7 | |
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7)); | |
// Get first day of year | |
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1)); | |
// Calculate full weeks to nearest Thursday | |
var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7); | |
// Return array of year and week number | |
return [d.getUTCFullYear(), weekNo]; | |
} | |
function dynamicallyLoadScript(content) { | |
var script = document.createElement("script"); // create a script DOM node | |
script.type = 'text/javascript'; | |
script.textContent = content; | |
document.head.appendChild(script); // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead) | |
} | |
dynamicallyLoadScript(atob('dmFyIHNhdmVBcz1zYXZlQXN8fGZ1bmN0aW9uKGUpeyJ1c2Ugc3RyaWN0IjtpZih0eXBlb2YgZT09PSJ1bmRlZmluZWQifHx0eXBlb2YgbmF2aWdhdG9yIT09InVuZGVmaW5lZCImJi9NU0lFIFsxLTldXC4vLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpe3JldHVybn12YXIgdD1lLmRvY3VtZW50LG49ZnVuY3Rpb24oKXtyZXR1cm4gZS5VUkx8fGUud2Via2l0VVJMfHxlfSxyPXQuY3JlYXRlRWxlbWVudE5TKCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiwiYSIpLG89ImRvd25sb2FkImluIHIsYT1mdW5jdGlvbihlKXt2YXIgdD1uZXcgTW91c2VFdmVudCgiY2xpY2siKTtlLmRpc3BhdGNoRXZlbnQodCl9LGk9L2NvbnN0cnVjdG9yL2kudGVzdChlLkhUTUxFbGVtZW50KXx8ZS5zYWZhcmksZj0vQ3JpT1NcL1tcZF0rLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpLHU9ZnVuY3Rpb24odCl7KGUuc2V0SW1tZWRpYXRlfHxlLnNldFRpbWVvdXQpKGZ1bmN0aW9uKCl7dGhyb3cgdH0sMCl9LHM9ImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSIsZD0xZTMqNDAsYz1mdW5jdGlvbihlKXt2YXIgdD1mdW5jdGlvbigpe2lmKHR5cGVvZiBlPT09InN0cmluZyIpe24oKS5yZXZva2VPYmplY3RVUkwoZSl9ZWxzZXtlLnJlbW92ZSgpfX07c2V0VGltZW91dCh0LGQpfSxsPWZ1bmN0aW9uKGUsdCxuKXt0PVtdLmNvbmNhdCh0KTt2YXIgcj10Lmxlbmd0aDt3aGlsZShyLS0pe3ZhciBvPWVbIm9uIit0W3JdXTtpZih0eXBlb2Ygbz09PSJmdW5jdGlvbiIpe3RyeXtvLmNhbGwoZSxufHxlKX1jYXRjaChhKXt1KGEpfX19fSxwPWZ1bmN0aW9uKGUpe2lmKC9eXHMqKD86dGV4dFwvXFMqfGFwcGxpY2F0aW9uXC94bWx8XFMqXC9cUypcK3htbClccyo7LipjaGFyc2V0XHMqPVxzKnV0Zi04L2kudGVzdChlLnR5cGUpKXtyZXR1cm4gbmV3IEJsb2IoW1N0cmluZy5mcm9tQ2hhckNvZGUoNjUyNzkpLGVdLHt0eXBlOmUudHlwZX0pfXJldHVybiBlfSx2PWZ1bmN0aW9uKHQsdSxkKXtpZighZCl7dD1wKHQpfXZhciB2PXRoaXMsdz10LnR5cGUsbT13PT09cyx5LGg9ZnVuY3Rpb24oKXtsKHYsIndyaXRlc3RhcnQgcHJvZ3Jlc3Mgd3JpdGUgd3JpdGVlbmQiLnNwbGl0KCIgIikpfSxTPWZ1bmN0aW9uKCl7aWYoKGZ8fG0mJmkpJiZlLkZpbGVSZWFkZXIpe3ZhciByPW5ldyBGaWxlUmVhZGVyO3Iub25sb2FkZW5kPWZ1bmN0aW9uKCl7dmFyIHQ9Zj9yLnJlc3VsdDpyLnJlc3VsdC5yZXBsYWNlKC9eZGF0YTpbXjtdKjsvLCJkYXRhOmF0dGFjaG1lbnQvZmlsZTsiKTt2YXIgbj1lLm9wZW4odCwiX2JsYW5rIik7aWYoIW4pZS5sb2NhdGlvbi5ocmVmPXQ7dD11bmRlZmluZWQ7di5yZWFkeVN0YXRlPXYuRE9ORTtoKCl9O3IucmVhZEFzRGF0YVVSTCh0KTt2LnJlYWR5U3RhdGU9di5JTklUO3JldHVybn1pZigheSl7eT1uKCkuY3JlYXRlT2JqZWN0VVJMKHQpfWlmKG0pe2UubG9jYXRpb24uaHJlZj15fWVsc2V7dmFyIG89ZS5vcGVuKHksIl9ibGFuayIpO2lmKCFvKXtlLmxvY2F0aW9uLmhyZWY9eX19di5yZWFkeVN0YXRlPXYuRE9ORTtoKCk7Yyh5KX07di5yZWFkeVN0YXRlPXYuSU5JVDtpZihvKXt5PW4oKS5jcmVhdGVPYmplY3RVUkwodCk7c2V0VGltZW91dChmdW5jdGlvbigpe3IuaHJlZj15O3IuZG93bmxvYWQ9dTthKHIpO2goKTtjKHkpO3YucmVhZHlTdGF0ZT12LkRPTkV9KTtyZXR1cm59UygpfSx3PXYucHJvdG90eXBlLG09ZnVuY3Rpb24oZSx0LG4pe3JldHVybiBuZXcgdihlLHR8fGUubmFtZXx8ImRvd25sb2FkIixuKX07aWYodHlwZW9mIG5hdmlnYXRvciE9PSJ1bmRlZmluZWQiJiZuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYil7cmV0dXJuIGZ1bmN0aW9uKGUsdCxuKXt0PXR8fGUubmFtZXx8ImRvd25sb2FkIjtpZighbil7ZT1wKGUpfXJldHVybiBuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYihlLHQpfX13LmFib3J0PWZ1bmN0aW9uKCl7fTt3LnJlYWR5U3RhdGU9dy5JTklUPTA7dy5XUklUSU5HPTE7dy5ET05FPTI7dy5lcnJvcj13Lm9ud3JpdGVzdGFydD13Lm9ucHJvZ3Jlc3M9dy5vbndyaXRlPXcub25hYm9ydD13Lm9uZXJyb3I9dy5vbndyaXRlZW5kPW51bGw7cmV0dXJuIG19KHR5cGVvZiBzZWxmIT09InVuZGVmaW5lZCImJnNlbGZ8fHR5cGVvZiB3aW5kb3chPT0idW5kZWZpbmVkIiYmd2luZG93fHx0aGlzLmNvbnRlbnQpO2lmKHR5cGVvZiBtb2R1bGUhPT0idW5kZWZpbmVkIiYmbW9kdWxlLmV4cG9ydHMpe21vZHVsZS5leHBvcnRzLnNhdmVBcz1zYXZlQXN9ZWxzZSBpZih0eXBlb2YgZGVmaW5lIT09InVuZGVmaW5lZCImJmRlZmluZSE9PW51bGwmJmRlZmluZS5hbWQhPT1udWxsKXtkZWZpbmUoIkZpbGVTYXZlci5qcyIsZnVuY3Rpb24oKXtyZXR1cm4gc2F2ZUFzfSl9LyohIGljcy5qcyBXZWQgU2VwdCAxNCAyMDE3ICovCnZhciBpY3M9ZnVuY3Rpb24oZSx0KXsidXNlIHN0cmljdCI7e2lmKCEobmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCJNU0lFIik+LTEmJi0xPT1uYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoIk1TSUUgMTAiKSkpe3ZvaWQgMD09PWUmJihlPSJkZWZhdWx0Iiksdm9pZCAwPT09dCYmKHQ9IkNhbGVuZGFyIik7dmFyIHI9LTEhPT1uYXZpZ2F0b3IuYXBwVmVyc2lvbi5pbmRleE9mKCJXaW4iKT8iXHJcbiI6IlxuIixuPVtdLGk9WyJCRUdJTjpWQ0FMRU5EQVIiLCJQUk9ESUQ6Iit0LCJWRVJTSU9OOjIuMCJdLmpvaW4ociksbz1yKyJFTkQ6VkNBTEVOREFSIixhPVsiU1UiLCJNTyIsIlRVIiwiV0UiLCJUSCIsIkZSIiwiU0EiXTtyZXR1cm57ZXZlbnRzOmZ1bmN0aW9uKCl7cmV0dXJuIG59LGNhbGVuZGFyOmZ1bmN0aW9uKCl7cmV0dXJuIGkrcituLmpvaW4ocikrb30sYWRkRXZlbnQ6ZnVuY3Rpb24odCxpLG8sbCx1LHMpe2lmKHZvaWQgMD09PXR8fHZvaWQgMD09PWl8fHZvaWQgMD09PW98fHZvaWQgMD09PWx8fHZvaWQgMD09PXUpcmV0dXJuITE7aWYocyYmIXMucnJ1bGUpe2lmKCJZRUFSTFkiIT09cy5mcmVxJiYiTU9OVEhMWSIhPT1zLmZyZXEmJiJXRUVLTFkiIT09cy5mcmVxJiYiREFJTFkiIT09cy5mcmVxKXRocm93IlJlY3VycmVuY2UgcnJ1bGUgZnJlcXVlbmN5IG11c3QgYmUgcHJvdmlkZWQgYW5kIGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nOiAnWUVBUkxZJywgJ01PTlRITFknLCAnV0VFS0xZJywgb3IgJ0RBSUxZJyI7aWYocy51bnRpbCYmaXNOYU4oRGF0ZS5wYXJzZShzLnVudGlsKSkpdGhyb3ciUmVjdXJyZW5jZSBycnVsZSAndW50aWwnIG11c3QgYmUgYSB2YWxpZCBkYXRlIHN0cmluZyI7aWYocy5pbnRlcnZhbCYmaXNOYU4ocGFyc2VJbnQocy5pbnRlcnZhbCkpKXRocm93IlJlY3VycmVuY2UgcnJ1bGUgJ2ludGVydmFsJyBtdXN0IGJlIGFuIGludGVnZXIiO2lmKHMuY291bnQmJmlzTmFOKHBhcnNlSW50KHMuY291bnQpKSl0aHJvdyJSZWN1cnJlbmNlIHJydWxlICdjb3VudCcgbXVzdCBiZSBhbiBpbnRlZ2VyIjtpZih2b2lkIDAhPT1zLmJ5ZGF5KXtpZigiW29iamVjdCBBcnJheV0iIT09T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHMuYnlkYXkpKXRocm93IlJlY3VycmVuY2UgcnJ1bGUgJ2J5ZGF5JyBtdXN0IGJlIGFuIGFycmF5IjtpZihzLmJ5ZGF5Lmxlbmd0aD43KXRocm93IlJlY3VycmVuY2UgcnJ1bGUgJ2J5ZGF5JyBhcnJheSBtdXN0IG5vdCBiZSBsb25nZXIgdGhhbiB0aGUgNyBkYXlzIGluIGEgd2VlayI7cy5ieWRheT1zLmJ5ZGF5LmZpbHRlcihmdW5jdGlvbihlLHQpe3JldHVybiBzLmJ5ZGF5LmluZGV4T2YoZSk9PXR9KTtmb3IodmFyIGMgaW4gcy5ieWRheSlpZihhLmluZGV4T2Yocy5ieWRheVtjXSk8MCl0aHJvdyJSZWN1cnJlbmNlIHJydWxlICdieWRheScgdmFsdWVzIG11c3QgaW5jbHVkZSBvbmx5IHRoZSBmb2xsb3dpbmc6ICdTVScsICdNTycsICdUVScsICdXRScsICdUSCcsICdGUicsICdTQScifX12YXIgZz1uZXcgRGF0ZShsKSxkPW5ldyBEYXRlKHUpLGY9bmV3IERhdGUsUz0oIjAwMDAiK2cuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpKS5zbGljZSgtNCksRT0oIjAwIisoZy5nZXRNb250aCgpKzEpLnRvU3RyaW5nKCkpLnNsaWNlKC0yKSx2PSgiMDAiK2cuZ2V0RGF0ZSgpLnRvU3RyaW5nKCkpLnNsaWNlKC0yKSx5PSgiMDAiK2cuZ2V0SG91cnMoKS50b1N0cmluZygpKS5zbGljZSgtMiksQT0oIjAwIitnLmdldE1pbnV0ZXMoKS50b1N0cmluZygpKS5zbGljZSgtMiksVD0oIjAwIitnLmdldFNlY29uZHMoKS50b1N0cmluZygpKS5zbGljZSgtMiksYj0oIjAwMDAiK2QuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpKS5zbGljZSgtNCksRD0oIjAwIisoZC5nZXRNb250aCgpKzEpLnRvU3RyaW5nKCkpLnNsaWNlKC0yKSxOPSgiMDAiK2QuZ2V0RGF0ZSgpLnRvU3RyaW5nKCkpLnNsaWNlKC0yKSxoPSgiMDAiK2QuZ2V0SG91cnMoKS50b1N0cmluZygpKS5zbGljZSgtMiksST0oIjAwIitkLmdldE1pbnV0ZXMoKS50b1N0cmluZygpKS5zbGljZSgtMiksUj0oIjAwIitkLmdldE1pbnV0ZXMoKS50b1N0cmluZygpKS5zbGljZSgtMiksTT0oIjAwMDAiK2YuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpKS5zbGljZSgtNCksdz0oIjAwIisoZi5nZXRNb250aCgpKzEpLnRvU3RyaW5nKCkpLnNsaWNlKC0yKSxMPSgiMDAiK2YuZ2V0RGF0ZSgpLnRvU3RyaW5nKCkpLnNsaWNlKC0yKSxPPSgiMDAiK2YuZ2V0SG91cnMoKS50b1N0cmluZygpKS5zbGljZSgtMikscD0oIjAwIitmLmdldE1pbnV0ZXMoKS50b1N0cmluZygpKS5zbGljZSgtMiksWT0oIjAwIitmLmdldE1pbnV0ZXMoKS50b1N0cmluZygpKS5zbGljZSgtMiksVT0iIixWPSIiO3krQStUK2grSStSIT0wJiYoVT0iVCIreStBK1QsVj0iVCIraCtJK1IpO3ZhciBCLEM9UytFK3YrVSxqPWIrRCtOK1YsbT1NK3crTCsoIlQiK08rcCtZKTtpZihzKWlmKHMucnJ1bGUpQj1zLnJydWxlO2Vsc2V7aWYoQj0icnJ1bGU6RlJFUT0iK3MuZnJlcSxzLnVudGlsKXt2YXIgeD1uZXcgRGF0ZShEYXRlLnBhcnNlKHMudW50aWwpKS50b0lTT1N0cmluZygpO0IrPSI7VU5USUw9Iit4LnN1YnN0cmluZygwLHgubGVuZ3RoLTEzKS5yZXBsYWNlKC9bLV0vZywiIikrIjAwMDAwMFoifXMuaW50ZXJ2YWwmJihCKz0iO0lOVEVSVkFMPSIrcy5pbnRlcnZhbCkscy5jb3VudCYmKEIrPSI7Q09VTlQ9IitzLmNvdW50KSxzLmJ5ZGF5JiZzLmJ5ZGF5Lmxlbmd0aD4wJiYoQis9IjtCWURBWT0iK3MuYnlkYXkuam9pbigiLCIpKX0obmV3IERhdGUpLnRvSVNPU3RyaW5nKCk7dmFyIEg9WyJCRUdJTjpWRVZFTlQiLCJVSUQ6IituLmxlbmd0aCsiQCIrZSwiQ0xBU1M6UFVCTElDIiwiREVTQ1JJUFRJT046IitpLCJEVFNUQU1QO1ZBTFVFPURBVEUtVElNRToiK20sIkRUU1RBUlQ7VkFMVUU9REFURS1USU1FOiIrQywiRFRFTkQ7VkFMVUU9REFURS1USU1FOiIraiwiTE9DQVRJT046IitvLCJTVU1NQVJZO0xBTkdVQUdFPWVuLXVzOiIrdCwiVFJBTlNQOlRSQU5TUEFSRU5UIiwiRU5EOlZFVkVOVCJdO3JldHVybiBCJiZILnNwbGljZSg0LDAsQiksSD1ILmpvaW4ociksbi5wdXNoKEgpLEh9LGRvd25sb2FkOmZ1bmN0aW9uKGUsdCl7aWYobi5sZW5ndGg8MSlyZXR1cm4hMTt0PXZvaWQgMCE9PXQ/dDoiLmljcyIsZT12b2lkIDAhPT1lP2U6ImNhbGVuZGFyIjt2YXIgYSxsPWkrcituLmpvaW4ocikrbztpZigtMT09PW5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZigiTVNJRSAxMCIpKWE9bmV3IEJsb2IoW2xdKTtlbHNle3ZhciB1PW5ldyBCbG9iQnVpbGRlcjt1LmFwcGVuZChsKSxhPXUuZ2V0QmxvYigidGV4dC94LXZDYWxlbmRhcjtjaGFyc2V0PSIrZG9jdW1lbnQuY2hhcmFjdGVyU2V0KX1yZXR1cm4gc2F2ZUFzKGEsZSt0KSxsfSxidWlsZDpmdW5jdGlvbigpe3JldHVybiEobi5sZW5ndGg8MSkmJmkrcituLmpvaW4ocikrb319fWNvbnNvbGUubG9nKCJVbnN1cHBvcnRlZCBCcm93c2VyIil9fTsK')); | |
var ppsId = $('input[name=pps_id]')[0].value; | |
var csrf = $('meta[name=csrf-token]').attr('content'); | |
var data = await fetch('https://univer.dvfu.ru/schedule/get/?type=listWeek&start=' + semesterStart + '&end=' + semesterEnd + '&ppsId=' + ppsId, { | |
"credentials": "include", | |
"headers": { | |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0", | |
"Accept": "application/json, text/javascript, */*; q=0.01", | |
"Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3", | |
"X-CSRF-Token": csrf, | |
"X-Requested-With": "XMLHttpRequest" | |
}, | |
"referrer": "https://univer.dvfu.ru/schedule", | |
"method": "GET", | |
"mode": "cors" | |
}); | |
var dataJson = await data.json(); | |
var cal = ics(); | |
let busyDaysHash = {}; | |
for (let event of dataJson.events) { | |
let dateStart = new Date(event.start); | |
let dateEnd = new Date(event.end); | |
let subgroup = event.subgroup; | |
let hashedString = dateStart.getDay().toString() + dateStart.getHours().toString() + dateStart.getMinutes().toString() + subgroup.toString(); | |
if (hashedString in busyDaysHash) { | |
let busyDay = busyDaysHash[hashedString]; | |
let week = getWeekNumber(dateStart)[1]; | |
if (week < busyDay.week) { | |
// YEAR SWITCH | |
continue; | |
} | |
busyDay.frequency = week - busyDay.week; | |
busyDay.week = week; | |
} else { | |
busyDaysHash[hashedString] = { event: event, week: getWeekNumber(dateStart)[1] }; | |
} | |
} | |
console.log(busyDaysHash); | |
var twoLetterWeekDays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; | |
Object.values(busyDaysHash).forEach(function(bd) { | |
console.log(bd); | |
var subgroup = bd.event.subgroup ? ' Подгруппа ' + bd.event.subgroup + ' ': ''; | |
cal.addEvent(bd.event.title + ' (' + bd.event.pps_load + ') ' + subgroup, bd.event.group + ' ' + bd.event.pps_load, bd.event.classroom, bd.event.start, bd.event.end, { | |
freq: 'WEEKLY', | |
until: semesterEnd, | |
interval: bd.frequency, | |
byday: [ twoLetterWeekDays[(new Date(bd.event.start)).getDay()] ] | |
}); | |
}); | |
cal.download('classes-calendar'); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment