transmission-rss 0.1.3 → 0.1.5

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.
@@ -62,5 +62,4 @@ defined by default, so the script runs as current user/group.
62
62
 
63
63
  * Timeout and error handling in +Aggregator+ and +Client+
64
64
  * Option to stop seeding after full download
65
- * Privileges configurable by GUI
66
- * Log level
65
+ * Configurable log level
@@ -1,63 +1,56 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require( 'getoptlong' )
4
- require( 'etc' )
3
+ require 'getoptlong'
4
+ require 'etc'
5
5
 
6
- $:.unshift( File.join( File.dirname( __FILE__ ), '../lib' ) )
7
- require( 'transmission-rss' )
6
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
7
+ require 'transmission-rss'
8
8
 
9
9
  include TransmissionRSS
10
10
 
11
11
  # Default config file path.
12
- configFile = '/etc/transmission-rss.conf'
12
+ config_file = '/etc/transmission-rss.conf'
13
13
 
14
14
  # Do not edit config file in Gtk GUI by default.
15
- editConfig = false
15
+ edit_config = false
16
16
 
17
17
  # Do not fork by default.
18
18
  dofork = false
19
19
 
20
- # Default not verbose.
21
- verbose = false
22
-
23
20
  # Shows a summary of the command line options.
24
- def usageMessage( configFile )
25
- $stderr << "#{File.basename( $0 )} [options]
21
+ def usage_message( config_file )
22
+ $stderr << "#{File.basename($0)} [options]
26
23
  Adds torrents from rss feeds to transmission web frontend.
27
24
 
28
- -c <file> Custom config file path. Default: #{configFile}
25
+ -c <file> Custom config file path. Default: #{config_file}
29
26
  -e Edit config file with Gtk GUI.
30
27
  -f Fork into background after startup.
31
28
  -h This help.
32
- -v Verbose mode.
33
29
 
34
30
  "
35
- exit( 1 )
31
+ exit(1)
36
32
  end
37
33
 
38
34
  # Define command-line options.
39
35
  options = GetoptLong.new(
40
- [ '-c', GetoptLong::REQUIRED_ARGUMENT ],
41
- [ '-e', GetoptLong::NO_ARGUMENT ],
42
- [ '-f', GetoptLong::NO_ARGUMENT ],
43
- [ '-h', GetoptLong::NO_ARGUMENT ],
44
- [ '-v', GetoptLong::NO_ARGUMENT ]
36
+ [ '-c', GetoptLong::REQUIRED_ARGUMENT ],
37
+ [ '-e', GetoptLong::NO_ARGUMENT ],
38
+ [ '-f', GetoptLong::NO_ARGUMENT ],
39
+ [ '-h', GetoptLong::NO_ARGUMENT ]
45
40
  )
46
41
 
47
42
  # Parse given options.
48
43
  options.each do |option, argument|
49
- case( option )
50
- when '-c'
51
- configFile = argument
52
- when '-e'
53
- editConfig = true
54
- when '-f'
55
- dofork = true
56
- when '-h'
57
- usageMessage( configFile )
58
- when '-v'
59
- verbose = true
60
- end
44
+ case(option)
45
+ when '-c'
46
+ config_file = argument
47
+ when '-e'
48
+ edit_config = true
49
+ when '-f'
50
+ dofork = true
51
+ when '-h'
52
+ usage_message(config_file)
53
+ end
61
54
  end
62
55
 
63
56
  # Seems to be necessary when called from gem installation.
@@ -65,96 +58,107 @@ end
65
58
  config = TransmissionRSS::Config.instance
66
59
 
67
60
  # Default configuration.
68
- config.load( {
69
- 'feeds' => [],
70
- 'update_interval' => 600,
71
- 'add_paused' => false,
72
- 'server' => {
73
- 'host' => 'localhost',
74
- 'port' => 9091
75
- },
76
- 'log_target' => $stderr,
77
- 'privileges' => {}
78
- } )
79
-
80
- # Initialize a log instance, configure it and run the consumer in a subthread.
61
+ config.load({
62
+ 'feeds' => [],
63
+ 'update_interval' => 600,
64
+ 'add_paused' => false,
65
+ 'server' => {
66
+ 'host' => 'localhost',
67
+ 'port' => 9091
68
+ },
69
+ 'log_target' => $stderr,
70
+ 'privileges' => {}
71
+ })
72
+
73
+ # Initialize a log instance and configure it.
81
74
  log = Log.instance
