Skip to content

Commit

Permalink
Support authentication.
Browse files Browse the repository at this point in the history
  • Loading branch information
nning committed Nov 9, 2014
1 parent 01af527 commit fde993a
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 45 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ Feed item titles can be filtered by a regular expression:
### All available options

The following configuration file example contains every existing option
(although `update_interval`, `add_paused` and `server` are default values
and could be omitted). The default `log_target` is STDERR. `privileges` is
not defined by default, so the script runs as current user/group.
(although `update_interval`, `add_paused`, `server`, `fork`, and `pid_file` are
default values and could be omitted). The default `log_target` is STDERR.
`privileges` is not defined by default, so the script runs as current
user/group. `login` is also not defined by default. It has to be defined, if
transmission is configured for HTTP basic authentication.

feeds:
- http://example.com/feed1
Expand All @@ -74,6 +76,10 @@ not defined by default, so the script runs as current user/group.
host: localhost
port: 9091

login:
username: transmission
password: transmission

log_target: /var/log/transmissiond-rss.log

privileges:
Expand Down
15 changes: 8 additions & 7 deletions bin/transmission-rss
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ options.each do |option, argument|
when '-f'
dofork = true
when '-h'
usage_message config_file
usage_message(config_file)
when '-p'
pid_file = argument
when '-v'
Expand All @@ -70,6 +70,7 @@ defaults = {
'host' => 'localhost',
'port' => 9091
},
'login' => nil,
'log_target' => $stderr,
'fork' => false,
'pid_file' => false,
Expand All @@ -88,7 +89,7 @@ end

# Load config file (default or given by argument).
begin
config.load config_file
config.load(config_file)
log.target = config.log_target
rescue Errno::ENOENT
log.error config_file + ' not found'
Expand Down Expand Up @@ -130,27 +131,27 @@ end
aggregator = Aggregator.new(config.feeds, seen_file: config.seen_file)

# Initialize communication to transmission.
client = Client.new config.server.host, config.server.port
client = Client.new(config.server.host, config.server.port, config.login)

# Callback for a new item on one of the feeds.
aggregator.on_new_item do |torrent_file|
client.add_torrent torrent_file, :url, config.add_paused
client.add_torrent(torrent_file, :url, config.add_paused)
end

# Save PID.
if config.pid_file
log.debug 'wrote pid to ' + config.pid_file
File.write config.pid_file, Process.pid
File.write(config.pid_file, Process.pid)
end

# Start the aggregation process.
begin
if config.fork
pid = fork { aggregator.run config.update_interval }
pid = fork { aggregator.run(config.update_interval) }
log.debug 'forked ' + pid.to_s
else
log.debug 'pid ' + Process.pid.to_s
aggregator.run config.update_interval
aggregator.run(config.update_interval)
end
rescue Interrupt
log.info 'interrupt caught'
Expand Down
45 changes: 21 additions & 24 deletions lib/transmission-rss/aggregator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module TransmissionRSS
# Class for aggregating torrent files through RSS feeds.
class Aggregator
extend Callback
callback :on_new_item # Declare callback for new items.
callback(:on_new_item) # Declare callback for new items.

def initialize(feeds = [], seen_file: nil)
# Prepare Array of feeds URLs.
Expand All @@ -36,37 +36,37 @@ def initialize(feeds = [], seen_file: nil)
'/.config/transmission/seen-torrents.conf')

# Make directories in path if they are not existing.
FileUtils.mkdir_p File.dirname(@seenfile)
FileUtils.mkdir_p(File.dirname(@seenfile))

# Touch seen torrents store file.
unless File.exists? @seenfile
FileUtils.touch @seenfile
unless File.exists?(@seenfile)
FileUtils.touch(@seenfile)
end

# Open file, read torrent URLs and add to +@seen+.
open(@seenfile).readlines.each do |line|
@seen.push line.chomp
@seen.push(line.chomp)
end

# Log number of +@seen+ URIs.
@log.debug @seen.size.to_s + ' uris from seenfile'
@log.debug(@seen.size.to_s + ' uris from seenfile')
end

# Get file enclosures from all feeds items and call on_new_item callback
# with torrent file URL as argument.
def run(interval = 600)
@log.debug 'aggregator start'
@log.debug('aggregator start')

while true
@feeds.each do |url|
url = URI.encode(url)
@log.debug 'aggregate ' + url
@log.debug('aggregate ' + url)

