epsi2ics/epsiEDTtoICS.sh

115 lines
4.1 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/bin/bash
# The epsi2ics project produces an ICS file from an EPSI school-year calendar.
# Copyright © 2019 Y. Gablin, under the GPL-3.0-or-later license.
# Full licensing information in the LICENSE file, or gnu.org/licences/gpl-3.0.txt if the file is missing.
#
# This script only works when executed in the timezone of the calendar, and only if this timezone offset
# is low enough to keep all events in the day they belong to in the web calendar (usually 6h ≤ TZ ≤ +8h).
#
# from EPSI “edtmobilityeng” to ICS, for the current school year
# $1: EPSI Login (firstname.lastname)
# $2: output file (else standard output)
if [ -n "$2" -a -d "$(dirname "$2")" -a -w "$(dirname "$2")" ]; then
exec >"$2"
fi
(
dtstamp=$(date -u +%Y%m%dT%H%M%SZ)
currentYear=$(date +%Y)
splitDay=$(date +%j -d "${currentYear}-08-01" | sed 's/^0*//') # XXXX-08-01 ∈ [1 … 366]
dayOfYear=$(date +%j | sed 's/^0*//') # this day ∈ [1 … 366]
if [ $dayOfYear -lt $splitDay ]; then
offsetMax=$(( splitDay-dayOfYear ))
offset=$(( offsetMax-365 ))
else
offset=$(( splitDay-dayOfYear ))
offsetMax=$(( 365+offset ))
fi
dayOfWeek=$(date +%u -d "${offset}days") # ∈ [1=monday … 5=friday]
cat <<-ENDOFTEXT
BEGIN:VCALENDAR
VERSION:2.0
PRODID:yalis.fr/epsi2ical v1.1
ENDOFTEXT
while [ $offset -lt $offsetMax ]; do
mon=$(date +%Y%m%dT%z -d "$(($offset+1-$dayOfWeek))days")
tue=$(date +%Y%m%dT%z -d "$(($offset+2-$dayOfWeek))days")
wed=$(date +%Y%m%dT%z -d "$(($offset+3-$dayOfWeek))days")
thu=$(date +%Y%m%dT%z -d "$(($offset+4-$dayOfWeek))days")
fri=$(date +%Y%m%dT%z -d "$(($offset+5-$dayOfWeek))days")
curl -s "https://edtmobiliteng.wigorservices.net/WebPsDyn.aspx?action=posEDTBEECOME&serverid=C&Tel=${1}&date=$(date +%m/%d/%Y -d "${offset}days")" \
| tr '\r\n' ' ' \
| sed -r 's/[[:blank:]]+/ /g' \
| grep -oE '<DIV [^>]*class="Case" [^>]*style="[^"]*left *:[^"]*"|DIV [^>]*style="[^"]*left *:[^"]*" [^>]*class="Case"|<td [^>]*class="TC(ase|Prof|hdeb|Salle)"([^<]|<[^/]|</[^t]|</t[^d])*</td>' \
| awk -vmon=$mon -vtue=$tue -vwed=$wed -vthu=$thu -vfri=$fri -vid="epsi2ics/${1}@${HOSTNAME}" -vdtstamp=$dtstamp -F$'\t' '
function out() {
if (from!="" && to!="" && ase!="") printf( \
"BEGIN:VEVENT\nUID:%s/%s\nDTSTAMP:%s\nDTSTART:%s\nDTEND:%s\nSUMMARY:%s\nLOCATION:%s\nDESCRIPTION:🗣 %s 👥 %s\nEND:VEVENT\n", \
from, id, dtstamp, from, to, ase, where, prof, who)
from=""
to=""
ase=""
where=""
prof=""
who=""
day=""
zoneH=0
zoneM=0
}
function toZtime(localH, localM) {
localM-=zoneM
if (localM<0) {
localM+=60
localH-=1
} else if (localM>59) {
localM-=60
localH+=1
}
localH-=zoneH
return sprintf("%s%02d%02d00Z", day, localH, localM)
}
/class="Case"/ {
out()
pc=gensub(".*left *: *([0-9]+)[%.].*", "\\1", 1)
if (pc < 110) tmpd=mon
else if (pc < 130) tmpd=tue
else if (pc < 150) tmpd=wed
else if (pc < 170) tmpd=thu
else tmpd=fri
day=substr(tmpd, 1, 9)
zoneH=substr(tmpd, 10, 3)+0
zoneM=(substr(tmpd, 10, 1) substr(tmpd, 13, 2))+0
}
/class="TCase"/ {
ase=gensub(".*</div>(.*)</.*", "\\1", 1)
}
/class="TCProf"/ {
split(gensub(".*>(.*)<br/?>(.*)</.*", "\\1\t\\2", 1), tmp)
prof=tmp[1]
who=tmp[2]
}
/class="TChdeb"/ {
split(gensub(".*> *0?([0-9]+):0?([0-9]+) *- *0?([0-9]+):0?([0-9]+) *</.*", "\\1\t\\2\t\\3\t\\4", 1), tmp)
from=toZtime(tmp[1], tmp[2])
to=toZtime(tmp[3], tmp[4])
}
/class="TCSalle"/ {
where=gensub(".*>(Salle:)?(.*)</.*", "\\2", 1)
}
END {
out()
}'
offset=$(($offset+7))
done
cat <<-ENDOFTEXT
END:VCALENDAR
ENDOFTEXT
) \
| env LANG=fr_FR@euro sed -r 's/(.{73})(.)/\1\n \2/g' \
| sed 's/$/\r/'