-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.lua
86 lines (79 loc) · 2.52 KB
/
feed.lua
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
local Feed = {}
function Feed:new(url, pollingIntervalSeconds)
local instance = { url = url, interval = pollingIntervalSeconds, data = {} }
setmetatable(instance, self)
self.__index = self
return instance
end
function Feed:getLink(itemBlock)
local descriptionBlock = itemBlock:match("<description>(.-)</description>")
local cdata = descriptionBlock:match("<!%[CDATA%[(.-)%]%]>") or nil
local link = nil
if cdata then
link = cdata:match('<a%s+href="(.-)"[^>]*')
else
link = itemBlock:match("<link>(.-)</link>")
end
return link
end
function Feed:getTitle(itemBlock)
local title = itemBlock:match("<title><!%[CDATA%[(.-)%]%]></title>")
return title or itemBlock:match("<title>(.-)</title>")
end
function Feed:getPubData(itemBlock)
local pubDate = itemBlock:match("<pubDate>(.-)</pubDate>")
local function toUnixTime(date)
local day, month, year, hour, min, sec = date:match(
"(%d+)%s+(%a+)%s+(%d+)%s+(%d+):(%d+):(%d+)"
)
local months = { Jan = 1, Feb = 2, Mar = 3, Apr = 4, May = 5, Jun = 6, Jul = 7, Aug = 8, Sep = 9, Oct = 10, Nov = 11, Dec = 12 }
local timeTable = {
year = tonumber(year),
month = months[month],
day = tonumber(day),
hour = tonumber(hour),
min = tonumber(min),
sec = tonumber(sec)
}
return os.time(timeTable)
end
return toUnixTime(pubDate)
end
function Feed:parseRSSBody(rss)
local items = {}
for itemBlock in rss:gmatch("<item>(.-)</item>") do
local item = {
link = self:getLink(itemBlock),
title = self:getTitle(itemBlock),
pubDate = self:getPubData(itemBlock)
}
if not (item.link and item.title and item.pubDate) then
goto continue
end
table.insert(items, item)
::continue::
end
return {
channel = {
title = rss:match("<title>(.-)</title>")
},
items = items
}
end
function Feed:poll(onRSSData)
local function getRSSData()
print("fetching RSS feed from " .. self.url)
local status, body, headers = hs.http.get(self.url)
if status ~= 200 then
error("got " .. status .. " from " .. self.url)
end
if not body then
error("got empty response body!")
end
self.data = self:parseRSSBody(body)
onRSSData(self.data)
end
getRSSData()
hs.timer.new(self.interval, getRSSData):start()
end
return Feed