class Torrent
Sample usage
t = Torrent.new
(“your.tracker.com”) t.add_file(“path/to/file.foo”) t.write_torrent(“~/Downloads/mytorrent.torrent”)
Attributes
creation_date[W]
defaultdir[RW]
filehashes[RW]
files[RW]
from_file[W]
info[RW]
infohash[R]
piecelength[RW]
pieces_from_file[RW]
privacy[RW]
size[RW]
torrent_file[R]
tracker[RW]
tracker_list[RW]
webseed[RW]
Public Class Methods
data_from_file(filename)
click to toggle source
# File lib/mktorrent.rb, line 131 def self.data_from_file(filename) torrent_file = File.absolute_path(filename) data = nil File.open(torrent_file, 'rb') do |f| data = BEncode.load(StringIO.new f.read) end raise unless data data end
from_file(filename) { |to| ... }
click to toggle source
# File lib/mktorrent.rb, line 112 def self.from_file(filename) data = data_from_file(filename) to = new(data['announce'], true ) do |t| t.tracker_list = data['announce-list'] t.creation_date = data['creation date'] t.defaultdir = data['info']['name'] t.piecelength = data['info']['piece length'] t.files = data['info']['files'] t.privacy = data['info']['private'] t.webseed = data['url-list'] t.pieces_from_file = data['info']['pieces'] t.build end yield to if block_given? to end
new(tracker, from_file = false) { |self| ... }
click to toggle source
optionally initialize filename
# File lib/mktorrent.rb, line 19 def initialize(tracker, from_file = false) @tracker = tracker @piecelength = 512 * 1024 # 512 KB @files = [] @filehashes = [] @size = 0 @tracker_list = [ [@tracker] ] @defaultdir = "torrent" @privacy = 0 @webseed = "" @dirbase = "" @from_file = from_file build_the_torrent yield(self) if block_given? end
Public Instance Methods
<=>(obj)
click to toggle source
Implement Comparable. Provides info about whether this torrent defines the same files as another one.
# File lib/mktorrent.rb, line 217 def <=>(obj) build obj.build return -1 if infohash < obj.infohash return 0 if infohash == obj.infohash 1 rescue StandardError -1 end
add_directory(path)
click to toggle source
# File lib/mktorrent.rb, line 177 def add_directory(path) path = Pathname.new(path) @dirbase = File.dirname(path) unless path.relative? add_directory_to_torrent(path) end
add_directory_to_torrent(path)
click to toggle source
# File lib/mktorrent.rb, line 183 def add_directory_to_torrent(path) # Using Dir.entries instead of glob so that non-escaped paths can be used Dir.entries(path).each do |entry| # Ignore unix current and parent directories next if entry == '.' or entry == '..' filename = File.join(path, entry).gsub(@dirbase, '') # Add a relative path if File.directory?(filename) add_directory_to_torrent(filename) else add_file(filename) end end end
add_file(filepath)
click to toggle source
# File lib/mktorrent.rb, line 156 def add_file(filepath) path_for_torrent = path_for_torrent_from_file(filepath) if((@files.select { |f| f[:path] == path_for_torrent } ).count > 0) raise IOError, "Can't add duplicate file #{File.basename(filepath)}" end # Remove a leading slash if ( ! @dirbase.empty?) && filepath[0] == '/' filepath = filepath.slice(1, filepath.length) end if File.exist?(filepath) @files << { path: path_for_torrent, length: File::open(filepath, "rb").size } elsif @dirbase && File.exist?(File.join(@dirbase, filepath)) @files << { path: path_for_torrent, length: File::open(File.join(@dirbase, filepath), "rb").size } else raise IOError, "Couldn't access #{filepath}" end end
add_tracker(tracker)
click to toggle source
# File lib/mktorrent.rb, line 203 def add_tracker(tracker) @tracker_list << [tracker] end
all_files()
click to toggle source
# File lib/mktorrent.rb, line 35 def all_files if @files.any? @files.collect { |file| file[:path] } end end
all_info_matches?(info)
click to toggle source
# File lib/mktorrent.rb, line 237 def all_info_matches?(info) @info.eql?(info) end
build()
click to toggle source
# File lib/mktorrent.rb, line 86 def build @info = { :announce => @tracker, :'announce-list' => @tracker_list, :'creation date' => creation_date, :info => { :name => @defaultdir, :'piece length' => @piecelength, :files => @files, :private => @privacy, } } @info[:info][:pieces] = "" @info.merge!({ :'url-list' => @webseed }) if @webseed if @files.count > 0 if from_file? @info[:info][:pieces] = pieces_from_file else read_pieces(all_files, @piecelength) do |piece| @info[:info][:pieces] += Digest::SHA1.digest(piece) end end end set_infohash end
Also aliased as: build_the_torrent
count()
click to toggle source
# File lib/mktorrent.rb, line 45 def count @files.count end
creation_date()
click to toggle source
# File lib/mktorrent.rb, line 49 def creation_date @creation_date ||= DateTime.now.strftime("%s") end
eql?(obj)
click to toggle source
Determine if this matches all the same resources (including tracker information)
# File lib/mktorrent.rb, line 229 def eql?(obj) build obj.build obj.all_info_matches?(@info) rescue StandardError false end
from_file?()
click to toggle source
# File lib/mktorrent.rb, line 41 def from_file? !!@from_file end
path_for_reading_pieces(f)
click to toggle source
# File lib/mktorrent.rb, line 53 def path_for_reading_pieces(f) if @dirbase.empty? # it's a single file torrent f = File.join(File.join(f)) end f = File.join(@dirbase, f) unless @dirbase.empty? f end
read_pieces(files, length) { |buffer| ... }
click to toggle source
# File lib/mktorrent.rb, line 61 def read_pieces(files, length) buffer = "" files.each do |file| f = path_for_reading_pieces(file) next if File.directory?(f) File.open(f) do |fh| begin read = fh.read(length - buffer.length) # Make sure file not empty unless read.nil? if (buffer.length + read.length) == length yield(buffer + read) buffer = "" else buffer += read end end end until fh.eof? end end yield buffer end
set_private()
click to toggle source
# File lib/mktorrent.rb, line 207 def set_private @privacy = 1 end
set_public()
click to toggle source
# File lib/mktorrent.rb, line 211 def set_public @privacy = 0 end
set_webseed(url)
click to toggle source
# File lib/mktorrent.rb, line 198 def set_webseed(url) validate_url!(url) @webseed = url end
to_s()
click to toggle source
Return the .torrent file as a string
# File lib/mktorrent.rb, line 150 def to_s return "You must add at least one file." if(@files.count < 1) build_the_torrent unless (@info[:info][:files].count == @files.count) @info.bencode end
write(filename)
click to toggle source
# File lib/mktorrent.rb, line 141 def write(filename) build_the_torrent @torrent_file = File.absolute_path(filename) open(@torrent_file, 'wb') do |file| file.write self.to_s end end
Also aliased as: write_torrent
Private Instance Methods
path_for_torrent_from_file(filepath)
click to toggle source
# File lib/mktorrent.rb, line 252 def path_for_torrent_from_file(filepath) unless @dirbase.empty? filepath = filepath.sub(@dirbase, '') end # Remove leading blank item path_for_torrent = filepath.split('/') - [""] path_for_torrent end
set_infohash()
click to toggle source
# File lib/mktorrent.rb, line 263 def set_infohash @infohash = Digest::SHA1.hexdigest @info[:info].bencode end
validate_url!(url)
click to toggle source
# File lib/mktorrent.rb, line 245 def validate_url!(url) u = URI.parse(url) if u.scheme.nil? || u.host.nil? raise ArgumentError.new("#{url} is not a valid URL") end end