torckapi 0.0.16 → 0.0.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e495bbcc0cb11ec0068098e7c26d5df80e6b0993
4
- data.tar.gz: 44342f08c1d9e6640a9e7a8c06c6e5397646b031
3
+ metadata.gz: 23d4a93deca3957dc10d4e056c505b5f57d92bd2
4
+ data.tar.gz: d4b1fe9fcb70d7ffa604209da48a3018702108dd
5
5
  SHA512:
6
- metadata.gz: 57f087caa172b88f83df1d6511dd124b2767749357ebdda87b59326edc86eda2f4b305977bcedb8ebd54a8a866b1eb4d05d41daaf37ce359355b649ee3c8fa5a
7
- data.tar.gz: dfc8f78453037d1d758985de50f618813eaffeb19b982a6b873133c034b79601e4c91639ac8899ef5ed6940a68bf41eaaef58aeded3f2c4e7e2fa7a8f7a416e1
6
+ metadata.gz: 2994677c358450c2a6e9a4d3a8ef2ef559e04b30963c37ae2b4ae96a793edef7c78d5abf653b61b3708e9db64c8ff8322bf0752600e3eb48bd1535eee0763851
7
+ data.tar.gz: 31f3e8806ab54efc32fa48db835f0b7ff1df1d7c64b67aa0908961121c44dddaee734dc022f4ea20d813d7dcef5e6b770fbb963a7506f6015c64c9755a00817b
data/README.md CHANGED
@@ -36,6 +36,4 @@ tracker.scrape(["0123456789ABCDEF0123456789ABCDEF01234567", "123456789ABCDEF0123
36
36
 
37
37
  Add tests.
38
38
 
39
- Add HTTP implementation.
40
-
41
39
  Document everything.
@@ -9,7 +9,7 @@ module Torckapi
9
9
  class CommunicationError < Error; end
10
10
  class CommunicationFailedError < CommunicationError; end
11
11
  class CommunicationTimeoutError < CommunicationError; end
12
- class MalformedResponseError < CommunicationError; end
12
+ class MalformedResponseError < Error; end
13
13
  class TransactionIdMismatchError < CommunicationError; end
14
14
  end
15
15
  end
@@ -1,9 +1,10 @@
1
1
  require 'ipaddr'
2
- require 'bencode'
2
+ require 'torckapi/response/base'
3
3
 
4
4
  module Torckapi
5
5
  module Response
6
- class Announce
6
+ # Announce response
7
+ class Announce < Base
7
8
  # @!attribute [r] info_hash
8
9
  # @return [String] 40-char hexadecimal string
9
10
  # @!attribute [r] leechers
@@ -12,6 +13,7 @@ module Torckapi
12
13
  # @return [Array<IPAddr, Fixnum>] list of peers
13
14
  # @!attribute [r] seeders
14
15
  # @return [Fixnum] number of seeders
16
+
15
17
  attr_reader :info_hash, :leechers, :peers, :seeders
16
18
 
17
19
  # Construct response object from udp response data
@@ -25,12 +27,11 @@ module Torckapi
25
27
  # Construct response object from http response data
26
28
  # @param info_hash [String] 40-char hexadecimal string
27
29
  # @param data [String] HTTP response data (bencoded)
28
- # @param compact [true, false] is peer data in compact format?
29
30
  # @return [Torckapi::Response::Announce] response
30
- def self.from_http info_hash, data, compact=true
31
- bdecoded_data = BEncode.load(data)
32
- raise Torckapi::Tracker::MalformedResponseError unless bdecoded_data.is_a? Hash and bdecoded_data.has_key? 'peers'
33
- new info_hash, *bdecoded_data.values_at("incomplete", "complete"), peers_from_compact(bdecoded_data['peers'])
31
+ # @raise [Torckapi::Tracker::MalformedResponseError]
32
+ def self.from_http info_hash, data
33
+ bdecoded_data = bdecode_and_check data, 'peers'
34
+ new info_hash, *bdecoded_data.values_at('incomplete', 'complete'), peers_from_compact(bdecoded_data['peers'])
34
35
  end
35
36
 
36
37
  private
@@ -0,0 +1,21 @@
1
+ require 'bencode'
2
+
3
+ module Torckapi
4
+ module Response
5
+ class Base
6
+ protected
7
+
8
+ def self.bdecode_and_check data, key
9
+ begin
10
+ bdecoded_data = BEncode.load(data)
11
+ rescue BEncode::DecodeError
12
+ raise Torckapi::Tracker::MalformedResponseError
13
+ end
14
+
15
+ raise Torckapi::Tracker::MalformedResponseError unless bdecoded_data.is_a? Hash and bdecoded_data.has_key? key
16
+
17
+ bdecoded_data
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,9 @@
1
+ require 'torckapi/response/base'
2
+
1
3
  module Torckapi
2
4
  module Response
3
- class Error
5
+ # Error response
6
+ class Error < Base
4
7
  # @!attribute [r] info_hash
5
8
  # @return [String] 40-char hexadecimal string
6
9
  # @!attribute [r] info_hashes
@@ -1,10 +1,9 @@
1
- require 'bencode'
1
+ require 'torckapi/response/base'
2
2
 
3
3
  module Torckapi
4
4
  module Response
5
-
6
5
  # Scrape response
7
- class Scrape
6
+ class Scrape < Base
8
7
  # @return [Hash<String, Hash>] scrape data
9
8
  attr_reader :data
10
9
 
@@ -12,29 +11,33 @@ module Torckapi
12
11
  # @param info_hashes [Array<String>] list of 40-char hexadecimal strings
13
12
  # @param data [String] UDP response data (omit action and transaction_id)
14
13
  # @return [Torckapi::Response::Scrape] response
14
+ # @raise [Torckapi::Tracker::MalformedResponseError]
15
15
  def self.from_udp info_hashes, data
16
- raise Torckapi::MalformedResponseError if data.length != info_hashes.count * 12
16
+ raise Torckapi::Tracker::MalformedResponseError if data.length != info_hashes.count * 12
17
17
  new Hash[info_hashes.zip(data.unpack('a12' * info_hashes.count).map { |i| counts_unpacked(i) })]
18
18
  end
19
19
 
20
+ # Construct response object from http response data
21
+ # @param data [String] HTTP response data (bencoded)
22
+ # @return [Torckapi::Response::Scrape] response
23
+ # @raise [Torckapi::Tracker::MalformedResponseError]
20
24
  def self.from_http data
21
- bdecoded_data = BEncode.load(data)
22
- raise Torckapi::MalformedResponseError unless bdecoded_data.is_a? Hash and bdecoded_data.has_key? 'files'
23
- new Hash[bdecoded_data["files"].map { |info_hash, counts| [info_hash.unpack('H*').join, counts_translated(counts) ]}]
25
+ bdecoded_data = bdecode_and_check data, 'files'
26
+ new Hash[bdecoded_data['files'].map { |info_hash, counts| [info_hash.unpack('H*').join, counts_translated(counts) ]}]
24
27
  end
25
28
 
26
29
  private
27
30
 
28
31
  def self.counts_unpacked data
29
- counts_with_block(data, lambda { |data| data.unpack('L>3').map(&:to_i) })
32
+ counts_with_block(data) { |data| data.unpack('L>3').map(&:to_i) }
30
33
  end
31
34
 
32
35
  def self.counts_translated data
33
- counts_with_block(data, lambda { |data| data.values_at("complete", "downloaded", "incomplete") })
36
+ counts_with_block(data) { |data| data.values_at('complete', 'downloaded', 'incomplete') }
34
37
  end
35
38
 
36
- def self.counts_with_block data, block
37
- Hash[[:seeders, :completed, :leechers].zip(block.call(data))]
39
+ def self.counts_with_block data, &block
40
+ Hash[[:seeders, :completed, :leechers].zip(yield data)]
38
41
  end
39
42
 
40
43
  def initialize data
@@ -3,16 +3,23 @@ module Torckapi
3
3
 
4
4
  # Public interface for torrent trackers
5
5
  class Base
6
- # Announce Request
6
+ # Announce request
7
7
  # @param info_hash [String] 40-char hexadecimal string
8
+ # @param peer_id [String] 20-byte binary string
8
9
  # @return [Torckapi::Response::Announce] a response object
9
- def announce info_hash
10
+ # @raise [Torckapi::InvalidInfohashError] when supplied with invalid info_hash
11
+ # @raise [Torckapi::Tracker::CommunicationFailedError] when tracker haven't responded at all
12
+ # @raise [Torckapi::Tracker::MalformedResponseError] when tracker returned junk
13
+ def announce info_hash, peer_id=SecureRandom.random_bytes(20)
10
14
  raise Torckapi::InvalidInfohashError if info_hash !~ /\A[0-9a-f]{40}\z/i
11
15
  end
12
16
 
13
- # Scrape Request
17
+ # Scrape request
14
18
  # @param info_hashes [Array<String>] An array of 40-char hexadecimal strings
15
19
  # @return [Torckapi::Response::Scrape] a response object
20
+ # @raise [Torckapi::InvalidInfohashError] when supplied with invalid info_hash
21
+ # @raise [Torckapi::Tracker::CommunicationFailedError] when tracker haven't responded at all
22
+ # @raise [Torckapi::Tracker::MalformedResponseError] when tracker returned junk
16
23
  def scrape info_hashes=[]
17
24
  raise Torckapi::InvalidInfohashError if info_hashes.any? { |i| i !~ /\A[0-9a-f]{40}\z/i }
18
25
  end
@@ -5,8 +5,6 @@ module Torckapi
5
5
  module Tracker
6
6
 
7
7
  class HTTP < Base
8
- REQUEST_ACTIONS = [Announce = 1, Scrape = 2].freeze
9
-
10
8
  # (see Base#announce)
11
9
  def announce info_hash
12
10
  super info_hash
@@ -21,6 +19,8 @@ module Torckapi
21
19
 
22
20
  private
23
21
 
22
+ REQUEST_ACTIONS = [Announce = 1, Scrape = 2].freeze
23
+
24
24
  def initialize url, options={}
25
25
  super url, options
26
26
  @url.query ||= ""
@@ -5,21 +5,13 @@ require 'torckapi/tracker/base'
5
5
 
6
6
  module Torckapi
7
7
  module Tracker
8
-
9
8
  # Implementation of http://www.bittorrent.org/beps/bep_0015.html
10
9
  class UDP < Base
11
- CONNECTION_TIMEOUT = 60
12
- REQUEST_ACTIONS = [Connect = 0, Announce = 1, Scrape = 2].freeze
13
- RESPONSE_CLASSES = [nil, Torckapi::Response::Announce, Torckapi::Response::Scrape, Torckapi::Response::Error].freeze
14
- RESPONSE_MIN_LENGTHS = [16, 20, 8, 8].freeze
15
-
16
- # (see Base#announce)
17
10
  def announce info_hash, peer_id=SecureRandom.random_bytes(20)
18
11
  super info_hash
19
12
  perform_request Announce, announce_request_data(info_hash, peer_id), info_hash
20
13
  end
21
14
 
22
- # (see Base#scrape)
23
15
  def scrape info_hashes=[]
24
16
  super info_hashes
25
17
  perform_request Scrape, scrape_request_data(info_hashes), info_hashes
@@ -27,6 +19,11 @@ module Torckapi
27
19
 
28
20
  private
29
21
 
22
+ CONNECTION_TIMEOUT = 60
23
+ REQUEST_ACTIONS = [Connect = 0, Announce = 1, Scrape = 2].freeze
24
+ RESPONSE_CLASSES = [nil, Torckapi::Response::Announce, Torckapi::Response::Scrape, Torckapi::Response::Error].freeze
25
+ RESPONSE_MIN_LENGTHS = [16, 20, 8, 8].freeze
26
+
30
27
  def perform_request action, data, *args
31
28
  connect
32
29
  response = communicate action, data
@@ -1,3 +1,3 @@
1
1
  module Torckapi
2
- VERSION = "0.0.16"
2
+ VERSION = "0.0.17"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: torckapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Krupenik
@@ -66,6 +66,7 @@ files:
66
66
  - lib/torckapi.rb
67
67
  - lib/torckapi/errors.rb
68
68
  - lib/torckapi/response/announce.rb
69
+ - lib/torckapi/response/base.rb
69
70
  - lib/torckapi/response/error.rb
70
71
  - lib/torckapi/response/scrape.rb
71
72
  - lib/torckapi/tracker/base.rb