junkie 0.0.3 → 0.0.4
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.
- data/junkie.gemspec +1 -0
- data/lib/junkie.rb +6 -1
- data/lib/junkie/episode.rb +1 -1
- data/lib/junkie/notification/twitter.rb +68 -0
- data/lib/junkie/pyload/observer.rb +63 -17
- data/lib/junkie/reactor.rb +20 -27
- data/lib/junkie/version.rb +1 -1
- metadata +19 -2
data/junkie.gemspec
CHANGED
data/lib/junkie.rb
CHANGED
@@ -8,10 +8,15 @@ require 'junkie/helper'
|
|
8
8
|
require 'junkie/patched/sjunkieex'
|
9
9
|
require 'junkie/pyload/api'
|
10
10
|
require 'junkie/pyload/observer'
|
11
|
+
require 'junkie/notification/twitter'
|
11
12
|
require 'logging'
|
12
13
|
|
14
|
+
Logging.appenders.stdout(
|
15
|
+
'stdout',
|
16
|
+
:level => :debug,
|
17
|
+
:layout => Logging.layouts.pattern(:pattern => '[%d] %-5l: %m\n')
|
18
|
+
)
|
13
19
|
Logging.logger.root.appenders = Logging.appenders.stdout
|
14
|
-
Logging.logger.root.level = :debug
|
15
20
|
|
16
21
|
module Junkie
|
17
22
|
|
data/lib/junkie/episode.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'twitter'
|
2
|
+
|
3
|
+
module Junkie
|
4
|
+
module Notification
|
5
|
+
|
6
|
+
class Twitter
|
7
|
+
include Log, Config
|
8
|
+
|
9
|
+
DEFAULT_CONFIG = {
|
10
|
+
twitter_enabled: false,
|
11
|
+
consumer_key: "",
|
12
|
+
consumer_secret: "",
|
13
|
+
oauth_token: "",
|
14
|
+
oauth_token_secret: "",
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(channels)
|
18
|
+
@channels = channels
|
19
|
+
@config = Config.get_config(self)
|
20
|
+
|
21
|
+
if @config[:twitter_enabled]
|
22
|
+
|
23
|
+
# check the configuration
|
24
|
+
[:consumer_key, :consumer_secret, :oauth_token,
|
25
|
+
:oauth_token_secret].each do |key|
|
26
|
+
|
27
|
+
unless @config[key] && @config[key].match(/\w+/)
|
28
|
+
raise InvalidConfigError, "#{key} option is missing"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# configure
|
33
|
+
::Twitter.configure do |config|
|
34
|
+
config.consumer_key = @config[:consumer_key]
|
35
|
+
config.consumer_secret = @config[:consumer_secret]
|
36
|
+
config.oauth_token = @config[:oauth_token]
|
37
|
+
config.oauth_token_secret = @config[:oauth_token_secret]
|
38
|
+
end
|
39
|
+
|
40
|
+
# bind to channel
|
41
|
+
@channels[:notifications].subscribe do |episode|
|
42
|
+
next unless episode.status == :extracted
|
43
|
+
|
44
|
+
log.info("Received an episode from channel. I will tweet about this")
|
45
|
+
send_notification(episode)
|
46
|
+
end
|
47
|
+
|
48
|
+
else
|
49
|
+
log.info("Twitter support is disabled")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Sends a formatted message out through Twitter
|
56
|
+
#
|
57
|
+
# @param [Junkie::Episode] episode that has been downloaded
|
58
|
+
def send_notification(episode)
|
59
|
+
begin
|
60
|
+
mess = "A new episode of #{episode} has been downloaded #junkie"
|
61
|
+
::Twitter.update(mess)
|
62
|
+
rescue Exception => e
|
63
|
+
log.error(e)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -11,18 +11,31 @@ module Junkie
|
|
11
11
|
watchdog_refresh: 10, # interval the watchdog_timer is fired
|
12
12
|
}
|
13
13
|
|
14
|
-
def initialize(
|
14
|
+
def initialize(channels)
|
15
15
|
@config = Config.get_config(self)
|
16
16
|
|
17
17
|
@api = Junkie::Pyload::Api.new
|
18
18
|
|
19
|
+
@channels = channels
|
20
|
+
|
21
|
+
@found_episodes = Array.new
|
22
|
+
|
23
|
+
@active_episode = nil
|
24
|
+
|
19
25
|
@ready_for_new_links = true
|
20
26
|
@watchdog_enabled = false
|
21
|
-
@active_downloads = Hash.new
|
22
|
-
|
23
27
|
@skipped_timer_at_first_complete_detection = false
|
28
|
+
@should_send_it_on_channel = false
|
29
|
+
|
30
|
+
@channels[:episodes].subscribe do |episode|
|
31
|
+
next unless episode.status == :found
|
32
|
+
|
33
|
+
log.info("Got episode from Channel: #{episode}")
|
34
|
+
@found_episodes.push(episode)
|
35
|
+
end
|
24
36
|
end
|
25
37
|
|
38
|
+
|
26
39
|
# is a method that is called once from inside the reactor and allows us
|
27
40
|
# to register custom actions into the reactor
|
28
41
|
def setup
|
@@ -32,32 +45,53 @@ module Junkie
|
|
32
45
|
}
|
33
46
|
|
34
47
|
EM.add_periodic_timer(@config[:watchdog_refresh]) do
|
48
|
+
|
49
|
+
# temporary fix for the SystemStackError
|
50
|
+
if @should_send_it_on_channel
|
51
|
+
log.info("Sending complete episode out on the channel")
|
52
|
+
@channels[:episodes].push(@active_episode)
|
53
|
+
@active_episode = nil
|
54
|
+
|
55
|
+
@should_send_it_on_channel = false
|
56
|
+
end
|
57
|
+
|
35
58
|
monitor_progress if @watchdog_enabled
|
59
|
+
|
60
|
+
in_fiber {
|
61
|
+
add_next_episode_to_pyload
|
62
|
+
}
|
36
63
|
end
|
37
64
|
end
|
38
65
|
|
39
|
-
|
40
|
-
#
|
41
|
-
# @param [Junkie::Episode] episode which should be downloaded
|
66
|
+
|
67
|
+
# Add next episode to Pyload which downloads the episode and extracts it
|
42
68
|
#
|
43
69
|
# @note should only be called if `is_ready?` returns true
|
44
|
-
def
|
45
|
-
|
46
|
-
|
70
|
+
def add_next_episode_to_pyload
|
71
|
+
|
72
|
+
# detect if we cann add a new episode
|
73
|
+
return unless is_ready?
|
74
|
+
return if @found_episodes.empty?
|
75
|
+
|
76
|
+
@active_episode = @found_episodes.shift
|
77
|
+
episode = @active_episode
|
47
78
|
|
79
|
+
@ready_for_new_links = false
|
48
80
|
episode.status = :downloading
|
49
81
|
|
50
82
|
package = "%s@%s" % [ episode.id, episode.series ]
|
51
83
|
|
52
|
-
pid = @api.call(:addPackage,
|
84
|
+
pid = @api.call(:addPackage,
|
85
|
+
{ name: package, links: [episode.link] })
|
53
86
|
|
54
|
-
|
87
|
+
episode.pid = pid
|
55
88
|
|
56
89
|
log.info("Added #{episode} to Pyload, Pid=#{pid}")
|
57
90
|
|
58
91
|
(@watchdog_enabled = true) unless @watchdog_enabled
|
59
92
|
end
|
60
93
|
|
94
|
+
|
61
95
|
# checks if the Observer is ready to add new episodes to Pyload
|
62
96
|
#
|
63
97
|
# @returns [Boolean] true if new links can be added
|
@@ -72,7 +106,6 @@ module Junkie
|
|
72
106
|
# It monitors the download process and reacts depending on the results
|
73
107
|
def monitor_progress
|
74
108
|
log.debug("Watchdog timer has been fired")
|
75
|
-
|
76
109
|
in_fiber {
|
77
110
|
catch(:break) {
|
78
111
|
queue_data = @api.call(:getQueueData)
|
@@ -97,10 +130,22 @@ module Junkie
|
|
97
130
|
|
98
131
|
if not pids.empty?
|
99
132
|
if @skipped_timer_at_first_complete_detection
|
133
|
+
|
134
|
+
# post process complete active download and send it out on the
|
135
|
+
# channel
|
136
|
+
if pids.include? @active_episode.pid
|
137
|
+
log.info("'#{@active_episode}' is extracted completely")
|
138
|
+
@active_episode.pid = nil
|
139
|
+
@active_episode.status = :extracted
|
140
|
+
|
141
|
+
@should_send_it_on_channel = true
|
142
|
+
end
|
143
|
+
|
144
|
+
# remove all complete packages
|
100
145
|
@api.call(:deletePackages, {pids: pids})
|
101
146
|
log.info("Complete packages are removed from Pyload Queue")
|
102
|
-
@skipped_timer_at_first_complete_detection = false
|
103
147
|
|
148
|
+
@skipped_timer_at_first_complete_detection = false
|
104
149
|
@ready_for_new_links = true
|
105
150
|
else
|
106
151
|
# If a package is complete, we are sometimes so fast to remove
|
@@ -114,6 +159,7 @@ module Junkie
|
|
114
159
|
}
|
115
160
|
end
|
116
161
|
|
162
|
+
|
117
163
|
# Searches for failed links in the pyload queue
|
118
164
|
#
|
119
165
|
# @param [Array] queue_data returned from :getQueueData api method
|
@@ -130,6 +176,7 @@ module Junkie
|
|
130
176
|
false
|
131
177
|
end
|
132
178
|
|
179
|
+
|
133
180
|
# Looks for complete downloads and returns their pids
|
134
181
|
#
|
135
182
|
# @param [Array] queue_data returned from :getQueueData api method
|
@@ -169,12 +216,11 @@ module Junkie
|
|
169
216
|
def update_package_ids(queue_data)
|
170
217
|
queue_data.each do |package|
|
171
218
|
pid = package['pid']
|
172
|
-
next if @
|
219
|
+
next if @active_episode.pid == pid
|
173
220
|
|
174
|
-
if @
|
221
|
+
if @active_episode.pid == pid-1
|
175
222
|
log.info("Package ID has been changed, I will correct this")
|
176
|
-
@
|
177
|
-
@active_downloads.delete(pid-1)
|
223
|
+
@active_episode.pid = pid
|
178
224
|
next
|
179
225
|
end
|
180
226
|
|
data/lib/junkie/reactor.rb
CHANGED
@@ -18,7 +18,6 @@ module Junkie
|
|
18
18
|
:hd_enabled => false,
|
19
19
|
:hoster_id => "ul",
|
20
20
|
:series_index_file => File.join(Dir.home, '.sindex/seriesindex.xml'),
|
21
|
-
:episode_queue_timer_refresh => 5, # in seconds
|
22
21
|
:episode_search_refresh => 15, # in minutes
|
23
22
|
}
|
24
23
|
|
@@ -26,9 +25,19 @@ module Junkie
|
|
26
25
|
def initialize
|
27
26
|
@config = Config.get_config(self)
|
28
27
|
|
29
|
-
|
28
|
+
log.info("Starting Junkie #{Junkie::VERSION}")
|
29
|
+
|
30
|
+
episode_channel = EM::Channel.new
|
31
|
+
notification_channel = EM::Channel.new
|
32
|
+
|
33
|
+
@channels = {
|
34
|
+
episodes: episode_channel,
|
35
|
+
notifications: notification_channel
|
36
|
+
}
|
37
|
+
|
38
|
+
@pyload_observer = Junkie::Pyload::Observer.new(@channels)
|
39
|
+
@twitter_notification = Junkie::Notification::Twitter.new(@channels)
|
30
40
|
|
31
|
-
@episode_queue = EM::Queue.new
|
32
41
|
@found_episodes = Hash.new
|
33
42
|
build_procs # has to be called here
|
34
43
|
end
|
@@ -52,37 +61,28 @@ module Junkie
|
|
52
61
|
|
53
62
|
if not @found_episodes.has_key? identifier
|
54
63
|
log.info("Found new episode '#{episode}'")
|
55
|
-
|
64
|
+
|
65
|
+
@channels[:episodes].push(episode)
|
56
66
|
@found_episodes[identifier] = episode
|
57
67
|
end
|
58
68
|
end
|
59
69
|
}
|
60
70
|
}
|
61
|
-
|
62
|
-
# Proc that checks is Pyload-Observer is ready for new episodes and the
|
63
|
-
# episode_queue contains new episodes.
|
64
|
-
#
|
65
|
-
# @note Is called from within the reactor
|
66
|
-
@add_episodes_to_pyload = Proc.new do
|
67
|
-
if @pyload_observer.is_ready?
|
68
|
-
@episode_queue.pop do |episode|
|
69
|
-
log.info("Popped episode '#{episode}' from queue")
|
70
|
-
in_fiber {
|
71
|
-
@pyload_observer.add_episode(episode)
|
72
|
-
}
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
71
|
end
|
77
72
|
|
78
73
|
###########################################################################
|
79
74
|
#################### The Reactor ##########################################
|
80
75
|
###########################################################################
|
81
76
|
def start
|
82
|
-
log.info("Starting Junkie #{Junkie::VERSION}")
|
83
77
|
|
84
78
|
EM.run do
|
85
79
|
|
80
|
+
@channels[:episodes].subscribe do |episode|
|
81
|
+
next unless episode.status == :extracted
|
82
|
+
|
83
|
+
@channels[:notifications].push(episode)
|
84
|
+
end
|
85
|
+
|
86
86
|
# do some initialization work
|
87
87
|
@pyload_observer.setup
|
88
88
|
|
@@ -96,13 +96,6 @@ module Junkie
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
# Add found episodes into Pyload if there are any episodes and pyload
|
100
|
-
# is ready
|
101
|
-
EM.add_periodic_timer(
|
102
|
-
@config[:episode_queue_timer_refresh], @add_episodes_to_pyload)
|
103
|
-
|
104
|
-
# for determining blocking operations
|
105
|
-
# EM.add_periodic_timer(1) { puts Time.now.to_i }
|
106
99
|
end
|
107
100
|
end
|
108
101
|
end
|
data/lib/junkie/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: junkie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -155,6 +155,22 @@ dependencies:
|
|
155
155
|
- - ~>
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: 1.8.0
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: twitter
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ~>
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 4.4.0
|
166
|
+
type: :runtime
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ~>
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 4.4.0
|
158
174
|
description: TV series management application
|
159
175
|
email:
|
160
176
|
- philipp-boehm@live.de
|
@@ -178,6 +194,7 @@ files:
|
|
178
194
|
- lib/junkie/errors.rb
|
179
195
|
- lib/junkie/helper.rb
|
180
196
|
- lib/junkie/log.rb
|
197
|
+
- lib/junkie/notification/twitter.rb
|
181
198
|
- lib/junkie/patched/sjunkieex.rb
|
182
199
|
- lib/junkie/pyload/api.rb
|
183
200
|
- lib/junkie/pyload/observer.rb
|