begin
content = open(url, allow_redirections: :safe).read
items = RSS::Parser.parse(content, false).items
rescue Exception => e
@log.debug "retrieval error (#{e.message})"
@log.debug("retrieval error (#{e.message})")
next
end

Expand All @@ -80,47 +80,44 @@ def run(interval = 600)
link = link.href if link.class != String

# The link is not in +@seen+ Array.
unless seen? link
# @log.debug 'unseen link ' + link

unless seen?(link)
# Skip if filter defined and not matching.
if @filters.include? url
if @filters.include?(url)
unless item.title[@filters[url]]
# @log.debug 'filter does not match ' + item.title
add_seen link
add_seen(link)
next
end
end

@log.debug 'on_new_item event ' + link
@log.debug('on_new_item event ' + link)

begin
on_new_item link
rescue Errno::ECONNREFUSED
# @log.debug 'not added to seenfile'
on_new_item(link)
rescue Errno::ECONNREFUSED, Client::Unauthorized
# Do not add to seen file.
else
add_seen link
add_seen(link)
end
end
end
end

sleep interval
sleep(interval)
end
end

# To add a link into the list of seen links.
def add_seen(link)
@seen.push link
@seen.push(link)

File.open(@seenfile, 'w') do |file|
file.write @seen.join("\n")
file.write(@seen.join("\n"))
end
end

# To test if a link is in the list of seen links.
def seen?(link)
@seen.include? link
@seen.include?(link)
end
end
end
40 changes: 31 additions & 9 deletions lib/transmission-rss/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
module TransmissionRSS
# Class for communication with transmission utilizing the RPC web interface.
class Client
def initialize(host = 'localhost', port = 9091, timeout: 5)
@host, @port, @timeout = host, port, timeout
class Unauthorized < StandardError
end

def initialize(host = 'localhost', port = 9091, login = nil, timeout: 5)
@host, @port, @login, @timeout = host, port, login, timeout
@log = TransmissionRSS::Log.instance
end

Expand All @@ -27,39 +30,58 @@ def add_torrent(file, type, paused = false)
when :file
hash.arguments.metainfo = Base64.encode64(File.read(file))
else
raise ArgumentError.new 'type has to be :url or :file.'
raise ArgumentError.new('type has to be :url or :file.')
end

sid = get_session_id
raise Unauthorized unless sid

post = Net::HTTP::Post.new \
'/transmission/rpc',
initheader = {
'Content-Type' => 'application/json',
'X-Transmission-Session-Id' => get_session_id
'X-Transmission-Session-Id' => sid
}

auth(post)

post.body = hash.to_json

response = request post
response = request(post)

result = JSON.parse(response.body).result

@log.debug 'add_torrent result: ' + result
@log.debug('add_torrent result: ' + result)
end

# Get transmission session id.
def get_session_id
get = Net::HTTP::Get.new '/transmission/rpc'
response = request get
get = Net::HTTP::Get.new('/transmission/rpc')

auth(get)

response = request(get)

id = response.header['x-transmission-session-id']

@log.debug 'got session id ' + id
if id.nil?
@log.debug("could not obtain session id (#{response.code}, " +
"#{response.class})")
else
@log.debug('got session id ' + id)
end

id
end

private

def auth(request)
unless @login.nil?
request.basic_auth(@login['username'], @login['password'])
end
end

def request(data)
Timeout::timeout(@timeout) do
Net::HTTP.new(@host, @port).start do |http|
Expand Down
2 changes: 1 addition & 1 deletion lib/transmission-rss/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module TransmissionRSS
VERSION = '0.1.18'
VERSION = '0.1.19'
end
6 changes: 6 additions & 0 deletions transmission-rss.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ feeds:
# host: localhost
# port: 9091

# Uncomment if transmission server requires login.

#login:
# username: transmission
# password: transmission

# Where to log. Default is stderr.

#log_target: /var/log/transmissiond-rss.log
Expand Down
3 changes: 2 additions & 1 deletion transmission-rss.gemspec
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require_relative 'lib/transmission-rss/version'
$: << File.dirname(__FILE__)
require 'lib/transmission-rss/version'

Gem::Specification.new do |s|
s.name = 'transmission-rss'
Expand Down

0 comments on commit fde993a

Please sign in to comment.