junkie 0.0.6 → 0.0.7
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/bin/junkie +9 -1
- data/lib/junkie/errors.rb +2 -0
- data/lib/junkie/pyload/api.rb +2 -2
- data/lib/junkie/pyload/observer.rb +120 -80
- data/lib/junkie/version.rb +1 -1
- data/lib/junkie.rb +0 -8
- data/spec/fixtures/pyload_queue_data.rb +94 -0
- data/spec/pyload_observer_spec.rb +216 -0
- metadata +6 -2
data/bin/junkie
CHANGED
@@ -5,6 +5,14 @@
|
|
5
5
|
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
6
6
|
|
7
7
|
require 'junkie'
|
8
|
-
|
8
|
+
require 'logging'
|
9
|
+
|
10
|
+
Logging.appenders.stdout(
|
11
|
+
'stdout',
|
12
|
+
:level => :debug,
|
13
|
+
:layout => Logging.layouts.pattern(:pattern => '[%d] %-5l: %m\n')
|
14
|
+
)
|
15
|
+
Logging.logger.root.appenders = Logging.appenders.stdout
|
9
16
|
|
17
|
+
include Junkie
|
10
18
|
start_reactor
|
data/lib/junkie/errors.rb
CHANGED
data/lib/junkie/pyload/api.rb
CHANGED
@@ -7,6 +7,8 @@ module Junkie
|
|
7
7
|
class Observer
|
8
8
|
include Log, Helper, Config
|
9
9
|
|
10
|
+
attr_accessor :api
|
11
|
+
|
10
12
|
DEFAULT_CONFIG = {
|
11
13
|
watchdog_refresh: 10, # interval the watchdog_timer is fired
|
12
14
|
}
|
@@ -25,7 +27,6 @@ module Junkie
|
|
25
27
|
@ready_for_new_links = true
|
26
28
|
@watchdog_enabled = false
|
27
29
|
@skipped_timer_at_first_complete_detection = false
|
28
|
-
@should_send_it_on_channel = false
|
29
30
|
|
30
31
|
@channels[:episodes].subscribe do |episode|
|
31
32
|
next unless episode.status == :found
|
@@ -45,24 +46,13 @@ module Junkie
|
|
45
46
|
}
|
46
47
|
|
47
48
|
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
|
-
|
58
49
|
monitor_progress if @watchdog_enabled
|
59
50
|
|
60
|
-
in_fiber {
|
61
|
-
add_next_episode_to_pyload
|
62
|
-
}
|
51
|
+
in_fiber { add_next_episode_to_pyload }
|
63
52
|
end
|
64
53
|
end
|
65
54
|
|
55
|
+
private
|
66
56
|
|
67
57
|
# Add next episode to Pyload which downloads the episode and extracts it
|
68
58
|
#
|
@@ -99,81 +89,132 @@ module Junkie
|
|
99
89
|
@ready_for_new_links
|
100
90
|
end
|
101
91
|
|
102
|
-
private
|
103
92
|
|
104
|
-
#
|
93
|
+
# Utility method that fetches the QueueData, validates it and returns
|
94
|
+
# the JSON Object as a real Ruby Object
|
105
95
|
#
|
106
|
-
#
|
96
|
+
# @raise [Junkie::InvalidResponse] if the response is faulty
|
97
|
+
# @return [Array] the JSON response as an object
|
98
|
+
def get_queue_data
|
99
|
+
data = @api.call(:getQueueData)
|
100
|
+
|
101
|
+
if data && data.is_a?(Array)
|
102
|
+
return data
|
103
|
+
end
|
104
|
+
raise Junkie::InvalidResponse,
|
105
|
+
"'#{data}' is not a valid response from Pyload"
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
#########################################################################
|
110
|
+
# This method is called from the watchdog timer periodically #
|
111
|
+
# #
|
112
|
+
# It monitors the download process and reacts depending on the results #
|
107
113
|
def monitor_progress
|
108
114
|
log.debug("Watchdog timer has been fired")
|
109
115
|
in_fiber {
|
110
116
|
catch(:break) {
|
111
|
-
queue_data =
|
117
|
+
queue_data = get_queue_data
|
112
118
|
|
113
|
-
|
114
|
-
|
115
|
-
@watchdog_enabled = false
|
116
|
-
throw :break
|
117
|
-
end
|
119
|
+
# check for empty queue and disable watchdog if needed
|
120
|
+
check_for_empty_queue(queue_data)
|
118
121
|
|
119
122
|
# extract package IDs and map them to current downloads
|
120
123
|
update_package_ids(queue_data)
|
121
124
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
throw :break
|
126
|
-
end
|
127
|
-
|
128
|
-
# look for complete downloads
|
129
|
-
pids = get_complete_downloads(queue_data)
|
130
|
-
|
131
|
-
if not pids.empty?
|
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
|
145
|
-
@api.call(:deletePackages, {pids: pids})
|
146
|
-
log.info("Complete packages are removed from Pyload Queue")
|
147
|
-
|
148
|
-
@skipped_timer_at_first_complete_detection = false
|
149
|
-
@ready_for_new_links = true
|
150
|
-
else
|
151
|
-
# If a package is complete, we are sometimes so fast to remove
|
152
|
-
# it, before the extracting can be started, so we will skip it
|
153
|
-
# the first time
|
154
|
-
log.info("Complete package detected, skip the first time")
|
155
|
-
@skipped_timer_at_first_complete_detection = true
|
156
|
-
end
|
157
|
-
end
|
125
|
+
check_for_failed_links(queue_data)
|
126
|
+
|
127
|
+
check_for_complete_packages(queue_data)
|
158
128
|
}
|
159
129
|
}
|
130
|
+
rescue Junkie::InvalidResponse => e
|
131
|
+
log.error("Pyload returns InvalidResponse (#{e}), I will ignore this")
|
160
132
|
end
|
161
133
|
|
162
134
|
|
163
|
-
#
|
135
|
+
# Checks if the Pyload Queue is empty and disables the watchdog if
|
136
|
+
# it is really real
|
164
137
|
#
|
165
138
|
# @param [Array] queue_data returned from :getQueueData api method
|
139
|
+
def check_for_empty_queue(queue_data)
|
140
|
+
if queue_data.empty?
|
141
|
+
|
142
|
+
unless @active_episode.nil?
|
143
|
+
log.info("Empty queue detected but a download is set as active")
|
144
|
+
return
|
145
|
+
end
|
146
|
+
|
147
|
+
log.info("Empty Pyload queue detected, will double check")
|
148
|
+
|
149
|
+
# check twice if the queue is definitely empty
|
150
|
+
check_data = get_queue_data
|
151
|
+
if check_data.empty?
|
152
|
+
log.info("Double check is successful, I will disable the watchdog")
|
153
|
+
@watchdog_enabled = false
|
154
|
+
throw :break
|
155
|
+
else
|
156
|
+
log.info("Double check failed, Queue is not empty")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Searches for failed links in the pyload queue and reacts on this
|
162
|
+
# through issuing a restartFailed call
|
166
163
|
#
|
167
|
-
# @
|
168
|
-
def
|
164
|
+
# @param [Array] queue_data returned from :getQueueData api method
|
165
|
+
def check_for_failed_links(queue_data)
|
166
|
+
failed = 0
|
169
167
|
queue_data.each do |package|
|
170
168
|
package['links'].each do |link|
|
171
169
|
status = Pyload::Api::FILE_STATUS[link['status']]
|
172
|
-
|
170
|
+
(failed += 1) if status == :failed
|
173
171
|
end
|
174
172
|
end
|
175
173
|
|
176
|
-
|
174
|
+
if failed > 0
|
175
|
+
log.info("There are failed links in the Queue, will fix this")
|
176
|
+
@api.call(:restartFailed)
|
177
|
+
throw :break
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
# Looks for complete packages and does some post-processing
|
183
|
+
#
|
184
|
+
# @param [Array] queue_data returned from :getQueueData api method
|
185
|
+
def check_for_complete_packages(queue_data)
|
186
|
+
pids = get_complete_downloads(queue_data)
|
187
|
+
|
188
|
+
throw :break if pids.empty?
|
189
|
+
|
190
|
+
if @skipped_timer_at_first_complete_detection
|
191
|
+
|
192
|
+
# post process complete active download and send it out on the
|
193
|
+
# channel
|
194
|
+
if pids.include? @active_episode.pid
|
195
|
+
log.info("'#{@active_episode}' has been extracted completely")
|
196
|
+
@active_episode.pid = nil
|
197
|
+
@active_episode.status = :extracted
|
198
|
+
|
199
|
+
log.info("Sending complete episode out on the channel")
|
200
|
+
@channels[:episodes].push(@active_episode)
|
201
|
+
@active_episode = nil
|
202
|
+
end
|
203
|
+
|
204
|
+
# remove all complete packages
|
205
|
+
@api.call(:deletePackages, { pids: pids })
|
206
|
+
log.info("Complete packages are removed from Pyload Queue #{ pids }")
|
207
|
+
|
208
|
+
@skipped_timer_at_first_complete_detection = false
|
209
|
+
@ready_for_new_links = true
|
210
|
+
|
211
|
+
else
|
212
|
+
# If a package is complete, we are sometimes so fast to remove
|
213
|
+
# it, before the extracting can be started, so we will skip it
|
214
|
+
# the first time
|
215
|
+
log.info("Complete package detected, skip the first time")
|
216
|
+
@skipped_timer_at_first_complete_detection = true
|
217
|
+
end
|
177
218
|
end
|
178
219
|
|
179
220
|
|
@@ -189,46 +230,45 @@ module Junkie
|
|
189
230
|
|
190
231
|
next if package['linksdone'] == 0
|
191
232
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
Pyload::Api::FILE_STATUS[link['status']] == :extracting
|
233
|
+
invalid_links = package['links'].reject do |e|
|
234
|
+
[:done, :skipped].include?(
|
235
|
+
Junkie::Pyload::Api::FILE_STATUS[e['status']])
|
196
236
|
end
|
197
|
-
next unless
|
237
|
+
next unless invalid_links.empty?
|
198
238
|
|
199
239
|
sizetotal = package['sizetotal'].to_i
|
200
240
|
sizedone = package['sizedone'].to_i
|
201
241
|
|
202
|
-
if sizetotal > 0 && sizedone > 0
|
203
|
-
|
204
|
-
if sizetotal == sizedone
|
242
|
+
if sizetotal > 0 && sizedone > 0 && sizetotal == sizedone
|
205
243
|
pids << package['pid']
|
206
|
-
end
|
207
244
|
end
|
208
245
|
end
|
209
246
|
|
210
247
|
pids
|
211
248
|
end
|
212
249
|
|
250
|
+
|
213
251
|
# extract package IDs and map them to current downloads
|
214
252
|
#
|
215
253
|
# @param [Array] queue_data returned from :getQueueData api method
|
216
254
|
def update_package_ids(queue_data)
|
217
|
-
queue_data.each do |package|
|
218
|
-
pid = package['pid']
|
219
|
-
next if @active_episode.pid == pid
|
220
255
|
|
221
|
-
|
222
|
-
|
256
|
+
if queue_data.size == 1
|
257
|
+
pid = queue_data[0]['pid']
|
258
|
+
if @active_episode && @active_episode.pid != pid
|
259
|
+
log.info("Package ID has been changed, New PID is #{pid}")
|
223
260
|
@active_episode.pid = pid
|
224
|
-
next
|
225
261
|
end
|
226
262
|
|
263
|
+
elsif queue_data.size > 1
|
227
264
|
raise InvalidStateError,
|
228
|
-
"
|
265
|
+
"There is more than 1 Package in the Queue"
|
229
266
|
end
|
230
267
|
end
|
231
268
|
|
269
|
+
|
270
|
+
# Removes existing packages from the Pyload Queue and creates a valid
|
271
|
+
# state to begin communication
|
232
272
|
def cleanup
|
233
273
|
log.debug("Made a cleanup of Pyload's Queue")
|
234
274
|
@api.call(:stopAllDownloads)
|
data/lib/junkie/version.rb
CHANGED
data/lib/junkie.rb
CHANGED
@@ -9,14 +9,6 @@ require 'junkie/patched/sjunkieex'
|
|
9
9
|
require 'junkie/pyload/api'
|
10
10
|
require 'junkie/pyload/observer'
|
11
11
|
require 'junkie/notification/twitter'
|
12
|
-
require 'logging'
|
13
|
-
|
14
|
-
Logging.appenders.stdout(
|
15
|
-
'stdout',
|
16
|
-
:level => :debug,
|
17
|
-
:layout => Logging.layouts.pattern(:pattern => '[%d] %-5l: %m\n')
|
18
|
-
)
|
19
|
-
Logging.logger.root.appenders = Logging.appenders.stdout
|
20
12
|
|
21
13
|
module Junkie
|
22
14
|
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Junkie::Pyload::Observer::TestData
|
4
|
+
def self.get_fixture
|
5
|
+
json = <<-eos
|
6
|
+
[
|
7
|
+
{
|
8
|
+
"name": "onetreehill_sl_s09e04",
|
9
|
+
"links": [
|
10
|
+
{
|
11
|
+
"status": 12,
|
12
|
+
"format_size": "102.00 MiB",
|
13
|
+
"name": "onetreehill_sl_s09e04.part1.rar",
|
14
|
+
"plugin": "UploadedTo",
|
15
|
+
"url": "http:\/\/uploaded.net\/file\/kigscay8",
|
16
|
+
"packageID": 11,
|
17
|
+
"fid": 827,
|
18
|
+
"error": "",
|
19
|
+
"statusmsg": "downloade",
|
20
|
+
"order": 0,
|
21
|
+
"size": 106954752
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"status": 12,
|
25
|
+
"format_size": "102.00 MiB",
|
26
|
+
"name": "onetreehill_sl_s09e04.part2.rar",
|
27
|
+
"plugin": "UploadedTo",
|
28
|
+
"url": "http:\/\/uploaded.net\/file\/pm6m7v3d",
|
29
|
+
"packageID": 11,
|
30
|
+
"fid": 828,
|
31
|
+
"error": "",
|
32
|
+
"statusmsg": "downloade",
|
33
|
+
"order": 1,
|
34
|
+
"size": 106954752
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"status": 12,
|
38
|
+
"format_size": "102.00 MiB",
|
39
|
+
"name": "onetreehill_sl_s09e04.part3.rar",
|
40
|
+
"plugin": "UploadedTo",
|
41
|
+
"url": "http:\/\/uploaded.net\/file\/3tzo52uh",
|
42
|
+
"packageID": 11,
|
43
|
+
"fid": 829,
|
44
|
+
"error": "",
|
45
|
+
"statusmsg": "downloade",
|
46
|
+
"order": 2,
|
47
|
+
"size": 106954752
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"status": 2,
|
51
|
+
"format_size": "102.00 MiB",
|
52
|
+
"name": "onetreehill_sl_s09e04.part4.rar",
|
53
|
+
"plugin": "UploadedTo",
|
54
|
+
"url": "http:\/\/uploaded.net\/file\/0e367cl3\/onetreehill_sl_s09e04.part4.rar",
|
55
|
+
"packageID": 11,
|
56
|
+
"fid": 830,
|
57
|
+
"error": "",
|
58
|
+
"statusmsg": "online",
|
59
|
+
"order": 3,
|
60
|
+
"size": 106954752
|
61
|
+
},
|
62
|
+
{
|
63
|
+
"status": 2,
|
64
|
+
"format_size": "78.96 MiB",
|
65
|
+
"name": "onetreehill_sl_s09e04.part5.rar",
|
66
|
+
"plugin": "UploadedTo",
|
67
|
+
"url": "http:\/\/uploaded.net\/file\/9iuhwfjk\/onetreehill_sl_s09e04.part5.rar",
|
68
|
+
"packageID": 11,
|
69
|
+
"fid": 831,
|
70
|
+
"error": "",
|
71
|
+
"statusmsg": "online",
|
72
|
+
"order": 4,
|
73
|
+
"size": 82795518
|
74
|
+
}
|
75
|
+
],
|
76
|
+
"dest": 1,
|
77
|
+
"pid": 11,
|
78
|
+
"site": "",
|
79
|
+
"linksdone": 0,
|
80
|
+
"fids": null,
|
81
|
+
"sizetotal": 510614526,
|
82
|
+
"sizedone": 0,
|
83
|
+
"linkstotal": null,
|
84
|
+
"folder": "onetreehill_sl_s09e04",
|
85
|
+
"password": "",
|
86
|
+
"order": 0
|
87
|
+
}
|
88
|
+
]
|
89
|
+
eos
|
90
|
+
|
91
|
+
JSON.load(json)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/fixtures/pyload_queue_data')
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
describe Junkie::Pyload::Observer do
|
6
|
+
include EMHelper
|
7
|
+
|
8
|
+
# remove the Config module behaviour
|
9
|
+
before(:each) do
|
10
|
+
Junkie::Config.stub!(:get_config) do |clas|
|
11
|
+
clas.class::DEFAULT_CONFIG
|
12
|
+
end
|
13
|
+
|
14
|
+
stub_const("Junkie::CONFIG_FILE", '/dev/null')
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:channels) { {episodes: EM::Channel.new} }
|
18
|
+
let(:epi_channel) { channels[:episodes]}
|
19
|
+
let(:episode) do
|
20
|
+
epi = Junkie::Episode.new( "One Tree Hill", "http://local.host/12345",
|
21
|
+
"One.Tree.Hill.S09E01.Testepisode")
|
22
|
+
epi.status = :found
|
23
|
+
epi
|
24
|
+
end
|
25
|
+
|
26
|
+
context "monitor the pyload progress" do
|
27
|
+
|
28
|
+
let(:observer) do
|
29
|
+
ob = Junkie::Pyload::Observer.new(channels)
|
30
|
+
ob.api.stub(:call).and_return(nil)
|
31
|
+
ob.instance_variable_set(:@found_episodes, [episode])
|
32
|
+
ob.instance_variable_set(:@ready_for_new_links, true)
|
33
|
+
ob.send(:add_next_episode_to_pyload)
|
34
|
+
|
35
|
+
episode.pid = 10
|
36
|
+
ob
|
37
|
+
end
|
38
|
+
|
39
|
+
context "#get_queue_data" do
|
40
|
+
|
41
|
+
it "should throw InvalidResponse on empty string" do
|
42
|
+
observer.api.should_receive(:call).and_return("")
|
43
|
+
expect {
|
44
|
+
observer.send(:get_queue_data)
|
45
|
+
}.to raise_error(Junkie::InvalidResponse)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should throw InvalidResponse on empty response" do
|
49
|
+
observer.api.should_receive(:call).and_return(nil)
|
50
|
+
expect {
|
51
|
+
observer.send(:get_queue_data)
|
52
|
+
}.to raise_error(Junkie::InvalidResponse)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return the valid response" do
|
56
|
+
response = [ {pid: 13} ]
|
57
|
+
observer.api.should_receive(:call).and_return(response)
|
58
|
+
observer.send(:get_queue_data).should eq response
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "#monitor_progress" do
|
63
|
+
|
64
|
+
let(:response) do
|
65
|
+
Junkie::Pyload::Observer::TestData::get_fixture
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should catch InvalidResponse raised from #get_queue_data" do
|
69
|
+
observer.api.should_receive(:call).and_return("")
|
70
|
+
|
71
|
+
expect {
|
72
|
+
observer.send(:monitor_progress)
|
73
|
+
}.to_not raise_error(Junkie::InvalidResponse)
|
74
|
+
end
|
75
|
+
|
76
|
+
context "#check_for_empty_queue" do
|
77
|
+
|
78
|
+
it "should be an active watchdog timer" do
|
79
|
+
observer.instance_variable_get(:@watchdog_enabled).should be true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should disable the watchdog if there isn't an active download" do
|
83
|
+
observer.instance_variable_set(:@active_episode, nil)
|
84
|
+
# it double checks for emptiness
|
85
|
+
observer.should_receive(:get_queue_data).and_return([])
|
86
|
+
|
87
|
+
expect {
|
88
|
+
observer.send(:check_for_empty_queue, [])
|
89
|
+
}.to throw_symbol(:break)
|
90
|
+
|
91
|
+
observer.instance_variable_get(:@watchdog_enabled).should be false
|
92
|
+
end
|
93
|
+
|
94
|
+
it "shouldn't disable the watchdog if double check fails" do
|
95
|
+
observer.instance_variable_set(:@active_episode, nil)
|
96
|
+
observer.should_receive(:get_queue_data).and_return(response)
|
97
|
+
|
98
|
+
observer.send(:check_for_empty_queue, [])
|
99
|
+
observer.instance_variable_get(:@watchdog_enabled).should be true
|
100
|
+
end
|
101
|
+
|
102
|
+
it "shouldn't disable the watchdog if there is an active download" do
|
103
|
+
observer.send(:check_for_empty_queue, [])
|
104
|
+
observer.instance_variable_get(:@watchdog_enabled).should be true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "#update_package_ids" do
|
109
|
+
|
110
|
+
it "should update the package id" do
|
111
|
+
observer.send(:update_package_ids, response)
|
112
|
+
episode.pid.should eq 11
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should update the pid also if it is not incremented by 1" do
|
116
|
+
response[0]['pid'] = 12
|
117
|
+
|
118
|
+
expect {
|
119
|
+
observer.send(:update_package_ids, response)
|
120
|
+
}.to_not raise_error(Junkie::InvalidStateError)
|
121
|
+
episode.pid.should eq 12
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "#react_on_failed_links" do
|
126
|
+
|
127
|
+
let(:failed_id){ Junkie::Pyload::Api::FILE_STATUS.key(:failed) }
|
128
|
+
|
129
|
+
it "should call restartFailed on the Api if there are failed links" do
|
130
|
+
response[0]['links'][0]['status'] = failed_id
|
131
|
+
|
132
|
+
observer.api.should_receive(:call).with(:restartFailed)
|
133
|
+
expect {
|
134
|
+
observer.send(:check_for_failed_links, response)
|
135
|
+
}.to throw_symbol(:break)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "#check_for_complete_packages" do
|
140
|
+
|
141
|
+
let(:file_status){ Junkie::Pyload::Api::FILE_STATUS }
|
142
|
+
let(:complete_response) do
|
143
|
+
copy = response.clone
|
144
|
+
new_links = copy[0]['links'].map do |e|
|
145
|
+
e['status'] = file_status.key(:done)
|
146
|
+
e
|
147
|
+
end
|
148
|
+
copy[0]['links'] = new_links
|
149
|
+
copy[0]['linksdone'] = new_links.size
|
150
|
+
copy[0]['sizedone'] = 12345
|
151
|
+
copy[0]['sizetotal'] = 12345
|
152
|
+
copy[0]['pid'] = 12
|
153
|
+
copy
|
154
|
+
end
|
155
|
+
|
156
|
+
context "#get_complete_downloads" do
|
157
|
+
it "should return pids where alle links are done and size is right" do
|
158
|
+
pids = observer.send(:get_complete_downloads, complete_response)
|
159
|
+
pids.should include(12)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should treat :skipped and :done links as complete" do
|
163
|
+
complete_response[0]['links'][1]['status'] = file_status.key(:skipped)
|
164
|
+
complete_response[0]['links'][3]['status'] = file_status.key(:skipped)
|
165
|
+
|
166
|
+
pids = observer.send(:get_complete_downloads, complete_response)
|
167
|
+
pids.should include(12)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should take file status more seriously than sizedone" do
|
171
|
+
complete_response[0]['links'][1]['status'] = file_status.key(:failed)
|
172
|
+
|
173
|
+
pids = observer.send(:get_complete_downloads, complete_response)
|
174
|
+
pids.should_not include(12)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
context "detected complete package the first time" do
|
180
|
+
|
181
|
+
it "should set a flag if a complete package has been detected" do
|
182
|
+
observer.send(:check_for_complete_packages, complete_response)
|
183
|
+
observer.instance_variable_get(
|
184
|
+
:@skipped_timer_at_first_complete_detection).should eq true
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "detected complete package second time" do
|
189
|
+
|
190
|
+
it "should remove the complete packages from Queue" do
|
191
|
+
observer.api.should_receive(:call).with(:deletePackages, {pids: [12]})
|
192
|
+
observer.instance_variable_set(
|
193
|
+
:@skipped_timer_at_first_complete_detection, true)
|
194
|
+
|
195
|
+
em {
|
196
|
+
observer.send(:check_for_complete_packages, complete_response)
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should send out the active episode out on the channel" do
|
201
|
+
observer.instance_variable_set(
|
202
|
+
:@skipped_timer_at_first_complete_detection, true)
|
203
|
+
episode.pid = 12
|
204
|
+
|
205
|
+
observer.send(:check_for_complete_packages, complete_response)
|
206
|
+
observer.instance_variable_get(:@active_episode).should be_nil
|
207
|
+
observer.send(:is_ready?).should be true
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
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.7
|
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-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -202,7 +202,9 @@ files:
|
|
202
202
|
- lib/junkie/version.rb
|
203
203
|
- spec/config_spec.rb
|
204
204
|
- spec/environment_spec.rb
|
205
|
+
- spec/fixtures/pyload_queue_data.rb
|
205
206
|
- spec/pyload_api_spec.rb
|
207
|
+
- spec/pyload_observer_spec.rb
|
206
208
|
- spec/spec_helper.rb
|
207
209
|
homepage: https://github.com/pboehm/junkie
|
208
210
|
licenses: []
|
@@ -231,6 +233,8 @@ summary: TV series managament tool that does all the work you have with your ser
|
|
231
233
|
test_files:
|
232
234
|
- spec/config_spec.rb
|
233
235
|
- spec/environment_spec.rb
|
236
|
+
- spec/fixtures/pyload_queue_data.rb
|
234
237
|
- spec/pyload_api_spec.rb
|
238
|
+
- spec/pyload_observer_spec.rb
|
235
239
|
- spec/spec_helper.rb
|
236
240
|
has_rdoc:
|