Skip to content

Commit 47982e2

Browse files
author
Colum Paget
committed
initial commit
0 parents  commit 47982e2

File tree

2 files changed

+365
-0
lines changed

2 files changed

+365
-0
lines changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
SYNOPSIS
2+
========
3+
4+
A lua script that grabs recent releases RSS feeds from fossies.org and freshcode.club, and outputs them at the text console. A limit can be placed on the number or days results returned. A list of package names can be specified on the command line to check for those particular packages.
5+
6+
LICENSE
7+
=======
8+
9+
This script is released under the Gnu Public License version 3
10+
11+
DEPENDANCIES
12+
============
13+
14+
libUseful (https://github.com/ColumPaget/libUseful) and libUseful-lua (https://github.com/ColumPaget/libUseful-lua) will need to be installed.
15+
16+
USAGE
17+
=====
18+
19+
```
20+
lua releases.lua [options] - display latest releases
21+
lua releases.lua watch [options] [name] [name] ... - display releases of named packages
22+
lua releases.lua help - display this help
23+
24+
options:
25+
-days <n> - show results for the last 'n' days
26+
-notext - do not show text description of package
27+
-? - show this help
28+
-h - show this help
29+
-help - show this help
30+
--help - show this help
31+
```
32+
33+
EXAMPLES
34+
========
35+
36+
```
37+
lua releases.lua -days 2 - show releases for the last two days
38+
lua releases.lua -days 1 -notext - show releases for the last 24 hours without descriptions
39+
lua releases.lua watch wine strace - show releases for the programs 'wine' and 'strace'
40+
```

releases.lua

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
require("stream")
2+
require("dataparser");
3+
require("process");
4+
require("terminal")
5+
require("strutil")
6+
require("net")
7+
require("time")
8+
9+
10+
--Some Global Variables
11+
today_items=0
12+
week_items=0
13+
total_items=0
14+
15+
16+
function ParseReleaseRSS(N)
17+
local Package={}
18+
local T, token
19+
20+
Package.name="";
21+
T=strutil.TOKENIZER( N:value("title"), "\\S")
22+
token=T:next()
23+
while (strutil.strlen(T:remaining()) > 0)
24+
do
25+
Package.name=Package.name..token.." "
26+
token=T:next()
27+
end
28+
29+
Package.name=strutil.stripTrailingWhitespace(Package.name)
30+
31+
if token ~= nil then Package.version=token else Package.version="" end
32+
Package.link=N:value("link")
33+
Package.date=time.tosecs("%a, %d %b %Y %H:%M:%S", N:value("pubDate"))
34+
return(Package)
35+
end
36+
37+
38+
function ParseFreshcodeItem(N)
39+
local Package={}
40+
local T
41+
42+
Package=ParseReleaseRSS(N)
43+
T=strutil.TOKENIZER( N:value("description"), "Changes:")
44+
Package.description=string.gsub(T:next(), "\n", " ")
45+
Package.feed="freshcode"
46+
47+
return(Package)
48+
end
49+
50+
51+
function ParseFreshcode(items)
52+
53+
local S, P, doc, item;
54+
55+
S=stream.STREAM("http://freshcode.club/projects.rss");
56+
doc=S:readdoc();
57+
P=dataparser.PARSER("rss",doc);
58+
59+
N=P:open("/")
60+
while N ~=nil
61+
do
62+
if (string.sub(N:name(), 1, 5)=="item:")
63+
then
64+
item=ParseFreshcodeItem(N)
65+
if items[item.name] == nil then items[item.name]=item end
66+
end
67+
N=P:next();
68+
end
69+
70+
end
71+
72+
73+
function ParseFossiesLink(Html)
74+
local Toks, tempstr, len, c
75+
76+
if Html ~= nil
77+
then
78+
Toks=strutil.TOKENIZER(Html, "\\S")
79+
tempstr=Toks:next()
80+
while tempstr ~= nil
81+
do
82+
83+
if string.sub(tempstr, 1, 5)=='href='
84+
then
85+
tempstr=string.sub(tempstr,6)
86+
c=string.sub(tempstr, 1, 1)
87+
len=strutil.strlen(tempstr)
88+
if c=='"' or c=="'"
89+
then
90+
tempstr=string.sub(tempstr, 2, len-1)
91+
end
92+
return(tempstr)
93+
end
94+
95+
tempstr=Toks:next()
96+
end
97+
end
98+
99+
return("")
100+
end
101+
102+
103+
function ParseFossiesItem()
104+
local Package={}
105+
local tempstr, Toks
106+
107+
Package=ParseReleaseRSS(N)
108+
109+
Toks=strutil.TOKENIZER(strutil.htmlUnQuote(N:value("description")), "<|>", "m")
110+
111+
tempstr=Toks:next()
112+
Package.link=ParseFossiesLink(string.lower(Toks:next()))
113+
tempstr=tempstr..Toks:next()
114+
Toks:next()
115+
tempstr=tempstr..Toks:remaining()
116+
Package.description=tempstr
117+
118+
Package.feed="fossies"
119+
120+
return(Package)
121+
end
122+
123+
124+
function ParseFossies(items)
125+
126+
local S, P, doc;
127+
128+
S=stream.STREAM("https://fossies.org/fresh.linux_misc.v.rss");
129+
doc=S:readdoc();
130+
P=dataparser.PARSER("rss",doc);
131+
132+
N=P:open("/")
133+
while N ~=nil
134+
do
135+
if (string.sub(N:name(), 1, 5)=="item:")
136+
then
137+
item=ParseFossiesItem(N)
138+
if items[item.name] == nil then items[item.name]=item end
139+
end
140+
N=P:next();
141+
end
142+
end
143+
144+
145+
function ReleasesSortFunc(r1, r2)
146+
return(r1.date > r2.date)
147+
end
148+
149+
150+
function GetReleases()
151+
local items={}
152+
local sorted={}
153+
local i, item
154+
155+
ParseFossies(items)
156+
ParseFreshcode(items)
157+
158+
--reorganize items into a table where the key values are numeric, so we can use table.sort
159+
i=1
160+
for k,item in pairs(items)
161+
do
162+
sorted[i]=item
163+
i=i+1
164+
end
165+
166+
table.sort(sorted, ReleasesSortFunc)
167+
return(sorted)
168+
end
169+
170+
171+
function DisplaySingleRelease(settings, Package)
172+
local Fmt, age, oldest
173+
174+
oldest=0
175+
if tonumber(settings.days) > 0
176+
then
177+
oldest=tonumber(settings.days) * 24 * 3600
178+
end
179+
180+
age=Now - Package.date
181+
182+
if oldest == 0 or age <= oldest
183+
then
184+
if age <= (24 * 3600)
185+
then
186+
Fmt="~e%Y/%m/%d~0"
187+
today_items=today_items + 1
188+
week_items=week_items + 1
189+
elseif age <= (24 * 2 * 3600)
190+
then
191+
Fmt="~y%Y/%m/%d~0"
192+
week_items=week_items + 1
193+
elseif age < (24 * 7 * 3600) then
194+
Fmt="~c%Y/%m/%d~0"
195+
week_items=week_items + 1
196+
else Fmt="%Y/%m/%d"
197+
end
198+
199+
total_items=total_items+1
200+
Out:puts(time.formatsecs(Fmt, Package.date))
201+
Out:puts(" ~e" .. Package.name .. "~0 ~m" .. Package.version .. "~0 " .. " ("..Package.feed..") ~b"..Package.link.."\n~0")
202+
if settings.text == "y" then
203+
Out:puts(Package.description.."\n")
204+
Out:puts("\n")
205+
end
206+
end
207+
208+
end
209+
210+
211+
function DisplayReleases()
212+
local items, n, Package
213+
214+
items=GetReleases()
215+
for n, Package in pairs(items)
216+
do
217+
DisplaySingleRelease(settings, Package)
218+
end
219+
220+
Out:puts(string.format("~e%d~0 items returned: ~e%d~0 releases today ~e%d~0 releases this week\n", total_items, today_items, week_items))
221+
222+
end
223+
224+
function ProcessWatch(settings, watchlist)
225+
local items, n, Package
226+
227+
items=GetReleases()
228+
for n, Package in pairs(items)
229+
do
230+
231+
if strutil.strlen(watchlist[string.lower(Package.name)]) > 0
232+
then
233+
DisplaySingleRelease(settings, Package)
234+
end
235+
236+
end
237+
238+
239+
end
240+
241+
242+
function DisplayUsage()
243+
244+
print("usage:")
245+
print(" lua releases.lua [options] - display latest releases");
246+
print(" lua releases.lua watch [options] [name] [name] ... - display releases of named packages");
247+
print(" lua releases.lua help - display this help");
248+
print("")
249+
print("options:")
250+
print(" -days <n> - show results for the last 'n' days");
251+
print(" -notext - do not show text description of package");
252+
print(" -? - show this help");
253+
print(" -h - show this help");
254+
print(" -help - show this help");
255+
print(" --help - show this help");
256+
print("")
257+
print("examples:")
258+
print(" lua releases.lua -days 2 - show releases for the last two days")
259+
print(" lua releases.lua -days 1 -notext - show releases for the last 24 hours without descriptions")
260+
print(" lua releases.lua watch wine strace - show releases for the programs 'wine' and 'strace'")
261+
end
262+
263+
264+
function ParseCommandLine(arg)
265+
local act, days, color="y"
266+
local watchlist={}
267+
local settings={}
268+
269+
settings.days=0
270+
settings.color="y"
271+
settings.text="y"
272+
273+
if arg[1]=="help"
274+
then
275+
act="help"
276+
elseif arg[1]=="watch"
277+
then
278+
act="watch"
279+
arg[1]=""
280+
else act="releases"
281+
end
282+
283+
for i,v in ipairs(arg)
284+
do
285+
if v=="-?" or v=="-h" or v=="-help" or v=="--help"
286+
then
287+
act="help"
288+
elseif v=="-days"
289+
then
290+
settings.days=arg[i+1]
291+
arg[i+1]=""
292+
elseif v=="-nocolor"
293+
then
294+
settings.color="n"
295+
arg[i]=""
296+
elseif v=="-notext"
297+
then
298+
settings.text="n"
299+
arg[i]=""
300+
else
301+
watchlist[ string.lower(v) ]=v
302+
end
303+
end
304+
305+
return act, settings, watchlist
306+
end
307+
308+
309+
310+
311+
312+
-- MAIN STARTS HERE --
313+
Now=time.secs()
314+
Out=terminal.TERM()
315+
316+
act,settings,watchlist=ParseCommandLine(arg)
317+
if act=="help"
318+
then
319+
DisplayUsage()
320+
elseif act=="watch"
321+
then
322+
ProcessWatch(settings, watchlist)
323+
else
324+
DisplayReleases(settings)
325+
end

0 commit comments

Comments
 (0)