transmission-rss 0.1.26 → 0.2.0

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: 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.