@xriss/weerss 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd.import.js +2 -0
- package/cmd.js +106 -0
- package/db.js +245 -0
- package/feeds.js +321 -0
- package/hoard.js +85 -0
- package/items.js +188 -0
- package/jxml.js +262 -0
- package/npm-publish +11 -0
- package/package.json +35 -0
- package/register-hooks.js +35 -0
- package/register.js +3 -0
- package/serv.js +21 -0
- package/shows.js +249 -0
- package/torrents.js +116 -0
- package/webpack.config.cjs +61 -0
- package/weerss.js +565 -0
package/cmd.import.js
ADDED
package/cmd.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
|
|
2
|
+
const cmd={}
|
|
3
|
+
export default cmd
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import minimist from "minimist"
|
|
7
|
+
|
|
8
|
+
import path from "path"
|
|
9
|
+
import url from "url"
|
|
10
|
+
|
|
11
|
+
import serv from "./serv.js"
|
|
12
|
+
import db from "./db.js"
|
|
13
|
+
|
|
14
|
+
import hoard from "./hoard.js"
|
|
15
|
+
import feeds from "./feeds.js"
|
|
16
|
+
import items from "./items.js"
|
|
17
|
+
|
|
18
|
+
import weerss from "./weerss.js"
|
|
19
|
+
|
|
20
|
+
const args = minimist(process.argv.slice(2),{boolean:true})
|
|
21
|
+
|
|
22
|
+
args.config=args.config || process.env.WEERSS_CONFIG
|
|
23
|
+
|
|
24
|
+
await weerss.load_config(args)
|
|
25
|
+
|
|
26
|
+
let arg1=args._[0] || "help"
|
|
27
|
+
let arg2=args._[1]
|
|
28
|
+
|
|
29
|
+
if( arg1=="help" )
|
|
30
|
+
{
|
|
31
|
+
console.log(`
|
|
32
|
+
|
|
33
|
+
options:
|
|
34
|
+
|
|
35
|
+
Load config file, you should always load your custom config for all
|
|
36
|
+
of the following commands...
|
|
37
|
+
|
|
38
|
+
--config=weerss.config
|
|
39
|
+
|
|
40
|
+
environment variables can also set options with the prefix WEERSS_
|
|
41
|
+
and the option name in all uppercase. eg:
|
|
42
|
+
|
|
43
|
+
export WEERSS_CONFIG=/home/dave/weerss.config
|
|
44
|
+
|
|
45
|
+
commands:
|
|
46
|
+
|
|
47
|
+
tvrss config
|
|
48
|
+
Print current config.
|
|
49
|
+
|
|
50
|
+
tvrss config FILENAME
|
|
51
|
+
Save current (default?) config to FILENAME.
|
|
52
|
+
|
|
53
|
+
tvrss fetch
|
|
54
|
+
Fetch all feeds and scan files with tvmaze.
|
|
55
|
+
|
|
56
|
+
tvrss list
|
|
57
|
+
List torrents in db.
|
|
58
|
+
|
|
59
|
+
tvrss rss
|
|
60
|
+
Save torrents as rss.
|
|
61
|
+
|
|
62
|
+
tvrss move
|
|
63
|
+
Move downloaded chaotic files to an organised location.
|
|
64
|
+
|
|
65
|
+
tvrss dirs
|
|
66
|
+
Create a script to cleanup TV dirs using tvmaze.
|
|
67
|
+
|
|
68
|
+
tvrss help
|
|
69
|
+
Print this help message.
|
|
70
|
+
|
|
71
|
+
`)
|
|
72
|
+
}
|
|
73
|
+
else
|
|
74
|
+
if( arg1=="config" )
|
|
75
|
+
{
|
|
76
|
+
await weerss.save_config(args)
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
if( arg1=="fetch" )
|
|
80
|
+
{
|
|
81
|
+
await weerss.fetch(args)
|
|
82
|
+
}
|
|
83
|
+
else
|
|
84
|
+
if( arg1=="list" )
|
|
85
|
+
{
|
|
86
|
+
await weerss.list(args)
|
|
87
|
+
}
|
|
88
|
+
else
|
|
89
|
+
if( arg1=="rss" )
|
|
90
|
+
{
|
|
91
|
+
await weerss.save_rss(args)
|
|
92
|
+
}
|
|
93
|
+
else
|
|
94
|
+
if( arg1=="move" )
|
|
95
|
+
{
|
|
96
|
+
await weerss.move(args)
|
|
97
|
+
}
|
|
98
|
+
else
|
|
99
|
+
if( arg1=="dirs" )
|
|
100
|
+
{
|
|
101
|
+
await weerss.dirs(args)
|
|
102
|
+
}
|
|
103
|
+
else
|
|
104
|
+
{
|
|
105
|
+
console.log(` Unknown weerss command "${arg1}" `)
|
|
106
|
+
}
|
package/db.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
|
|
2
|
+
let db={}
|
|
3
|
+
export default db
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import { AsyncDatabase } from "promised-sqlite3"
|
|
7
|
+
|
|
8
|
+
import { configure } from 'safe-stable-stringify'
|
|
9
|
+
const stringify = configure({})
|
|
10
|
+
|
|
11
|
+
import weerss from "./weerss.js"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
db.test=async function()
|
|
15
|
+
{
|
|
16
|
+
await db.setup()
|
|
17
|
+
await db.set(null,"hello","world")
|
|
18
|
+
await db.set(null,"hell","{world:poop}")
|
|
19
|
+
|
|
20
|
+
console.log( await db.list() )
|
|
21
|
+
|
|
22
|
+
await db.close()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
db.name="weerss"
|
|
28
|
+
|
|
29
|
+
db.setup=async function()
|
|
30
|
+
{
|
|
31
|
+
|
|
32
|
+
db.handle = await AsyncDatabase.open( weerss.get_config_path("sqlite_filename") );
|
|
33
|
+
|
|
34
|
+
// db.handle.inner.on("trace", (sql) => console.log("[TRACE]", sql));
|
|
35
|
+
|
|
36
|
+
await db.handle.run("PRAGMA synchronous = 0 ;");
|
|
37
|
+
await db.handle.run("PRAGMA encoding = \"UTF-8\" ;");
|
|
38
|
+
await db.handle.run("PRAGMA journal_mode=WAL;");
|
|
39
|
+
await db.handle.run("PRAGMA mmap_size=268435456;");
|
|
40
|
+
await db.handle.run("PRAGMA temp_store=2;");
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
await db.handle.run(`
|
|
44
|
+
|
|
45
|
+
CREATE TABLE IF NOT EXISTS keyval
|
|
46
|
+
(
|
|
47
|
+
key STRING PRIMARY KEY ,
|
|
48
|
+
value JSONB NOT NULL
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
`);
|
|
52
|
+
|
|
53
|
+
await db.handle.run(`
|
|
54
|
+
|
|
55
|
+
CREATE TABLE IF NOT EXISTS hoard
|
|
56
|
+
(
|
|
57
|
+
key STRING PRIMARY KEY ,
|
|
58
|
+
value JSONB NOT NULL
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
`);
|
|
62
|
+
|
|
63
|
+
await db.handle.run(`
|
|
64
|
+
|
|
65
|
+
CREATE TABLE IF NOT EXISTS feeds
|
|
66
|
+
(
|
|
67
|
+
key STRING PRIMARY KEY ,
|
|
68
|
+
value JSONB NOT NULL
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
`);
|
|
72
|
+
|
|
73
|
+
await db.handle.run(`
|
|
74
|
+
|
|
75
|
+
CREATE TABLE IF NOT EXISTS items
|
|
76
|
+
(
|
|
77
|
+
key STRING PRIMARY KEY ,
|
|
78
|
+
value JSONB NOT NULL
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
`);
|
|
82
|
+
|
|
83
|
+
await db.handle.run(`
|
|
84
|
+
|
|
85
|
+
CREATE TABLE IF NOT EXISTS torrents
|
|
86
|
+
(
|
|
87
|
+
key STRING PRIMARY KEY ,
|
|
88
|
+
value JSONB NOT NULL
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
`);
|
|
92
|
+
|
|
93
|
+
await db.handle.run(`
|
|
94
|
+
|
|
95
|
+
CREATE TABLE IF NOT EXISTS shows
|
|
96
|
+
(
|
|
97
|
+
key STRING PRIMARY KEY ,
|
|
98
|
+
value JSONB NOT NULL
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
`);
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
db.close=async function()
|
|
106
|
+
{
|
|
107
|
+
await db.handle.close()
|
|
108
|
+
db.handle=null
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
db.get=async function(table,key)
|
|
112
|
+
{
|
|
113
|
+
table=table||"keyval"
|
|
114
|
+
let row=await db.handle.get(`
|
|
115
|
+
|
|
116
|
+
SELECT * FROM ${table}
|
|
117
|
+
WHERE key=$key;
|
|
118
|
+
|
|
119
|
+
`,{$key:key})
|
|
120
|
+
return row && row.value && JSON.parse(row.value)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
db.set=async function(table,key,value)
|
|
124
|
+
{
|
|
125
|
+
table=table||"keyval"
|
|
126
|
+
await db.handle.run(`
|
|
127
|
+
|
|
128
|
+
INSERT INTO ${table} (key,value)
|
|
129
|
+
VALUES ($key,$value)
|
|
130
|
+
ON CONFLICT (key)
|
|
131
|
+
DO
|
|
132
|
+
UPDATE SET value = $value
|
|
133
|
+
WHERE key = $key;
|
|
134
|
+
|
|
135
|
+
`,{$key:key,$value:stringify(value)})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
db.clear=async function(table)
|
|
140
|
+
{
|
|
141
|
+
table=table||"keyval"
|
|
142
|
+
await db.handle.run(`
|
|
143
|
+
|
|
144
|
+
DELETE FROM ${table};
|
|
145
|
+
|
|
146
|
+
`,{})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
db.delete=async function(table,key)
|
|
150
|
+
{
|
|
151
|
+
table=table||"keyval"
|
|
152
|
+
await db.handle.run(`
|
|
153
|
+
|
|
154
|
+
DELETE FROM ${table} WHERE key=$key;
|
|
155
|
+
|
|
156
|
+
`,{$key:key})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
db.list=async function(table,filter)
|
|
160
|
+
{
|
|
161
|
+
table=table||"keyval"
|
|
162
|
+
filter=filter || {}
|
|
163
|
+
let rs=[]
|
|
164
|
+
|
|
165
|
+
let filters=[]
|
|
166
|
+
for(let fb in filter)
|
|
167
|
+
{
|
|
168
|
+
let fv=filter[fb]
|
|
169
|
+
if(typeof fv=="Number")
|
|
170
|
+
{
|
|
171
|
+
fv=String(fv)
|
|
172
|
+
}
|
|
173
|
+
else
|
|
174
|
+
{
|
|
175
|
+
fv='"'+String(fv)+'"'
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if(fb.endsWith("_is_null"))
|
|
179
|
+
{
|
|
180
|
+
let f=fb.substring(0,fb.length-8)
|
|
181
|
+
filters.push(" json_extract (value, '$."+f+"') IS NULL ")
|
|
182
|
+
}
|
|
183
|
+
else
|
|
184
|
+
if(fb.endsWith("_is_not_null"))
|
|
185
|
+
{
|
|
186
|
+
let f=fb.substring(0,fb.length-12)
|
|
187
|
+
filters.push(" json_extract (value, '$."+f+"') IS NOT NULL ")
|
|
188
|
+
}
|
|
189
|
+
else
|
|
190
|
+
if(fb.endsWith("_lt"))
|
|
191
|
+
{
|
|
192
|
+
let f=fb.substring(0,fb.length-3)
|
|
193
|
+
filters.push(" json_extract (value, '$."+f+"') < "+fv)
|
|
194
|
+
}
|
|
195
|
+
else
|
|
196
|
+
if(fb.endsWith("_lteq"))
|
|
197
|
+
{
|
|
198
|
+
let f=fb.substring(0,fb.length-5)
|
|
199
|
+
filters.push(" json_extract (value, '$."+f+"') <= "+fv)
|
|
200
|
+
}
|
|
201
|
+
else
|
|
202
|
+
if(fb.endsWith("_gt"))
|
|
203
|
+
{
|
|
204
|
+
let f=fb.substring(0,fb.length-3)
|
|
205
|
+
filters.push(" json_extract (value, '$."+f+"') > "+fv)
|
|
206
|
+
}
|
|
207
|
+
else
|
|
208
|
+
if(fb.endsWith("_gteq"))
|
|
209
|
+
{
|
|
210
|
+
let f=fb.substring(0,fb.length-5)
|
|
211
|
+
filters.push(" json_extract (value, '$."+f+"') >= "+fv)
|
|
212
|
+
}
|
|
213
|
+
else
|
|
214
|
+
if(fb.endsWith("_not"))
|
|
215
|
+
{
|
|
216
|
+
let f=fb.substring(0,fb.length-4)
|
|
217
|
+
filters.push(" json_extract (value, '$."+f+"') != "+fv)
|
|
218
|
+
}
|
|
219
|
+
else
|
|
220
|
+
{
|
|
221
|
+
filters.push(" json_extract (value, '$."+fb+"') = "+fv)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if( filters.length==0 )
|
|
225
|
+
{
|
|
226
|
+
filters=""
|
|
227
|
+
}
|
|
228
|
+
else
|
|
229
|
+
{
|
|
230
|
+
filters="WHERE "+filters.join(" AND\n")
|
|
231
|
+
}
|
|
232
|
+
// console.log(filters)
|
|
233
|
+
|
|
234
|
+
await db.handle.each(`
|
|
235
|
+
|
|
236
|
+
SELECT * FROM ${table}
|
|
237
|
+
${filters}
|
|
238
|
+
|
|
239
|
+
`,{},function(row)
|
|
240
|
+
{
|
|
241
|
+
rs.push(JSON.parse(row.value))
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
return rs // filtered only, sorted by date
|
|
245
|
+
}
|
package/feeds.js
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
|
|
2
|
+
let feeds={}
|
|
3
|
+
export default feeds
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import items from "./items.js"
|
|
7
|
+
import db from "./db.js"
|
|
8
|
+
import jxml from "./jxml.js"
|
|
9
|
+
import hoard from "./hoard.js"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import { configure } from 'safe-stable-stringify'
|
|
13
|
+
const stringify = configure({})
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
feeds.cached={}
|
|
17
|
+
|
|
18
|
+
feeds.precache=async function() // faster then individual cache, db is fecking slow
|
|
19
|
+
{
|
|
20
|
+
for(let feed of await db.list("feeds"))
|
|
21
|
+
{
|
|
22
|
+
feeds.cache(feed.url,feed)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
feeds.cache=async function(url,feed) // probably fast
|
|
27
|
+
{
|
|
28
|
+
if(feed) { feeds.cached[url]=feed ; return feed }
|
|
29
|
+
if(feeds.cached[url]) { return feeds.cached[url] }
|
|
30
|
+
await feeds.get(url)
|
|
31
|
+
return feeds.cached[url]
|
|
32
|
+
}
|
|
33
|
+
feeds.get=async function(url) // always slow
|
|
34
|
+
{
|
|
35
|
+
let feed=await db.get("feeds",url)
|
|
36
|
+
if(feed) { feeds.cache(feed.url,feed) }
|
|
37
|
+
return feed
|
|
38
|
+
}
|
|
39
|
+
feeds.set=async function(feed)
|
|
40
|
+
{
|
|
41
|
+
await db.set("feeds",feed.url,feed)
|
|
42
|
+
if(feed) { feeds.cache(feed.url,feed) }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
feeds.prepare=function(feed)
|
|
46
|
+
{
|
|
47
|
+
let atom=feed.atom||{}
|
|
48
|
+
let rss=feed.rss||{}
|
|
49
|
+
|
|
50
|
+
if(rss["/rss/channel/title"])
|
|
51
|
+
{
|
|
52
|
+
feed.title=rss["/rss/channel/title"]
|
|
53
|
+
}
|
|
54
|
+
else
|
|
55
|
+
if(atom["/feed/title"])
|
|
56
|
+
{
|
|
57
|
+
feed.title=atom["/feed/title"]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if(rss["/rss/channel/pubdate"])
|
|
61
|
+
{
|
|
62
|
+
feed.date=new Date(rss["/rss/channel/pubdate"])
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
if(atom["/feed/updated"])
|
|
66
|
+
{
|
|
67
|
+
feed.date=new Date(atom["/feed/updated"])
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return feed
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
feeds.add=async function(it)
|
|
74
|
+
{
|
|
75
|
+
let old=await feeds.cache(it.url) // await db.get("feeds",it.url)
|
|
76
|
+
|
|
77
|
+
let feed={} // merge old and new here
|
|
78
|
+
if(old)
|
|
79
|
+
{
|
|
80
|
+
for(let n in old ){ feed[n]=old[n] }
|
|
81
|
+
}
|
|
82
|
+
for(let n in it ){ feed[n]=it[n] }
|
|
83
|
+
// maintain defaults
|
|
84
|
+
feed.date=feed.date || new Date()
|
|
85
|
+
feed.fails=feed.fails || 0
|
|
86
|
+
|
|
87
|
+
if( stringify(old) != stringify(feed) ) // something changed
|
|
88
|
+
{
|
|
89
|
+
await feeds.set(feed)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
feeds.add_opml=async function(data,url)
|
|
95
|
+
{
|
|
96
|
+
if(url){data=await hoard.fetch_text(url,true)}
|
|
97
|
+
if(!data){return}
|
|
98
|
+
let jsn=jxml.parse_xml(data,jxml.xmap.opml)
|
|
99
|
+
//console.log(jsn)
|
|
100
|
+
|
|
101
|
+
let check;check=async function(it)
|
|
102
|
+
{
|
|
103
|
+
if( it["@xmlurl"] )
|
|
104
|
+
{
|
|
105
|
+
let feed={}
|
|
106
|
+
feed.url=it["@xmlurl"]
|
|
107
|
+
await feeds.add(feed)
|
|
108
|
+
}
|
|
109
|
+
if(it["/outline"]) // check sub outlines
|
|
110
|
+
{
|
|
111
|
+
for(let it2 of it["/outline"] )
|
|
112
|
+
{
|
|
113
|
+
await check(it2)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if( jsn["/opml/body/outline"] )
|
|
119
|
+
{
|
|
120
|
+
for(let it of jsn["/opml/body/outline"] )
|
|
121
|
+
{
|
|
122
|
+
await check(it)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else
|
|
126
|
+
if( jsn["/rss/channel/item/title"] ) // looks like a rss
|
|
127
|
+
{
|
|
128
|
+
if(url) // so subscribe to this url
|
|
129
|
+
{
|
|
130
|
+
let feed={}
|
|
131
|
+
feed.url=url
|
|
132
|
+
await feeds.add(feed)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else
|
|
136
|
+
if( jsn["/feed/entry/title"] ) // looks like attom
|
|
137
|
+
{
|
|
138
|
+
if(url) // so subscribe to this url
|
|
139
|
+
{
|
|
140
|
+
let feed={}
|
|
141
|
+
feed.url=url
|
|
142
|
+
await feeds.add(feed)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
feeds.build_opml=async function()
|
|
148
|
+
{
|
|
149
|
+
let j={
|
|
150
|
+
"/opml/head/title": "RERSS filter",
|
|
151
|
+
"/opml@version": "1.0",
|
|
152
|
+
"/opml/body/outline": [],
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
let out=j["/opml/body/outline"]
|
|
156
|
+
|
|
157
|
+
let feeds=await db.list("feeds")
|
|
158
|
+
let now=(new Date()).getTime()
|
|
159
|
+
|
|
160
|
+
for(let feed of feeds)
|
|
161
|
+
{
|
|
162
|
+
if(!feed.off) // disabled feeds are not exported
|
|
163
|
+
{
|
|
164
|
+
let it={}
|
|
165
|
+
it["@type"]="rss"
|
|
166
|
+
it["@xmlUrl"]=feed.url
|
|
167
|
+
it["@text"]=feed.title
|
|
168
|
+
it["@title"]=feed.title
|
|
169
|
+
out.push(it)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
let x=jxml.build_xml(j)
|
|
173
|
+
return x
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
feeds.load_opml=async function()
|
|
177
|
+
{
|
|
178
|
+
/*
|
|
179
|
+
let data=await gist.read("weerss.opml")
|
|
180
|
+
await feeds.add_opml(data)
|
|
181
|
+
*/
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
feeds.save_opml=async function()
|
|
185
|
+
{
|
|
186
|
+
/*
|
|
187
|
+
let data=await feeds.build_opml()
|
|
188
|
+
await gist.write("weerss.opml",data)
|
|
189
|
+
*/
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
feeds.list_length=0
|
|
193
|
+
feeds.list_length_count=0
|
|
194
|
+
feeds.fetch_all=async function()
|
|
195
|
+
{
|
|
196
|
+
console.log("starting feeds fetch_all")
|
|
197
|
+
|
|
198
|
+
let rets=[]
|
|
199
|
+
let list=await db.list("feeds")
|
|
200
|
+
|
|
201
|
+
feeds.list_length=list.length
|
|
202
|
+
feeds.list_length_count=0
|
|
203
|
+
|
|
204
|
+
// try and get popular feeds first
|
|
205
|
+
list.sort(function(a,b){
|
|
206
|
+
return ( b.items_date || 0 ) - ( a.items_date || 0 )
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
let topitem=(await db.list("items",{},"date","prev",1))[0] ; topitem=topitem && topitem.uuid
|
|
210
|
+
|
|
211
|
+
for(let feed of list )
|
|
212
|
+
{
|
|
213
|
+
await feeds.cache(feed.url,feed)
|
|
214
|
+
await feeds.fetch(feed)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if(items.add_count>0)
|
|
218
|
+
{
|
|
219
|
+
console.log("+"+items.add_count)
|
|
220
|
+
}
|
|
221
|
+
else
|
|
222
|
+
{
|
|
223
|
+
console.log("")
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
feeds.fetch=async function(feed)
|
|
229
|
+
{
|
|
230
|
+
console.log(feeds.list_length_count +"/"+ feeds.list_length + " +"+items.add_count)
|
|
231
|
+
if(!feed.off) // check if the feed is turned off
|
|
232
|
+
{
|
|
233
|
+
try{
|
|
234
|
+
|
|
235
|
+
console.log("fetching feed",feed.url)
|
|
236
|
+
let before_count=items.add_count
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
let txt=await hoard.fetch_text(feed.url)
|
|
240
|
+
|
|
241
|
+
let e1,e2
|
|
242
|
+
try{ feed.rss=jxml.parse_xml(txt,jxml.xmap.rss) }
|
|
243
|
+
catch(e){e1=e}
|
|
244
|
+
|
|
245
|
+
try{ feed.atom=jxml.parse_xml(txt,jxml.xmap.atom) }
|
|
246
|
+
catch(e){e2=e}
|
|
247
|
+
|
|
248
|
+
if( e1 && e2 ) // something really went wrong
|
|
249
|
+
{
|
|
250
|
+
console.log(e1)
|
|
251
|
+
console.log(e2)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
feeds.prepare(feed)
|
|
255
|
+
|
|
256
|
+
// feed.items_date date is date of most recent item we have seen in the feed
|
|
257
|
+
let check_date=function(it)
|
|
258
|
+
{
|
|
259
|
+
if(it.date)
|
|
260
|
+
{
|
|
261
|
+
if(feed.items_date)
|
|
262
|
+
{
|
|
263
|
+
if( feed.items_date < it.date )
|
|
264
|
+
{
|
|
265
|
+
feed.items_date=it.date
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else
|
|
269
|
+
{
|
|
270
|
+
feed.items_date=it.date
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if(feed.rss && feed.rss["/rss/channel/item"])
|
|
276
|
+
{
|
|
277
|
+
feed.items_count=0
|
|
278
|
+
for(let rss_item of feed.rss["/rss/channel/item"] )
|
|
279
|
+
{
|
|
280
|
+
let item={rss:rss_item}
|
|
281
|
+
feed.items_count++
|
|
282
|
+
items.prepare(item,feed)
|
|
283
|
+
check_date(item)
|
|
284
|
+
await items.add(item)
|
|
285
|
+
// await hoard.first_text(item.link)
|
|
286
|
+
}
|
|
287
|
+
feed.fails=0
|
|
288
|
+
}
|
|
289
|
+
else
|
|
290
|
+
if(feed.atom && feed.atom["/feed/entry"])
|
|
291
|
+
{
|
|
292
|
+
feed.items_count=0
|
|
293
|
+
for(let atom_entry of feed.atom["/feed/entry"] )
|
|
294
|
+
{
|
|
295
|
+
let item={atom:atom_entry}
|
|
296
|
+
feed.items_count++
|
|
297
|
+
items.prepare(item,feed)
|
|
298
|
+
check_date(item)
|
|
299
|
+
await items.add(item)
|
|
300
|
+
// await hoard.first_text(item.link)
|
|
301
|
+
}
|
|
302
|
+
feed.fails=0
|
|
303
|
+
}
|
|
304
|
+
else
|
|
305
|
+
{
|
|
306
|
+
feed.fails=(feed.fails||0)+1
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
await db.set("feeds",feed.url,feed) // save updated feed info
|
|
310
|
+
|
|
311
|
+
let count=items.add_count-before_count
|
|
312
|
+
if(count>0)
|
|
313
|
+
{
|
|
314
|
+
console.log("added "+count+" new items")
|
|
315
|
+
}
|
|
316
|
+
}catch(e){console.error(e)}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
feeds.list_length_count++
|
|
320
|
+
}
|
|
321
|
+
|