Skip to content

Instantly share code, notes, and snippets.

@theirix
Created December 4, 2010 15:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theirix/728266 to your computer and use it in GitHub Desktop.
Save theirix/728266 to your computer and use it in GitHub Desktop.
Relocate rtorrent session file to another dl/watch location
#!/usr/bin/env ruby
require 'rubygems'
require 'xmlrpc/client'
require 'bencode'
require 'fileutils'
mode = :list if ARGV[0] == nil
if ARGV[0] == nil
mode = :list
elsif ARGV[0] == 'list'
mode = :list
elsif ARGV[0] == 'close'
mode = :close
elsif ARGV[0] == 'closeremove'
mode = :closeremove
else
raise "Usage: #{$0} [close|closeremove]"
end
rt = XMLRPC::Client.new('localhost')
count = 0
Dir.glob(ENV['HOME']+'/rtorrent/session/*.torrent').sort.each do |file|
data = IO.read(file).bdecode
closed = data['rtorrent']['state'] == 0
# strict, closed only because of seeding completed
closed = closed && data['rtorrent']['complete'] == 1 && data['rtorrent']['ignore_commands'] == 1
if closed
count += 1
hash = File.basename(file).gsub(/\.torrent$/,'')
raise 'Wrong hash ' + hash unless hash =~ /^[0-9A-F]+$/
name = data['info']['name']
if data['info']['files']
files = data['info']['files'].map { |fs| fs['path'].join '/' }
else
files = [name]
end
puts name + ' # ' + hash
#puts 'files ' + files.size.to_s
if mode == :close || mode == :closeremove
puts ' erasing torrent'
sleep(1)
status = rt.call('d.erase',hash)
if status != 0
puts 'Error calling a command'
end
if mode == :closeremove
sleep(1)
deleted_dir = ENV['HOME']+'/seed/'+name
if File.exists?(deleted_dir) && name != ''
puts ' also delete ' + deleted_dir
FileUtils.rm_r(deleted_dir, :verbose => true)
else
puts '---------- ERROR: no such dir ' + deleted_dir
end
end
end
end
end
# files_data = data['info']['files']
# if files_data
# files = files_data.map { |fs| fs['path'].join '/' }
# else
# files = [name]
# end
# dir = data['rtorrent']['directory']
# dir = dir.gsub(/\/home\/irix\/seed/,'').gsub(/^\//,'')
# if (dir or '') != ''
# files.map! { |f| dir + '/' + f }
# end
# raise 'Wrong stuff with ' + name if files.empty?
# top_level = files.first.split('/').first
# raise 'Can\'t detect dir of ' + name if (top_level or '') == ''
#!/usr/bin/env ruby
require 'bencode'
require 'uri'
require 'fileutils'
class TorrentRelocate
attr_accessor :kinds, :default_kind, :base_watch_dir, :download_dir, :torrents_dir, :dry_run, :views
def initialize
@dry_run = false
end
def make_two_host host
c = host.split('.')
(c.size > 2 ? c[-2..-1] : c).join('.')
end
def what_kind tracker
@kinds.each_pair do |kind, trackers|
return kind if trackers.detect { |t| tracker.include? t }
end
@default_kind
end
def watchdir_by_kind kind
raise 'Wrong kind' unless @kinds.keys.detect kind
File.join(@base_watch_dir, 'watch-'+kind.to_s)
end
def default_watchdir
File.join(@base_watch_dir, 'watch')
end
def which_trackers
puts 'Available: ' + Dir.glob(@torrents_dir+'/*torrent').map { |file|
make_two_host URI.parse((IO.read(file).bdecode)['announce']).host
}.uniq.join(', ')
end
def recode_torrent file
data = IO.read(file).bdecode
raise "Can\'t decode torrent #{file}" unless data
tracker = URI.parse(data['announce']).host
raise 'No announce' unless tracker
kind = what_kind(tracker)
puts ''
puts data['info']['name']
puts ' ...' + tracker + " => " + kind.to_s
# set dl dirs
dl = data['rtorrent']['directory']
if dl == ''
puts 'No dl'
@failed << data['info']['name']
return
end
puts ' ...old dl ' + dl
new_dl = File.join(@download_dir, File.basename(dl))
if @download_dir != dl
puts ' ...new dl ' + new_dl
data['rtorrent']['directory'] = new_dl
end
# set watch dirs
watchdir = watchdir_by_kind(kind)
tied = data['rtorrent']['tied_to_file']
if tied == ''
puts 'No tied'
@failed << data['info']['name']
return
end
puts ' ...old tied ' + tied
new_tied = File.join(watchdir, File.basename(tied))
data['rtorrent']['tied_to_file'] = new_tied
puts ' ...new tied ' + new_tied
# set views
if @views
view_name = @views[kind]
raise 'No view for kind ' + kind unless view_name
data['rtorrent']['views'] << view_name
puts data['rtorrent']['views'].inspect
end
# move files
from_tied = File.join(default_watchdir, File.basename(tied))
puts " ...copy tied torrent #{from_tied} to #{new_tied}"
unless @dry_run
FileUtils.cp(from_tied, new_tied)
File.open(file, 'wb') { |f| f.write data.bencode }
end
end
def proceed_rename g
if g.kind_of?(Hash)
g.each { |k,v| proceed_rename v unless k=="pieces" }
elsif g.kind_of?(Array)
g.each { |k| proceed_rename k }
elsif g.kind_of?(String)
if g =~ /\/mnt\/second-hd\/home/
g.gsub!(/\/mnt\/second-hd\/home/,'/home')
end
end
end
def rename_from_secondhd(file)
data = IO.read(file).bdecode
raise "Can\'t decode torrent #{file}" unless data
puts file
proceed_rename data
unless @dry_run
File.open(file, 'wb') { |f| f.write data.bencode }
end
end
def rename_all
@failed = []
Dir.glob(@base_watch_dir+'/**/*.torrent') { |file| rename_from_secondhd file }
@failed.each { |t| puts 'Failed: ' + t }
end
def recode
@failed = []
Dir.glob(@torrents_dir+'/*torrent') { |file| recode_torrent file }
@failed.each { |t| puts 'Failed: ' + t }
end
end
relocate = TorrentRelocate.new
relocate.kinds = {
:private => [ 'what.cd', 'thebox.bz', 'tv-vault.org', 'x264.me', 'tehconnection.eu' ],
:moderate => [ 'rutor.org', 'rutracker.org' ],
:greedy => [ 'btjunkie.org' ]
}
relocate.default_kind = :greedy
relocate.dry_run = false
relocate.views = {
:private => 'group_private',
:moderate => 'group_moderate',
:greedy => 'group_greedy'
}
home_dir = '/home/irix'
relocate.download_dir = home_dir + '/seed'
relocate.base_watch_dir = home_dir + '/rtorrent'
relocate.torrents_dir = home_dir + '/rtorrent/session'
#relocate.which_trackers
#relocate.recode
relocate.rename_all
#!/usr/bin/env ruby
require 'rubygems'
require 'bencode'
file = ARGV[0]
data = IO.read(file).bdecode
data.keys.each { |g|
puts ''
puts g+':'
puts data[g].inspect
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment