rutorrent 0.0.1

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.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ doc/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2011 Can Berk Guder
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ = RUTorrent
2
+
3
+ RUTorrent is a Ruby library for the remote management of µTorrent clients via
4
+ the Web UI API.
5
+
6
+ == Installation
7
+
8
+ gem install rutorrent
9
+
10
+ == Synopsis
11
+
12
+ require 'rutorrent'
13
+
14
+ s = RUTorrent::Server.new('127.0.0.1', 6881, 'username', 'password')
15
+ t = s.torrents[0]
16
+ puts t.name
17
+
18
+ Produces:
19
+
20
+ ubuntu-10.10-desktop-i386.iso
21
+
22
+ == Documentation
23
+
24
+ http://rdoc.info/github/cbguder/rutorrent/master/frames
25
+
26
+ == Caveat emptor
27
+
28
+ As the version number implies, RUTorrent is undocumented and untested.
29
+ Specifically, only read-only methods have been tested with µTorrent 2.2.1. Use
30
+ it at your own risk.
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ require 'rake/rdoctask'
3
+ require 'rake/testtask'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ Rake::TestTask.new
8
+
9
+ Rake::RDocTask.new do |rd|
10
+ rd.main = 'README.rdoc'
11
+
12
+ rd.options << '--charset=utf8'
13
+
14
+ rd.rdoc_dir = 'doc'
15
+
16
+ rd.rdoc_files.include 'README.rdoc'
17
+ rd.rdoc_files.include 'LICENSE'
18
+ rd.rdoc_files.include 'lib/**/*.rb'
19
+
20
+ rd.title = 'RUTorrent'
21
+ end
@@ -0,0 +1,8 @@
1
+ require 'rutorrent/file'
2
+ require 'rutorrent/helpers'
3
+ require 'rutorrent/job_properties'
4
+ require 'rutorrent/label'
5
+ require 'rutorrent/rssfilter'
6
+ require 'rutorrent/server'
7
+ require 'rutorrent/settings'
8
+ require 'rutorrent/torrent'
@@ -0,0 +1,18 @@
1
+ module RUTorrent
2
+ class File
3
+ attr_reader :name, :size, :downloaded, :priority
4
+
5
+ def initialize(torrent, index, array)
6
+ @torrent = torrent
7
+ @index = index
8
+ @name, @size, @downloaded, @priority = array
9
+ end
10
+
11
+ def priority=(value)
12
+ raise 'Invalid priority.' unless (0..3).include?(value)
13
+
14
+ @torrent.server.request(:action => 'setprio', :hash => @torrent.hash, :p => value, :f => @index)
15
+ @priority = value
16
+ end
17
+ end
18
+ end
@@ -0,0 +1 @@
1
+ require 'rutorrent/helpers/url_helper'
@@ -0,0 +1,26 @@
1
+ module RUTorrent
2
+ module Helpers
3
+ module URLHelper
4
+ BASE_PATH = '/gui'
5
+ KEYS = [:token, :list, :cid, :action, :hash, :s, :v, :p, :f]
6
+
7
+ def self.path_for(args)
8
+ path = BASE_PATH.dup
9
+
10
+ case args
11
+ when String
12
+ path << args
13
+ when Hash
14
+ query = []
15
+
16
+ KEYS.each do |key|
17
+ query << "#{key}=#{args[key]}" if args.key?(key)
18
+ end
19
+
20
+ path << '/?'
21
+ path << query.join('&')
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ module RUTorrent
2
+ class JobProperties
3
+ attr_reader :hash, :trackers, :ulrate, :dlrate, :superseed, :dht, :pex,
4
+ :seed_override, :seed_ratio, :seed_time, :ulslots
5
+
6
+ def initialize(hash)
7
+ @hash = hash['hash']
8
+ @trackers = hash['trackers']
9
+ @ulrate = hash['ulrate']
10
+ @dlrate = hash['dlrate']
11
+ @superseed = hash['superseed']
12
+ @dht = hash['dht']
13
+ @pex = hash['pex']
14
+ @seed_override = hash['seed_override']
15
+ @seed_ratio = hash['seed_ratio']
16
+ @seed_time = hash['seed_time']
17
+ @ulslots = hash['ulslots']
18
+ end
19
+
20
+ def superseed?
21
+ @superseed == 1
22
+ end
23
+
24
+ def dht?
25
+ @dht == 1
26
+ end
27
+
28
+ def pex?
29
+ @pex == 1
30
+ end
31
+
32
+ def seed_override?
33
+ @seed_override == 1
34
+ end
35
+
36
+ def seed_ratio
37
+ @seed_ratio / 1000.0
38
+ end
39
+
40
+ def trackers
41
+ @trackers.split("\r\n")
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,9 @@
1
+ module RUTorrent
2
+ class Label
3
+ attr_reader :label, :torrent_count
4
+
5
+ def initialize(array)
6
+ @label, @torrent_count = array
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ module RUTorrent
2
+ class RSSFilter
3
+ QUALITIES = %w{HDTV TVRip DVDRip SVCD DSRip DVBRip PDTV HR.HDTV HR.PDTV DVDR
4
+ DVDScr 720p 1080i 1080p WebRip SatRip}
5
+
6
+ attr_reader :id, :flags, :name, :filter, :not_filter, :directory, :feed,
7
+ :quality, :label, :postpone_mode, :last_match, :smart_ep_filter,
8
+ :repack_ep_filter, :episode_filter_str, :episode_filter,
9
+ :resolving_candidate
10
+
11
+ def initialize(array)
12
+ @id, @flags, @name, @filter, @not_filter, @directory, @feed, @quality,
13
+ @label, @postpone_mode, @last_match, @smart_ep_filter, @repack_ep_filter,
14
+ @episode_filter_str, @episode_filter, @resolving_candidate = array
15
+ end
16
+
17
+ def enabled?; !@flags[0].zero? end
18
+ def matches_original_name?; !@flags[1].zero? end
19
+ def high_priority?; !@flags[2].zero? end
20
+ def smart_episode_filter?; !@flags[3].zero? end
21
+ def add_stopped?; !@flags[4].zero? end
22
+
23
+ def qualities
24
+ unless @qualities
25
+ @qualities = []
26
+ QUALITIES.each_with_index do |q,i|
27
+ @qualities << q unless @quality[i].zero?
28
+ end
29
+ end
30
+
31
+ @qualities
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,105 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+ require 'net/http'
4
+ require 'json'
5
+
6
+ module RUTorrent
7
+ class Server
8
+ TOKEN_PATH = '/gui/token.html'
9
+
10
+ attr_reader :host, :port, :user, :token, :build
11
+
12
+ def initialize(host, port, user, pass)
13
+ @host = host
14
+ @port = port
15
+ @user = user
16
+ @pass = pass
17
+
18
+ @token = nil
19
+ @build = nil
20
+
21
+ @http = Net::HTTP.new(@host, @port)
22
+
23
+ get_token
24
+ end
25
+
26
+ def settings
27
+ @settings ||= RUTorrent::Settings.new(self)
28
+ end
29
+
30
+ def labels
31
+ reload unless @labels
32
+ @labels
33
+ end
34
+
35
+ def torrents
36
+ reload unless @torrents
37
+ @torrents
38
+ end
39
+
40
+ def rssfilters
41
+ reload unless @rssfilters
42
+ @rssfilters
43
+ end
44
+
45
+ def request(args)
46
+ args[:token] ||= @token if @token
47
+
48
+ path = RUTorrent::Helpers::URLHelper.path_for(args)
49
+ resp = request_raw(path)
50
+
51
+ begin
52
+ json = JSON.parse(resp.body)
53
+ @build = json['build'] if json.has_key?('build')
54
+ ret = json
55
+ rescue
56
+ ret = resp.body
57
+ end
58
+
59
+ ret
60
+ end
61
+
62
+ def reload
63
+ json = request(:list => 1)
64
+
65
+ @labels = []
66
+ json['label'].each do |label|
67
+ @labels << Label.new(label)
68
+ end
69
+
70
+ @torrents = []
71
+ json['torrents'].each do |torrent|
72
+ @torrents << Torrent.new(self, torrent)
73
+ end
74
+
75
+ @rssfilters = []
76
+ json['rssfilters'].each do |rssfilter|
77
+ @rssfilters << RSSFilter.new(rssfilter)
78
+ end
79
+ end
80
+
81
+ def inspect
82
+ '#<%s:0x%8x %s@%s:%s>' % [self.class, object_id * 2, @user, @host, @port]
83
+ end
84
+
85
+ private
86
+
87
+ def request_raw(path, authenticate=true)
88
+ req = Net::HTTP::Get.new(path)
89
+ req.basic_auth @user, @pass if authenticate
90
+ @http.request(req)
91
+ end
92
+
93
+ def get_token
94
+ response = request_raw(TOKEN_PATH, false)
95
+
96
+ if response.code != '401' or response['WWW-Authenticate'] != 'Basic realm="uTorrent"'
97
+ raise "#{@host} is not a valid uTorrent server."
98
+ end
99
+
100
+ response = request_raw(TOKEN_PATH)
101
+ html = Nokogiri::HTML.parse(response.body)
102
+ @token = html.css("#token").text
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,36 @@
1
+ module RUTorrent
2
+ class Settings
3
+ def initialize(server)
4
+ @server = server
5
+ @settings = nil
6
+ @dirty = false
7
+ end
8
+
9
+ def reload
10
+ json = @server.request(:action => 'getsettings')
11
+ @settings = Hash[json['settings'].map{|s| [s[0], s[2]] }]
12
+ @dirty = false
13
+ end
14
+
15
+ def [](key)
16
+ reload_if_necessary
17
+ @settings[key]
18
+ end
19
+
20
+ def []=(key, value)
21
+ @server.request(:action => 'setsetting', :s => key, :v => value)
22
+ @dirty = true
23
+ end
24
+
25
+ def to_hash
26
+ reload_if_necessary
27
+ @settings.dup
28
+ end
29
+
30
+ private
31
+
32
+ def reload_if_necessary
33
+ reload if @dirty or @settings.nil?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,87 @@
1
+ module RUTorrent
2
+ class Torrent
3
+ attr_reader :hash, :status, :name, :size, :progress, :downloaded, :uploaded,
4
+ :ratio, :upload_speed, :download_speed, :eta, :label, :peers_connected,
5
+ :peers_in_swarm, :seeds_connected, :seeds_in_swarm, :availability,
6
+ :torrent_queue_order, :remaining
7
+
8
+ attr_reader :server
9
+
10
+ def initialize(server, array)
11
+ @server = server
12
+
13
+ @hash, @status, @name, @size, @progress, @downloaded, @uploaded, @ratio,
14
+ @upload_speed, @download_speed, @eta, @label, @peers_connected,
15
+ @peers_in_swarm, @seeds_connected, @seeds_in_swarm, @availability,
16
+ @torrent_queue_order, @remaining = array
17
+ end
18
+
19
+ def files
20
+ load_files unless @files
21
+ @files
22
+ end
23
+
24
+ def progress
25
+ @progress / 1000.0
26
+ end
27
+
28
+ def ratio
29
+ @ratio / 1000.0
30
+ end
31
+
32
+ def availability
33
+ @availability / 65536.0
34
+ end
35
+
36
+ def properties
37
+ load_properties unless @properties
38
+ @properties
39
+ end
40
+
41
+ def start; perform 'start' end
42
+ def stop; perform 'stop' end
43
+ def pause; perform 'pause' end
44
+ def unpause; perform 'unpause' end
45
+ def forcestart; perform 'forcestart' end
46
+ def recheck; perform 'recheck' end
47
+ def remove; perform 'remove' end
48
+ def removedata; perform 'removedata' end
49
+ def queuebottom; perform 'queuebottom' end
50
+ def queuedown; perform 'queuedown' end
51
+ def queuetop; perform 'queuetop' end
52
+ def queueup; perform 'queueup' end
53
+
54
+ def started?; !@status[0].zero? end
55
+ def checking?; !@status[1].zero? end
56
+ def start_after_check?; !@status[2].zero? end
57
+ def checked?; !@status[3].zero? end
58
+ def error?; !@status[4].zero? end
59
+ def paused?; !@status[5].zero? end
60
+ def queued?; !@status[6].zero? end
61
+ def loaded?; !@status[7].zero? end
62
+
63
+ def inspect
64
+ '#<%s:0x%8x %s>' % [self.class, object_id * 2, @name]
65
+ end
66
+
67
+ private
68
+
69
+ def load_files
70
+ json = @server.request(:action => 'getfiles', :hash => @hash)
71
+
72
+ @files = []
73
+ json['files'][1].each_with_index do |file,i|
74
+ @files << RUTorrent::File.new(@torrent, i, file)
75
+ end
76
+ end
77
+
78
+ def load_properties
79
+ json = @server.request(:action => 'getprops', :hash => @hash)
80
+ @properties = RUTorrent::JobProperties.new(json['props'][0])
81
+ end
82
+
83
+ def perform(action)
84
+ @server.request(:action => action, :hash => @hash)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module RUTorrent
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rutorrent/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rutorrent"
7
+ s.version = RUTorrent::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+
10
+ s.authors = ["Can Berk Güder"]
11
+ s.email = ["cbguder@gmail.com"]
12
+ s.homepage = "http://cbg.me/"
13
+
14
+ s.summary = %q{Library for the remote management of uTorrent clients}
15
+ s.description = <<-EOF.strip.gsub(/^\s+/, '')
16
+ RUTorrent is a Ruby library for the remote management of uTorrent clients
17
+ via the Web UI API.
18
+ EOF
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+
23
+ s.add_dependency("json", "~> 1.5.1")
24
+ s.add_dependency("nokogiri", "~> 1.4.4")
25
+
26
+ s.add_development_dependency("bundler")
27
+ end
@@ -0,0 +1,50 @@
1
+ require 'rutorrent'
2
+ require 'test/unit'
3
+
4
+ class TestURLHelper < Test::Unit::TestCase
5
+ def path_for(args)
6
+ args[:token] = 'TOKEN' if Hash === args
7
+ RUTorrent::Helpers::URLHelper::path_for(args)
8
+ end
9
+
10
+ def test_token_html
11
+ assert_equal '/gui/token.html', path_for('/token.html')
12
+ end
13
+
14
+ def test_list
15
+ assert_equal '/gui/?token=TOKEN&list=1', path_for(:list => 1)
16
+ end
17
+
18
+ def test_list_cid
19
+ assert_equal '/gui/?token=TOKEN&list=1&cid=CACHEID', path_for(:list => 1, :cid => 'CACHEID')
20
+ end
21
+
22
+ def test_action
23
+ assert_equal "/gui/?token=TOKEN&action=getsettings", path_for(:action => 'getsettings')
24
+ end
25
+
26
+ def test_action_s
27
+ assert_equal '/gui/?token=TOKEN&action=add-url&s=URL', path_for(:action => 'add-url', :s => 'URL')
28
+ end
29
+
30
+ def test_action_s_v
31
+ assert_equal '/gui/?token=TOKEN&action=setsetting&s=SETTING&v=VALUE', path_for(:action => 'setsetting', :s => 'SETTING', :v => 'VALUE')
32
+ end
33
+
34
+ def test_action_hash
35
+ actions = %q{getfiles getprops start stop pause unpause forcestart recheck
36
+ remove removedata queuebottom queuedown queuetop queueup}
37
+
38
+ actions.each do |action|
39
+ assert_equal "/gui/?token=TOKEN&action=#{action}&hash=HASH", path_for(:action => action, :hash => 'HASH')
40
+ end
41
+ end
42
+
43
+ def test_action_hash_s_v
44
+ assert_equal '/gui/?token=TOKEN&action=setprops&hash=HASH&s=PROPERTY&v=VALUE', path_for(:action => 'setprops', :hash => 'HASH', :s=> 'PROPERTY', :v => 'VALUE')
45
+ end
46
+
47
+ def test_action_hash_p_f
48
+ assert_equal '/gui/?token=TOKEN&action=setprio&hash=HASH&p=0&f=0', path_for(:action => 'setprio', :hash => 'HASH', :p=> 0, :f => 0)
49
+ end
50
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rutorrent
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - "Can Berk G\xC3\xBCder"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-31 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 1
30
+ segments:
31
+ - 1
32
+ - 5
33
+ - 1
34
+ version: 1.5.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: nokogiri
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 15
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 4
50
+ version: 1.4.4
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: bundler
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :development
66
+ version_requirements: *id003
67
+ description: |-
68
+ RUTorrent is a Ruby library for the remote management of uTorrent clients
69
+ via the Web UI API.
70
+ email:
71
+ - cbguder@gmail.com
72
+ executables: []
73
+
74
+ extensions: []
75
+
76
+ extra_rdoc_files: []
77
+
78
+ files:
79
+ - .gitignore
80
+ - Gemfile
81
+ - LICENSE
82
+ - README.rdoc
83
+ - Rakefile
84
+ - lib/rutorrent.rb
85
+ - lib/rutorrent/file.rb
86
+ - lib/rutorrent/helpers.rb
87
+ - lib/rutorrent/helpers/url_helper.rb
88
+ - lib/rutorrent/job_properties.rb
89
+ - lib/rutorrent/label.rb
90
+ - lib/rutorrent/rssfilter.rb
91
+ - lib/rutorrent/server.rb
92
+ - lib/rutorrent/settings.rb
93
+ - lib/rutorrent/torrent.rb
94
+ - lib/rutorrent/version.rb
95
+ - rutorrent.gemspec
96
+ - test/test_url_helper.rb
97
+ has_rdoc: true
98
+ homepage: http://cbg.me/
99
+ licenses: []
100
+
101
+ post_install_message:
102
+ rdoc_options: []
103
+
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ requirements: []
125
+
126
+ rubyforge_project:
127
+ rubygems_version: 1.6.2
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Library for the remote management of uTorrent clients
131
+ test_files:
132
+ - test/test_url_helper.rb