transmission-rss 0.1.18 → 0.1.19
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 +4 -4
- data/README.md +11 -3
- data/bin/transmission-rss +8 -7
- data/lib/transmission-rss/aggregator.rb +21 -24
- data/lib/transmission-rss/client.rb +31 -9
- data/lib/transmission-rss/version.rb +1 -1
- data/transmission-rss.conf.example +6 -0
- metadata +2 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa29b326e65a186b541ecaf1fb4e18adf0cc6743
|
|
4
|
+
data.tar.gz: 5eb9e985f291c12f9070d30b0901309efc5491f1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 05e689315452724d6f16a311623968095874fd643edc6ef1b11fad16d4ef8ab4eb4dc2195a204ee3e36bd3b6ff287a8be2384ff64c6a99beae1b48f1b59f5511
|
|
7
|
+
data.tar.gz: 7779b1fca58a0e8d2c7f5bb16bf238a381ef256314a5a6fd0c1babd9c9c92904d0e0ffd8595fe60ba902efcd8b2d83b2519cdf2318dac059f2bd87b827b09ef1
|
data/README.md
CHANGED
|
@@ -14,6 +14,8 @@ torrent files.
|
|
|
14
14
|
As it's done with poems, I devote this very artful and romantic piece of
|
|
15
15
|
code to the single most delightful human being: Ann.
|
|
16
16
|
|
|
17
|
+
The minimum supported Ruby version is 2.0.0.
|
|
18
|
+
|
|
17
19
|
Installation
|
|
18
20
|
------------
|
|
19
21
|
|
|
@@ -52,9 +54,11 @@ Feed item titles can be filtered by a regular expression:
|
|
|
52
54
|
### All available options
|
|
53
55
|
|
|
54
56
|
The following configuration file example contains every existing option
|
|
55
|
-
(although `update_interval`, `add_paused` and `
|
|
56
|
-
and could be omitted). The default `log_target` is STDERR.
|
|
57
|
-
not defined by default, so the script runs as current
|
|
57
|
+
(although `update_interval`, `add_paused`, `server`, `fork`, and `pid_file` are
|
|
58
|
+
default values and could be omitted). The default `log_target` is STDERR.
|
|
59
|
+
`privileges` is not defined by default, so the script runs as current
|
|
60
|
+
user/group. `login` is also not defined by default. It has to be defined, if
|
|
61
|
+
transmission is configured for HTTP basic authentication.
|
|
58
62
|
|
|
59
63
|
feeds:
|
|
60
64
|
- http://example.com/feed1
|
|
@@ -72,6 +76,10 @@ not defined by default, so the script runs as current user/group.
|
|
|
72
76
|
host: localhost
|
|
73
77
|
port: 9091
|
|
74
78
|
|
|
79
|
+
login:
|
|
80
|
+
username: transmission
|
|
81
|
+
password: transmission
|
|
82
|
+
|
|
75
83
|
log_target: /var/log/transmissiond-rss.log
|
|
76
84
|
|
|
77
85
|
privileges:
|
data/bin/transmission-rss
CHANGED
|
@@ -48,7 +48,7 @@ options.each do |option, argument|
|
|
|
48
48
|
when '-f'
|
|
49
49
|
dofork = true
|
|
50
50
|
when '-h'
|
|
51
|
-
usage_message
|
|
51
|
+
usage_message(config_file)
|
|
52
52
|
when '-p'
|
|
53
53
|
pid_file = argument
|
|
54
54
|
when '-v'
|
|
@@ -70,6 +70,7 @@ defaults = {
|
|
|
70
70
|
'host' => 'localhost',
|
|
71
71
|
'port' => 9091
|
|
72
72
|
},
|
|
73
|
+
'login' => nil,
|
|
73
74
|
'log_target' => $stderr,
|
|
74
75
|
'fork' => false,
|
|
75
76
|
'pid_file' => false,
|
|
@@ -88,7 +89,7 @@ end
|
|
|
88
89
|
|
|
89
90
|
# Load config file (default or given by argument).
|
|
90
91
|
begin
|
|
91
|
-
config.load
|
|
92
|
+
config.load(config_file)
|
|
92
93
|
log.target = config.log_target
|
|
93
94
|
rescue Errno::ENOENT
|
|
94
95
|
log.error config_file + ' not found'
|
|
@@ -130,27 +131,27 @@ end
|
|
|
130
131
|
aggregator = Aggregator.new(config.feeds, seen_file: config.seen_file)
|
|
131
132
|
|
|
132
133
|
# Initialize communication to transmission.
|
|
133
|
-
client = Client.new
|
|
134
|
+
client = Client.new(config.server.host, config.server.port, config.login)
|
|
134
135
|
|
|
135
136
|
# Callback for a new item on one of the feeds.
|
|
136
137
|
aggregator.on_new_item do |torrent_file|
|
|
137
|
-
client.add_torrent
|
|
138
|
+
client.add_torrent(torrent_file, :url, config.add_paused)
|
|
138
139
|
end
|
|
139
140
|
|
|
140
141
|
# Save PID.
|
|
141
142
|
if config.pid_file
|
|
142
143
|
log.debug 'wrote pid to ' + config.pid_file
|
|
143
|
-
File.write
|
|
144
|
+
File.write(config.pid_file, Process.pid)
|
|
144
145
|
end
|
|
145
146
|
|
|
146
147
|
# Start the aggregation process.
|
|
147
148
|
begin
|
|
148
149
|
if config.fork
|
|
149
|
-
pid = fork { aggregator.run
|
|
150
|
+
pid = fork { aggregator.run(config.update_interval) }
|
|
150
151
|
log.debug 'forked ' + pid.to_s
|
|
151
152
|
else
|
|
152
153
|
log.debug 'pid ' + Process.pid.to_s
|
|
153
|
-
aggregator.run
|
|
154
|
+
aggregator.run(config.update_interval)
|
|
154
155
|
end
|
|
155
156
|
rescue Interrupt
|
|
156
157
|
log.info 'interrupt caught'
|
|
@@ -12,7 +12,7 @@ module TransmissionRSS
|
|
|
12
12
|
# Class for aggregating torrent files through RSS feeds.
|
|
13
13
|
class Aggregator
|
|
14
14
|
extend Callback
|
|
15
|
-
callback
|
|
15
|
+
callback(:on_new_item) # Declare callback for new items.
|
|
16
16
|
|
|
17
17
|
def initialize(feeds = [], seen_file: nil)
|
|
18
18
|
# Prepare Array of feeds URLs.
|
|
@@ -36,37 +36,37 @@ module TransmissionRSS
|
|
|
36
36
|
'/.config/transmission/seen-torrents.conf')
|
|
37
37
|
|
|
38
38
|
# Make directories in path if they are not existing.
|
|
39
|
-
FileUtils.mkdir_p
|
|
39
|
+
FileUtils.mkdir_p(File.dirname(@seenfile))
|
|
40
40
|
|
|
41
41
|
# Touch seen torrents store file.
|
|
42
|
-
unless File.exists?
|
|
43
|
-
FileUtils.touch
|
|
42
|
+
unless File.exists?(@seenfile)
|
|
43
|
+
FileUtils.touch(@seenfile)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
# Open file, read torrent URLs and add to +@seen+.
|
|
47
47
|
open(@seenfile).readlines.each do |line|
|
|
48
|
-
@seen.push
|
|
48
|
+
@seen.push(line.chomp)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# Log number of +@seen+ URIs.
|
|
52
|
-
@log.debug
|
|
52
|
+
@log.debug(@seen.size.to_s + ' uris from seenfile')
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
# Get file enclosures from all feeds items and call on_new_item callback
|
|
56
56
|
# with torrent file URL as argument.
|
|
57
57
|
def run(interval = 600)
|
|
58
|
-
@log.debug
|
|
58
|
+
@log.debug('aggregator start')
|
|
59
59
|
|
|
60
60
|
while true
|
|
61
61
|
@feeds.each do |url|
|
|
62
62
|
url = URI.encode(url)
|
|
63
|
-
@log.debug
|
|
63
|
+
@log.debug('aggregate ' + url)
|
|
64
64
|
|
|
65
65
|
begin
|
|
66
66
|
content = open(url, allow_redirections: :safe).read
|
|
67
67
|
items = RSS::Parser.parse(content, false).items
|
|
68
68
|
rescue Exception => e
|
|
69
|
-
@log.debug
|
|
69
|
+
@log.debug("retrieval error (#{e.message})")
|
|
70
70
|
next
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -80,47 +80,44 @@ module TransmissionRSS
|
|
|
80
80
|
link = link.href if link.class != String
|
|
81
81
|
|
|
82
82
|
# The link is not in +@seen+ Array.
|
|
83
|
-
unless seen?
|
|
84
|
-
# @log.debug 'unseen link ' + link
|
|
85
|
-
|
|
83
|
+
unless seen?(link)
|
|
86
84
|
# Skip if filter defined and not matching.
|
|
87
|
-
if @filters.include?
|
|
85
|
+
if @filters.include?(url)
|
|
88
86
|
unless item.title[@filters[url]]
|
|
89
|
-
|
|
90
|
-
add_seen link
|
|
87
|
+
add_seen(link)
|
|
91
88
|
next
|
|
92
89
|
end
|
|
93
90
|
end
|
|
94
91
|
|
|
95
|
-
@log.debug
|
|
92
|
+
@log.debug('on_new_item event ' + link)
|
|
96
93
|
|
|
97
94
|
begin
|
|
98
|
-
on_new_item
|
|
99
|
-
rescue Errno::ECONNREFUSED
|
|
100
|
-
#
|
|
95
|
+
on_new_item(link)
|
|
96
|
+
rescue Errno::ECONNREFUSED, Client::Unauthorized
|
|
97
|
+
# Do not add to seen file.
|
|
101
98
|
else
|
|
102
|
-
add_seen
|
|
99
|
+
add_seen(link)
|
|
103
100
|
end
|
|
104
101
|
end
|
|
105
102
|
end
|
|
106
103
|
end
|
|
107
104
|
|
|
108
|
-
sleep
|
|
105
|
+
sleep(interval)
|
|
109
106
|
end
|
|
110
107
|
end
|
|
111
108
|
|
|
112
109
|
# To add a link into the list of seen links.
|
|
113
110
|
def add_seen(link)
|
|
114
|
-
@seen.push
|
|
111
|
+
@seen.push(link)
|
|
115
112
|
|
|
116
113
|
File.open(@seenfile, 'w') do |file|
|
|
117
|
-
file.write
|
|
114
|
+
file.write(@seen.join("\n"))
|
|
118
115
|
end
|
|
119
116
|
end
|
|
120
117
|
|
|
121
118
|
# To test if a link is in the list of seen links.
|
|
122
119
|
def seen?(link)
|
|
123
|
-
@seen.include?
|
|
120
|
+
@seen.include?(link)
|
|
124
121
|
end
|
|
125
122
|
end
|
|
126
123
|
end
|
|
@@ -7,8 +7,11 @@ require File.join(File.dirname(__FILE__), 'log')
|
|
|
7
7
|
module TransmissionRSS
|
|
8
8
|
# Class for communication with transmission utilizing the RPC web interface.
|
|
9
9
|
class Client
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
class Unauthorized < StandardError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(host = 'localhost', port = 9091, login = nil, timeout: 5)
|
|
14
|
+
@host, @port, @login, @timeout = host, port, login, timeout
|
|
12
15
|
@log = TransmissionRSS::Log.instance
|
|
13
16
|
end
|
|
14
17
|
|
|
@@ -27,39 +30,58 @@ module TransmissionRSS
|
|
|
27
30
|
when :file
|
|
28
31
|
hash.arguments.metainfo = Base64.encode64(File.read(file))
|
|
29
32
|
else
|
|
30
|
-
raise ArgumentError.new
|
|
33
|
+
raise ArgumentError.new('type has to be :url or :file.')
|
|
31
34
|
end
|
|
32
35
|
|
|
36
|
+
sid = get_session_id
|
|
37
|
+
raise Unauthorized unless sid
|
|
38
|
+
|
|
33
39
|
post = Net::HTTP::Post.new \
|
|
34
40
|
'/transmission/rpc',
|
|
35
41
|
initheader = {
|
|
36
42
|
'Content-Type' => 'application/json',
|
|
37
|
-
'X-Transmission-Session-Id' =>
|
|
43
|
+
'X-Transmission-Session-Id' => sid
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
auth(post)
|
|
47
|
+
|
|
40
48
|
post.body = hash.to_json
|
|
41
49
|
|
|
42
|
-
response = request
|
|
50
|
+
response = request(post)
|
|
43
51
|
|
|
44
52
|
result = JSON.parse(response.body).result
|
|
45
53
|
|
|
46
|
-
@log.debug
|
|
54
|
+
@log.debug('add_torrent result: ' + result)
|
|
47
55
|
end
|
|
48
56
|
|
|
49
57
|
# Get transmission session id.
|
|
50
58
|
def get_session_id
|
|
51
|
-
get = Net::HTTP::Get.new
|
|
52
|
-
|
|
59
|
+
get = Net::HTTP::Get.new('/transmission/rpc')
|
|
60
|
+
|
|
61
|
+
auth(get)
|
|
62
|
+
|
|
63
|
+
response = request(get)
|
|
53
64
|
|
|
54
65
|
id = response.header['x-transmission-session-id']
|
|
55
66
|
|
|
56
|
-
|
|
67
|
+
if id.nil?
|
|
68
|
+
@log.debug("could not obtain session id (#{response.code}, " +
|
|
69
|
+
"#{response.class})")
|
|
70
|
+
else
|
|
71
|
+
@log.debug('got session id ' + id)
|
|
72
|
+
end
|
|
57
73
|
|
|
58
74
|
id
|
|
59
75
|
end
|
|
60
76
|
|
|
61
77
|
private
|
|
62
78
|
|
|
79
|
+
def auth(request)
|
|
80
|
+
unless @login.nil?
|
|
81
|
+
request.basic_auth(@login['username'], @login['password'])
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
63
85
|
def request(data)
|
|
64
86
|
Timeout::timeout(@timeout) do
|
|
65
87
|
Net::HTTP.new(@host, @port).start do |http|
|
|
@@ -27,6 +27,12 @@ feeds:
|
|
|
27
27
|
# host: localhost
|
|
28
28
|
# port: 9091
|
|
29
29
|
|
|
30
|
+
# Uncomment if transmission server requires login.
|
|
31
|
+
|
|
32
|
+
#login:
|
|
33
|
+
# username: transmission
|
|
34
|
+
# password: transmission
|
|
35
|
+
|
|
30
36
|
# Where to log. Default is stderr.
|
|
31
37
|
|
|
32
38
|
#log_target: /var/log/transmissiond-rss.log
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: transmission-rss
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- henning mueller
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-
|
|
11
|
+
date: 2014-11-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: open_uri_redirections
|
|
@@ -78,4 +78,3 @@ signing_key:
|
|
|
78
78
|
specification_version: 4
|
|
79
79
|
summary: Adds torrents from rss feeds to transmission web frontend.
|
|
80
80
|
test_files: []
|
|
81
|
-
has_rdoc:
|