~fabrixxm/confy

ref: 00b88b02ca719529be4807b5b272cf4a817503d2 confy/src/remotes/ics.py -rw-r--r-- 4.2 KiB
00b88b02fabrixxm [WIP] Timezone support 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# ics.py
#
# Copyright 2020 Fabio
#
# 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/>.

import time
import html
from datetime import datetime, timedelta, timezone
from dateutil.tz import UTC
from icalendar import Calendar, Event

from .exceptions import InvalidFormatException
from .. import local
from ..models import Meta


def import_ics(content:str, url:str):
    """Import data from ICS

    all dates will be converted to UTC and stored in db without tzinfo,
    because sqlite3 driver spits errors otherwise.
    """

    cal = Calendar.from_ical(content)

    _db = local.getDb()

    meta_title = None
    meta_end = datetime(1970,1,1,0,0,0)
    meta_start = datetime(3100,12,12,23,59,59)

    for c in cal.walk():
        if c.name == "VCALENDAR":
            meta_title = c.get('X-WR-CALNAME')

        if c.name == "VEVENT":
            fulltextsearch = []
            eventid = c['UID']
            if c.get('DTSTART'):
                start = c['DTSTART'].dt.astimezone(UTC).replace(tzinfo=None)
            else:
                start = c['DTSTAMP'].dt.astimezone(UTC).replace(tzinfo=None)
            if c.get('DURATION'):
                end = start + c['DURATION'].dt
            elif c.get('DTEND'):
                end = c['DTEND'].dt.astimezone(UTC).replace(tzinfo=None)
            else:
                end = start + timedelta(hours=1)
            evtdate = start.date()
            room = c.get('LOCATION')
            slug = None
            title = c.get('SUMMARY', "")
            subtitle = None
            track = None
            evtype = None
            abstract = None
            description = c.get('DESCRIPTION', "")

            if title == "" and description == "":
                title = "Untitled event"
            if title == "" and description != "":
                title = description[:20]
                if len(description) > 20:
                    title = title + "…"

            if room:
                room = html.unescape(room)
            if room == "":
                room = None

            if start < meta_start:
                meta_start = start
            if end > meta_end:
                meta_end = end

            fulltextsearch += [ s for s in [title, subtitle, abstract, description, room, track] if s is not None ]

            links = []
            _url = c.get('URL')
            if _url:
                links.append((eventid, _url, _url))

            _db.execute("""INSERT OR REPLACE INTO events
                                (id, date, start, end, room, slug, title, subtitle, track, type, abstract, description, starred)
                                VALUES (?,?,?,?,?,?,?,?,?,?,?,?, (SELECT starred FROM events WHERE id=?))""",
                                (eventid, evtdate, start, end, room, slug, title, subtitle, track, evtype, abstract, description, eventid))
            #_db.executemany("INSERT OR REPLACE INTO persons (id, name) VALUES (?, ?)", persons)
            #_db.executemany("""INSERT OR REPLACE INTO event_person (event_id, person_id)
            #                    VALUES (?, ?) ON CONFLICT DO NOTHING""",
            #                    [ (eventid, p[0]) for p in persons ])
            _db.executemany("""INSERT OR REPLACE INTO links
                                (event_id, href, name) VALUES (?,?,?)""", links)
            fulltextsearchstr = ' '.join(fulltextsearch)
            _db.execute("""INSERT OR REPLACE INTO fts_event (event_id, text) VALUES (?, ?)""", (eventid, fulltextsearchstr))
    _db.commit()

    with Meta() as m:
        m.url = url
        m.title = meta_title
        m.last_update = time.time() # timestamp
        m.start = meta_start.date()
        m.end = meta_end.date()