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 +7 -0
- data/.document +4 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/ChangeLog.rdoc +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.md +134 -0
- data/Rakefile +36 -0
- data/bin/feed_torrents +25 -0
- data/examples/feed_torrents.yml +35 -0
- data/feed_torrents.gemspec +27 -0
- data/lib/feed_torrents/configuration.rb +54 -0
- data/lib/feed_torrents/feed/download.rb +54 -0
- data/lib/feed_torrents/feed/factory.rb +21 -0
- data/lib/feed_torrents/feed/list.rb +87 -0
- data/lib/feed_torrents/feed/magnet-uri.rb +33 -0
- data/lib/feed_torrents/log_functions.rb +18 -0
- data/lib/feed_torrents/reactor.rb +62 -0
- data/lib/feed_torrents/store.rb +51 -0
- data/lib/feed_torrents/version.rb +4 -0
- data/lib/feed_torrents.rb +11 -0
- data/spec/feed_torrents_spec.rb +8 -0
- data/spec/spec_helper.rb +4 -0
- metadata +181 -0
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
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation
|
data/ChangeLog.rdoc
ADDED
data/Gemfile
ADDED
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
|
+
[](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 (2014) - 40 [720p][AAC].mp4
|
82
|
+
I, [2015-01-10T20:32:25.061733 #21457] INFO -- : FeedTorrents::Feed::Download#process: Downloading torrent for '[DeadFish] Fairy Tail (2014) - 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 (2014) - 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,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'
|
data/spec/spec_helper.rb
ADDED
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
|