diff options
Diffstat (limited to 'email_assistant/plugins/delta.py')
-rw-r--r-- | email_assistant/plugins/delta.py | 115 |
1 files changed, 115 insertions, 0 deletions
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 | ||