82
- log.verbose = verbose
83
75
  log.target = config.log_target
84
- tLog = Thread.start do log.run end
76
+ log.level = Logger::DEBUG
77
+ log.formatter = proc do |sev, time, prog, msg|
78
+ "#{time.to_i}(#{sev.downcase}) #{msg}\n"
79
+ end
85
80
 
86
81
  # Load config file (default or given by argument).
87
82
  begin
88
- config.load( configFile )
83
+ config.load(config_file)
84
+ log.target = config.log_target
89
85
  rescue Errno::ENOENT
90
- log.add( configFile + ' not found' )
86
+ log.error(config_file + ' not found')
91
87
  end
92
- log.add( config )
88
+ log.debug(config)
93
89
 
94
90
  # Drop privileges, if section is given in config file.
95
- if( not config.privileges.empty? )
96
- Process::Sys.setgid(
97
- Etc.getgrnam( config.privileges.group ).gid
98
- )
99
-
100
- Process::Sys.setuid(
101
- Etc.getpwnam( config.privileges.user ).uid
102
- )
103
-
104
- log.add(
105
- 'dropped privileges ' +
106
- config.privileges.user +
107
- ':' +
108
- config.privileges.group
109
- )
91
+ if(not config.privileges.empty?)
92
+ Process::Sys.setgid(
93
+ Etc.getgrnam(config.privileges.group).gid
94
+ )
95
+
96
+ Process::Sys.setuid(
97
+ Etc.getpwnam(config.privileges.user).uid
98
+ )
99
+
100
+ log.debug(
101
+ 'dropped privileges ' +
102
+ config.privileges.user +
103
+ ':' +
104
+ config.privileges.group
105
+ )
110
106
  else
111
- log.add( 'no privilege dropping' )
107
+ log.debug('no privilege dropping')
108
+ end
109
+
110
+ # Warn if no feeds are given.
111
+ if(config.feeds.empty?)
112
+ log.warn('no feeds given')
112
113
  end
113
114
 
114
115
  # Start GUI if config edit option is given.
115
- if( editConfig )
116
- require( 'transmission-rss/config-editor' )
116
+ if(edit_config)
117
+ require 'transmission-rss/config-editor'
117
118
 
118
- Gtk.init
119
+ Gtk.init
119
120
 
120
- ConfigEditor.new( configFile, config )
121
- Gtk.main
121
+ ConfigEditor.new(config_file, config)
122
+ Gtk.main
122
123
 
123
- exit( 0 )
124
+ exit(0)
124
125
  end
125
126
 
126
127
  # Connect reload of config file to SIGHUP.
127
- trap( 'HUP' ) do
128
- config.load( configFile )
129
- log.add( 'got hup', config )
128
+ trap('HUP') do
129
+ config.load(config_file)
130
+ log.info('got hup', config)
130
131
  end
131
132
 
132
133
  # Initialize feed aggregator.
133
134
  aggregator = Aggregator.new
134
135
 
135
136
  # Initialize communication to transmission.
136
- client = Client.new( config.server.host, config.server.port )
137
+ client = Client.new(config.server.host, config.server.port)
137
138
 
138
139
  # Add feeds from config file to +Aggregator+ class.
139
- aggregator.feeds.concat( config.feeds )
140
+ aggregator.feeds.concat(config.feeds)
140
141
 
141
142
  # Callback for a new item on one of the feeds.
142
143
  aggregator.on_new_item do |torrentFile|
143
- Thread.start do
144
- client.addTorrent( torrentFile, config.add_paused )
145
- end
144
+ Thread.start do
145
+ client.addTorrent(torrentFile, config.add_paused)
146
+ end
146
147
  end
