transmission-rss 0.1.26 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de5e80915f41e877d053a9f12b6ecb1385d5540b
4
- data.tar.gz: 0c10f53b725b7e6b867844b5215bc9457960987c
3
+ metadata.gz: 5d767ee42ccfae63d8fe0dcbd4646c2b76e92afd
4
+ data.tar.gz: aad93524c03fc281512d4279e5cce49877f6e41e
5
5
  SHA512:
6
- metadata.gz: cd103f696e3699c12eda5b33e4777179e5a0ef3be68b521936db6e010073a1af0db91b42e18b1bf2a556f7286ab6fb24441cdc9c58f63f95572181f8cbd61855
7
- data.tar.gz: 2ced9cfeceed1bdea1ed66cb2759d1aa85e3cf73a5b3c97b20fa23e9b6b6f4e0d84f298199ea5d5fb3e3fcfe37c20b32895f2d85fee601f1753065224cdb4a3d
6
+ metadata.gz: f3d62fe42f81e4c3fe76254411e7cba5ed5ffa305f06116326449348b26ff8857f645ade5479aacd90908995438829ccb5ca0cae8b4f5cb429ebff4eb7f6c51d
7
+ data.tar.gz: a2326919928da2f78a315f0bc022f32236fe2c44420b28f1e7c6333e8cfb55488537efcc1994ade7ae852b3392bec7a088bc53bba92663418b4595f717719549
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  transmission-rss
2
2
  ================
3
3
 
