-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnews_headlines.py
170 lines (129 loc) · 4.81 KB
/
news_headlines.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
from urllib import urequest
import gc
import qrcode
# Uncomment one URL to use (Top Stories, World News and technology)
# URL = "https://feeds.bbci.co.uk/news/rss.xml"
# URL = "https://feeds.bbci.co.uk/news/world/rss.xml"
URL = "https://feeds.bbci.co.uk/news/technology/rss.xml"
# Length of time between updates in minutes.
# Frequent updates will reduce battery life!
UPDATE_INTERVAL = 90
graphics = None
WIDTH = None
HEIGHT = None
code = qrcode.QRCode()
def read_until(stream, find):
result = b""
while len(c := stream.read(1)) > 0:
if c == find:
return result
result += c
def discard_until(stream, find):
_ = read_until(stream, find)
def parse_xml_stream(s, accept_tags, group_by, max_items=3):
tag = []
text = b""
count = 0
current = {}
while True:
char = s.read(1)
if len(char) == 0:
break
if char == b"<":
next_char = s.read(1)
# Discard stuff like <?xml vers...
if next_char == b"?":
discard_until(s, b">")
continue
# Detect <![CDATA
elif next_char == b"!":
s.read(1) # Discard [
discard_until(s, b"[") # Discard CDATA[
text = read_until(s, b"]")
discard_until(s, b">") # Discard ]>
gc.collect()
elif next_char == b"/":
current_tag = read_until(s, b">")
top_tag = tag[-1]
# Populate our result dict
if top_tag in accept_tags:
current[top_tag.decode("utf-8")] = text.decode("utf-8")
# If we've found a group of items, yield the dict
elif top_tag == group_by:
yield current
current = {}
count += 1
if count == max_items:
return
tag.pop()
text = b""
gc.collect()
continue
else:
current_tag = read_until(s, b">")
if not current_tag.endswith(b"/"):
tag += [next_char + current_tag.split(b" ")[0]]
text = b""
else:
text += char
def measure_qr_code(size, code):
w, h = code.get_size()
module_size = int(size / w)
return module_size * w, module_size
def draw_qr_code(ox, oy, size, code):
size, module_size = measure_qr_code(size, code)
graphics.set_pen(1)
graphics.rectangle(ox, oy, size, size)
graphics.set_pen(0)
for x in range(size):
for y in range(size):
if code.get_module(x, y):
graphics.rectangle(ox + x * module_size, oy + y * module_size, module_size, module_size)
# A function to get the data from an RSS Feed, this in case BBC News.
def get_rss():
try:
stream = urequest.urlopen(URL)
output = list(parse_xml_stream(stream, [b"title", b"description", b"guid", b"pubDate"], b"item"))
return output
except OSError as e:
print(e)
return []
feed = None
def update():
global feed
# Gets Feed Data
feed = get_rss()
def draw():
global feed
graphics.set_font("bitmap8")
# Clear the screen
graphics.set_pen(1)
graphics.clear()
graphics.set_pen(0)
# Draws 2 articles from the feed if they're available.
if len(feed) > 0:
# Title
graphics.set_pen(graphics.create_pen(200, 0, 0))
graphics.rectangle(0, 0, WIDTH, 40)
graphics.set_pen(1)
graphics.text("Headlines from BBC News:", 10, 10, 320, 3)
graphics.set_pen(4)
graphics.text(feed[0]["title"], 10, 70, WIDTH - 150, 3 if graphics.measure_text(feed[0]["title"]) < WIDTH else 2)
graphics.text(feed[1]["title"], 130, 260, WIDTH - 140, 3 if graphics.measure_text(feed[1]["title"]) < WIDTH else 2)
graphics.set_pen(3)
graphics.text(feed[0]["description"], 10, 135 if graphics.measure_text(feed[0]["title"]) < 650 else 90, WIDTH - 150, 2)
graphics.text(feed[1]["description"], 130, 320 if graphics.measure_text(feed[1]["title"]) < 650 else 340, WIDTH - 145, 2)
graphics.line(10, 215, WIDTH - 10, 215)
code.set_text(feed[0]["guid"])
draw_qr_code(WIDTH - 110, 65, 100, code)
code.set_text(feed[1]["guid"])
draw_qr_code(10, 265, 100, code)
graphics.set_pen(graphics.create_pen(200, 0, 0))
graphics.rectangle(0, HEIGHT - 20, WIDTH, 20)
else:
graphics.set_pen(4)
graphics.rectangle(0, (HEIGHT // 2) - 20, WIDTH, 40)
graphics.set_pen(1)
graphics.text("Unable to display news feed!", 5, (HEIGHT // 2) - 15, WIDTH, 2)
graphics.text("Check your network settings in secrets.py", 5, (HEIGHT // 2) + 2, WIDTH, 2)
graphics.update()