transmission-rss 0.1.12 → 0.1.13
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.rdoc +5 -1
- data/bin/transmission-rss +49 -38
- data/lib/transmission-rss.rb +1 -1
- data/lib/transmission-rss/aggregator.rb +24 -29
- data/lib/transmission-rss/client.rb +11 -16
- data/lib/transmission-rss/config.rb +5 -5
- data/lib/transmission-rss/hash.rb +2 -2
- data/lib/transmission-rss/log.rb +4 -4
- data/transmission-rss.conf.example +8 -0
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8eb08d11496d24bd539bd17237ea5aa523b362a
|
4
|
+
data.tar.gz: 26f4c37a9e38353be0cf07dd3e58aa4f8e64a9be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b26fdbcee2bf111a750a1aab971414e9c9ea28caea33a759c1e31b7bd7055a8048d5d710ed80d45f432a59ddf905f1647392cb6999c28f48994f8a89947da65
|
7
|
+
data.tar.gz: 93196eb479cbcedd731f2db63aae7e5c1da222f31b9dcd28ee8ffee5b330acd501bb7304b101236b1885cbbcafc1768035fd3a6cab9c6bbd447111ee76acc73a
|
data/README.rdoc
CHANGED
@@ -28,7 +28,7 @@ code to the single most delightful human being: Ann.
|
|
28
28
|
git clone git://git.orgizm.net/transmission-rss.git
|
29
29
|
cd transmission-rss
|
30
30
|
gem build transmission-rss.gemspec
|
31
|
-
|
31
|
+
gem install transmission-rss-*.gem
|
32
32
|
|
33
33
|
== Configuration
|
34
34
|
|
@@ -67,6 +67,10 @@ not defined by default, so the script runs as current user/group.
|
|
67
67
|
user: nobody
|
68
68
|
group: nobody
|
69
69
|
|
70
|
+
fork: false
|
71
|
+
|
72
|
+
pid_file: false
|
73
|
+
|
70
74
|
== TODO
|
71
75
|
|
72
76
|
* Better library abilities.
|
data/bin/transmission-rss
CHANGED
@@ -14,13 +14,17 @@ config_file = '/etc/transmission-rss.conf'
|
|
14
14
|
# Do not fork by default.
|
15
15
|
dofork = false
|
16
16
|
|
17
|
+
# No PID file by default.
|
18
|
+
pid_file = false
|
19
|
+
|
17
20
|
# Shows a summary of the command line options.
|
18
|
-
def usage_message(
|
19
|
-
$stderr << "#{File.basename
|
21
|
+
def usage_message(config_file)
|
22
|
+
$stderr << "#{File.basename $0} [option]..
|
20
23
|
Adds torrents from rss feeds to transmission web frontend.
|
21
24
|
|
22
25
|
-c <file> Custom config file path. Default: #{config_file}
|
23
26
|
-f Fork into background after startup.
|
27
|
+
-p <file> Write PID to file.
|
24
28
|
-h This help.
|
25
29
|
|
26
30
|
"
|
@@ -28,21 +32,23 @@ Adds torrents from rss feeds to transmission web frontend.
|
|
28
32
|
end
|
29
33
|
|
30
34
|
# Define command-line options.
|
31
|
-
options = GetoptLong.new
|
35
|
+
options = GetoptLong.new \
|
32
36
|
[ '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
33
37
|
[ '-f', GetoptLong::NO_ARGUMENT ],
|
38
|
+
[ '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
34
39
|
[ '-h', GetoptLong::NO_ARGUMENT ]
|
35
|
-
)
|
36
40
|
|
37
41
|
# Parse given options.
|
38
42
|
options.each do |option, argument|
|
39
|
-
case
|
43
|
+
case option
|
40
44
|
when '-c'
|
41
45
|
config_file = argument
|
42
46
|
when '-f'
|
43
47
|
dofork = true
|
48
|
+
when '-p'
|
49
|
+
pid_file = argument
|
44
50
|
when '-h'
|
45
|
-
usage_message
|
51
|
+
usage_message config_file
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
@@ -51,7 +57,7 @@ end
|
|
51
57
|
config = TransmissionRSS::Config.instance
|
52
58
|
|
53
59
|
# Default configuration.
|
54
|
-
|
60
|
+
defaults = {
|
55
61
|
'feeds' => [],
|
56
62
|
'update_interval' => 600,
|
57
63
|
'add_paused' => false,
|
@@ -60,8 +66,11 @@ config.load({
|
|
60
66
|
'port' => 9091
|
61
67
|
},
|
62
68
|
'log_target' => $stderr,
|
69
|
+
'fork' => false,
|
70
|
+
'pid_file' => false,
|
63
71
|
'privileges' => {}
|
64
|
-
}
|
72
|
+
}
|
73
|
+
config.load defaults
|
65
74
|
|
66
75
|
# Initialize a log instance and configure it.
|
67
76
|
log = Log.instance
|
@@ -73,73 +82,75 @@ end
|
|
73
82
|
|
74
83
|
# Load config file (default or given by argument).
|
75
84
|
begin
|
76
|
-
config.load
|
85
|
+
config.load config_file
|
77
86
|
log.target = config.log_target
|
78
87
|
rescue Errno::ENOENT
|
79
|
-
log.error
|
88
|
+
log.error config_file + ' not found'
|
80
89
|
end
|
81
|
-
log.debug
|
90
|
+
log.debug config
|
91
|
+
|
92
|
+
# Fork value from command line.
|
93
|
+
config.fork = dofork if dofork
|
94
|
+
|
95
|
+
# PID file path from command line.
|
96
|
+
config.pid_file = pid_file if pid_file
|
82
97
|
|
83
98
|
# Drop privileges, if section is given in config file.
|
84
|
-
|
85
|
-
Process::Sys.setgid
|
99
|
+
unless config.privileges.empty?
|
100
|
+
Process::Sys.setgid \
|
86
101
|
Etc.getgrnam(config.privileges.group).gid
|
87
|
-
)
|
88
102
|
|
89
|
-
Process::Sys.setuid
|
103
|
+
Process::Sys.setuid \
|
90
104
|
Etc.getpwnam(config.privileges.user).uid
|
91
|
-
)
|
92
105
|
|
93
|
-
log.debug
|
106
|
+
log.debug \
|
94
107
|
'dropped privileges ' +
|
95
108
|
config.privileges.user +
|
96
109
|
':' +
|
97
110
|
config.privileges.group
|
98
|
-
)
|
99
111
|
else
|
100
|
-
log.debug
|
112
|
+
log.debug 'no privilege dropping'
|
101
113
|
end
|
102
114
|
|
103
115
|
# Warn if no feeds are given.
|
104
|
-
if
|
105
|
-
log.warn('no feeds given')
|
106
|
-
end
|
116
|
+
log.warn 'no feeds given' if config.feeds.empty?
|
107
117
|
|
108
118
|
# Connect reload of config file to SIGHUP.
|
109
|
-
trap
|
110
|
-
config.load
|
111
|
-
log.info('got hup', config)
|
119
|
+
trap 'HUP' do
|
120
|
+
config.load config_file rescue nil
|
112
121
|
end
|
113
122
|
|
114
123
|
# Initialize feed aggregator.
|
115
124
|
aggregator = Aggregator.new
|
116
125
|
|
117
126
|
# Initialize communication to transmission.
|
118
|
-
client = Client.new
|
127
|
+
client = Client.new config.server.host, config.server.port
|
119
128
|
|
120
129
|
# Add feeds from config file to +Aggregator+ class.
|
121
|
-
aggregator.feeds.concat
|
130
|
+
aggregator.feeds.concat config.feeds
|
122
131
|
|
123
132
|
# Callback for a new item on one of the feeds.
|
124
133
|
aggregator.on_new_item do |torrent_file|
|
125
|
-
Thread.start
|
126
|
-
|
127
|
-
|
134
|
+
Thread.start { client.add_torrent torrent_file, :url, config.add_paused }
|
135
|
+
end
|
136
|
+
|
137
|
+
# Save PID.
|
138
|
+
if config.pid_file
|
139
|
+
log.debug 'wrote pid to ' + config.pid_file
|
140
|
+
File.write config.pid_file, Process.pid
|
128
141
|
end
|
129
142
|
|
130
143
|
# Start the aggregation process.
|
131
144
|
begin
|
132
|
-
if
|
133
|
-
pid = fork
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
puts('forked ' + pid.to_s)
|
145
|
+
if config.fork
|
146
|
+
pid = fork { aggregator.run config.update_interval }
|
147
|
+
log.debug 'forked ' + pid.to_s
|
138
148
|
else
|
139
|
-
|
149
|
+
log.debug 'pid ' + Process.pid.to_s
|
150
|
+
aggregator.run config.update_interval
|
140
151
|
end
|
141
152
|
rescue Interrupt
|
142
|
-
log.info
|
153
|
+
log.info 'interrupt caught'
|
143
154
|
end
|
144
155
|
|
145
156
|
log.close
|
data/lib/transmission-rss.rb
CHANGED
@@ -15,45 +15,44 @@ class TransmissionRSS::Aggregator
|
|
15
15
|
@log = Log.instance
|
16
16
|
|
17
17
|
# Declare callback for new items.
|
18
|
-
callback
|
18
|
+
callback :on_new_item
|
19
19
|
|
20
20
|
# Generate path for seen torrents store file.
|
21
|
-
@seenfile = File.join
|
21
|
+
@seenfile = File.join \
|
22
22
|
Etc.getpwuid.dir,
|
23
23
|
'/.config/transmission/seen-torrents.conf'
|
24
|
-
)
|
25
24
|
|
26
25
|
# Make directories in path if they are not existing.
|
27
|
-
FileUtils.mkdir_p
|
26
|
+
FileUtils.mkdir_p File.dirname(@seenfile)
|
28
27
|
|
29
28
|
# Touch seen torrents store file.
|
30
|
-
|
31
|
-
FileUtils.touch
|
29
|
+
unless File.exists? @seenfile
|
30
|
+
FileUtils.touch @seenfile
|
32
31
|
end
|
33
32
|
|
34
33
|
# Open file, read torrent URLs and add to +@seen+.
|
35
34
|
open(@seenfile).readlines.each do |line|
|
36
|
-
@seen.push
|
35
|
+
@seen.push line.chomp
|
37
36
|
end
|
38
37
|
|
39
38
|
# Log number of +@seen+ URIs.
|
40
|
-
@log.debug
|
39
|
+
@log.debug @seen.size.to_s + ' uris from seenfile'
|
41
40
|
end
|
42
41
|
|
43
42
|
# Get file enclosures from all feeds items and call on_new_item callback
|
44
43
|
# with torrent file URL as argument.
|
45
44
|
def run(interval = 600)
|
46
|
-
@log.debug
|
45
|
+
@log.debug 'aggregator start'
|
47
46
|
|
48
|
-
while
|
47
|
+
while true
|
49
48
|
feeds.each do |url|
|
50
|
-
@log.debug
|
49
|
+
@log.debug 'aggregate ' + url
|
51
50
|
|
52
51
|
begin
|
53
52
|
content = open(url).readlines.join("\n")
|
54
53
|
items = RSS::Parser.parse(content, false).items
|
55
54
|
rescue
|
56
|
-
@log.debug
|
55
|
+
@log.debug 'retrieval error'
|
57
56
|
next
|
58
57
|
end
|
59
58
|
|
@@ -61,41 +60,37 @@ class TransmissionRSS::Aggregator
|
|
61
60
|
link = item.enclosure.url rescue item.link
|
62
61
|
|
63
62
|
# Item contains no link.
|
64
|
-
if
|
65
|
-
next
|
66
|
-
end
|
63
|
+
next if link.nil?
|
67
64
|
|
68
65
|
# Link is not a String directly.
|
69
|
-
if
|
70
|
-
link = link.href
|
71
|
-
end
|
66
|
+
link = link.href if link.class != String
|
72
67
|
|
73
68
|
# The link is not in +@seen+ Array.
|
74
|
-
|
75
|
-
on_new_item
|
76
|
-
@log.debug
|
69
|
+
unless seen? link
|
70
|
+
on_new_item link
|
71
|
+
@log.debug 'on_new_item event ' + link
|
77
72
|
|
78
|
-
add_seen
|
73
|
+
add_seen link
|
79
74
|
end
|
80
75
|
end
|
81
76
|
end
|
82
77
|
|
83
|
-
sleep
|
78
|
+
sleep interval
|
84
79
|
end
|
85
80
|
end
|
86
81
|
|
87
82
|
# To add a link into the list of seen links.
|
88
83
|
def add_seen(link)
|
89
|
-
@seen.push
|
84
|
+
@seen.push link
|
90
85
|
|
91
86
|
File.open(@seenfile, 'w') do |file|
|
92
|
-
file.write
|
87
|
+
file.write @seen.join("\n")
|
93
88
|
end
|
94
89
|
end
|
95
90
|
|
96
91
|
# To test if a link is in the list of seen links.
|
97
92
|
def seen?(link)
|
98
|
-
@seen.include?
|
93
|
+
@seen.include? link
|
99
94
|
end
|
100
95
|
|
101
96
|
# Method to define callback methods.
|
@@ -104,10 +99,10 @@ class TransmissionRSS::Aggregator
|
|
104
99
|
eval <<-EOF
|
105
100
|
@#{name} = false
|
106
101
|
def #{name}(*args, &block)
|
107
|
-
if
|
102
|
+
if block
|
108
103
|
@#{name} = block
|
109
|
-
elsif
|
110
|
-
@#{name}.call
|
104
|
+
elsif @#{name}
|
105
|
+
@#{name}.call *args
|
111
106
|
end
|
112
107
|
end
|
113
108
|
EOF
|
@@ -17,15 +17,13 @@ class TransmissionRSS::Client
|
|
17
17
|
|
18
18
|
# Get transmission session id by simple GET.
|
19
19
|
def get_session_id
|
20
|
-
get = Net::HTTP::Get.new
|
21
|
-
'/transmission/rpc'
|
22
|
-
)
|
20
|
+
get = Net::HTTP::Get.new '/transmission/rpc'
|
23
21
|
|
24
22
|
# retries = 3
|
25
23
|
# begin
|
26
24
|
# Timeout::timeout(5) do
|
27
25
|
response = Net::HTTP.new(@host, @port).start do |http|
|
28
|
-
http.request
|
26
|
+
http.request get
|
29
27
|
end
|
30
28
|
# end
|
31
29
|
# rescue Timeout::Error
|
@@ -41,7 +39,7 @@ class TransmissionRSS::Client
|
|
41
39
|
|
42
40
|
id = response.header['x-transmission-session-id']
|
43
41
|
|
44
|
-
@log.debug
|
42
|
+
@log.debug 'got session id ' + id
|
45
43
|
|
46
44
|
id
|
47
45
|
end
|
@@ -49,9 +47,9 @@ class TransmissionRSS::Client
|
|
49
47
|
# POST json packed torrent add command.
|
50
48
|
def add_torrent(file, type, paused = false)
|
51
49
|
hash = {
|
52
|
-
|
53
|
-
|
54
|
-
|
50
|
+
'method' => 'torrent-add',
|
51
|
+
'arguments' => {
|
52
|
+
'paused' => paused
|
55
53
|
}
|
56
54
|
}
|
57
55
|
|
@@ -59,20 +57,17 @@ class TransmissionRSS::Client
|
|
59
57
|
when :url
|
60
58
|
hash.arguments.filename = file
|
61
59
|
when :file
|
62
|
-
hash.arguments.metainfo = Base64.encode64(
|
63
|
-
File.readlines(file).join
|
64
|
-
)
|
60
|
+
hash.arguments.metainfo = Base64.encode64 File.readlines(file).join
|
65
61
|
else
|
66
|
-
raise ArgumentError.new
|
62
|
+
raise ArgumentError.new 'type has to be :url or :file.'
|
67
63
|
end
|
68
64
|
|
69
|
-
post = Net::HTTP::Post.new
|
65
|
+
post = Net::HTTP::Post.new \
|
70
66
|
'/transmission/rpc',
|
71
67
|
initheader = {
|
72
68
|
'Content-Type' => 'application/json',
|
73
69
|
'X-Transmission-Session-Id' => get_session_id
|
74
70
|
}
|
75
|
-
)
|
76
71
|
|
77
72
|
post.body = hash.to_json
|
78
73
|
|
@@ -80,7 +75,7 @@ class TransmissionRSS::Client
|
|
80
75
|
# begin
|
81
76
|
# Timeout::timeout(5) do
|
82
77
|
response = Net::HTTP.new(@host, @port).start do |http|
|
83
|
-
http.request
|
78
|
+
http.request post
|
84
79
|
end
|
85
80
|
# end
|
86
81
|
# rescue Timeout::Error
|
@@ -96,6 +91,6 @@ class TransmissionRSS::Client
|
|
96
91
|
|
97
92
|
result = JSON.parse(response.body).result
|
98
93
|
|
99
|
-
@log.debug
|
94
|
+
@log.debug 'add_torrent result: ' + result
|
100
95
|
end
|
101
96
|
end
|
@@ -8,18 +8,18 @@ class TransmissionRSS::Config < Hash
|
|
8
8
|
|
9
9
|
# Merges a Hash or YAML file (containing a Hash) with itself.
|
10
10
|
def load(config)
|
11
|
-
if
|
12
|
-
self.merge!
|
11
|
+
if config.class == Hash
|
12
|
+
self.merge! config
|
13
13
|
return
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
self.merge_yaml!
|
16
|
+
unless config.nil?
|
17
|
+
self.merge_yaml! config
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
# Merge Config Hash with Hash from YAML file.
|
22
22
|
def merge_yaml!(path)
|
23
|
-
self.merge!
|
23
|
+
self.merge! YAML.load_file(path)
|
24
24
|
end
|
25
25
|
end
|
@@ -3,10 +3,10 @@ class Hash
|
|
3
3
|
# method has an argument (for example by "method="), the key called "method"
|
4
4
|
# is set to the respective argument.
|
5
5
|
def method_missing(symbol, *args)
|
6
|
-
if
|
6
|
+
if args.size == 0
|
7
7
|
self[symbol.to_s]
|
8
8
|
else
|
9
|
-
self[symbol.to_s.slice
|
9
|
+
self[symbol.to_s.slice 0..-2] = args.first
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/transmission-rss/log.rb
CHANGED
@@ -8,9 +8,9 @@ class TransmissionRSS::Log
|
|
8
8
|
# Change log target (IO or path to a file as String).
|
9
9
|
def target=(target)
|
10
10
|
old_logger = @logger
|
11
|
-
@logger = Logger.new
|
11
|
+
@logger = Logger.new target
|
12
12
|
|
13
|
-
if
|
13
|
+
if old_logger
|
14
14
|
@logger.level = old_logger.level
|
15
15
|
@logger.formatter = old_logger.formatter
|
16
16
|
end
|
@@ -18,7 +18,7 @@ class TransmissionRSS::Log
|
|
18
18
|
|
19
19
|
# If this class misses a method, call it on the encapsulated Logger class.
|
20
20
|
def method_missing(sym, *args)
|
21
|
-
@logger ||= Logger.new
|
22
|
-
@logger.send
|
21
|
+
@logger ||= Logger.new $stderr
|
22
|
+
@logger.send sym, *args
|
23
23
|
end
|
24
24
|
end
|
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.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- henning mueller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
transmission-rss is basically a workaround for
|
@@ -21,18 +21,19 @@ executables:
|
|
21
21
|
extensions: []
|
22
22
|
extra_rdoc_files: []
|
23
23
|
files:
|
24
|
+
- README.rdoc
|
24
25
|
- bin/transmission-add-file
|
25
26
|
- bin/transmission-rss
|
26
27
|
- lib/transmission-rss.rb
|
27
|
-
- lib/transmission-rss/
|
28
|
-
- lib/transmission-rss/log.rb
|
28
|
+
- lib/transmission-rss/aggregator.rb
|
29
29
|
- lib/transmission-rss/client.rb
|
30
|
+
- lib/transmission-rss/config.rb
|
30
31
|
- lib/transmission-rss/hash.rb
|
31
|
-
- lib/transmission-rss/
|
32
|
-
- README.rdoc
|
32
|
+
- lib/transmission-rss/log.rb
|
33
33
|
- transmission-rss.conf.example
|
34
34
|
homepage: https://rubygems.org/gems/transmission-rss
|
35
|
-
licenses:
|
35
|
+
licenses:
|
36
|
+
- GPL-3.0
|
36
37
|
metadata: {}
|
37
38
|
post_install_message:
|
38
39
|
rdoc_options: []
|
@@ -40,17 +41,17 @@ require_paths:
|
|
40
41
|
- lib
|
41
42
|
required_ruby_version: !ruby/object:Gem::Requirement
|
42
43
|
requirements:
|
43
|
-
- -
|
44
|
+
- - ">="
|
44
45
|
- !ruby/object:Gem::Version
|
45
46
|
version: '0'
|
46
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
48
|
requirements:
|
48
|
-
- -
|
49
|
+
- - ">="
|
49
50
|
- !ruby/object:Gem::Version
|
50
51
|
version: '0'
|
51
52
|
requirements: []
|
52
53
|
rubyforge_project:
|
53
|
-
rubygems_version: 2.0
|
54
|
+
rubygems_version: 2.2.0
|
54
55
|
signing_key:
|
55
56
|
specification_version: 4
|
56
57
|
summary: Adds torrents from rss feeds to transmission web frontend.
|