4
+ [![Gem Version](https://img.shields.io/gem/v/transmission-rss.svg)](http://badge.fury.io/rb/transmission-rss)
5
+ [![Build Status](https://img.shields.io/travis/nning/transmission-rss/master.svg)](https://travis-ci.org/nning/transmission-rss)
6
+ [![Coverage Status](https://img.shields.io/coveralls/nning/transmission-rss/master.svg)](https://coveralls.io/r/nning/transmission-rss)
7
+ [![Code Climate](https://img.shields.io/codeclimate/github/nning/transmission-rss.svg)](https://codeclimate.com/github/nning/transmission-rss)
8
+
4
9
  transmission-rss is basically a workaround for transmission's lack of the
5
10
  ability to monitor RSS feeds and automatically add enclosed torrent links.
6
11
 
@@ -27,6 +32,7 @@ Installation
27
32
 
28
33
  git clone https://github.com/nning/transmission-rss
29
34
  cd transmission-rss
35
+ bundle
30
36
  gem build transmission-rss.gemspec
31
37
  gem install transmission-rss-*.gem
32
38
 
@@ -57,7 +63,7 @@ Feed item titles can be filtered by a regular expression:
57
63
  Feeds can also be configured to download files to specific directory:
58
64
 
59
65
  feeds:
60
- - url: http://example.com/feed1:
66
+ - url: http://example.com/feed1
61
67
  download_path: /home/user/Downloads
62
68
 
63
69
  ### All available options
@@ -78,6 +84,16 @@ transmission is configured for HTTP basic authentication.
78
84
  regexp: (match1|match2)
79
85
  - url: http://example.com/feed4
80
86
  download_path: /home/user/Downloads
87
+ - url: http://example.com/feed4
88
+ regexp:
89
+ - match1
90
+ - match2
91
+ - url: http://example.com/feed5
92
+ regexp:
93
+ - matcher: match1
94
+ download_path: /home/user/match1
95
+ - matcher: match2
96
+ download_path: /home/user/match2
81
97
 
82
98
  update_interval: 600
83
99
 
@@ -86,6 +102,7 @@ transmission is configured for HTTP basic authentication.
86
102
  server:
87
103
  host: localhost
88
104
  port: 9091
105
+ rpc_path: /transmission/rpc
89
106
 
90
107
  login:
91
108
  username: transmission
@@ -101,6 +118,8 @@ transmission is configured for HTTP basic authentication.
101
118
 
102
119
  pid_file: false
103
120
 
121
+ seen_file: ~/.config/transmission/seen
122
+
104
123
  Daemonized Startup
105
124
  ------------------
106
125
 
@@ -44,24 +44,11 @@ usage_message(config_file) if ARGV.empty?
44
44
  # Otherwise Config is somehow mixed up with RbConfig.
45
45
  config = TransmissionRSS::Config.instance
46
46
 
47
- # Default configuration.
48
- config.load({
49
- 'feeds' => [],
50
- 'update_interval' => 600,
51
- 'add_paused' => false,
52
- 'server' => {
53
- 'host' => 'localhost',
54
- 'port' => 9091
55
- },
56
- 'log_target' => $stderr,
57
- 'privileges' => {}
58
- })
59
-
60
47
  # Initialize a log instance and configure it.
61
48
  log = Log.instance
62
49
  log.target = config.log_target
63
50
  log.level = Logger::DEBUG
64
- log.formatter = proc do |sev, time, prog, msg|
51
+ log.formatter = proc do |sev, time, _, msg|
65
52
  "#{time.to_i}(#{sev.downcase}) #{msg}\n"
66
53
  end
67
54
 
@@ -75,7 +62,7 @@ end
75
62
  log.debug(config)
76
63
 
77
64
  # Initialize communication to transmission.
78
- client = Client.new(config.server.host, config.server.port)
65
+ client = Client.new(config.server, config.login)
79
66
 
80
67
  ARGV.each do |torrent_file|
81
68
  client.add_torrent(torrent_file, :file, paused: config.add_paused)
@@ -18,6 +18,9 @@ dofork = false
18
18
  # No PID file by default.
19
19
  pid_file = false
20
20
 
21
+ # Seen file not reset by default.
22
+ reset_seen_file = false
23
+
21
24
  # Shows a summary of the command line options.
22
25
  def usage_message(config_file)
23
26
  $stderr << "#{File.basename $0} [options]
@@ -27,6 +30,7 @@ Adds torrents from rss feeds to transmission web frontend.
27
30
  -f Fork into background after startup.
28
31
  -h This help.
29
32
  -p <file> Write PID to file.
33
+ -r Reset seenfile on startup.
30
34
  -v Show program version and exit.
31
35
 
32
36
  "
@@ -39,6 +43,7 @@ options = GetoptLong.new \
39
43
  ['-f', GetoptLong::NO_ARGUMENT],
40
44
  ['-h', GetoptLong::NO_ARGUMENT],
41
45
  ['-p', GetoptLong::REQUIRED_ARGUMENT],
46
+ ['-r', GetoptLong::NO_ARGUMENT],
42
47
  ['-v', GetoptLong::NO_ARGUMENT]
43
48
 
44
49
  # Parse given options.
@@ -53,39 +58,23 @@ options.each do |option, argument|
53
58
  usage_message(config_file)
54
59
  when '-p'
55
60
  pid_file = argument
61
+ when '-r'
62
+ reset_seen_file = true
56
63
  when '-v'
57
64
  puts TransmissionRSS::VERSION
58
65
  exit
59
66
  end
60
67
  end
61
68
 
62
- # Seems to be necessary when called from gem installation.
69
+ # Module prefix seems to be necessary when called from gem installation.
63
70
  # Otherwise Config is somehow mixed up with RbConfig.
64
71
  config = TransmissionRSS::Config.instance
65
72
 
66
- # Default configuration.
67
- defaults = {
68
- 'feeds' => [],
69
- 'update_interval' => 600,
70
- 'add_paused' => false,
71
- 'server' => {
72
- 'host' => 'localhost',
73
- 'port' => 9091
74
- },
75
- 'login' => nil,
76
- 'log_target' => $stderr,
77
- 'fork' => false,
78
- 'pid_file' => false,
79
- 'privileges' => {},
80
- 'seen_file' => nil
81
- }
82
- config.load(defaults)
83
-
84
73
  # Initialize a log instance and configure it.
85
74
  log = Log.instance
86
75
  log.target = config.log_target
87
76
  log.level = Logger::DEBUG
88
- log.formatter = proc do |sev, time, prog, msg|
77
+ log.formatter = proc do |sev, time, _, msg|
89
78
  "#{time.to_i}(#{sev.downcase}) #{msg}\n"
90
79
  end
91
80
 
@@ -103,7 +92,7 @@ if !(custom_config || ENV['HOME'].nil?)
103
92
  prefix = ENV['XDG_CONFIG_HOME'] || File.expand_path('~/.config')
104
93
  path = File.join(prefix, 'transmission-rss', 'config.yml')
105
94
 
106
- if File.exists?(path)
95
+ if File.exist?(path)
107
96
  log.debug('loading user config ' + path)
108
97
  config.load(path)
109
98
  end
@@ -146,12 +135,22 @@ end
146
135
  # Initialize feed aggregator.
147
136
  aggregator = Aggregator.new(config.feeds, seen_file: config.seen_file)
148
137
 
138
+ if reset_seen_file
139
+ aggregator.seen.clear!
140
+ log.debug('seenfile reset')
141
+ end
142
+
149
143
  # Initialize communication to transmission.
150
- client = Client.new(config.server.host, config.server.port, config.login)
144
+ client = Client.new(config.server, config.login)
151
145
 
152
146
  # Callback for a new item on one of the feeds.
153
- aggregator.on_new_item do |torrent_file, feed|
154
- client.add_torrent(torrent_file, :url, paused: config.add_paused, download_path: feed.download_path)
147
+ aggregator.on_new_item do |torrent_file, feed, download_path|
148
+ client.add_torrent(torrent_file, :url, paused: config.add_paused, download_path: download_path)
149
+ end
150
+
151
+ # Callback for changes to the config.
152
+ config.on_change do
153
+ aggregator.reinitialize!(config.feeds, seen_file: config.seen_file)
155
154
  end
156
155
 
157
156
  # Start the aggregation process.
@@ -3,6 +3,8 @@ $:.unshift(File.dirname(__FILE__))
3
3
  module TransmissionRSS
4
4
  end
5
5
 
6
+ require 'transmission-rss/core_ext/object'
7
+
6
8
  Dir.glob($:.first + '/**/*.rb').each do |lib|
7
9
  require lib
8
10
  end
@@ -1,5 +1,3 @@
1
- require 'etc'
2
- require 'fileutils'
3
1
  require 'open-uri'
4
2
  require 'open_uri_redirections'
5
3
  require 'rss'
@@ -14,35 +12,24 @@ module TransmissionRSS
14
12
  extend Callback
15
13
  callback(:on_new_item) # Declare callback for new items.
16
14
 
15
+ attr_reader :seen
16
+
17
17
  def initialize(feeds = [], options = {})
18
+ reinitialize!(feeds, options)
19
+ end
20
+
21
+ def reinitialize!(feeds = [], options = {})
18
22
  seen_file = options[:seen_file]
19
23
 
20
24
  # Prepare Array of feeds URLs.
21
25
  @feeds = feeds.map { |config| TransmissionRSS::Feed.new(config) }
22
26
 
23
27
  # Nothing seen, yet.
24
- @seen = []
28
+ @seen = SeenFile.new(nil, seen_file)
25
29
 
26
30
  # Initialize log instance.
27
31
  @log = Log.instance
28
32
 
29
- # Generate path for seen torrents store file.
30
- @seenfile = seen_file || File.join(Etc.getpwuid.dir,
31
- '/.config/transmission/seen-torrents.conf')
32
-
33
- # Make directories in path if they are not existing.
34
- FileUtils.mkdir_p(File.dirname(@seenfile))
35
-
36
- # Touch seen torrents store file.
37
- unless File.exists?(@seenfile)
38
- FileUtils.touch(@seenfile)
39
- end
40
-
41
- # Open file, read torrent URLs and add to +@seen+.
42
- open(@seenfile).readlines.each do |line|
43
- @seen.push(line.chomp)
44
- end
45
-
46
33
  # Log number of +@seen+ URIs.
47
34
  @log.debug(@seen.size.to_s + ' uris from seenfile')
48
35
  end
@@ -52,13 +39,13 @@ module TransmissionRSS
52
39
  def run(interval = 600)
53
40
  @log.debug('aggregator start')
54
41
 
55
- while true
42
+ loop do
56
43
  @feeds.each do |feed|
57
44
  @log.debug('aggregate ' + feed.url)
58
45
 
59
46
  begin
60
47
  content = open(feed.url, allow_redirections: :safe).read
61
- rescue Exception => e
48
+ rescue StandardError => e
62
49
  @log.debug("retrieval error (#{e.class}: #{e.message})")
63
50
  next
64
51
  end
@@ -68,38 +55,14 @@ module TransmissionRSS
68
55
  content = decompress(content) if RUBY_VERSION == '1.9.3'
69
56
  begin
70
57
  items = RSS::Parser.parse(content, false).items
71
- rescue Exception => e
58
+ rescue StandardError => e
72
59
  @log.debug("parse error (#{e.class}: #{e.message})")
73
60
  next
74
61
  end
75
62
 
76
63
  items.each do |item|
77
- link = item.enclosure.url rescue item.link
78
-
79
- # Item contains no link.
80
- next if link.nil?
81
-
82
- # Link is not a String directly.
83
- link = link.href if link.class != String
84
-
85
- # The link is not in +@seen+ Array.
86
- unless seen?(link)
87
- # Skip if filter defined and not matching.
88
- unless feed.matches_regexp?(item.title)
89
- add_seen(link)
90
- next
91
- end
92
-
93
- @log.debug('on_new_item event ' + link)
94
-
95
- begin
96
- on_new_item(link, feed)
97
- rescue Client::Unauthorized, Errno::ECONNREFUSED, Timeout::Error
98
- # Do not add to seen file.
99
- else
100
- add_seen(link)
101
- end
102
- end
64
+ result = process_link(feed, item)
65
+ next if result.nil?
103
66
  end
104
67
  end
105
68
 
@@ -107,20 +70,6 @@ module TransmissionRSS
107
70
  end
108
71
  end
109
72
 
110
- # To add a link into the list of seen links.
111
- def add_seen(link)
112
- @seen.push(link)
113
-
114
- File.open(@seenfile, 'w') do |file|
115
- file.write(@seen.join("\n"))
116
- end
117
- end
118
-
119
- # To test if a link is in the list of seen links.
120
- def seen?(link)
121
- @seen.include?(link)
122
- end
123
-
124
73
  private
125
74
 
126
75
  def decompress(string)
@@ -128,5 +77,38 @@ module TransmissionRSS
128
77
  rescue Zlib::GzipFile::Error, Zlib::Error
129
78
  string
130
79
  end
80
+
81
+ def process_link(feed, item)
82
+ link = item.enclosure.url rescue item.link
83
+
84
+ # Item contains no link.
85
+ return if link.nil?
86
+
87
+ # Link is not a String directly.
88
+ link = link.href if link.class != String
89
+
90
+ # The link is not in +@seen+ Array.
91
+ unless @seen.include?(link)
92
+ # Skip if filter defined and not matching.
93
+ unless feed.matches_regexp?(item.title)
94
+ @seen.add(link)
95
+ return
96
+ end
97
+
98
+ @log.debug('on_new_item event ' + link)
99
+
100
+ download_path = feed.download_path(item.title)
101
+
102
+ begin
103
+ on_new_item(link, feed, download_path)
104
+ rescue Client::Unauthorized, Errno::ECONNREFUSED, Timeout::Error
105
+ @log.debug('not added to seen file ' + link)
106
+ else
107
+ @seen.add(link)
108
+ end
109
+ end
110
+
111
+ return link
112
+ end
131
113
  end
132
114
  end
@@ -9,7 +9,7 @@ module TransmissionRSS
9
9
  if block
10
10
  @callbacks[name] = block
11
11
  elsif @callbacks[name]
12
- @callbacks[name].call *args
12
+ @callbacks[name].call(*args)
13
13
  end
14
14
  end
15
15
  end
@@ -10,10 +10,14 @@ module TransmissionRSS
10
10
  class Unauthorized < StandardError
11
11
  end
12
12
 
13
- def initialize(host = 'localhost', port = 9091, login = nil, options = {})
14
- @host, @port, @login = host, port, login
15
- @timeout = options[:timeout] || 5
16
- @log = TransmissionRSS::Log.instance
13
+ def initialize(server = {}, login = nil, options = {})
14
+ @host = server[:host] || 'localhost'
15
+ @port = server[:port] || 9091
16
+ @rpc_path = server[:rpc_path] || '/transmission/rpc'
17
+ @login = login
18
+
19
+ @timeout = options[:timeout] || 5
20
+ @log = TransmissionRSS::Log.instance
17
21
  end
18
22
 
19
23
  # POST json packed torrent add command.
@@ -39,8 +43,8 @@ module TransmissionRSS
39
43
  raise Unauthorized unless sid
40
44
 
41
45
  post = Net::HTTP::Post.new \
42
- '/transmission/rpc',
43
- initheader = {
46
+ @rpc_path,
47
+ {
44
48
  'Content-Type' => 'application/json',
45
49
  'X-Transmission-Session-Id' => sid
46
50
  }
@@ -58,7 +62,7 @@ module TransmissionRSS
58
62
 
59
63
  # Get transmission session id.
60
64
  def get_session_id
61
- get = Net::HTTP::Get.new('/transmission/rpc')
65
+ get = Net::HTTP::Get.new(@rpc_path)
62
66
 
63
67
  auth(get)
64
68
 
@@ -89,16 +93,14 @@ module TransmissionRSS
89
93
 
90
94
  Timeout.timeout(@timeout) do
91
95
  @log.debug("request #@host:#@port")
92
- Net::HTTP.new(@host, @port).start do |http|
93
- http.request(data)
94
- end
96
+ http_get(data)
95
97
  end
96
98
  rescue Errno::ECONNREFUSED
97
99
  @log.debug('connection refused')
98
100
  raise
99
101
  rescue Timeout::Error
100
102
  s = 'connection timeout'
101
- s += " (retry #{c})" if c > 0
103
+ s << " (retry #{c})" if c > 0
102
104
  @log.debug(s)
103
105
 
104
106
  c += 1
@@ -106,5 +108,11 @@ module TransmissionRSS
106
108
 
107
109
  raise
108
110
  end
111
+
112
+ def http_get(data)
113
+ Net::HTTP.new(@host, @port).start do |http|
114
+ http.request(data)
115
+ end
116
+ end
109
117
  end
110
118
  end
@@ -1,27 +1,91 @@
1
+ require 'pathname'
2
+ require 'rb-inotify' if linux?
1
3
  require 'singleton'
2
4
  require 'yaml'
3
5
 
6
+ libdir = File.dirname(__FILE__)
7
+ require File.join(libdir, 'log')
8
+ require File.join(libdir, 'callback')
9
+
4
10
  module TransmissionRSS
5
11
  # Class handles configuration parameters.
6
12
  class Config < Hash
7
13
  # This is a singleton class.
8
14
  include Singleton
9
15
 
16
+ extend Callback
17
+ callback(:on_change) # Declare callback for changed config.
18
+
19
+ def initialize(file = nil)
20
+ self.merge_defaults!
21
+ self.load(file) unless file.nil?
22
+
23
+ @log = Log.instance
24
+ end
25
+
10
26
  # Merges a Hash or YAML file (containing a Hash) with itself.
11
27
  def load(config)
12
28
  case config.class.to_s
13
29
  when 'Hash'
14
- self.merge! config
30
+ self.merge!(config)
15
31
  when 'String'
16
- self.merge_yaml! config
32
+ self.merge_yaml!(config)
17
33
  else
18
- raise ArgumentError.new 'Could not load config.'
34
+ raise ArgumentError.new('Could not load config.')
19
35
  end
20
36
  end
21
37
 
38
+ def merge_defaults!
39
+ self.merge!({
40
+ 'feeds' => [],
41
+ 'update_interval' => 600,
42
+ 'add_paused' => false,
43
+ 'server' => {
44
+ 'host' => 'localhost',
45
+ 'port' => 9091,
46
+ 'rpc_path' => '/transmission/rpc'
47
+ },
48
+ 'login' => nil,
49
+ 'log_target' => $stderr,
50
+ 'fork' => false,
51
+ 'pid_file' => false,
52
+ 'privileges' => {},
53
+ 'seen_file' => nil
54
+ })
55
+ end
56
+
22
57
  # Merge Config Hash with Hash from YAML file.
23
- def merge_yaml!(path)
24
- self.merge! YAML.load_file(path)
58
+ def merge_yaml!(path, watch = true)
59
+ self.merge!(YAML.load_file(path))
60
+ rescue TypeError
61
+ # If YAML loading fails, .load_file returns `false`.
62
+ else
63
+ watch_file(path) if watch && linux?
64
+ end
65
+
66
+ def reset!
67
+ self.clear
68
+ self.merge_defaults!
69
+ end
70
+
71
+ def watch_file(path)
72
+ path = Pathname.new(path).realpath.to_s
73
+ @log.debug('watch_file ' + path)
74
+
75
+ @notifier ||= INotify::Notifier.new
76
+ @notifier.watch(path, :close_write) do |e|
77
+ self.reset!
78
+ self.merge_yaml!(path, false)
79
+
80
+ @log.debug('reloaded config file ' + path)
81
+ @log.debug(self)
82
+
83
+ on_change
84
+ end
85
+
86
+ @notifier_thread ||= Thread.start do
87
+ @notifier.run
88
+ end
25
89
  end
26
90
  end
27
91
  end
@@ -0,0 +1,5 @@
1
+ class Object
2
+ def linux?
3
+ RUBY_PLATFORM.downcase.include?('linux')
4
+ end
5
+ end
@@ -1,20 +1,62 @@
1
1
  module TransmissionRSS
2
2
  class Feed
3
- attr_reader :url, :regexp, :download_path
3
+ attr_reader :url, :regexp
4
4
 
5
5
  def initialize(config = {})
6
+ @download_paths = {}
7
+
6
8
  case config
7
9
  when Hash
8
10
  @url = URI.encode(config['url'] || config.keys.first)
9
- @regexp = Regexp.new(config['regexp'], Regexp::IGNORECASE) if config['regexp']
11
+
10
12
  @download_path = config['download_path']
13
+
14
+ matchers = Array(config['regexp']).map do |e|
15
+ e.is_a?(String) ? e : e['matcher']
16
+ end
17
+
18
+ @regexp = build_regexp(matchers)
19
+
20
+ initialize_download_paths(config['regexp'])
11
21
  else
12
22
  @url = config.to_s
13
23
  end
14
24
  end
15
25
 
26
+ def download_path(title = nil)
27
+ return @download_path if title.nil?
28
+
29
+ @download_paths.each do |regexp, path|
30
+ return path if title =~ to_regexp(regexp)
31
+ end
32
+
33
+ return @download_path
34
+ end
35
+
16
36
  def matches_regexp?(title)
17
37
  @regexp.nil? || !(title =~ @regexp).nil?
18
38
  end
39
+
40
+ private
41
+
42
+ def build_regexp(matchers)
43
+ matchers = Array(matchers).map { |m| to_regexp(m) }
44
+ matchers.empty? ? nil : Regexp.union(matchers)
45
+ end
46
+
47
+ def initialize_download_paths(regexps)
48
+ return unless regexps.is_a?(Array)
49
+
50
+ regexps.each do |regexp|
51
+ matcher = regexp['matcher']
52
+ path = regexp['download_path']
53
+
54
+ @download_paths[matcher] = path if matcher && path
55
+ end
56
+ end
57
+
58
+ def to_regexp(s)
59
+ Regexp.new(s, Regexp::IGNORECASE)
60
+ end
19
61
  end
20
62
  end
@@ -0,0 +1,81 @@
1
+ require 'digest'
2
+ require 'etc'
3
+ require 'fileutils'
4
+ require 'forwardable'
5
+
6
+ module TransmissionRSS
7
+ # Persist seen torrent URLs
8
+ class SeenFile
9
+ extend ::Forwardable
10
+
11
+ DEFAULT_LEGACY_PATH =
12
+ File.join(Etc.getpwuid.dir, '.config/transmission/seen-torrents.conf')
13
+
14
+ DEFAULT_PATH =
15
+ File.join(Etc.getpwuid.dir, '.config/transmission/seen')
16
+
17
+ def_delegators :@seen, :size, :to_a
18
+
19
+ def initialize(path = nil, legacy_path = nil)
20
+ @legacy_path = legacy_path || DEFAULT_LEGACY_PATH
21
+ @path = path || DEFAULT_PATH
22
+
23
+ initialize_path!
24
+ migrate!
25
+
26
+ @seen = Set.new(file_to_array(@path))
27
+ end
28
+
29
+ def add(url)
30
+ hash = digest(url)
31
+
32
+ return if @seen.include?(hash)
33
+
34
+ @seen << hash
35
+
36
+ open(@path, 'a') do |f|
37
+ f.write(hash + "\n")
38
+ end
39
+ end
40
+
41
+ def clear!
42
+ @seen.clear
43
+ open(@path, 'w') {}
44
+ end
45
+
46
+ def include?(url)
47
+ @seen.include?(digest(url))
48
+ end
49
+
50
+ private
51
+
52
+ def digest(s)
53
+ Digest::SHA256.hexdigest(s)
54
+ end
55
+
56
+ def file_to_array(path)
57
+ open(path, 'r').readlines.map(&:chomp)
58
+ end
59
+
60
+ def initialize_path!
61
+ return if File.exist?(@path)
62
+
63
+ FileUtils.mkdir_p(File.dirname(@path))
64
+ FileUtils.touch(@path)
65
+ end
66
+
67
+ def migrate!
68
+ return unless File.exist?(@legacy_path)
69
+
70
+ legacy_seen = file_to_array(@legacy_path)
71
+ hashes = legacy_seen.map { |url| digest(url) }
72
+
73
+ open(@path, 'w') do |f|
74
+ f.write(hashes.join("\n"))
75
+ f.write("\n")
76
+ end
77
+
78
+ FileUtils.rm_f(@legacy_path)
79
+ end
80
+ end
81
+ end
@@ -1,3 +1,3 @@
1
1
  module TransmissionRSS
2
- VERSION = '0.1.26'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -14,6 +14,16 @@ feeds:
14
14
  regexp: (match1|match2)
15
15
  - url: http://example.com/feed4
16
16
  download_path: /home/user/Downloads
17
+ - url: http://example.com/feed4
18
+ regexp:
19
+ - match1
20
+ - match2
21
+ - url: http://example.com/feed5
22
+ regexp:
23
+ - matcher: match1
24
+ download_path: /home/user/match1
25
+ - matcher: match2
26
+ download_path: /home/user/match2
17
27
 
18
28
  # Feed probing interval in seconds. Default is 600.
19
29
 
@@ -28,6 +38,7 @@ feeds:
28
38
  #server:
29
39
  # host: localhost
30
40
  # port: 9091
41
+ # rpc_path: /transmission/rpc
31
42
 
32
43
  # Uncomment if transmission server requires login.
33
44
 
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.26
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - henning mueller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-02 00:00:00.000000000 Z
11
+ date: 2016-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: open_uri_redirections
@@ -30,6 +30,26 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 0.1.4
33
+ - !ruby/object:Gem::Dependency
34
+ name: rb-inotify
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.9'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.9.7
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.9'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.9.7
33
53
  description: |-
34
54
  transmission-rss is basically a workaround for
35
55
  transmission's lack of the ability to monitor RSS feeds and
@@ -49,9 +69,11 @@ files:
49
69
  - lib/transmission-rss/callback.rb
50
70
  - lib/transmission-rss/client.rb
51
71
  - lib/transmission-rss/config.rb
72
+ - lib/transmission-rss/core_ext/object.rb
52
73
  - lib/transmission-rss/feed.rb
53
74
  - lib/transmission-rss/hash.rb
54
75
  - lib/transmission-rss/log.rb
76
+ - lib/transmission-rss/seen_file.rb
55
77
  - lib/transmission-rss/version.rb
56
78
  - transmission-rss.conf.example
57
79
  homepage: https://rubygems.org/gems/transmission-rss
@@ -74,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
96
  version: '0'
75
97
  requirements: []
76
98
  rubyforge_project:
77
- rubygems_version: 2.5.1
99
+ rubygems_version: 2.6.3
78
100
  signing_key:
79
101
  specification_version: 4
80
102
  summary: Adds torrents from rss feeds to transmission web frontend.