Class: Torrent
Overview
Sample usage t = Torrent.new(“your.tracker.com”) t.add_file(“path/to/file.foo”) t.write_torrent(“~/Downloads/mytorrent.torrent”)
Instance Attribute Summary collapse
- #creation_date ⇒ Object
-
#defaultdir ⇒ Object
Returns the value of attribute defaultdir.
-
#filehashes ⇒ Object
Returns the value of attribute filehashes.
-
#files ⇒ Object
Returns the value of attribute files.
-
#from_file ⇒ Object
writeonly
Sets the attribute from_file.
-
#info ⇒ Object
Returns the value of attribute info.
-
#infohash ⇒ Object
readonly
Returns the value of attribute infohash.
-
#piecelength ⇒ Object
Returns the value of attribute piecelength.
-
#pieces_from_file ⇒ Object
Returns the value of attribute pieces_from_file.
-
#privacy ⇒ Object
Returns the value of attribute privacy.
-
#size ⇒ Object
Returns the value of attribute size.
-
#torrent_file ⇒ Object
readonly
Returns the value of attribute torrent_file.
-
#tracker ⇒ Object
Returns the value of attribute tracker.
-
#tracker_list ⇒ Object
Returns the value of attribute tracker_list.
-
#webseed ⇒ Object
Returns the value of attribute webseed.
Class Method Summary collapse
Instance Method Summary collapse
-
#<=>(obj) ⇒ Object
Implement Comparable.
- #add_directory(path) ⇒ Object
- #add_directory_to_torrent(path) ⇒ Object
- #add_file(filepath) ⇒ Object
- #add_tracker(tracker) ⇒ Object
- #all_files ⇒ Object
- #all_info_matches?(info) ⇒ Boolean
- #build ⇒ Object (also: #build_the_torrent)
- #count ⇒ Object
-
#eql?(obj) ⇒ Boolean
Determine if this matches all the same resources (including tracker information).
- #from_file? ⇒ Boolean
-
#initialize(tracker, from_file = false) {|_self| ... } ⇒ Torrent
constructor
optionally initialize filename.
- #path_for_reading_pieces(f) ⇒ Object
- #read_pieces(files, length) {|buffer| ... } ⇒ Object
- #set_private ⇒ Object
- #set_public ⇒ Object
- #set_webseed(url) ⇒ Object
-
#to_s ⇒ Object
Return the .torrent file as a string.
- #write(filename) ⇒ Object (also: #write_torrent)
Constructor Details
#initialize(tracker, from_file = false) {|_self| ... } ⇒ Torrent
optionally initialize filename
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# 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 |
Instance Attribute Details
#creation_date ⇒ Object
49 50 51 |
# File 'lib/mktorrent.rb', line 49 def creation_date @creation_date ||= DateTime.now.strftime("%s") end |
#defaultdir ⇒ Object
Returns the value of attribute defaultdir.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def defaultdir @defaultdir end |
#filehashes ⇒ Object
Returns the value of attribute filehashes.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def filehashes @filehashes end |
#files ⇒ Object
Returns the value of attribute files.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def files @files end |
#from_file=(value) ⇒ Object (writeonly)
Sets the attribute from_file
16 17 18 |
# File 'lib/mktorrent.rb', line 16 def from_file=(value) @from_file = value end |
#info ⇒ Object
Returns the value of attribute info.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def info @info end |
#infohash ⇒ Object (readonly)
Returns the value of attribute infohash.
14 15 16 |
# File 'lib/mktorrent.rb', line 14 def infohash @infohash end |
#piecelength ⇒ Object
Returns the value of attribute piecelength.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def piecelength @piecelength end |
#pieces_from_file ⇒ Object
Returns the value of attribute pieces_from_file.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def pieces_from_file @pieces_from_file end |
#privacy ⇒ Object
Returns the value of attribute privacy.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def privacy @privacy end |
#size ⇒ Object
Returns the value of attribute size.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def size @size end |
#torrent_file ⇒ Object (readonly)
Returns the value of attribute torrent_file.
14 15 16 |
# File 'lib/mktorrent.rb', line 14 def torrent_file @torrent_file end |
#tracker ⇒ Object
Returns the value of attribute tracker.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def tracker @tracker end |
#tracker_list ⇒ Object
Returns the value of attribute tracker_list.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def tracker_list @tracker_list end |
#webseed ⇒ Object
Returns the value of attribute webseed.
15 16 17 |
# File 'lib/mktorrent.rb', line 15 def webseed @webseed end |
Class Method Details
.data_from_file(filename) ⇒ Object
131 132 133 134 135 136 137 138 139 |
# 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| ... } ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# 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 |
Instance Method Details
#<=>(obj) ⇒ Object
Implement Comparable. Provides info about whether this torrent defines the same files as another one.
217 218 219 220 221 222 223 224 225 |
# 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) ⇒ Object
177 178 179 180 181 |
# 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) ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# 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) ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# 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) ⇒ Object
203 204 205 |
# File 'lib/mktorrent.rb', line 203 def add_tracker(tracker) @tracker_list << [tracker] end |
#all_files ⇒ Object
35 36 37 38 39 |
# File 'lib/mktorrent.rb', line 35 def all_files if @files.any? @files.collect { |file| file[:path] } end end |
#all_info_matches?(info) ⇒ Boolean
237 238 239 |
# File 'lib/mktorrent.rb', line 237 def all_info_matches?(info) @info.eql?(info) end |
#build ⇒ Object Also known as: build_the_torrent
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# 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 |
#count ⇒ Object
45 46 47 |
# File 'lib/mktorrent.rb', line 45 def count @files.count end |
#eql?(obj) ⇒ Boolean
Determine if this matches all the same resources (including tracker information)
229 230 231 232 233 234 235 |
# File 'lib/mktorrent.rb', line 229 def eql?(obj) build obj.build obj.all_info_matches?(@info) rescue StandardError false end |
#from_file? ⇒ Boolean
41 42 43 |
# File 'lib/mktorrent.rb', line 41 def from_file? !!@from_file end |
#path_for_reading_pieces(f) ⇒ Object
53 54 55 56 57 58 59 |
# 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| ... } ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# 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 ⇒ Object
207 208 209 |
# File 'lib/mktorrent.rb', line 207 def set_private @privacy = 1 end |
#set_public ⇒ Object
211 212 213 |
# File 'lib/mktorrent.rb', line 211 def set_public @privacy = 0 end |
#set_webseed(url) ⇒ Object
198 199 200 201 |
# File 'lib/mktorrent.rb', line 198 def set_webseed(url) validate_url!(url) @webseed = url end |
#to_s ⇒ Object
Return the .torrent file as a string
150 151 152 153 154 |
# 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) ⇒ Object Also known as: write_torrent
141 142 143 144 145 146 147 |
# 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 |