-
Notifications
You must be signed in to change notification settings - Fork 2
/
menu.py
executable file
·214 lines (184 loc) · 6.78 KB
/
menu.py
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#!/usr/bin/env python
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import collections
import datetime
import urllib2
import unicodedata
import xml.dom.minidom
from HTMLParser import HTMLParser
MENU_RSS_URL = 'http://legacy.cafebonappetit.com/rss/menu/633'
COLOR_MAP = {
'BLACK': "\033[30m",
'RED': "\033[31m",
'GREEN': "\033[32m",
'YELLOW': "\033[33m",
'BLUE': "\033[34m",
'PURPLE': "\033[35m",
'CYAN': "\033[36m",
'WHITE': "\033[37m",
'BOLD_BLACK': "\033[30;1m",
'BOLD_RED': "\033[31;1m",
'BOLD_GREEN': "\033[32;1m",
'BOLD_YELLOW': "\033[33;1m",
'BOLD_BLUE': "\033[34;1m",
'BOLD_PURPLE': "\033[35;1m",
'BOLD_CYAN': "\033[36;1m",
'BOLD_WHITE': "\033[37;1m",
}
COLOR_RESET = "\033[0m"
class MenuParser(HTMLParser):
'''
Menu parser
'''
def __init__(self):
self.parsed_menu = collections.defaultdict(list)
self._cur_course = None
self._change_cur_course = False
self._cur_entree = None
self._change_cur_entree = False
self._append_cur_entree = False
HTMLParser.__init__(self)
def handle_starttag(self, tag, attrs):
if tag == 'h3':
self._change_cur_course = True
elif tag == 'h4':
self._change_cur_entree = True
elif tag == 'p':
self._append_cur_entree = True
def handle_data(self, data):
if self._change_cur_course is True:
if self._cur_course is not None:
self.parsed_menu[self._cur_course].append(' '.join(self._cur_entree))
self._cur_course = data
self._cur_entree = None
self._change_cur_course = False
elif self._change_cur_entree is True:
self._cur_entree = [data.strip()]
self._change_cur_entree = False
elif self._append_cur_entree:
self._cur_entree.append(data.strip())
self.parsed_menu[self._cur_course].append(' '.join(self._cur_entree))
self._append_cur_entree = False
def get_menu(url):
'''
Return list of days, menus
menus: course->entrees->list(entree)
'''
full_menu = []
menu = urllib2.urlopen(url)
# Workaround bad UTF-8 characters
menu_string = menu.read().decode('utf-8', 'replace').encode('utf-8')
menu_dom = xml.dom.minidom.parseString(menu_string)
for item in menu_dom.getElementsByTagName('item'):
menu_parser = MenuParser()
title = item.getElementsByTagName('title').item(0)
day = datetime.datetime.strptime(title.firstChild.data, '%a, %d %b %Y').date()
description = item.getElementsByTagName('description').item(0)
day_menu = description.firstChild.data
menu_parser.feed(day_menu)
full_menu.append((day, menu_parser.parsed_menu))
return full_menu
def color_print(color, text):
print("{0}{1}{2}".format(COLOR_MAP[color], text, COLOR_RESET))
def print_entrees(courses, course, color):
'''
Entree printer
'''
entrees = courses[course]
if len(entrees) == 0:
return
color_print(color, course)
color_print(color, '-' * len(course))
for entree in sorted(entrees):
print(entree)
print()
def next_three_meals(menu):
breakfast_end = datetime.time(9, 30)
lunch_end = datetime.time(13, 30)
dinner_end = datetime.time(20, 30)
time = datetime.datetime.today().time()
date = datetime.date.today()
tomorrow = date + datetime.timedelta(1, 0)
if time < breakfast_end:
return [(day, courses) for day, courses in menu if day == date]
elif time < lunch_end:
new_menu = []
for day, courses in menu:
if day == date:
try:
del courses['Breakfast']
except KeyError:
pass
new_menu.append((day, courses))
if day == tomorrow:
for course in ('Lunch', 'Dinner'):
try:
del courses[course]
except KeyError:
pass
new_menu.append((day, courses))
return new_menu
elif time < dinner_end:
new_menu = []
for day, courses in menu:
if day == date:
for course in ('Breakfast', 'Lunch'):
try:
del courses[course]
except KeyError:
pass
new_menu.append((day, courses))
if day == tomorrow:
try:
del courses['Dinner']
except KeyError:
pass
new_menu.append((day, courses))
return new_menu
if time > dinner_end:
return [(day, courses) for day, courses in menu if day == tomorrow]
return menu
def print_menu(menu, show_breakfast=False, show_lunch=False, show_dinner=False, show_week=False, show_tomorrow=False):
'''
Menu printer
'''
if show_breakfast is not True and show_lunch is not True and show_dinner is not True:
# Nothing selected, so show all
show_breakfast, show_lunch, show_dinner = True, True, True
if show_tomorrow:
menu = [(day, courses) for day, courses in menu if day == (datetime.date.today() + datetime.timedelta(1, 0))]
elif not show_week:
menu = next_three_meals(menu)
for day, courses in menu:
# FIXME: Going to assume we always get 5 days
daylabel = day.strftime('%Y-%m-%d (%a)').upper()
color_print('BOLD_WHITE', daylabel)
color_print('BOLD_WHITE', '=' * len(daylabel))
if show_breakfast is True:
print_entrees(courses, 'Breakfast', 'YELLOW')
if show_lunch is True:
print_entrees(courses, 'Lunch', 'CYAN')
if show_dinner is True:
print_entrees(courses, 'Dinner', 'GREEN')
def main():
'''
Fetch the menu!
'''
parser = argparse.ArgumentParser()
parser.add_argument('-b', '--breakfast', action='store_true', help='show breakfast')
parser.add_argument('-l', '--lunch', action='store_true', help='show lunch')
parser.add_argument('-d', '--dinner', action='store_true', help='show dinner')
group = parser.add_mutually_exclusive_group()
group.add_argument("-t", "--tomorrow", action="store_true", help='show tomorrow')
group.add_argument('-w', '--week', action='store_true', help='show week')
parser.add_argument('-u', '--url', default=MENU_RSS_URL, help=argparse.SUPPRESS)
args = parser.parse_args()
menu = get_menu(args.url)
print_menu(menu, show_breakfast=args.breakfast, show_lunch=args.lunch, show_dinner=args.dinner,
show_week=args.week, show_tomorrow=args.tomorrow)
if __name__ == '__main__':
main()