diff options
Diffstat (limited to 'email_assistant/plugins')
-rw-r--r-- | email_assistant/plugins/__init__.py | 2 | ||||
-rw-r--r-- | email_assistant/plugins/delta.py | 115 | ||||
-rw-r--r-- | email_assistant/plugins/eventbrite.py | 2 | ||||
-rw-r--r-- | email_assistant/plugins/general.py | 2 | ||||
-rw-r--r-- | email_assistant/plugins/marriott.py | 2 | ||||
-rw-r--r-- | email_assistant/plugins/united.py | 2 |
6 files changed, 121 insertions, 4 deletions
diff --git a/email_assistant/plugins/__init__.py b/email_assistant/plugins/__init__.py index 10b28f0..295852e 100644 --- a/email_assistant/plugins/__init__.py +++ b/email_assistant/plugins/__init__.py | |||
@@ -21,9 +21,11 @@ | |||
21 | from . import eventbrite | 21 | from . import eventbrite |
22 | from . import marriott | 22 | from . import marriott |
23 | from . import united | 23 | from . import united |
24 | from . import delta | ||
24 | 25 | ||
25 | plugins = [ | 26 | plugins = [ |
26 | eventbrite.Plugin, | 27 | eventbrite.Plugin, |
27 | marriott.Plugin, | 28 | marriott.Plugin, |
28 | united.Plugin, | 29 | united.Plugin, |
30 | delta.Plugin, | ||
29 | ] | 31 | ] |
diff --git a/email_assistant/plugins/delta.py b/email_assistant/plugins/delta.py new file mode 100644 index 0000000..50da506 --- /dev/null +++ b/email_assistant/plugins/delta.py | |||
@@ -0,0 +1,115 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | |||
3 | # Copyright (C) 2019 James E. Blair <corvus@gnu.org> | ||
4 | # | ||
5 | # This file is part of Email-assistant. | ||
6 | # | ||
7 | # Email-assistant is free software: you can redistribute it and/or | ||
8 | # modify it under the terms of the GNU Affero General Public License | ||
9 | # as published by the Free Software Foundation, either version 3 of | ||
10 | # the License, or (at your option) any later version. | ||
11 | # | ||
12 | # Email-assistant is distributed in the hope that it will be useful, | ||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | # General Public License for more details. | ||
16 | # | ||
17 | # You should have received a copy of the GNU General Public License | ||
18 | # along with Email-assistant. If not, see | ||
19 | # <https://www.gnu.org/licenses/>. | ||
20 | |||
21 | import re | ||
22 | import logging | ||
23 | import hashlib | ||
24 | |||
25 | from bs4 import BeautifulSoup | ||
26 | import dateutil.parser | ||
27 | import dateutil.tz | ||
28 | import inscriptis | ||
29 | import vobject | ||
30 | |||
31 | from email_assistant import iata | ||
32 | from email_assistant import plugin | ||
33 | |||
34 | def parse_dep_arr(dep_date, flight_date, flight_time, code): | ||
35 | flight_year = dep_date.year | ||
36 | tz = iata.tzmap[code] | ||
37 | flight_time = dateutil.parser.parse(flight_date + ' ' + flight_time) | ||
38 | if flight_time.year < flight_year: | ||
39 | flight_time.replace(year=flight_year) | ||
40 | flight_time = flight_time.replace(tzinfo=dateutil.tz.gettz(tz)) | ||
41 | return flight_time | ||
42 | |||
43 | class Plugin(plugin.Plugin): | ||
44 | name = 'delta' | ||
45 | |||
46 | def match(self, msg): | ||
47 | if ('DeltaAirLines@e.delta.com' in msg['From'] and | ||
48 | 'Your Flight Receipt' in msg['Subject']): | ||
49 | return True | ||
50 | |||
51 | def get_events(self, msg): | ||
52 | events = [] | ||
53 | for part in msg.walk(): | ||
54 | if part.get_content_type() == 'text/html': | ||
55 | soup = BeautifulSoup(part.get_payload(decode=True), 'html.parser') | ||
56 | flights = [] | ||
57 | flight = None | ||
58 | dep_date = None | ||
59 | start = soup.find(string=re.compile('FLIGHT INFO STARTS')) | ||
60 | for row in start.parent.find_all('tr', recursive=False): | ||
61 | row = [x.strip() for x in row.strings if x.strip()] | ||
62 | if len(row) == 3 and row[1:] == ['DEPART', 'ARRIVE']: | ||
63 | dep_date = row[0] | ||
64 | continue | ||
65 | if dep_date is None: continue | ||
66 | f = { | ||
67 | 'dep_date': dep_date, | ||
68 | #'num': row[0], | ||
69 | #'cabin': row[1], | ||
70 | 'dep_city': row[2], | ||
71 | 'dep_time': row[3], | ||
72 | 'arr_city': row[4], | ||
73 | 'arr_time': row[5]} | ||
74 | if len(row) > 6: | ||
75 | f['arr_date'] = row[6].replace('*', '').strip() | ||
76 | else: | ||
77 | f['arr_date'] = dep_date | ||
78 | flights.append(f) | ||
79 | start = soup.find(string=re.compile('Checked Bag Allowance')) | ||
80 | while start.name != 'table': start = start.parent | ||
81 | start = start.parent | ||
82 | while start.name != 'table': start = start.parent | ||
83 | index = 0 | ||
84 | for row in start.find_all('tr', recursive=False): | ||
85 | row = [x.strip() for x in row.strings if x.strip()] | ||
86 | if len(row) != 3: continue | ||
87 | try: | ||
88 | dep_date = dateutil.parser.parse(row[0]) | ||
89 | except Exception: | ||
90 | continue | ||
91 | f = flights[index] | ||
92 | f['dep_code'] = row[1].split()[-1].strip() | ||
93 | f['arr_code'] = row[2].split()[-1].strip() | ||
94 | f['dep_dt'] = parse_dep_arr( | ||
95 | dep_date, f['dep_date'], f['dep_time'], f['dep_code']) | ||
96 | f['arr_dt'] = parse_dep_arr( | ||
97 | dep_date, f['arr_date'], f['arr_time'], f['arr_code']) | ||
98 | index += 1 | ||
99 | for f in flights: | ||
100 | self.log.debug('%s %s %s %s', | ||
101 | f['dep_dt'], f['arr_dt'], f['dep_code'], f['arr_code']) | ||
102 | cal = vobject.iCalendar() | ||
103 | event = cal.add('vevent') | ||
104 | event.add('dtstart').value = f['dep_dt'] | ||
105 | event.add('dtend').value = f['arr_dt'] | ||
106 | summary = "Flight from %s to %s" % (f['dep_code'], f['arr_code']) | ||
107 | event.add('summary').value = summary | ||
108 | text = inscriptis.get_text(str(soup)) | ||
109 | text = re.sub(r'([^ ]+)\s*\n', '\\1\n', text) | ||
110 | event.add('description').value = text | ||
111 | event.add('location').value = "%s airport" % (f['dep_code'],) | ||
112 | uid = hashlib.sha1((str(f['dep_time']) + summary).encode('utf8')).hexdigest() | ||
113 | event.add('uid').value = uid | ||
114 | events.append(cal) | ||
115 | return events | ||
diff --git a/email_assistant/plugins/eventbrite.py b/email_assistant/plugins/eventbrite.py index 9ef073a..afd869f 100644 --- a/email_assistant/plugins/eventbrite.py +++ b/email_assistant/plugins/eventbrite.py | |||
@@ -44,7 +44,7 @@ class Plugin(plugin.Plugin): | |||
44 | events = [] | 44 | events = [] |
45 | for part in msg.walk(): | 45 | for part in msg.walk(): |
46 | if part.get_content_type() == 'text/html': | 46 | if part.get_content_type() == 'text/html': |
47 | soup = BeautifulSoup(part.get_payload(decode=True).decode('utf8'), 'html.parser') | 47 | soup = BeautifulSoup(part.get_payload(decode=True), 'html.parser') |
48 | data = json.loads(soup.find('script', type="application/ld+json").string) | 48 | data = json.loads(soup.find('script', type="application/ld+json").string) |
49 | 49 | ||
50 | address = data['reservationFor']['location']['address'] | 50 | address = data['reservationFor']['location']['address'] |
diff --git a/email_assistant/plugins/general.py b/email_assistant/plugins/general.py index c0517b8..e21274d 100644 --- a/email_assistant/plugins/general.py +++ b/email_assistant/plugins/general.py | |||
@@ -24,7 +24,7 @@ def get_events(msg): | |||
24 | log = logging.getLogger('assistant.marriott') | 24 | log = logging.getLogger('assistant.marriott') |
25 | for part in msg.walk(): | 25 | for part in msg.walk(): |
26 | if part.get_content_type() == 'text/html': | 26 | if part.get_content_type() == 'text/html': |
27 | soup = BeautifulSoup(part.get_payload(decode=True).decode('utf8'), 'html.parser') | 27 | soup = BeautifulSoup(part.get_payload(decode=True), 'html.parser') |
28 | 28 | ||
29 | start = end = location = None | 29 | start = end = location = None |
30 | for element in soup.descendants: | 30 | for element in soup.descendants: |
diff --git a/email_assistant/plugins/marriott.py b/email_assistant/plugins/marriott.py index 52597cd..1f2abab 100644 --- a/email_assistant/plugins/marriott.py +++ b/email_assistant/plugins/marriott.py | |||
@@ -43,7 +43,7 @@ class Plugin(plugin.Plugin): | |||
43 | events = [] | 43 | events = [] |
44 | for part in msg.walk(): | 44 | for part in msg.walk(): |
45 | if part.get_content_type() == 'text/html': | 45 | if part.get_content_type() == 'text/html': |
46 | soup = BeautifulSoup(part.get_payload(decode=True).decode('utf8'), 'html.parser') | 46 | soup = BeautifulSoup(part.get_payload(decode=True), 'html.parser') |
47 | summary = soup.find_all('table')[7].a.string.strip() | 47 | summary = soup.find_all('table')[7].a.string.strip() |
48 | location = soup.find_all('table')[9].a.string.strip() | 48 | location = soup.find_all('table')[9].a.string.strip() |
49 | start = (soup.find('th', string=re.compile('Check-In:')). | 49 | start = (soup.find('th', string=re.compile('Check-In:')). |
diff --git a/email_assistant/plugins/united.py b/email_assistant/plugins/united.py index 0b33cd9..38de3e2 100644 --- a/email_assistant/plugins/united.py +++ b/email_assistant/plugins/united.py | |||
@@ -60,7 +60,7 @@ class Plugin(plugin.Plugin): | |||
60 | events = [] | 60 | events = [] |
61 | for part in msg.walk(): | 61 | for part in msg.walk(): |
62 | if part.get_content_type() == 'text/html': | 62 | if part.get_content_type() == 'text/html': |
63 | soup = BeautifulSoup(part.get_payload(decode=True).decode('utf8'), 'html.parser') | 63 | soup = BeautifulSoup(part.get_payload(decode=True), 'html.parser') |
64 | # confirmation_number = soup.find(class_="eTicketConfirmation").string | 64 | # confirmation_number = soup.find(class_="eTicketConfirmation").string |
65 | 65 | ||
66 | index = 0 | 66 | index = 0 |