|
@@ -0,0 +1,144 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+
|
|
|
+import requests
|
|
|
+import os
|
|
|
+from bs4 import BeautifulSoup
|
|
|
+from datetime import datetime, timedelta
|
|
|
+import locale
|
|
|
+import pytz
|
|
|
+from icalendar import Calendar, Event
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def zic2ics():
|
|
|
+ locale.setlocale(locale.LC_TIME,'it_IT.UTF-8')
|
|
|
+ os.makedirs('history', exist_ok=True)
|
|
|
+
|
|
|
+ cal = Calendar()
|
|
|
+ cal.add('prodid', '-//Agenda di zic.it//')
|
|
|
+ cal.add('version', '2.0')
|
|
|
+
|
|
|
+ page = requests.get("https://zic.it/agenda/")
|
|
|
+ soup = BeautifulSoup(page.content, "html.parser")
|
|
|
+
|
|
|
+ agenda = soup.find("div", class_="entry-content clearfix")
|
|
|
+ entries = agenda.find_all("p", style=None)
|
|
|
+
|
|
|
+ for entry in entries:
|
|
|
+ try:
|
|
|
+ lnk = entry.find('a', href=True)['href']
|
|
|
+
|
|
|
+ spe = entry.get_text(strip=True, separator='\n').splitlines()
|
|
|
+ tit = spe[0].strip()
|
|
|
+ dat = datetime.strptime(spe[2], "%A %d %B %Y - %H:%M").replace(tzinfo=pytz.timezone('Europe/Rome'))
|
|
|
+
|
|
|
+ det = spe[3][2:-2].split(";")
|
|
|
+ dov = det[0].strip()
|
|
|
+ chi = det[1].strip() if 1 < len(det) else ""
|
|
|
+ # print(" ~ ".join([tit, str(dat), dov, chi]))
|
|
|
+
|
|
|
+ uid = "|".join([dat.strftime("%Y%m%d"), tit, dov])
|
|
|
+
|
|
|
+ event = Event()
|
|
|
+ event.add('summary', tit)
|
|
|
+ event.add('dtstart', dat)
|
|
|
+ event.add('description', chi)
|
|
|
+ event.add('location', dov)
|
|
|
+ event.add('url', lnk)
|
|
|
+ event.add('uid', uid)
|
|
|
+ cal.add_component(event)
|
|
|
+
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+ ical = cal.to_ical()
|
|
|
+
|
|
|
+ try:
|
|
|
+ with open('zic.ics', 'rb') as f:
|
|
|
+ ical_last = f.read()
|
|
|
+ except:
|
|
|
+ ical_last = ""
|
|
|
+
|
|
|
+ if ical != ical_last:
|
|
|
+
|
|
|
+ try:
|
|
|
+ with open('zic_all.ics', 'rb') as f:
|
|
|
+ cal_all = Calendar.from_ical(f.read())
|
|
|
+ except:
|
|
|
+ cal_all = Calendar()
|
|
|
+ ical_all = icalmerge(cal_all, cal).to_ical()
|
|
|
+
|
|
|
+ with open('zic.ics', 'wb') as f:
|
|
|
+ f.write(ical)
|
|
|
+
|
|
|
+ with open('zic_all.ics', 'wb') as f:
|
|
|
+ f.write(ical_all)
|
|
|
+
|
|
|
+ with open(os.path.join('history','zic_%s.ics' % datetime.now().strftime("%Y%m%d%H%M%S")), 'wb') as f:
|
|
|
+ f.write(ical)
|
|
|
+
|
|
|
+ with open(os.path.join('history','zic_%s.html' % datetime.now().strftime("%Y%m%d%H%M%S")), 'wb') as f:
|
|
|
+ f.write(page.content)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def icalmerge(calold, calnew, delete = False, tolerance = 15):
|
|
|
+
|
|
|
+ cal = Calendar()
|
|
|
+ cal.add('prodid', calnew.get('prodid').to_ical().decode('utf-8'))
|
|
|
+ cal.add('version', calnew.get('version').to_ical().decode('utf-8'))
|
|
|
+
|
|
|
+
|
|
|
+ #Add a computed UID if missing
|
|
|
+ for e in calold.walk('VEVENT'):
|
|
|
+ if e.get('UID') is None:
|
|
|
+ uid = "|".join([e.decoded('dtstart').strftime("%Y%m%d"), e.get('Summary').to_ical().decode('utf-8'), e.get('Location').to_ical().decode('utf-8')])
|
|
|
+ e.add('uid', uid)
|
|
|
+
|
|
|
+ for e in calnew.walk('VEVENT'):
|
|
|
+ if e.get('UID') is None:
|
|
|
+ uid = "|".join([e.decoded('dtstart').strftime("%Y%m%d"), e.get('Summary').to_ical().decode('utf-8'), e.get('Location').to_ical().decode('utf-8')])
|
|
|
+ e.add('uid', uid)
|
|
|
+
|
|
|
+ calold_uids = [e.get('UID').to_ical().decode('utf-8') for e in calold.walk('VEVENT')]
|
|
|
+ calnew_uids = [e.get('UID').to_ical().decode('utf-8') for e in calnew.walk('VEVENT')]
|
|
|
+
|
|
|
+ imported_uids = []
|
|
|
+ for e in calold.walk('VEVENT'):
|
|
|
+ uid = e.get('UID').to_ical().decode('utf-8')
|
|
|
+
|
|
|
+ if uid not in calnew_uids:
|
|
|
+ if e.decoded('dtstart') < datetime.now(pytz.UTC) + timedelta(minutes = tolerance):
|
|
|
+ print("Past \"%s\"" % uid)
|
|
|
+ cal.add_component(e)
|
|
|
+ else:
|
|
|
+ if delete:
|
|
|
+ print("Deleted \"%s\"" % uid)
|
|
|
+ else:
|
|
|
+ print("Cancelled \"%s\"" % uid)
|
|
|
+ e.add('status', 'CANCELLED')
|
|
|
+ cal.add_component(e)
|
|
|
+
|
|
|
+ for e in calnew.walk('VEVENT'):
|
|
|
+ uid = e.get('UID').to_ical().decode('utf-8')
|
|
|
+ if uid not in calold_uids:
|
|
|
+ print("Added \"%s\"" % uid)
|
|
|
+ cal.add_component(e)
|
|
|
+ else:
|
|
|
+ # print("Updated \"%s\"" % uid)
|
|
|
+ cal.add_component(e)
|
|
|
+
|
|
|
+ return(cal)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ os.chdir(os.path.dirname(__file__))
|
|
|
+ zic2ics()
|
|
|
+
|