147
148
 
148
149
  # Start the aggregation process.
149
150
  begin
150
- if( dofork )
151
- pid = fork do
152
- aggregator.run( config.update_interval )
153
- end
154
-
155
- puts( 'forked ' + pid.to_s )
156
- else
157
- aggregator.run( config.update_interval )
158
- end
151
+ if(dofork)
152
+ pid = fork do
153
+ aggregator.run(config.update_interval)
154
+ end
155
+
156
+ puts('forked ' + pid.to_s)
157
+ else
158
+ aggregator.run(config.update_interval)
159
+ end
159
160
  rescue Interrupt
161
+ log.info('interrupt caught')
160
162
  end
163
+
164
+ log.close
@@ -1,7 +1,7 @@
1
- $:.unshift( File.dirname( __FILE__ ) )
1
+ $:.unshift(File.dirname(__FILE__))
2
2
 
3
3
  module TransmissionRSS
4
- VERSION = '0.1.3'
4
+ VERSION = '0.1.5'
5
5
  end
6
6
 
7
7
  dir = 'transmission-rss'
@@ -14,6 +14,6 @@ blacklist.map! do |name|
14
14
  $:.first + '/' + dir + '/' + name + '.rb'
15
15
  end
16
16
 
17
- ( Dir.glob( $:.first + '/' + dir + '/*.rb' ) - blacklist ).each do |lib|
18
- require( lib )
17
+ (Dir.glob($:.first + '/' + dir + '/*.rb') - blacklist).each do |lib|
18
+ require lib
19
19
  end
@@ -1,114 +1,116 @@
1
- require( 'etc' )
2
- require( 'fileutils' )
3
- require( 'open-uri' )
4
- require( 'rss' )
1
+ require 'etc'
2
+ require 'fileutils'
3
+ require 'open-uri'
4
+ require 'rss'
5
5
 
6
6
  # Class for aggregating torrent files through RSS feeds.
7
7
  class TransmissionRSS::Aggregator
8
- attr_accessor :feeds
9
-
10
- def initialize( feeds = [] )
11
- @feeds = feeds
12
- @seen = []
13
-
14
- # Initialize log instance.
15
- @log = Log.instance
16
-
17
- # Declare callback for new items.
18
- callback( :on_new_item )
19
-
20
- # Generate path for seen torrents store file.
21
- @seenfile = File.join(
22
- Etc.getpwuid.dir,
23
- '/.config/transmission/seen-torrents.conf'
24
- )
25
-
26
- # Make directories in path if they are not existing.
27
- FileUtils.mkdir_p( File.dirname( @seenfile ) )
28
-
29
- # Touch seen torrents store file.
30
- if( not File.exists?( @seenfile ) )
31
- FileUtils.touch( @seenfile )
32
- end
33
-
34
- # Open file, read torrent URLs and add to +@seen+.
35
- open( @seenfile ).readlines.each do |line|
36
- @seen.push( line.chomp )
37
- @log.add( 'from seenfile ' + line.chomp )
38
- end
39
- end
40
-
41
- # Get file enclosures from all feeds items and call on_new_item callback
42
- # with torrent file URL as argument.
43
- def run( interval = 600 )
44
- @log.add( 'aggregator start' )
45
-
46
- while( true )
47
- feeds.each do |url|
48
- # @log.add( 'aggregate ' + url )
49
-
50
- begin
51
- content = open( url ).readlines.join( "\n" )
52
- items = RSS::Parser.parse( content, false ).items
53
- rescue
54
- @log.add( 'retrieval error' )
55
- next
56
- end
57
-
58
- items.each do |item|
59
- link = item.link
8
+ attr_accessor :feeds
9
+
10
+ def initialize(feeds = [])
11
+ @feeds = feeds
12
+ @seen = []
13
+
14
+ # Initialize log instance.
15
+ @log = Log.instance
16
+
17
+ # Declare callback for new items.
18
+ callback(:on_new_item)
19
+
20
+ # Generate path for seen torrents store file.
21
+ @seenfile = File.join(
22
+ Etc.getpwuid.dir,
23
+ '/.config/transmission/seen-torrents.conf'
24
+ )
25
+
26
+ # Make directories in path if they are not existing.
27
+ FileUtils.mkdir_p(File.dirname(@seenfile))
28
+
29
+ # Touch seen torrents store file.
30
+ if(not File.exists?(@seenfile))
31
+ FileUtils.touch(@seenfile)
32
+ end
33
+
34
+ # Open file, read torrent URLs and add to +@seen+.
35
+ open(@seenfile).readlines.each do |line|
36
+ @seen.push(line.chomp)
37
+ end
38
+
39
+ # Log number of +@seen+ URIs.
40
+ @log.debug(@seen.size.to_s + ' uris from seenfile')
41
+ end
42
+
43
+ # Get file enclosures from all feeds items and call on_new_item callback
44
+ # with torrent file URL as argument.
45
+ def run(interval = 600)
46
+ @log.debug('aggregator start')
47
+
48
+ while(true)
49
+ feeds.each do |url|
50
+ @log.debug('aggregate ' + url)
51
+
52
+ begin
53
+ content = open(url).readlines.join("\n")
54
+ items = RSS::Parser.parse(content, false).items
55
+ rescue
56
+ @log.debug('retrieval error')
57
+ next
58
+ end
59
+
60
+ items.each do |item|
61
+ link = item.link
60
62
 
