feed_torrents 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ab95c88a022529d22ef12ba2e63243d30c75ab9
4
+ data.tar.gz: d633d34caee9592a45156d20b61f9a4c3db3a7bb
5
+ SHA512:
6
+ metadata.gz: 1a2d78dc6761e530ae6e0672fd027b63de38671274f0bfdabdcc2317ab783de6b9c53f7724b5659d4b403c2d05985baa485a64cfec570a327a7cfe9562dd85d3
7
+ data.tar.gz: 5f0f736ab30488b1c4d779ecf917829ef3054cdab06a849859e7913bea8a74db93f8abf42634a1f8a2a9e73307bbe2f4dddaa656f5c149d4c75be30ac5ed0599
data/.document ADDED
@@ -0,0 +1,4 @@
1
+ lib/**/*.rb
2
+ README.rdoc
3
+ ChangeLog.rdoc
4
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ Gemfile.lock
2
+ html/
3
+ pkg/
4
+ vendor/cache/*.gem
5
+ .idea/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/ChangeLog.rdoc ADDED
@@ -0,0 +1,4 @@
1
+ === 0.1.0 / 2015-01-10
2
+
3
+ * Initial release:
4
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 Tom van Leeuwen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # FeedTorrents
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/feed_torrents.png)](http://rubygems.org/gems/feed_torrents)
4
+
5
+ ## Install
6
+
7
+ Install with Rubygems:
8
+
9
+ gem install feed_torrents
10
+
11
+ If you use bundler, add it to your Gemfile:
12
+
13
+ gem "feed_torrents", "~>0.1.0"
14
+
15
+ ## Usage
16
+
17
+ Create a configuration file: /tmp/feed_torrents.yml
18
+ ```yaml
19
+ log:
20
+ :out: STDOUT # or some file path
21
+ :rotate: 5
22
+ :size: 1048576 # 1MB
23
+ :level: DEBUG
24
+ :format: '%Y-%m-%d %H:%M:%S'
25
+
26
+ datastore: /tmp/feed_torrents.store
27
+
28
+ # Default configuration items for a feed
29
+ default_feed: &default_feed
30
+ :enabled: true
31
+ :interval: 900 # 900 seconds is 15 minutes
32
+ :timeout: 30
33
+ :directory: /tmp/incoming_torrents
34
+ :regex_filters:
35
+ - '.*'
36
+
37
+ # Interval is in seconds
38
+ feeds:
39
+ showrss:
40
+ <<: *default_feed
41
+ :url: 'http://showrss.info/rss.php?user_id=0000'
42
+ :interval: 900
43
+ :enabled: true
44
+
45
+ nyaa:
46
+ <<: *default_feed
47
+ :url: 'http://www.nyaa.se/?page=rss&cats=1_37'
48
+ :interval: 1800
49
+ :enabled: true
50
+ :regex_filters:
51
+ - 'HorribleSubs.*Fairy Tail S2 .*720p'
52
+ - 'HorribleSubs.*Magic Kaito .*1080p'
53
+ - '\[DeadFish\]'
54
+ ```
55
+
56
+ Now simply start the application:
57
+ ```bash
58
+ feed_torrents /tmp/feed_torrents.yml
59
+ I, [2015-01-10T20:32:24.171075 #21457] INFO -- : FeedTorrents::Reactor#initialize: Initialize new Reactor version 0.1.0
60
+ I, [2015-01-10T20:32:24.171184 #21457] INFO -- : FeedTorrents::Reactor#start: Starting eventmachine loop
61
+ I, [2015-01-10T20:32:24.171450 #21457] INFO -- : FeedTorrents::Feed::List#initialize: showrss (enabled: true interval: 900 link: http://showrss.info/rss.php?user_id=0000)
62
+ I, [2015-01-10T20:32:24.171484 #21457] INFO -- : FeedTorrents::Feed::List#initialize: nyaa (enabled: true interval: 1800 link: http://www.nyaa.se/?page=rss&cats=1_37)
63
+ I, [2015-01-10T20:32:24.171540 #21457] INFO -- : FeedTorrents::Feed::List#download_new_items: feed showrss
64
+ I, [2015-01-10T20:32:24.182937 #21457] INFO -- : FeedTorrents::Feed::List#download_new_items: feed nyaa
65
+ I, [2015-01-10T20:32:24.321911 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: American Horror Story 4x11 Magical Thinking 720p
66
+ I, [2015-01-10T20:32:24.322063 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for 'American Horror Story 4x11 Magical Thinking 720p' (http://reflektor.karmorra.info/torrent/54D7C99225897595AF1E4F85B5B317FEEF0119C5.torrent)
67
+ I, [2015-01-10T20:32:24.352748 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: American Horror Story 4x10 Orphans 720p
68
+ I, [2015-01-10T20:32:24.352990 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for 'American Horror Story 4x10 Orphans 720p' (http://reflektor.karmorra.info/torrent/CA85592A0850E361AC0840ED510A036FA2A1828C.torrent)
69
+ I, [2015-01-10T20:32:24.971696 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [DeadFish] Tokyo Ghoul √A - 01 [720p][AAC].mp4
70
+ I, [2015-01-10T20:32:24.971757 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[DeadFish] Tokyo Ghoul √A - 01 [720p][AAC].mp4' (http://www.nyaa.se/?page=download&tid=643972)
71
+ I, [2015-01-10T20:32:24.987967 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [HorribleSubs] Magic Kaito 1412 - 06 [1080p].mkv
72
+ I, [2015-01-10T20:32:24.988158 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[HorribleSubs] Magic Kaito 1412 - 06 [1080p].mkv' (http://www.nyaa.se/?page=download&tid=643846)
73
+ I, [2015-01-10T20:32:25.003946 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [HorribleSubs] Magic Kaito 1412 - 05 [1080p].mkv
74
+ I, [2015-01-10T20:32:25.004167 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[HorribleSubs] Magic Kaito 1412 - 05 [1080p].mkv' (http://www.nyaa.se/?page=download&tid=643845)
75
+ I, [2015-01-10T20:32:25.019271 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [HorribleSubs] Magic Kaito 1412 - 13 [1080p].mkv
76
+ I, [2015-01-10T20:32:25.019460 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[HorribleSubs] Magic Kaito 1412 - 13 [1080p].mkv' (http://www.nyaa.se/?page=download&tid=643830)
77
+ I, [2015-01-10T20:32:25.032232 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [HorribleSubs] Magic Kaito 1412 - 12 [1080p].mkv
78
+ I, [2015-01-10T20:32:25.032379 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[HorribleSubs] Magic Kaito 1412 - 12 [1080p].mkv' (http://www.nyaa.se/?page=download&tid=643758)
79
+ I, [2015-01-10T20:32:25.047954 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [DeadFish] Beast Saga - 23 [720p][AAC].mp4
80
+ I, [2015-01-10T20:32:25.048285 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[DeadFish] Beast Saga - 23 [720p][AAC].mp4' (http://www.nyaa.se/?page=download&tid=643723)
81
+ I, [2015-01-10T20:32:25.061514 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [DeadFish] Fairy Tail &#40;2014&#41; - 40 [720p][AAC].mp4
82
+ I, [2015-01-10T20:32:25.061733 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[DeadFish] Fairy Tail &#40;2014&#41; - 40 [720p][AAC].mp4' (http://www.nyaa.se/?page=download&tid=643722)
83
+ I, [2015-01-10T20:32:25.094340 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [HorribleSubs] Fairy Tail S2 - 40 [720p].mkv
84
+ I, [2015-01-10T20:32:25.094561 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[HorribleSubs] Fairy Tail S2 - 40 [720p].mkv' (http://www.nyaa.se/?page=download&tid=643668)
85
+ I, [2015-01-10T20:32:25.108556 #21457] INFO -- : FeedTorrents::Feed::List#process: Processing: [DeadFish] Military! - 01v2 [720p][AAC].mp4
86
+ I, [2015-01-10T20:32:25.108750 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[DeadFish] Military! - 01v2 [720p][AAC].mp4' (http://www.nyaa.se/?page=download&tid=643646)
87
+ I, [2015-01-10T20:32:25.275709 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for American Horror Story 4x10 Orphans 720p completed
88
+ I, [2015-01-10T20:32:25.289581 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [DeadFish] Beast Saga - 23 [720p][AAC].mp4 completed
89
+ I, [2015-01-10T20:32:25.337757 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [DeadFish] Military! - 01v2 [720p][AAC].mp4 completed
90
+ I, [2015-01-10T20:32:25.345284 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [DeadFish] Tokyo Ghoul √A - 01 [720p][AAC].mp4 completed
91
+ I, [2015-01-10T20:32:25.394842 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [DeadFish] Fairy Tail &#40;2014&#41; - 40 [720p][AAC].mp4 completed
92
+ I, [2015-01-10T20:32:25.413424 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [HorribleSubs] Fairy Tail S2 - 40 [720p].mkv completed
93
+ I, [2015-01-10T20:32:25.441256 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [HorribleSubs] Magic Kaito 1412 - 06 [1080p].mkv completed
94
+ I, [2015-01-10T20:32:25.445882 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [HorribleSubs] Magic Kaito 1412 - 13 [1080p].mkv completed
95
+ I, [2015-01-10T20:32:25.468350 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [HorribleSubs] Magic Kaito 1412 - 05 [1080p].mkv completed
96
+ I, [2015-01-10T20:32:25.475861 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for [HorribleSubs] Magic Kaito 1412 - 12 [1080p].mkv completed
97
+ I, [2015-01-10T20:32:30.767287 #21457] INFO -- : FeedTorrents::Feed::Download#block in process: Downloading torrent for American Horror Story 4x11 Magical Thinking 720p completed
98
+ ```
99
+
100
+ My qbittorrent-nox headless torrent client with webui loves this!
101
+
102
+ ## Upstart script
103
+
104
+ Tested this on my ubuntu-14.04 server.
105
+ Put these contents in /etc/init/feed_torrents.conf:
106
+ ```bash
107
+ start on (started networking)
108
+ stop on runlevel [!023456]
109
+
110
+ setuid tom
111
+ setgid tom
112
+
113
+ exec /usr/local/bin/feed_torrents /tmp/feed_torrents.yml
114
+ ```
115
+
116
+ And start it
117
+
118
+ ```bash
119
+ sudo start feed_torrents
120
+ ```
121
+
122
+ ## Issues
123
+
124
+ If you have found a bug then please raise an issue here on github.
125
+
126
+ ## Authors
127
+
128
+ - [Tom van Leeuwen](http://github.com/TvL2386) - Initial author.
129
+
130
+ ## Copyright
131
+
132
+ Copyright (c) 2015 Tom van Leeuwen
133
+
134
+ See LICENSE.txt for details.
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler'
7
+ rescue LoadError => e
8
+ warn e.message
9
+ warn "Run `gem install bundler` to install Bundler."
10
+ exit -1
11
+ end
12
+
13
+ begin
14
+ Bundler.setup(:development)
15
+ rescue Bundler::BundlerError => e
16
+ warn e.message
17
+ warn "Run `bundle install` to install missing gems."
18
+ exit e.status_code
19
+ end
20
+
21
+ require 'rake'
22
+
23
+ require 'rubygems/tasks'
24
+ Gem::Tasks.new
25
+
26
+ require 'rdoc/task'
27
+ RDoc::Task.new do |rdoc|
28
+ rdoc.title = "feed_torrents"
29
+ end
30
+ task :doc => :rdoc
31
+
32
+ require 'rspec/core/rake_task'
33
+ RSpec::Core::RakeTask.new
34
+
35
+ task :test => :spec
36
+ task :default => :spec
data/bin/feed_torrents ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ root = File.expand_path(File.join(File.dirname(__FILE__),'..'))
4
+ if File.directory?(File.join(root,'.git'))
5
+ Dir.chdir(root) do
6
+ begin
7
+ require 'bundler/setup'
8
+ rescue LoadError => e
9
+ warn e.message
10
+ warn "Run `gem install bundler` to install Bundler"
11
+ exit -1
12
+ end
13
+ end
14
+ end
15
+
16
+ require 'feed_torrents'
17
+
18
+ if ARGV.length != 1
19
+ puts "Usage: #{$0} <configfile>"
20
+ exit 1
21
+ else
22
+ FeedTorrents.configuration.yaml_from_file ARGV[0]
23
+ end
24
+
25
+ FeedTorrents::Reactor.start!
@@ -0,0 +1,35 @@
1
+ log:
2
+ :out: STDOUT # or some file path
3
+ :rotate: 5
4
+ :size: 10485760 # 10MB
5
+ :level: INFO
6
+ :format: '%Y-%m-%d %H:%M:%S'
7
+
8
+ datastore: /tmp/feed_torrents.store
9
+
10
+ # Default configuration items for a feed
11
+ default_feed: &default_feed
12
+ :enabled: true
13
+ :interval: 900 # 900 seconds is 15 minutes
14
+ :timeout: 30
15
+ :directory: /tmp/incoming_torrents
16
+ :regex_filters:
17
+ - '.*'
18
+
19
+ # Interval is in seconds
20
+ feeds:
21
+ showrss:
22
+ <<: *default_feed
23
+ :url: 'http://showrss.info/rss.php?user_id=0000'
24
+ :interval: 900
25
+ :enabled: true
26
+
27
+ tokyo_ghoul_s2:
28
+ <<: *default_feed
29
+ :url: 'http://www.nyaa.se/?page=rss&cats=1_37'
30
+ :interval: 1800
31
+ :enabled: true
32
+ :regex_filters:
33
+ - 'HorribleSubs.*Fairy Tail S2 .*720p'
34
+ - 'HorribleSubs.*Magic Kaito .*1080p'
35
+ - '\[DeadFish\]'
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../lib/feed_torrents/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "feed_torrents"
5
+ gem.version = FeedTorrents::VERSION
6
+ gem.summary = %q{Follow configurable feeds and download torrents, even from magnet urls}
7
+ gem.description = %q{Follow configurable feeds and download torrents, even from magnet urls}
8
+ gem.license = "MIT"
9
+ gem.authors = ["Tom van Leeuwen"]
10
+ gem.email = "tom@vleeuwen.eu"
11
+ gem.homepage = "https://rubygems.org/gems/feed_torrents"
12
+
13
+ gem.files = `git ls-files`.split($/)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.require_paths = ['lib']
17
+
18
+ gem.add_dependency 'eventmachine', '~> 1.0'
19
+ gem.add_dependency 'simple-rss', '~> 1.3'
20
+ gem.add_dependency 'em-http-request', '~> 1.1'
21
+
22
+ gem.add_development_dependency 'bundler', '~> 1.5'
23
+ gem.add_development_dependency 'rake', '~> 10.4'
24
+ gem.add_development_dependency 'rdoc', '~> 4.1'
25
+ gem.add_development_dependency 'rspec', '~> 3.1'
26
+ gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
27
+ end
@@ -0,0 +1,54 @@
1
+ require 'singleton'
2
+ require 'ostruct'
3
+ require 'yaml'
4
+ require 'logger'
5
+ require 'pstore'
6
+
7
+ module FeedTorrents
8
+ def self.configuration
9
+ Configuration.instance
10
+ end
11
+
12
+ def self.logger
13
+ configuration.logger
14
+ end
15
+
16
+ class Configuration
17
+ include Singleton
18
+
19
+ def yaml_from_file(file)
20
+ set_config YAML.load_file(File.expand_path(file))
21
+ nil
22
+ end
23
+
24
+ def set_config(hash)
25
+ @source = OpenStruct.new(hash)
26
+ end
27
+
28
+ def logger
29
+ @logger ||= create_logger
30
+ end
31
+
32
+ def method_missing(method, *args, &block)
33
+ @source.send(method, *args, &block)
34
+ end
35
+
36
+ private
37
+
38
+ def source
39
+ @source ||= OpenStruct.new
40
+ end
41
+
42
+ def create_logger
43
+ if self.log and self.log[:out] == 'STDOUT'
44
+ obj = Logger.new(STDOUT)
45
+ else
46
+ obj = Logger.new(File.expand_path(self.log[:out]), self.log[:rotate], self.log[:size])
47
+ obj.level = Logger.const_get(self.log[:level])
48
+ obj.datetime_format = self.log[:format]
49
+ end
50
+
51
+ obj
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ require 'pathname'
2
+
3
+ module FeedTorrents
4
+ module Feed
5
+ class Download
6
+ include LogFunctions
7
+
8
+ def initialize(title, link, timeout, directory)
9
+ @title, @link, @timeout, @directory = title, link, timeout, directory
10
+ end
11
+
12
+ def process
13
+ info "Downloading torrent for '#{@title}' (#{torrent_link})"
14
+ http = EM::HttpRequest.new(torrent_link, inactivity_timeout: @timeout).get
15
+ fh = File.new(file,'wb')
16
+
17
+ http.stream { |chunk| fh.write chunk }
18
+
19
+ http.errback do
20
+ error "failure retrieving torrent for '#{@title}' (#{torrent_link})"
21
+ end
22
+
23
+ http.callback do
24
+ info "Downloading torrent for #{@title} completed"
25
+ fh.close
26
+ FeedTorrents.store.persist(@link)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def torrent_link
33
+ @torrent_link ||= determine_link
34
+ end
35
+
36
+ def determine_link
37
+ if is_magnet?
38
+ MagnetURI.new(@link).reflektor_link
39
+ else
40
+ @link
41
+ end
42
+ end
43
+
44
+ def is_magnet?
45
+ @link =~ /^magnet:\?/
46
+ end
47
+
48
+ def file
49
+ Pathname.new(@directory).join("#{@title}.torrent").expand_path
50
+ end
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,21 @@
1
+ module FeedTorrents
2
+ module Feed
3
+ class Factory
4
+ include LogFunctions
5
+
6
+ def initialize
7
+ end
8
+
9
+ def lists
10
+ return @lists if defined?(@lists)
11
+
12
+ @lists = Array.new
13
+ FeedTorrents.configuration.feeds.each do |name,options|
14
+ @lists << List.new(name, options)
15
+ end
16
+
17
+ @lists
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,87 @@
1
+ require 'simple-rss'
2
+ require 'em-http'
3
+
4
+ module FeedTorrents
5
+ module Feed
6
+ class List
7
+ include LogFunctions
8
+
9
+ attr_reader :name
10
+
11
+ def initialize(name, options)
12
+ @name = name
13
+ @options = options
14
+
15
+ info "#{name} (enabled: #{enabled?} interval: #{interval} link: #{url})"
16
+ end
17
+
18
+ def interval
19
+ @options[:interval].to_i >= 1 ? @options[:interval].to_i : 3600
20
+ end
21
+
22
+ def enabled?
23
+ @options[:enabled]
24
+ end
25
+
26
+ def download_new_items
27
+ info "feed #{name}"
28
+
29
+ case url
30
+ when /^file:\/\/(.*)$/
31
+ process_raw(File.read($1))
32
+ when /^https?:\/\//
33
+ http = EM::HttpRequest.new(url, inactivity_timeout: timeout).get
34
+
35
+ http.errback do
36
+ error "failure retrieving #{name}"
37
+ end
38
+
39
+ http.callback do
40
+ process_raw http.response
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def url
48
+ @options[:url]
49
+ end
50
+
51
+ def timeout
52
+ @options[:timeout].to_i || 30
53
+ end
54
+
55
+ def process_raw(contents)
56
+ rss = SimpleRSS.parse contents
57
+
58
+ rss.items.each do |item|
59
+ link = CGI.unescapeHTML(item.link)
60
+ process(item.title, link) if !already_processed?(link) and matches_filter?(item.title)
61
+ end
62
+ end
63
+
64
+ def process(title, link)
65
+ info "Processing: #{title}"
66
+
67
+ Download.new(title, link, timeout, @options[:directory]).process
68
+ end
69
+
70
+ def regex_filters
71
+ @options[:regex_filters].map { |regex| /#{regex}/ }
72
+ end
73
+
74
+ def matches_filter?(title)
75
+ regex_filters.each do |filter|
76
+ return true if title =~ filter
77
+ end
78
+
79
+ false
80
+ end
81
+
82
+ def already_processed?(item)
83
+ FeedTorrents.store.present?(item)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,33 @@
1
+ # Blatently copied from: https://github.com/prep/magnet-uri
2
+
3
+ require 'cgi'
4
+ require 'uri'
5
+
6
+ module FeedTorrents
7
+ module Feed
8
+ class MagnetURI
9
+ def initialize(uri)
10
+ raise ArgumentError, 'bad argument (expected magnet URI)' unless uri =~ /^magnet:\?/
11
+
12
+ uri = CGI.unescapeHTML(uri)
13
+
14
+ scheme, params = uri.split('?', 2)
15
+
16
+ @params = {}.tap do |param|
17
+ CGI.parse(URI.decode(params)).each do |name, value|
18
+ name = name.to_sym
19
+ value = (value.size == 1 ? value.first : value)
20
+
21
+ param[name] = value
22
+ end
23
+ end
24
+
25
+ @info_hash = @params[:xt].split(':').last
26
+ end
27
+
28
+ def reflektor_link
29
+ "http://reflektor.karmorra.info/torrent/#{@info_hash}.torrent"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ module FeedTorrents
2
+ module LogFunctions
3
+ def log
4
+ FeedTorrents.logger
5
+ end
6
+
7
+ def log_caller
8
+ caller[1][/`.*'/][1..-2]
9
+ end
10
+
11
+ [:debug, :info, :warn, :error, :fatal].each do |sym|
12
+ define_method(sym) do |arg|
13
+ arg = "#{self.class.to_s}##{log_caller}: #{arg}"
14
+ log.send(sym, arg)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,62 @@
1
+ require 'eventmachine'
2
+
3
+ module FeedTorrents
4
+ class Reactor
5
+ include LogFunctions
6
+
7
+ def self.start!
8
+ new.start
9
+ end
10
+
11
+ def initialize
12
+ info "Initialize new Reactor version #{FeedTorrents::VERSION}"
13
+ end
14
+
15
+ def start
16
+ info 'Starting eventmachine loop'
17
+
18
+ EventMachine.run do
19
+ factory.lists.each do |list|
20
+ next unless list.enabled?
21
+
22
+ EM.add_periodic_timer(list.interval) { list.download_new_items }
23
+
24
+ EM.schedule { list.download_new_items }
25
+ end
26
+
27
+ EM.add_periodic_timer(1800) { debug '-- MARK --' }
28
+
29
+ EM.add_periodic_timer(3600) do
30
+ FeedTorrents.store.prune
31
+ end
32
+
33
+ # EM.add_timer(3) do
34
+ # puts 'I waited 3 seconds'
35
+ # # EM.stop_event_loop
36
+ # end
37
+
38
+ stop_block = Proc.new do
39
+ EM.add_timer(0) do
40
+ EventMachine.stop
41
+ end
42
+ end
43
+
44
+ Signal.trap('INT') do
45
+ info 'received sigint signal'
46
+ stop_block.call
47
+ end
48
+
49
+ Signal.trap('TERM') do
50
+ info 'received sigterm signal'
51
+ stop_block.call
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def factory
59
+ @factory ||= Feed::Factory.new
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,51 @@
1
+ require 'pstore'
2
+
3
+ module FeedTorrents
4
+ def self.store
5
+ Store.instance
6
+ end
7
+
8
+ class Store
9
+ include Singleton
10
+ include LogFunctions
11
+
12
+ def present?(item)
13
+ pstore.transaction(true) { return !!pstore[item] }
14
+ end
15
+
16
+ def persist(item)
17
+ pstore.transaction { pstore[item] = Time.now.to_i }
18
+ end
19
+
20
+ def prune
21
+ prune_count = 0
22
+
23
+ pstore.transaction do
24
+ pstore.roots.each do |item|
25
+ if outdated?(item)
26
+ pstore.delete(item)
27
+ prune_count += 1
28
+ end
29
+ end
30
+ end
31
+
32
+ if prune_count > 0
33
+ info "Pruned #{prune_count} items"
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def pstore
40
+ @pstore ||= PStore.new(pstore_file)
41
+ end
42
+
43
+ def pstore_file
44
+ File.expand_path(FeedTorrents.configuration.datastore)
45
+ end
46
+
47
+ def outdated?(time)
48
+ (Time.now.to_i - time < 7776000) # older than 90 days is outdated
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,4 @@
1
+ module FeedTorrents
2
+ # feed_torrents version
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,11 @@
1
+ require 'feed_torrents/log_functions'
2
+ require 'feed_torrents/configuration'
3
+
4
+ require 'feed_torrents/version'
5
+ require 'feed_torrents/store'
6
+ require 'feed_torrents/reactor'
7
+
8
+ require 'feed_torrents/feed/factory'
9
+ require 'feed_torrents/feed/list'
10
+ require 'feed_torrents/feed/download'
11
+ require 'feed_torrents/feed/magnet-uri'
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'feed_torrents'
3
+
4
+ describe FeedTorrents do
5
+ it "should have a VERSION constant" do
6
+ subject.const_get('VERSION').should_not be_empty
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ require 'rspec'
2
+ require 'feed_torrents/version'
3
+
4
+ include FeedTorrents
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: feed_torrents
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tom van Leeuwen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: eventmachine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: simple-rss
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: em-http-request
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rdoc
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '4.1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '4.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubygems-tasks
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.2'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.2'
125
+ description: Follow configurable feeds and download torrents, even from magnet urls
126
+ email: tom@vleeuwen.eu
127
+ executables:
128
+ - feed_torrents
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".document"
133
+ - ".gitignore"
134
+ - ".rspec"
135
+ - ChangeLog.rdoc
136
+ - Gemfile
137
+ - LICENSE.txt
138
+ - README.md
139
+ - Rakefile
140
+ - bin/feed_torrents
141
+ - examples/feed_torrents.yml
142
+ - feed_torrents.gemspec
143
+ - lib/feed_torrents.rb
144
+ - lib/feed_torrents/configuration.rb
145
+ - lib/feed_torrents/feed/download.rb
146
+ - lib/feed_torrents/feed/factory.rb
147
+ - lib/feed_torrents/feed/list.rb
148
+ - lib/feed_torrents/feed/magnet-uri.rb
149
+ - lib/feed_torrents/log_functions.rb
150
+ - lib/feed_torrents/reactor.rb
151
+ - lib/feed_torrents/store.rb
152
+ - lib/feed_torrents/version.rb
153
+ - spec/feed_torrents_spec.rb
154
+ - spec/spec_helper.rb
155
+ homepage: https://rubygems.org/gems/feed_torrents
156
+ licenses:
157
+ - MIT
158
+ metadata: {}
159
+ post_install_message:
160
+ rdoc_options: []
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ requirements: []
174
+ rubyforge_project:
175
+ rubygems_version: 2.2.0
176
+ signing_key:
177
+ specification_version: 4
178
+ summary: Follow configurable feeds and download torrents, even from magnet urls
179
+ test_files:
180
+ - spec/feed_torrents_spec.rb
181
+ - spec/spec_helper.rb