xget 2.1.1 → 2.1.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.
- checksums.yaml +4 -4
- data/bin/xget +319 -321
- data/xget.rb +319 -321
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 83fdd3d062e8a390cfcfa6ae370b0a8e60b13f0c
|
|
4
|
+
data.tar.gz: 03e0bdbe3fe72a6218c267e23f523538273cd71c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ee5154095a6fca530c8d305ec6b2600d606e74338e483605232e93c5816754111b29a6c1c5cd56e4d983eda57237cee58e649c7a6a5b0e9bad18367399b2c9a
|
|
7
|
+
data.tar.gz: d1d5ac5df98bb374e06b4383009c99ecf9913456898a061cf10c6e76efd4acd74eb2f6491f41daf9d2c305f7160f3e04263e9d589f1991a45b9f2ced8dc6e01a
|
data/bin/xget
CHANGED
|
@@ -321,391 +321,389 @@ rescue EOFError, SocketError => e
|
|
|
321
321
|
puts "\n! ERROR: #{File.basename fname} failed to download! #{e}"
|
|
322
322
|
end
|
|
323
323
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
o.bool '-h', '--help', 'Prints help'
|
|
328
|
-
|
|
329
|
-
o.on '-v', '--version', 'Print version' do
|
|
330
|
-
puts "#{$0}: v#{$ver_str}"
|
|
331
|
-
exit
|
|
332
|
-
end
|
|
324
|
+
opts = Slop.parse do |o|
|
|
325
|
+
o.banner = " Usage: #{$0} [options] [value] [links] [--files] [file1:file2:file3]\n"
|
|
326
|
+
o.bool '-h', '--help', 'Prints help'
|
|
333
327
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
o.string '--nick', 'IRC nick'
|
|
337
|
-
o.string '--pass', 'IRC \'PASS\' for Ident'
|
|
338
|
-
o.string '--realname', 'Realname for \'USER\' Ident'
|
|
339
|
-
o.string '--nickserv', 'Password for Nickserv'
|
|
340
|
-
o.array '--files', 'Pass list of files to parse for links', as: Array, delimiter: ':'
|
|
341
|
-
o.string '--out-dir', 'Output directory to save fiels to', :default => "./"
|
|
342
|
-
o.bool '--skip-existing', 'Don\' download files that already exist'
|
|
343
|
-
o.bool '--allow-queueing', 'Wait for pack to start downloading rather than fail immediately when queued'
|
|
344
|
-
o.int '--sleep-interval', 'Time in seconds to sleep before requesting next pack. Zero for no sleep.'
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
if opts.help?
|
|
348
|
-
puts opts
|
|
349
|
-
puts "\n Examples"
|
|
350
|
-
puts " \txget.rb --config config.conf --nick test"
|
|
351
|
-
puts " \txget.rb --files test1.txt:test2.txt:test3.txt"
|
|
352
|
-
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/1"
|
|
353
|
-
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/41..46"
|
|
354
|
-
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/41..46|2"
|
|
355
|
-
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/41..46&49..52|2&30"
|
|
328
|
+
o.on '-v', '--version', 'Print version' do
|
|
329
|
+
puts "#{$0}: v#{$ver_str}"
|
|
356
330
|
exit
|
|
357
331
|
end
|
|
358
332
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
333
|
+
o.string '--config', 'Config file location'
|
|
334
|
+
o.string '--user', 'IRC \'USER\' for Ident'
|
|
335
|
+
o.string '--nick', 'IRC nick'
|
|
336
|
+
o.string '--pass', 'IRC \'PASS\' for Ident'
|
|
337
|
+
o.string '--realname', 'Realname for \'USER\' Ident'
|
|
338
|
+
o.string '--nickserv', 'Password for Nickserv'
|
|
339
|
+
o.array '--files', 'Pass list of files to parse for links', as: Array, delimiter: ':'
|
|
340
|
+
o.string '--out-dir', 'Output directory to save fiels to', :default => "./"
|
|
341
|
+
o.bool '--skip-existing', 'Don\' download files that already exist'
|
|
342
|
+
o.bool '--allow-queueing', 'Wait for pack to start downloading rather than fail immediately when queued'
|
|
343
|
+
o.int '--sleep-interval', 'Time in seconds to sleep before requesting next pack. Zero for no sleep.'
|
|
344
|
+
end
|
|
365
345
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
346
|
+
if opts.help?
|
|
347
|
+
puts opts
|
|
348
|
+
puts "\n Examples"
|
|
349
|
+
puts " \txget.rb --config config.conf --nick test"
|
|
350
|
+
puts " \txget.rb --files test1.txt:test2.txt:test3.txt"
|
|
351
|
+
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/1"
|
|
352
|
+
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/41..46"
|
|
353
|
+
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/41..46|2"
|
|
354
|
+
puts " \txget.rb #news@irc.rizon.net/ginpachi-sensei/41..46&49..52|2&30"
|
|
355
|
+
exit
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# Get the config location
|
|
359
|
+
config_loc = opts["config"]
|
|
360
|
+
config_loc = File.expand_path config_loc unless config_loc.nil?
|
|
361
|
+
if config_loc.nil? or not File.exists? config_loc
|
|
362
|
+
config_loc = File.expand_path "~/.xget.conf"
|
|
363
|
+
config_loc = ".xget.conf" unless File.exists? config_loc
|
|
364
|
+
|
|
365
|
+
unless File.exists? config_loc
|
|
366
|
+
puts "ERROR! Invalid config path '#{config_loc}''. Exiting!"
|
|
367
|
+
exit
|
|
370
368
|
end
|
|
369
|
+
end
|
|
371
370
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
# Check if specified output directory actually exists
|
|
380
|
-
puts_abort "Out directory, \"#{opts["out-dir"]}\" doesn't exist!" unless Dir.exists? opts["out-dir"]
|
|
381
|
-
config["out-dir"] = opts["out-dir"].dup
|
|
382
|
-
config["out-dir"] << "/" unless config["out-dir"][-1] == "/"
|
|
383
|
-
|
|
384
|
-
# Parse config
|
|
385
|
-
config_copies = {}
|
|
386
|
-
File.open(config_loc, "r").each_line do |line|
|
|
387
|
-
next if line.length <= 1 or line[0] == '#'
|
|
388
|
-
|
|
389
|
-
if line =~ /^\[(\S+)\]$/ # Check if header
|
|
390
|
-
cur_block = $1
|
|
391
|
-
if cur_block.include? ',' # Check if header contains more than one server
|
|
392
|
-
tmp_split = cur_block.split(",")
|
|
393
|
-
next unless tmp_split[0] =~ /^(\w+?).(\w+?).(\w+?)$/
|
|
394
|
-
config_copies[tmp_split[0]] = []
|
|
395
|
-
tmp_split.each do |x| # Add all copies to copies hash
|
|
396
|
-
next if x == tmp_split[0] or not x =~ /^(\w+?).(\w+?).(\w+?)$/
|
|
397
|
-
config_copies[tmp_split[0]].push x unless config_copies[tmp_split[0]].include? x
|
|
398
|
-
end
|
|
399
|
-
cur_block = tmp_split[0]
|
|
400
|
-
end
|
|
371
|
+
# Insert config settings from arguments into config hash
|
|
372
|
+
cur_block = "*"
|
|
373
|
+
config["servers"][cur_block] = {}
|
|
374
|
+
%w(user nick pass real nserv).each do |x|
|
|
375
|
+
config["servers"][cur_block][x.to_sym] = opts[x] unless opts[x].nil?
|
|
376
|
+
end
|
|
401
377
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
378
|
+
# Check if specified output directory actually exists
|
|
379
|
+
puts_abort "Out directory, \"#{opts["out-dir"]}\" doesn't exist!" unless Dir.exists? opts["out-dir"]
|
|
380
|
+
config["out-dir"] = opts["out-dir"].dup
|
|
381
|
+
config["out-dir"] << "/" unless config["out-dir"][-1] == "/"
|
|
382
|
+
|
|
383
|
+
# Parse config
|
|
384
|
+
config_copies = {}
|
|
385
|
+
File.open(config_loc, "r").each_line do |line|
|
|
386
|
+
next if line.length <= 1 or line[0] == '#'
|
|
387
|
+
|
|
388
|
+
if line =~ /^\[(\S+)\]$/ # Check if header
|
|
389
|
+
cur_block = $1
|
|
390
|
+
if cur_block.include? ',' # Check if header contains more than one server
|
|
391
|
+
tmp_split = cur_block.split(",")
|
|
392
|
+
next unless tmp_split[0] =~ /^(\w+?).(\w+?).(\w+?)$/
|
|
393
|
+
config_copies[tmp_split[0]] = []
|
|
394
|
+
tmp_split.each do |x| # Add all copies to copies hash
|
|
395
|
+
next if x == tmp_split[0] or not x =~ /^(\w+?).(\w+?).(\w+?)$/
|
|
396
|
+
config_copies[tmp_split[0]].push x unless config_copies[tmp_split[0]].include? x
|
|
420
397
|
end
|
|
398
|
+
cur_block = tmp_split[0]
|
|
421
399
|
end
|
|
422
|
-
end
|
|
423
400
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
401
|
+
# Set current block to the new header
|
|
402
|
+
config["servers"][cur_block] = {} unless config["servers"].has_key? cur_block
|
|
403
|
+
elsif line =~ /^(\S+)=(.*+?)$/
|
|
404
|
+
# Check if current line is specifying out directory
|
|
405
|
+
case $1
|
|
406
|
+
when "out-dir"
|
|
407
|
+
t_out_dir = File.expand_path $2
|
|
408
|
+
puts_abort "Out directory, \"#{t_out_dir}\" doesn't exist!" unless Dir.exists? t_out_dir
|
|
409
|
+
config[$1] = t_out_dir
|
|
410
|
+
config[$1] << "/" unless config[$1][-1] == "/"
|
|
411
|
+
next
|
|
412
|
+
when "sleep-interval" then config[$1] = $2.to_i
|
|
413
|
+
when "skip-existing" then config[$1] = ($2 == "true")
|
|
414
|
+
when "allow-queueing" then config[$1] = ($2 == "true")
|
|
415
|
+
else
|
|
416
|
+
# Add value to current header, default is *
|
|
417
|
+
t_sym = $1.downcase.to_sym
|
|
418
|
+
config["servers"][cur_block][t_sym] = $2 unless config["servers"][cur_block].has_key? t_sym
|
|
428
419
|
end
|
|
429
420
|
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
# Go through each and make copies of the original
|
|
424
|
+
unless config_copies.empty?
|
|
425
|
+
config_copies.each do |k,v|
|
|
426
|
+
v.each { |x| config["servers"][x] = config["servers"][k] }
|
|
427
|
+
end
|
|
428
|
+
end
|
|
430
429
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
430
|
+
# Set the set the command line config options if specified
|
|
431
|
+
config["skip-existing"] = opts["skip-existing"] if opts["skip-existing"]
|
|
432
|
+
config["allow-queueing"] = opts["allow-queueing"] if opts["allow-queueing"]
|
|
433
|
+
config["sleep-interval"] = opts["sleep-interval"] unless opts["sleep-interval"].nil?
|
|
435
434
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
end
|
|
435
|
+
# Take remaining arguments and all lines from --files arg and put into array
|
|
436
|
+
to_check = ($*)
|
|
437
|
+
if opts['files'] != nil and not opts['files'].empty?
|
|
438
|
+
opts['files'].each do |x|
|
|
439
|
+
File.open(x, "r").each_line { |y| to_check << y.chomp } if File.exists? x
|
|
442
440
|
end
|
|
441
|
+
end
|
|
443
442
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
# Parse to_check array for valid XDCC links, irc.serv.org/#chan/bot/pack
|
|
450
|
-
tmp_requests = []
|
|
451
|
-
to_check.each do |x|
|
|
452
|
-
if x =~ /^(#\S+)@(irc.\w+.\w+{2,3})\/(\S+)\/([\.&\|\d]+)$/
|
|
453
|
-
chan = $1
|
|
454
|
-
serv = $2
|
|
455
|
-
bot = $3
|
|
456
|
-
info = config["servers"].has_key?(serv) ? serv : "*"
|
|
457
|
-
$4.split('&').each do |y|
|
|
458
|
-
if y =~ /^(\d+)(\.\.\d+(\|\d+)?)?$/
|
|
459
|
-
pack = $1.to_i
|
|
460
|
-
if $2.nil?
|
|
461
|
-
tmp_requests.push XDCC_REQ.new serv, chan, bot, pack, info
|
|
462
|
-
else
|
|
463
|
-
step = $3.nil? ? 1 : $3[1..-1].to_i
|
|
464
|
-
range = $2[2..-1].to_i
|
|
443
|
+
if to_check.empty?
|
|
444
|
+
puts opts
|
|
445
|
+
abort "\n No jobs, nothing to do!"
|
|
446
|
+
end
|
|
465
447
|
|
|
466
|
-
|
|
448
|
+
# Parse to_check array for valid XDCC links, irc.serv.org/#chan/bot/pack
|
|
449
|
+
tmp_requests = []
|
|
450
|
+
to_check.each do |x|
|
|
451
|
+
if x =~ /^(#\S+)@(irc.\w+.\w+{2,3})\/(\S+)\/([\.&\|\d]+)$/
|
|
452
|
+
chan = $1
|
|
453
|
+
serv = $2
|
|
454
|
+
bot = $3
|
|
455
|
+
info = config["servers"].has_key?(serv) ? serv : "*"
|
|
456
|
+
$4.split('&').each do |y|
|
|
457
|
+
if y =~ /^(\d+)(\.\.\d+(\|\d+)?)?$/
|
|
458
|
+
pack = $1.to_i
|
|
459
|
+
if $2.nil?
|
|
460
|
+
tmp_requests.push XDCC_REQ.new serv, chan, bot, pack, info
|
|
461
|
+
else
|
|
462
|
+
step = $3.nil? ? 1 : $3[1..-1].to_i
|
|
463
|
+
range = $2[2..-1].to_i
|
|
467
464
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
465
|
+
puts_abort "Invalid range #{pack} to #{range} in \"#{x}\"" if pack > range or pack == range
|
|
466
|
+
|
|
467
|
+
(pack..range).step(step).each do |z|
|
|
468
|
+
tmp_requests.push XDCC_REQ.new serv, chan, bot, z, info
|
|
471
469
|
end
|
|
472
470
|
end
|
|
473
471
|
end
|
|
474
|
-
else
|
|
475
|
-
puts_abort "#{x} is not a valid XDCC address\n XDCC Address format: #chan@irc.serv.com/bot/pack(s)"
|
|
476
472
|
end
|
|
473
|
+
else
|
|
474
|
+
puts_abort "#{x} is not a valid XDCC address\n XDCC Address format: #chan@irc.serv.com/bot/pack(s)"
|
|
477
475
|
end
|
|
476
|
+
end
|
|
478
477
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
end
|
|
487
|
-
i += 1
|
|
488
|
-
end
|
|
489
|
-
to_pop.each { |x| tmp_requests.delete_at(x) }
|
|
490
|
-
|
|
491
|
-
# Sort requests array to hash, serv {} -> chan {} -> requests []
|
|
492
|
-
requests = {}
|
|
493
|
-
tmp_requests.each do |x|
|
|
494
|
-
requests[x.serv] = [] unless requests.has_key? x.serv
|
|
495
|
-
requests[x.serv] << x
|
|
496
|
-
end
|
|
497
|
-
|
|
498
|
-
if requests.empty?
|
|
499
|
-
puts opts
|
|
500
|
-
abort "\n No jobs, nothing to do!"
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
# Sort requests by pack
|
|
504
|
-
requests.each do |k,v|
|
|
505
|
-
puts "#{k} \e[1;37m->\e[0m"
|
|
506
|
-
v.sort_by { |x| [x.chan, x.bot, x.pack] }.each { |x| puts " #{x}" }
|
|
478
|
+
# Remove duplicate entries from requests
|
|
479
|
+
i = j = 0
|
|
480
|
+
to_pop = []
|
|
481
|
+
tmp_requests.each do |x|
|
|
482
|
+
tmp_requests.each do |y|
|
|
483
|
+
to_pop << j if x.eql? y if i != j
|
|
484
|
+
j += 1
|
|
507
485
|
end
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
requests.each do |k, v|
|
|
512
|
-
req, info = v[0], config["servers"][v[0].info]
|
|
513
|
-
last_chan, cur_req, motd = "", -1, false
|
|
514
|
-
nick_sent, nick_check, nick_valid = false, false, false
|
|
515
|
-
xdcc_sent, xdcc_accepted, xdcc_queued = false, false, false
|
|
516
|
-
xdcc_accept_time, xdcc_ret, req_send_time = nil, nil, nil
|
|
486
|
+
i += 1
|
|
487
|
+
end
|
|
488
|
+
to_pop.each { |x| tmp_requests.delete_at(x) }
|
|
517
489
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
490
|
+
# Sort requests array to hash, serv {} -> chan {} -> requests []
|
|
491
|
+
requests = {}
|
|
492
|
+
tmp_requests.each do |x|
|
|
493
|
+
requests[x.serv] = [] unless requests.has_key? x.serv
|
|
494
|
+
requests[x.serv] << x
|
|
495
|
+
end
|
|
523
496
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
497
|
+
if requests.empty?
|
|
498
|
+
puts opts
|
|
499
|
+
abort "\n No jobs, nothing to do!"
|
|
500
|
+
end
|
|
528
501
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
502
|
+
# Sort requests by pack
|
|
503
|
+
requests.each do |k,v|
|
|
504
|
+
puts "#{k} \e[1;37m->\e[0m"
|
|
505
|
+
v.sort_by { |x| [x.chan, x.bot, x.pack] }.each { |x| puts " #{x}" }
|
|
506
|
+
end
|
|
507
|
+
puts
|
|
508
|
+
|
|
509
|
+
# H-h-here we g-go...
|
|
510
|
+
requests.each do |k, v|
|
|
511
|
+
req, info = v[0], config["servers"][v[0].info]
|
|
512
|
+
last_chan, cur_req, motd = "", -1, false
|
|
513
|
+
nick_sent, nick_check, nick_valid = false, false, false
|
|
514
|
+
xdcc_sent, xdcc_accepted, xdcc_queued = false, false, false
|
|
515
|
+
xdcc_accept_time, xdcc_ret, req_send_time = nil, nil, nil
|
|
516
|
+
|
|
517
|
+
stream = Stream.new req.serv
|
|
518
|
+
bot = Bot.new stream
|
|
519
|
+
stream << "NICK #{info[:nick]}"
|
|
520
|
+
stream << "USER #{info[:user]} 0 * #{info[:real]}"
|
|
521
|
+
stream << "PASS #{info[:pass]}" unless info[:pass].nil?
|
|
522
|
+
|
|
523
|
+
# Handle read data
|
|
524
|
+
stream.on :READ do |data|
|
|
525
|
+
/^(?:[:](?<prefix>\S+) )?(?<type>\S+)(?: (?!:)(?<dest>.+?))?(?: [:](?<msg>.+))?$/ =~ data
|
|
526
|
+
#puts "\e[1;37m>>\e[0m #{prefix} | #{type} | #{dest} | #{msg}"
|
|
527
|
+
|
|
528
|
+
case type
|
|
529
|
+
when 'NOTICE'
|
|
530
|
+
if dest == 'AUTH'
|
|
531
|
+
if msg =~ /erroneous nickname/i
|
|
532
|
+
puts_error 'Login failed'
|
|
533
|
+
stream.disconnect
|
|
534
|
+
end
|
|
535
|
+
#puts "> \e[1;32m#{msg}\e[0m"
|
|
536
|
+
else
|
|
537
|
+
if prefix =~ /^NickServ!/
|
|
538
|
+
if not nick_sent and info[:nserv] != nil
|
|
539
|
+
stream << "PRIVMSG NickServ :IDENTIFY #{info[:nserv]}"
|
|
540
|
+
nick_sent = true
|
|
541
|
+
elsif nick_sent and not nick_check
|
|
554
542
|
case msg
|
|
555
|
-
when /
|
|
543
|
+
when /password incorrect/i
|
|
544
|
+
nick_valid = false
|
|
545
|
+
nick_check = true
|
|
546
|
+
when /password accepted/i
|
|
547
|
+
nick_valid = true
|
|
548
|
+
nick_check = true
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
#puts "> \e[1;33m#{msg}\e[0m"
|
|
552
|
+
elsif prefix =~ /^#{Regexp.escape req.bot}!(.*)$/i
|
|
553
|
+
case msg
|
|
554
|
+
when /already requested that pack/i, /closing connection/i, /you have a dcc pending/i
|
|
555
|
+
puts_error msg
|
|
556
|
+
stream << "PRIVMSG #{req.bot} :XDCC CANCEL"
|
|
557
|
+
stream << 'QUIT'
|
|
558
|
+
when /you can only have (\d+?) transfer at a time/i
|
|
559
|
+
if config["allow-queueing"]
|
|
560
|
+
puts "! #{prefix}: #{msg}"
|
|
561
|
+
puts_warning "Pack queued, waiting for transfer to start..."
|
|
562
|
+
xdcc_queued = true
|
|
563
|
+
else
|
|
556
564
|
puts_error msg
|
|
557
565
|
stream << "PRIVMSG #{req.bot} :XDCC CANCEL"
|
|
558
566
|
stream << 'QUIT'
|
|
559
|
-
when /you can only have (\d+?) transfer at a time/i
|
|
560
|
-
if config["allow-queueing"]
|
|
561
|
-
puts "! #{prefix}: #{msg}"
|
|
562
|
-
puts_warning "Pack queued, waiting for transfer to start..."
|
|
563
|
-
xdcc_queued = true
|
|
564
|
-
else
|
|
565
|
-
puts_error msg
|
|
566
|
-
stream << "PRIVMSG #{req.bot} :XDCC CANCEL"
|
|
567
|
-
stream << 'QUIT'
|
|
568
|
-
end
|
|
569
|
-
else
|
|
570
|
-
puts "! #{prefix}: #{msg}"
|
|
571
567
|
end
|
|
568
|
+
else
|
|
569
|
+
puts "! #{prefix}: #{msg}"
|
|
572
570
|
end
|
|
573
571
|
end
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
xdcc_sent, xdcc_accepted, xdcc_queued = false, false, false
|
|
598
|
-
xdcc_accept_time, xdcc_ret = nil, nil
|
|
599
|
-
next
|
|
600
|
-
else
|
|
601
|
-
puts_warnings "File already existing, using a safe name..."
|
|
602
|
-
xdcc_ret.fname = safe_fname xdcc_ret.fname
|
|
603
|
-
end
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
# It's a new download, start from beginning
|
|
607
|
-
Thread.new do
|
|
608
|
-
pid = fork do
|
|
609
|
-
puts "Connecting to: #{req.bot} @ #{xdcc_ret.ip}:#{xdcc_ret.port}"
|
|
610
|
-
dcc_download xdcc_ret.ip, xdcc_ret.port, xdcc_ret.fname, xdcc_ret.fsize
|
|
611
|
-
end
|
|
572
|
+
end
|
|
573
|
+
when 'PRIVMSG'
|
|
574
|
+
if xdcc_sent and not xdcc_accepted and prefix =~ /#{Regexp.escape req.bot}!(.*)$/i
|
|
575
|
+
/^\001DCC SEND (?<fname>((".*?").*?|(\S+))) (?<ip>\d+) (?<port>\d+) (?<fsize>\d+)\001\015$/ =~ msg
|
|
576
|
+
unless $~.nil?
|
|
577
|
+
req_send_time = nil
|
|
578
|
+
|
|
579
|
+
tmp_fname = fname
|
|
580
|
+
fname = $1 if tmp_fname =~ /^"(.*)"$/
|
|
581
|
+
puts "Preparing to download: \e[36m#{fname}\e[0m"
|
|
582
|
+
fname = (config["out-dir"].dup << fname)
|
|
583
|
+
xdcc_ret = XDCC_SEND.new fname, fsize.to_i, [ip.to_i].pack('N').unpack('C4') * '.', port.to_i
|
|
584
|
+
|
|
585
|
+
# Check if the for unfinished download amd try to resume
|
|
586
|
+
if File.exists? xdcc_ret.fname and File.stat(xdcc_ret.fname).size < xdcc_ret.fsize
|
|
587
|
+
stream << "PRIVMSG #{req.bot} :\001DCC RESUME #{tmp_fname} #{xdcc_ret.port} #{File.stat(xdcc_ret.fname).size}\001"
|
|
588
|
+
xdcc_accepted = true
|
|
589
|
+
print "! Incomplete file detected. Attempting to resume..."
|
|
590
|
+
next # Skip and wait for "DCC ACCEPT"
|
|
591
|
+
elsif File.exists? xdcc_ret.fname
|
|
592
|
+
if config["skip-existing"]
|
|
593
|
+
puts_warning "File already exists, skipping..."
|
|
594
|
+
stream << "PRIVMSG #{req.bot} :XDCC CANCEL"
|
|
612
595
|
|
|
613
|
-
Process.wait pid
|
|
614
596
|
xdcc_sent, xdcc_accepted, xdcc_queued = false, false, false
|
|
615
597
|
xdcc_accept_time, xdcc_ret = nil, nil
|
|
598
|
+
next
|
|
599
|
+
else
|
|
600
|
+
puts_warnings "File already existing, using a safe name..."
|
|
601
|
+
xdcc_ret.fname = safe_fname xdcc_ret.fname
|
|
616
602
|
end
|
|
617
603
|
end
|
|
618
|
-
elsif xdcc_accepted and xdcc_ret != nil and msg =~ /^\001DCC ACCEPT ((".*?").*?|(\S+)) (\d+) (\d+)\001\015$/
|
|
619
|
-
# DCC RESUME request accepted, continue the download!
|
|
620
|
-
xdcc_accept_time = nil
|
|
621
|
-
xdcc_accepted = false
|
|
622
|
-
puts "\e[1;32mSUCCESS\e[0m!"
|
|
623
604
|
|
|
605
|
+
# It's a new download, start from beginning
|
|
624
606
|
Thread.new do
|
|
625
607
|
pid = fork do
|
|
626
608
|
puts "Connecting to: #{req.bot} @ #{xdcc_ret.ip}:#{xdcc_ret.port}"
|
|
627
|
-
dcc_download xdcc_ret.ip, xdcc_ret.port, xdcc_ret.fname, xdcc_ret.fsize
|
|
609
|
+
dcc_download xdcc_ret.ip, xdcc_ret.port, xdcc_ret.fname, xdcc_ret.fsize
|
|
628
610
|
end
|
|
629
611
|
|
|
630
612
|
Process.wait pid
|
|
631
613
|
xdcc_sent, xdcc_accepted, xdcc_queued = false, false, false
|
|
632
|
-
xdcc_accept_time, xdcc_ret
|
|
614
|
+
xdcc_accept_time, xdcc_ret = nil, nil
|
|
633
615
|
end
|
|
634
616
|
end
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
617
|
+
elsif xdcc_accepted and xdcc_ret != nil and msg =~ /^\001DCC ACCEPT ((".*?").*?|(\S+)) (\d+) (\d+)\001\015$/
|
|
618
|
+
# DCC RESUME request accepted, continue the download!
|
|
619
|
+
xdcc_accept_time = nil
|
|
620
|
+
xdcc_accepted = false
|
|
621
|
+
puts "\e[1;32mSUCCESS\e[0m!"
|
|
622
|
+
|
|
623
|
+
Thread.new do
|
|
624
|
+
pid = fork do
|
|
625
|
+
puts "Connecting to: #{req.bot} @ #{xdcc_ret.ip}:#{xdcc_ret.port}"
|
|
626
|
+
dcc_download xdcc_ret.ip, xdcc_ret.port, xdcc_ret.fname, xdcc_ret.fsize, File.stat(xdcc_ret.fname).size
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
Process.wait pid
|
|
630
|
+
xdcc_sent, xdcc_accepted, xdcc_queued = false, false, false
|
|
631
|
+
xdcc_accept_time, xdcc_ret = nil, nil
|
|
646
632
|
end
|
|
647
|
-
when 'PING' then stream << "PONG :#{msg}"
|
|
648
|
-
when 'ERROR' then (msg =~ /closing link/i ? puts(msg) : puts_error(msg))
|
|
649
633
|
end
|
|
634
|
+
when /^\d+?$/
|
|
635
|
+
type_i = type.to_i
|
|
636
|
+
case type_i
|
|
637
|
+
# when 1 # Print welcome message, because it's nice
|
|
638
|
+
# msg.sub!(/#{Regexp.escape info[:nick]}/, "\e[34m#{info[:nick]}\e[0m")
|
|
639
|
+
# puts "! #{msg}"
|
|
640
|
+
when 400..533 # Handle errors, except a few
|
|
641
|
+
next if [439, 462, 477].include? type_i
|
|
642
|
+
puts_error "#{msg}"
|
|
643
|
+
stream.disconnect
|
|
644
|
+
when 376 then motd = true # Mark the end of the MOTD
|
|
645
|
+
end
|
|
646
|
+
when 'PING' then stream << "PONG :#{msg}"
|
|
647
|
+
when 'ERROR' then (msg =~ /closing link/i ? puts(msg) : puts_error(msg))
|
|
650
648
|
end
|
|
649
|
+
end
|
|
651
650
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
if req.chan != last_chan
|
|
664
|
-
stream << "PART #{last_chan}" unless last_chan == ""
|
|
665
|
-
last_chan = req.chan
|
|
666
|
-
stream << "JOIN #{req.chan}"
|
|
667
|
-
end
|
|
668
|
-
|
|
669
|
-
# Cooldown between downloads
|
|
670
|
-
if cur_req > 0
|
|
671
|
-
puts "Sleeping for #{config["sleep-interval"]} seconds before requesting the next pack"
|
|
672
|
-
sleep(config["sleep-interval"])
|
|
673
|
-
end
|
|
651
|
+
# Handle things while waiting for data
|
|
652
|
+
stream.on :WAITING do
|
|
653
|
+
unless xdcc_accepted
|
|
654
|
+
if motd and not xdcc_sent
|
|
655
|
+
cur_req += 1
|
|
656
|
+
if cur_req >= v.length
|
|
657
|
+
stream.disconnect
|
|
658
|
+
next
|
|
659
|
+
end
|
|
660
|
+
req = v[cur_req]
|
|
674
661
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
662
|
+
if req.chan != last_chan
|
|
663
|
+
stream << "PART #{last_chan}" unless last_chan == ""
|
|
664
|
+
last_chan = req.chan
|
|
665
|
+
stream << "JOIN #{req.chan}"
|
|
678
666
|
end
|
|
679
667
|
|
|
680
|
-
#
|
|
681
|
-
if
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
end
|
|
685
|
-
if (Time.now - req_send_time).floor > 10
|
|
686
|
-
puts_error "#{req.bot} took too long to respond, are you sure it's a bot?"
|
|
687
|
-
stream.disconnect
|
|
688
|
-
bot.stop
|
|
689
|
-
end
|
|
668
|
+
# Cooldown between downloads
|
|
669
|
+
if cur_req > 0
|
|
670
|
+
puts "Sleeping for #{config["sleep-interval"]} seconds before requesting the next pack"
|
|
671
|
+
sleep(config["sleep-interval"])
|
|
690
672
|
end
|
|
691
673
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
674
|
+
stream << "PRIVMSG #{req.bot} :XDCC SEND #{req.pack}"
|
|
675
|
+
req_send_time = Time.now
|
|
676
|
+
xdcc_sent = true
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
# Wait 3 seconds for DCC SEND response, if there isn't one, abort
|
|
680
|
+
if xdcc_sent and not req_send_time.nil? and not xdcc_accepted
|
|
681
|
+
if config["allow-queueing"] and xdcc_queued
|
|
682
|
+
next
|
|
683
|
+
end
|
|
684
|
+
if (Time.now - req_send_time).floor > 10
|
|
685
|
+
puts_error "#{req.bot} took too long to respond, are you sure it's a bot?"
|
|
686
|
+
stream.disconnect
|
|
687
|
+
bot.stop
|
|
699
688
|
end
|
|
700
689
|
end
|
|
701
|
-
end
|
|
702
690
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
691
|
+
# Wait 3 seconds for a DCC ACCEPT response, if there isn't one, don't resume
|
|
692
|
+
if xdcc_sent and xdcc_accepted and not xdcc_accept_time.nil?
|
|
693
|
+
if (Time.now - xdcc_accept_time).floor > 10
|
|
694
|
+
puts "FAILED! Bot client doesn't support resume!"
|
|
695
|
+
puts "Connecting to: #{req.bot} @ #{xdcc_ret.ip}:#{xdcc_ret.port}"
|
|
696
|
+
dcc_download xdcc_ret.ip, xdcc_ret.port, xdcc_ret.fname, xdcc_ret.fsize
|
|
697
|
+
end
|
|
698
|
+
end
|
|
706
699
|
end
|
|
700
|
+
end
|
|
707
701
|
|
|
708
|
-
|
|
709
|
-
|
|
702
|
+
# Print sent data, for debugging only really
|
|
703
|
+
stream.on :WROTE do |data|
|
|
704
|
+
#puts "\e[1;37m<<\e[0m #{data}"
|
|
710
705
|
end
|
|
706
|
+
|
|
707
|
+
# Start the bot
|
|
708
|
+
bot.start
|
|
711
709
|
end
|