|
|
|
|
@ -6,7 +6,7 @@ import pyperclip
@@ -6,7 +6,7 @@ import pyperclip
|
|
|
|
|
import requests |
|
|
|
|
|
|
|
|
|
# typing |
|
|
|
|
RawEvent = dict[str:tuple[str|datetime,str]] |
|
|
|
|
RawEvent = dict[str : tuple[str | datetime, str]] |
|
|
|
|
Event = dict[str:str] |
|
|
|
|
TableMetaData = dict[str:int] |
|
|
|
|
|
|
|
|
|
@ -16,22 +16,24 @@ ICS_DATE_FORMAT = "%Y%m%dT%H%M%S"
@@ -16,22 +16,24 @@ ICS_DATE_FORMAT = "%Y%m%dT%H%M%S"
|
|
|
|
|
GERMAN_DATE_FORMAT = "%d.%m.%Y %H:%M" |
|
|
|
|
|
|
|
|
|
EARLIEST = datetime.now() - timedelta(days=30 * 3) |
|
|
|
|
LATEST = datetime.now() + timedelta(days=30 * 6) |
|
|
|
|
LATEST = datetime.now() + timedelta(days=30 * 6) |
|
|
|
|
|
|
|
|
|
TABLE_COLUMN_ORDER = ("date", "location", "presenter") |
|
|
|
|
|
|
|
|
|
# for mail sending |
|
|
|
|
|
|
|
|
|
MAIL_RECIPIENTS = ",".join([ |
|
|
|
|
"cpistaff@imtek.de", |
|
|
|
|
"andrea.paola.layedra.almeida@uniklinik-freiburg.de", |
|
|
|
|
"jaro.homburger@biologie.uni-freiburg.de", |
|
|
|
|
"kubilay.acar@continental.com", |
|
|
|
|
"Mario.diehlmann@basf.com", |
|
|
|
|
"paul.fernandez@fmf.uni-freiburg.de", |
|
|
|
|
"sunil.shetty@uniklinik-freiburg.de", |
|
|
|
|
"sofia.genoves94@gmail.com", "sofia.genoves@yahoo.com.ar" |
|
|
|
|
]) |
|
|
|
|
MAIL_RECIPIENTS = ",".join( |
|
|
|
|
[ |
|
|
|
|
"cpistaff@imtek.de", |
|
|
|
|
"andrea.paola.layedra.almeida@uniklinik-freiburg.de", |
|
|
|
|
"jaro.homburger@biologie.uni-freiburg.de", |
|
|
|
|
"kubilay.acar@continental.com", |
|
|
|
|
"Mario.diehlmann@basf.com", |
|
|
|
|
"paul.fernandez@fmf.uni-freiburg.de", |
|
|
|
|
"sunil.shetty@uniklinik-freiburg.de", |
|
|
|
|
"sofia.genoves94@gmail.com", |
|
|
|
|
"sofia.genoves@yahoo.com.ar", |
|
|
|
|
] |
|
|
|
|
) |
|
|
|
|
MAIL_SUBJECT = "Updated Group Meeting Schedule" |
|
|
|
|
MAIL_START = """ |
|
|
|
|
Dear All, |
|
|
|
|
@ -56,23 +58,27 @@ Holgi
@@ -56,23 +58,27 @@ Holgi
|
|
|
|
|
|
|
|
|
|
# parsers |
|
|
|
|
|
|
|
|
|
def _parse_text(ics_text:str) -> str: |
|
|
|
|
|
|
|
|
|
def _parse_text(ics_text: str) -> str: |
|
|
|
|
text = ics_text.strip() |
|
|
|
|
return text.replace("\\,", ",") |
|
|
|
|
|
|
|
|
|
def _parse_presenter(ics_text:str) -> str: |
|
|
|
|
|
|
|
|
|
def _parse_presenter(ics_text: str) -> str: |
|
|
|
|
text = _parse_text(ics_text) |
|
|
|
|
first, sep, last = text.partition(":") |
|
|
|
|
return first if not sep else last.strip() |
|
|
|
|
|
|
|
|
|
def _parse_datetime(ics_text:str) -> str: |
|
|
|
|
return datetime.strptime(ics_text.strip(), ICS_DATE_FORMAT) |
|
|
|
|
|
|
|
|
|
def _parse_datetime(ics_text: str) -> str: |
|
|
|
|
return datetime.strptime(ics_text.strip(), ICS_DATE_FORMAT) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _format_datetime(date: datetime) -> str: |
|
|
|
|
return datetime.strftime(date, GERMAN_DATE_FORMAT) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Transformer(): |
|
|
|
|
class Transformer: |
|
|
|
|
def __init__(self, name, parser, formater): |
|
|
|
|
self.name = name |
|
|
|
|
self.parser = parser |
|
|
|
|
@ -80,37 +86,41 @@ class Transformer():
@@ -80,37 +86,41 @@ class Transformer():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vevent_transformer = { |
|
|
|
|
"DTSTART": Transformer("date", parser=_parse_datetime, formater=_format_datetime), |
|
|
|
|
"LOCATION": Transformer("location", parser=_parse_text, formater=str), |
|
|
|
|
"SUMMARY": Transformer("presenter", parser=_parse_presenter, formater=str), |
|
|
|
|
"DTSTART": Transformer( |
|
|
|
|
"date", parser=_parse_datetime, formater=_format_datetime |
|
|
|
|
), |
|
|
|
|
"LOCATION": Transformer("location", parser=_parse_text, formater=str), |
|
|
|
|
"SUMMARY": Transformer("presenter", parser=_parse_presenter, formater=str), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_ics(url:str) -> str: |
|
|
|
|
def get_ics(url: str) -> str: |
|
|
|
|
try: |
|
|
|
|
response = requests.get(url) |
|
|
|
|
except IndexError: |
|
|
|
|
except IndexError: |
|
|
|
|
msg = f"Could not load calender from url" |
|
|
|
|
raise IOError(msg) |
|
|
|
|
return response.text |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extract_event_info(response:str) -> Iterable[Event]: |
|
|
|
|
def extract_event_info(response: str) -> Iterable[Event]: |
|
|
|
|
events = ( |
|
|
|
|
event for event in |
|
|
|
|
_extract_event_info(response) |
|
|
|
|
event |
|
|
|
|
for event in _extract_event_info(response) |
|
|
|
|
if EARLIEST < event["date"][0] < LATEST |
|
|
|
|
) |
|
|
|
|
for event in sorted(events, key=lambda d: d["date"]): |
|
|
|
|
yield {key: values[1] for key, values in event.items()} |
|
|
|
|
|
|
|
|
|
def _extract_event_info(response:str) -> Iterable[RawEvent]: |
|
|
|
|
|
|
|
|
|
def _extract_event_info(response: str) -> Iterable[RawEvent]: |
|
|
|
|
handle = (line for line in response.splitlines()) |
|
|
|
|
for line in handle: |
|
|
|
|
if line.upper().startswith("BEGIN:VEVENT"): |
|
|
|
|
yield extract_vevent(handle) |
|
|
|
|
|
|
|
|
|
def extract_vevent(handle:Iterable[str]) -> RawEvent: |
|
|
|
|
|
|
|
|
|
def extract_vevent(handle: Iterable[str]) -> RawEvent: |
|
|
|
|
event = {} |
|
|
|
|
for line in handle: |
|
|
|
|
if line.upper().startswith("END:VEVENT"): |
|
|
|
|
@ -124,7 +134,7 @@ def extract_vevent(handle:Iterable[str]) -> RawEvent:
@@ -124,7 +134,7 @@ def extract_vevent(handle:Iterable[str]) -> RawEvent:
|
|
|
|
|
return event |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_wiki_table(events:Iterable[Event]) -> str: |
|
|
|
|
def create_wiki_table(events: Iterable[Event]) -> str: |
|
|
|
|
table_meta_data = _get_table_meta_data(events) |
|
|
|
|
headers = {key: f"'''{key.capitalize()}'''" for key in TABLE_COLUMN_ORDER} |
|
|
|
|
lines = [ |
|
|
|
|
@ -135,13 +145,13 @@ def create_wiki_table(events:Iterable[Event]) -> str:
@@ -135,13 +145,13 @@ def create_wiki_table(events:Iterable[Event]) -> str:
|
|
|
|
|
return "\n".join(lines) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _create_table_line(event:Event, meta:TableMetaData) -> str: |
|
|
|
|
def _create_table_line(event: Event, meta: TableMetaData) -> str: |
|
|
|
|
columns = [event[key].ljust(meta[key]) for key in TABLE_COLUMN_ORDER] |
|
|
|
|
inner = " || ".join(columns) |
|
|
|
|
return f"|| {inner} ||" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _get_table_meta_data(events:Iterable[Event]) -> TableMetaData: |
|
|
|
|
def _get_table_meta_data(events: Iterable[Event]) -> TableMetaData: |
|
|
|
|
meta = {} |
|
|
|
|
for event in events: |
|
|
|
|
for key, value in event.items(): |
|
|
|
|
@ -149,12 +159,13 @@ def _get_table_meta_data(events:Iterable[Event]) -> TableMetaData:
@@ -149,12 +159,13 @@ def _get_table_meta_data(events:Iterable[Event]) -> TableMetaData:
|
|
|
|
|
return meta |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_email_table(events:Iterable[Event]) -> str: |
|
|
|
|
def create_email_table(events: Iterable[Event]) -> str: |
|
|
|
|
table_meta_data = _get_table_meta_data(events) |
|
|
|
|
date_key, _, name_key = TABLE_COLUMN_ORDER |
|
|
|
|
pad_date = table_meta_data[date_key] |
|
|
|
|
lines = [ |
|
|
|
|
(event[date_key].ljust(pad_date) + " | " + event[name_key]) for event in events |
|
|
|
|
(event[date_key].ljust(pad_date) + " | " + event[name_key]) |
|
|
|
|
for event in events |
|
|
|
|
] |
|
|
|
|
return "\n".join(lines) |
|
|
|
|
|
|
|
|
|
@ -166,7 +177,7 @@ def group_schedule():
@@ -166,7 +177,7 @@ def group_schedule():
|
|
|
|
|
|
|
|
|
|
wiki_table = create_wiki_table(events) |
|
|
|
|
email_table = create_email_table(events) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
components = [ |
|
|
|
|
wiki_table, |
|
|
|
|
"", |
|
|
|
|
@ -177,9 +188,8 @@ def group_schedule():
@@ -177,9 +188,8 @@ def group_schedule():
|
|
|
|
|
MAIL_SUBJECT, |
|
|
|
|
MAIL_START, |
|
|
|
|
email_table, |
|
|
|
|
MAIL_END |
|
|
|
|
MAIL_END, |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
text = "\n".join(components) |
|
|
|
|
print(text) |
|
|
|
|
pyperclip.copy(text) |
|
|
|
|
pyperclip.copy(text) |
|
|
|
|
|