junkie 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|