61
- # Item contains no link.
62
- if( link.nil? )
63
- next
64
- end
65
-
66
- # Link is not a String directly.
67
- if( link.class != String )
68
- link = link.href
69
- end
70
-
71
- # The link is not in +@seen+ Array.
72
- if( not seen?( link ) )
73
- on_new_item( link )
74
- @log.add( 'on_new_item event ' + link )
75
-
76
- add_seen( link )
77
- end
78
- end
79
- end
80
-
81
- sleep( interval )
82
- end
83
- end
84
-
85
- # To add a link into the list of seen links.
86
- def add_seen( link )
87
- @seen.push( link )
88
-
89
- File.open( @seenfile, 'w' ) do |file|
90
- file.write( @seen.join( "\n" ) )
91
- end
92
- end
93
-
94
- # To test if a link is in the list of seen links.
95
- def seen?( link )
96
- @seen.include?( link )
97
- end
98
-
99
- # Method to define callback methods.
100
- def callback( *names )
101
- names.each do |name|
102
- eval <<-EOF
103
- @#{name} = false
104
- def #{name}( *args, &block )
105
- if( block )
106
- @#{name} = block
107
- elsif( @#{name} )
108
- @#{name}.call( *args )
109
- end
110
- end
111
- EOF
112
- end
113
- end
63
+ # Item contains no link.
64
+ if(link.nil?)
65
+ next
66
+ end
67
+
68
+ # Link is not a String directly.
69
+ if(link.class != String)
70
+ link = link.href
71
+ end
72
+
73
+ # The link is not in +@seen+ Array.
74
+ if(not seen?(link))
75
+ on_new_item(link)
76
+ @log.debug('on_new_item event ' + link)
77
+
78
+ add_seen(link)
79
+ end
80
+ end
81
+ end
82
+
83
+ sleep(interval)
84
+ end
85
+ end
86
+
87
+ # To add a link into the list of seen links.
88
+ def add_seen(link)
89
+ @seen.push(link)
90
+
91
+ File.open(@seenfile, 'w') do |file|
92
+ file.write(@seen.join("\n"))
93
+ end
94
+ end
95
+
96
+ # To test if a link is in the list of seen links.
97
+ def seen?(link)
98
+ @seen.include?(link)
99
+ end
100
+
101
+ # Method to define callback methods.
102
+ def callback(*names)
103
+ names.each do |name|
104
+ eval <<-EOF
105
+ @#{name} = false
106
+ def #{name}(*args, &block)
107
+ if(block)
108
+ @#{name} = block
109
+ elsif(@#{name})
110
+ @#{name}.call(*args)
111
+ end
112
+ end
113
+ EOF
114
+ end
115
+ end
114
116
  end