@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/weerss.js ADDED
@@ -0,0 +1,565 @@
1
+
2
+ const weerss={}
3
+ export default weerss
4
+
5
+ //import serv from "./serv.js"
6
+
7
+ import db from "./db.js"
8
+ import jxml from "./jxml.js"
9
+
10
+ import hoard from "./hoard.js"
11
+ import feeds from "./feeds.js"
12
+ import items from "./items.js"
13
+ import torrents from "./torrents.js"
14
+ import shows from "./shows.js"
15
+
16
+
17
+ import util from "util"
18
+ import {moveFile} from 'move-file'
19
+
20
+ import fs from "fs"
21
+ import path from "path"
22
+
23
+ import sanitize from "sanitize-filename"
24
+
25
+
26
+ import djon from "@xriss/djon"
27
+
28
+
29
+
30
+ weerss.config_default=`
31
+ {
32
+ debug = FALSE
33
+ feeds = [
34
+ "https://archive.org/services/collection-rss.php?collection=television_inbox"
35
+ ]
36
+ rss = {
37
+ length = 100
38
+ }
39
+ show = {
40
+ rules = [
41
+ [ TRUE ]
42
+ [ "!english" FALSE ]
43
+ ]
44
+ }
45
+ episode = {
46
+ best = "small"
47
+ maxsize = 4000000000
48
+ minsize = 1000000
49
+ rules = [
50
+ [ TRUE ]
51
+ [ "480p" FALSE ]
52
+ ]
53
+ }
54
+ sqlite_filename = "./weerss.sqlite"
55
+ download_dirname = "./download"
56
+ tv_dirname = "./TV"
57
+ }
58
+ `
59
+
60
+ weerss.config=djon.load(weerss.config_default)
61
+
62
+ weerss.load_config=async function(args)
63
+ {
64
+ if(args.config)
65
+ {
66
+ if( fs.existsSync(args.config) ) // only load if files exists
67
+ {
68
+ console.log(` Loading config from `+args.config)
69
+ weerss.config=djon.load_file(args.config)
70
+
71
+ let def=djon.load(weerss.config_default)
72
+ for(let n in def )
73
+ {
74
+ if( typeof weerss.config[n] == "undefined" ) // use defaults
75
+ {
76
+ weerss.config[n] = def[n]
77
+ }
78
+ }
79
+ }
80
+ else // reset
81
+ {
82
+ weerss.config=djon.load(weerss.config_default)
83
+ }
84
+ }
85
+ for(let n in args ) // set from args
86
+ {
87
+ if(n!="_")
88
+ {
89
+ weerss.config[n]=args[n]
90
+ }
91
+ }
92
+ }
93
+
94
+ weerss.save_config=async function(args)
95
+ {
96
+ if( args._[1] )
97
+ {
98
+ let fname=args._[1]
99
+ console.log(` Saving config to `+fname)
100
+ if(args.config) // loading a config
101
+ {
102
+ djon.save_file(fname,weerss.config,"djon","strict")
103
+ }
104
+ else // save default
105
+ {
106
+ fs.writeFileSync( fname , weerss.config_default )
107
+ }
108
+ return
109
+ }
110
+
111
+ console.log( djon.save(weerss.config,"djon","strict") )
112
+ }
113
+
114
+ weerss.get_config_path=function(name)
115
+ {
116
+ let d
117
+ if( weerss.config.config ) // relative to config path
118
+ {
119
+ d=path.dirname( path.resolve(weerss.config.config) )
120
+ }
121
+ else
122
+ {
123
+ d=path.resolve( "." )
124
+ }
125
+
126
+ let f=weerss.config[name] || "."
127
+ if( ! f.startsWith("/" ) )
128
+ {
129
+ f=path.join( d , f )
130
+ }
131
+
132
+ return f
133
+ }
134
+
135
+ //console.log( djon.save(weerss.config) )
136
+
137
+
138
+ let item_to_string=function(item)
139
+ {
140
+ let torrent=item.torrent || {}
141
+ let show=item.show || {}
142
+ let tvmaze=show.tvmaze || {}
143
+ let siz=Math.floor((torrent.file_length||0)/(1024*1024)).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")+".MB"
144
+ let SxxExx=("S"+(show.season||0).toString().padStart(2, "0")+"E"+(show.episode||0).toString().padStart(2, "0") )
145
+ return ( siz.padStart(9, " ")+" "+(tvmaze.name||torrent.file_name||item.uuid)+" "+SxxExx)
146
+ }
147
+
148
+ weerss.fetch=async function()
149
+ {
150
+ await db.setup()
151
+ // db.clear("hoard") // delete cache on startup
152
+
153
+ for(let feed of await db.list("feeds") )
154
+ {
155
+ let keep=false
156
+ for(let url of weerss.config.feeds)
157
+ {
158
+ if(url==feed.url)
159
+ {
160
+ keep=true
161
+ }
162
+ }
163
+ if(!keep)
164
+ {
165
+ console.log("removing old feed",feed.url)
166
+ await db.delete("feeds",feed.url)
167
+ }
168
+ }
169
+
170
+
171
+ for(let url of weerss.config.feeds)
172
+ {
173
+ await feeds.add({url:url})
174
+ }
175
+ await feeds.fetch_all()
176
+
177
+ {
178
+ let its=await db.list("items",{torrent_is_null:1})
179
+ console.log("Checking torrents : "+its.length)
180
+ for(let item of its)
181
+ {
182
+ console.log(item.uuid)
183
+ await torrents.fill_torrent(item)
184
+ console.log(item.torrent)
185
+ items.set(item)
186
+ }
187
+ }
188
+
189
+ {
190
+ let its=await db.list("items",{show_is_null:1,torrent_is_not_null:1})
191
+ console.log("Checking shows : "+its.length)
192
+ for(let item of its)
193
+ {
194
+ await shows.fill_show(item)
195
+
196
+ console.log( item_to_string(item) )
197
+
198
+ items.set(item)
199
+ }
200
+ }
201
+
202
+ await db.close()
203
+ }
204
+
205
+ weerss.getlist=async function()
206
+ {
207
+ // all items then we sort and filter and list
208
+ let its=await db.list("items",{})
209
+
210
+ let buckets={}
211
+ let itemshows={}
212
+
213
+ for(let item of its)
214
+ {
215
+ if(!item.show) { continue }
216
+ // if(!item.show.tvmaze) { continue }
217
+ if(item.show.fail) { continue }
218
+
219
+ // let bid=item.show.id+"_"+item.show.season+"_"+item.show.episode
220
+
221
+ let SxxExx=("S"+item.show.season.toString().padStart(2, "0")+"E"+item.show.episode.toString().padStart(2, "0") )
222
+
223
+ if(!buckets[item.show.id]){buckets[item.show.id]={}}
224
+ if(!buckets[item.show.id][SxxExx]){buckets[item.show.id][SxxExx]=[]}
225
+
226
+ buckets[item.show.id][SxxExx].push(item)
227
+
228
+ itemshows[item.show.id] = item.show
229
+ }
230
+
231
+ let list=[]
232
+ for( let showid in itemshows )
233
+ {
234
+ let show=itemshows[showid]
235
+
236
+ if( show.tvmaze )
237
+ {
238
+ if( ! shows.good_show(show,weerss.config.show.rules) ) // skip this show?
239
+ {
240
+ continue
241
+ }
242
+ // console.log("SHOW : "+show.tvmaze.name+" + "+(show.tvmaze.type+" "+show.tvmaze.genres.join(" ")).toLowerCase() )
243
+
244
+ for( let SxxExx in buckets[showid] )
245
+ {
246
+ let bucket=buckets[showid][SxxExx]
247
+ // console.log( SxxExx + " x " + bucket.length )
248
+ if( weerss.config.episode.best == "small" )
249
+ {
250
+ bucket.sort(function(a,b){
251
+ return a.torrent.file_length - b.torrent.file_length
252
+ })
253
+ }
254
+ else
255
+ if( weerss.config.episode.best == "large" )
256
+ {
257
+ bucket.sort(function(a,b){
258
+ return b.torrent.file_length - a.torrent.file_length
259
+ })
260
+ }
261
+ else
262
+ {
263
+ error("unknown config.episode.best option")
264
+ }
265
+
266
+ while( bucket.length>0 ) // be real picky about size
267
+ {
268
+ if( bucket[ bucket.length-1 ].torrent.file_length > weerss.config.episode.maxsize ) // 3GB
269
+ {
270
+ bucket.pop()
271
+ }
272
+ else
273
+ if( bucket[ 0 ].torrent.file_length < weerss.config.episode.minsize ) // 3GB
274
+ {
275
+ bucket.shift()
276
+ }
277
+ else
278
+ {
279
+ break
280
+ }
281
+ }
282
+ while( bucket.length>0 ) // check episode flags
283
+ {
284
+ if( ! shows.good_episode(bucket[ 0 ].show,weerss.config.episode.rules) ) // skip this episode?
285
+ {
286
+ bucket.shift() // remove
287
+ }
288
+ else
289
+ {
290
+ break
291
+ }
292
+ }
293
+ // console.log(aa.join(" "))
294
+ // console.log(bucket[0].show.tags.join(" ") + " : " + Math.floor(bucket[0].torrent.file_length/(1024*1024)) )
295
+ if( bucket[0] )
296
+ {
297
+ list.push( bucket[0] )
298
+ }
299
+ }
300
+ }
301
+ else
302
+ {
303
+ // console.log("UNKNOWN : "+show.name)
304
+ }
305
+ }
306
+ list.sort( function(a,b){
307
+ return new Date(b.date) - new Date(a.date)
308
+ })
309
+ return list
310
+ }
311
+
312
+ weerss.list=async function(args)
313
+ {
314
+ await db.setup()
315
+
316
+ let list=(await weerss.getlist())
317
+ for(let item of list)
318
+ {
319
+ console.log( item_to_string(item))
320
+ }
321
+
322
+ await db.close()
323
+ }
324
+
325
+ weerss.save_rss=async function(args)
326
+ {
327
+ await db.setup()
328
+
329
+ let dates=(new Date()).toUTCString()
330
+ let rss_items=[]
331
+ let dat={
332
+ "/rss@version" : "2.0" ,
333
+ "/rss/channel/language" : "en-us" ,
334
+ "/rss/channel/lastBuildDate" : dates ,
335
+ "/rss/channel/pubDate" : dates ,
336
+ "/rss/channel/description" : "RERSS" ,
337
+ "/rss/channel/generator" : "RERSS" ,
338
+ "/rss/channel/link" : "RERSS" ,
339
+ "/rss/channel/title" : "RERSS" ,
340
+ "/rss/channel/item" : rss_items ,
341
+ }
342
+
343
+ let push_item=function(item)
344
+ {
345
+ if(!item.torrent) { return }
346
+
347
+ let url=item.torrent.torrent_name
348
+
349
+ let dates=(new Date(item.date)).toUTCString()
350
+ let isodates=(new Date(item.date)).toISOString()
351
+
352
+ let it={
353
+ "/guid" : url ,
354
+ "/link" : url ,
355
+ "/pubDate" : dates ,
356
+ "/size" : item.torrent.torrent_length ,
357
+ "/title" : item_to_string(item) ,
358
+ "/description" : item_to_string(item) ,
359
+ "/enclosure" : [
360
+ {
361
+ "@length" : item.torrent.torrent_length ,
362
+ "@type" : "application/x-bittorrent" ,
363
+ "@url" : url
364
+ }
365
+ ] ,
366
+ }
367
+ rss_items.push(it)
368
+ }
369
+
370
+ let list=(await weerss.getlist(weerss.config.show.rules)).slice(0,100)
371
+ for(let item of list)
372
+ {
373
+ push_item(item)
374
+ }
375
+
376
+
377
+ if( args._[1] )
378
+ {
379
+ let fname=args._[1]
380
+ console.log(` Saving rss to `+fname)
381
+
382
+ fs.writeFileSync( fname , jxml.build_xml(dat) )
383
+ }
384
+ else
385
+ {
386
+ process.stdout.write( jxml.build_xml(dat) )
387
+ }
388
+
389
+ await db.close()
390
+ }
391
+
392
+
393
+ weerss.move=async function(args)
394
+ {
395
+
396
+ let from=weerss.get_config_path("download_dirname") //args._[2] // optional dest dir
397
+ let dest=weerss.get_config_path("tv_dirname") //args._[2] // optional dest dir
398
+
399
+ dest=null // do not move
400
+
401
+ if(dest)
402
+ {
403
+ console.log( "Moving file from "+from+" to "+dest )
404
+ }
405
+ else
406
+ {
407
+ console.log( "Testing moving files from "+from )
408
+ }
409
+
410
+ await db.setup()
411
+
412
+ let getallfiles=function(dir, a)
413
+ {
414
+ a = a || []
415
+ let aa = fs.readdirSync(dir)
416
+ aa.forEach(
417
+ function(file)
418
+ {
419
+ if (fs.statSync(dir + "/" + file).isDirectory())
420
+ {
421
+ a = getallfiles(dir + "/" + file, a)
422
+ }
423
+ else
424
+ {
425
+ a.push(path.join(dir, "/", file))
426
+ }
427
+ }
428
+ )
429
+ return a
430
+ }
431
+
432
+ let files=getallfiles( from )
433
+
434
+ let exts={}
435
+ for( let e of ["mov","avi","mp4","wmv","webm","flv","mkv","vob","ogv","mpg","mpeg"] )
436
+ { exts["."+e]=true }
437
+
438
+ for( let file of files )
439
+ {
440
+ try{ // continue if we get file errors?
441
+
442
+ let ext=path.extname(file).toLowerCase()
443
+ let base=path.basename(file)
444
+ if( exts[ext] )
445
+ {
446
+ let show=await shows.get_show(base+ext)
447
+ if( show )
448
+ {
449
+ let xtra=""
450
+ if(show.year)
451
+ {
452
+ xtra=xtra+" ("+show.year+")"
453
+ }
454
+
455
+ let SxxExx=("S"+show.season.toString().padStart(2, "0")+"E"+show.episode.toString().padStart(2, "0") )
456
+
457
+ // console.log(base , show.tvmaze.name , show.season , show.episode)
458
+ let showname=show.tvmaze.name.replace(/[/\\?%*:|"<>]/g, "-") // remove problematic chars
459
+ let to = showname+xtra+"/Season "+show.season+"/"+showname+" "+SxxExx+ext
460
+ console.log(file)
461
+
462
+ if( dest )
463
+ {
464
+ to=path.join(dest , to)
465
+ await moveFile(file,to)
466
+ console.log("\t"+to)
467
+ }
468
+ else
469
+ {
470
+ console.log("\t"+to)
471
+ }
472
+ }
473
+ }
474
+
475
+ }catch(e){console.log(e)}
476
+ }
477
+
478
+
479
+
480
+ await db.close()
481
+ }
482
+
483
+
484
+ weerss.dirs=async function(args)
485
+ {
486
+ let dest=weerss.get_config_path("tv_dirname")
487
+
488
+
489
+ await db.setup()
490
+
491
+ let getdirs=function(dir, a)
492
+ {
493
+ a = a || []
494
+ let aa = fs.readdirSync(dir)
495
+ aa.forEach(
496
+ function(file)
497
+ {
498
+ if (fs.statSync(dir + "/" + file).isDirectory())
499
+ {
500
+ a.push(path.join(file))
501
+ }
502
+ }
503
+ )
504
+ return a
505
+ }
506
+
507
+ let files=getdirs(dest)
508
+
509
+ for( let file of files )
510
+ {
511
+ // if( ! file.match(/\((\d\d\d\d)\)/) ) { continue }
512
+
513
+ try{ // continue if we get file errors?
514
+
515
+ let escfile=`'${file.replace(/'/g, `'\\''`)}'`
516
+
517
+ // console.log(file)
518
+ let show={
519
+ name:shows.clean_name(file),
520
+ tags:[],
521
+ season:0,
522
+ episode:0,
523
+ }
524
+ await shows.get_tvmaze(show,true)
525
+
526
+ // console.log(show.tvmaze)
527
+ console.log(`echo ${escfile}`)
528
+ if( show.tvmaze )
529
+ {
530
+ let tvname=sanitize(show.tvmaze.name)
531
+ let year=file.match(/\((\d\d\d\d)\)/);
532
+ year=year && year[1]
533
+ if(year)
534
+ {
535
+ tvname=tvname+" ("+year+")" // keep year in dirname
536
+ }
537
+ let esctvname=`'${tvname.replace(/'/g, `'\\''`)}'`
538
+ let good=shows.good_show(show,weerss.config.show.rules)
539
+ if(good)
540
+ {
541
+ if(file!=tvname)
542
+ {
543
+ console.log(`cp -rl ${escfile} ${esctvname}`)
544
+ console.log(`rm -rf ${escfile}`)
545
+ }
546
+ }
547
+ else
548
+ {
549
+ console.log(`rm -rf ${escfile}`)
550
+ }
551
+ }
552
+ else
553
+ {
554
+ console.log(`rm -rf ${escfile}`)
555
+ }
556
+
557
+ await new Promise(resolve => setTimeout(resolve, 500))
558
+
559
+ }catch(e){console.log(e)}
560
+ }
561
+
562
+
563
+
564
+ await db.close()
565
+ }