XDCC-Fetch 1.386
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/COPYING +23 -0
- data/XDCC-Fetch.rbw +54 -0
- data/doc/ark.png +0 -0
- data/doc/connect_established.png +0 -0
- data/doc/index.html +300 -0
- data/doc/mega_ark.png +0 -0
- data/doc/package.png +0 -0
- data/doc/package_unknown.png +0 -0
- data/doc/shot1.png +0 -0
- data/doc/shot1_mini.png +0 -0
- data/doc/shot2.png +0 -0
- data/doc/shot2_mini.png +0 -0
- data/doc/xdccfetch.css +155 -0
- data/icons/ark.png +0 -0
- data/icons/ark_big.png +0 -0
- data/icons/camera_test.png +0 -0
- data/icons/cancel.png +0 -0
- data/icons/connect_creating.png +0 -0
- data/icons/connect_established.png +0 -0
- data/icons/connect_failed.png +0 -0
- data/icons/connect_no.png +0 -0
- data/icons/edit_add.png +0 -0
- data/icons/edit_remove.png +0 -0
- data/icons/exit.png +0 -0
- data/icons/fileclose.png +0 -0
- data/icons/folder_inbox.png +0 -0
- data/icons/idea.png +0 -0
- data/icons/mega_ark.png +0 -0
- data/icons/messagebox_critical.png +0 -0
- data/icons/messagebox_info.png +0 -0
- data/icons/messagebox_warning.png +0 -0
- data/icons/messagebox_warning_small.png +0 -0
- data/icons/package.png +0 -0
- data/icons/package_favourite.png +0 -0
- data/icons/package_unknown.png +0 -0
- data/src/Console/Console_Parser.rb +71 -0
- data/src/Console/XDCC_Pack_Match_Template.rb +29 -0
- data/src/Console/xdcc-fetch.rb +123 -0
- data/src/GUI/About_Dialog.rb +50 -0
- data/src/GUI/Application_Builder.rb +280 -0
- data/src/GUI/Context_Menu.rb +81 -0
- data/src/GUI/Custom_Tabs.rb +60 -0
- data/src/GUI/Dialog_Box.rb +116 -0
- data/src/GUI/Download_Finished_Box.rb +41 -0
- data/src/GUI/Empty_Text_Field_Handler.rb +86 -0
- data/src/GUI/Gui_Logic.rb +629 -0
- data/src/GUI/Icon_Loader.rb +58 -0
- data/src/GUI/Main_Window.rb +227 -0
- data/src/GUI/Packet_Item.rb +171 -0
- data/src/GUI/Packet_List.rb +145 -0
- data/src/GUI/Speed_Widget.rb +101 -0
- data/src/GUI/Talk_Back.rb +118 -0
- data/src/GUI/Toggle_Button.rb +56 -0
- data/src/Network/CTCP_Handler.rb +61 -0
- data/src/Network/DCC_File.rb +323 -0
- data/src/Network/DCC_Parser.rb +71 -0
- data/src/Network/IPAddr_Ext.rb +76 -0
- data/src/Network/IRC_Message.rb +161 -0
- data/src/Network/IRC_Server.rb +273 -0
- data/src/Network/IRC_Server_Respond_Map.rb +223 -0
- data/src/Network/IRC_User.rb +58 -0
- data/src/Network/TCP_Connection.rb +168 -0
- data/src/Network/XDCC_Announcement.rb +120 -0
- data/src/Network/XDCC_Announcement_Storage.rb +167 -0
- data/src/Network/XDCC_Download_Handler.rb +412 -0
- data/src/Network/XDCC_Pack.rb +58 -0
- data/src/Network/XDCC_Parser.rb +253 -0
- data/src/Translations/README +61 -0
- data/src/Translations/check_translations +83 -0
- data/src/Translations/de.rb +140 -0
- data/src/Translations/en.rb +145 -0
- data/src/Utilities/Configuration.rb +91 -0
- data/src/Utilities/Events.rb +87 -0
- data/src/Utilities/Globals.rb +138 -0
- data/src/Utilities/PrettyException.rb +1091 -0
- data/src/Utilities/Recursive_Open_Struct.rb +159 -0
- data/src/Utilities/Timer.rb +71 -0
- metadata +135 -0
@@ -0,0 +1,412 @@
|
|
1
|
+
# Copyright (c) 2004-2005, Christoph Heindl
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
# are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright notice, this list
|
8
|
+
# of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright notice, this list
|
10
|
+
# of conditions and the following disclaimer in the documentation and/or other materials
|
11
|
+
# provided with the distribution.
|
12
|
+
# * Neither the name of Christoph Heindl nor the names of its contributors may be used to
|
13
|
+
# endorse or promote products derived from this software without specific prior written
|
14
|
+
# permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
17
|
+
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
18
|
+
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
19
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
21
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
22
|
+
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
23
|
+
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
|
+
|
25
|
+
|
26
|
+
require 'src/Network/DCC_File.rb'
|
27
|
+
require 'src/Utilities/Events.rb'
|
28
|
+
require 'src/Utilities/Timer.rb'
|
29
|
+
|
30
|
+
require 'digest/md5'
|
31
|
+
|
32
|
+
# Handles all downloads from a single bot.
|
33
|
+
# Only one pack at a time is allowed to be downloaded/queued from/at the bot. However,
|
34
|
+
# more than one pack may be added to the handler, which in turn will be stored in a local queue
|
35
|
+
# and be processed when a download finished/was cancelled.
|
36
|
+
#
|
37
|
+
# Supports the generation of md5 sums on the fly. However, md5 is unavailable for resumed
|
38
|
+
# packs, as (of now) ruby does not support marshaling of md5 objects. Therefore, md5 context
|
39
|
+
# generation would require running through the entire (partly) downloaded file. As this would be
|
40
|
+
# to time consuming, md5 support has been disabled for resumed packs. However, as soon as marshaling
|
41
|
+
# md5 objects is supported in ruby, md5 support may come available for resumed packs.
|
42
|
+
#
|
43
|
+
# Handling multiple packs simultaneously from a single bot is very challenging, since the bot's
|
44
|
+
# status messages don't provide enough differentiation characteristics in order to assign them
|
45
|
+
# to a single pack. Thats why only one pack is allowed at a time.
|
46
|
+
class XDCC_Download_Handler
|
47
|
+
include Event_Publisher
|
48
|
+
|
49
|
+
# Timer used for detecting various stalled cases
|
50
|
+
@@timer = Timer.new(3)
|
51
|
+
|
52
|
+
# The xdcc bot we are dealing with
|
53
|
+
attr_reader :irc_user_bot
|
54
|
+
# Current XDCC_Pack
|
55
|
+
attr_reader :current_pack
|
56
|
+
# Current XDCC_Pack status
|
57
|
+
attr_reader :current_pack_status
|
58
|
+
# Real filename of where pack is downloaded to
|
59
|
+
attr_reader :current_pack_filename
|
60
|
+
# ipaddr of bot we are connecting to
|
61
|
+
|
62
|
+
# -- Connectable events
|
63
|
+
|
64
|
+
# Before the Handler shuts down. Args: none
|
65
|
+
ON_SHUTDOWN = Event_Publisher.next_global_eventID
|
66
|
+
|
67
|
+
# When a pack gets requested. Args: pack
|
68
|
+
ON_PACK_REQUESTED = Event_Publisher.next_global_eventID
|
69
|
+
|
70
|
+
# When a pack is queued locally, because another pack is already in progress.
|
71
|
+
# Also triggered if an update of the local queue happens.
|
72
|
+
# Args: pack, local queue position, local queue length
|
73
|
+
ON_QUEUED_LOCALLY = Event_Publisher.next_global_eventID
|
74
|
+
|
75
|
+
# When no free slots are available and the item gets remotely queued.
|
76
|
+
# Also triggered if an update of the remote queue happens
|
77
|
+
# Args: pack, (remote queue position||nil)
|
78
|
+
ON_QUEUED_REMOTELY = Event_Publisher.next_global_eventID
|
79
|
+
|
80
|
+
# Whenever a download started. Args: pack, filename where pack data is stored to
|
81
|
+
ON_DOWNLOAD_STARTED = Event_Publisher.next_global_eventID
|
82
|
+
|
83
|
+
# Whenever a download finished. Args: pack
|
84
|
+
ON_DOWNLOAD_FINISHED = Event_Publisher.next_global_eventID
|
85
|
+
|
86
|
+
# When we receive a delayed md5 status. Args: pack, md5status
|
87
|
+
ON_MD5_STATUS = Event_Publisher.next_global_eventID
|
88
|
+
|
89
|
+
# Whenever a download failed. Args: pack, errormessage?
|
90
|
+
ON_DOWNLOAD_FAILED = Event_Publisher.next_global_eventID
|
91
|
+
|
92
|
+
# Every timespan_download_progress seconds (update of progress).
|
93
|
+
# Args: pack, percent completed, nr of bytes received, nr of kilo bytes per second
|
94
|
+
ON_DOWNLOAD_PROGRESS = Event_Publisher.next_global_eventID
|
95
|
+
|
96
|
+
# All events packed in one
|
97
|
+
ON_ALL_EVENTS = ON_SHUTDOWN|
|
98
|
+
ON_PACK_REQUESTED|
|
99
|
+
ON_QUEUED_LOCALLY|
|
100
|
+
ON_QUEUED_REMOTELY|
|
101
|
+
ON_DOWNLOAD_STARTED|
|
102
|
+
ON_DOWNLOAD_FINISHED|
|
103
|
+
ON_DOWNLOAD_FAILED|
|
104
|
+
ON_DOWNLOAD_PROGRESS|
|
105
|
+
ON_MD5_STATUS
|
106
|
+
|
107
|
+
# -- Other constants
|
108
|
+
|
109
|
+
# MD5 is disabled in the settings
|
110
|
+
MD5_DISABLED = 0
|
111
|
+
|
112
|
+
# MD5 is enabled, but we are waiting for a delayed md5 checksum message
|
113
|
+
# MD5 is enabled, but pack was resumed
|
114
|
+
MD5_UNAVAILABLE = 1
|
115
|
+
|
116
|
+
# MD5 checksum matches the transferred data
|
117
|
+
MD5_OK = 2
|
118
|
+
|
119
|
+
# MD5 checksum failed to match transferred data
|
120
|
+
MD5_FAILED = 3
|
121
|
+
|
122
|
+
|
123
|
+
# Initialize with irc_user_bot
|
124
|
+
def initialize(irc_user_bot)
|
125
|
+
@mutex = Mutex.new # Mutex used to synchronize
|
126
|
+
@irc_user_bot = irc_user_bot
|
127
|
+
@server = irc_user_bot.irc_server # The server the bot is on
|
128
|
+
@current_pack = nil # Pack which has the focus of the handler
|
129
|
+
@current_pack_status = -1 # Status of current pack. -1 indicates no status yet. Else one of the following:
|
130
|
+
# ON_PACK_REQUESTED, ON_QUEUED_REMOTELY, ON_DOWNLOAD_STARTED,
|
131
|
+
# ON_DOWNLOAD_FINISHED
|
132
|
+
@current_pack_md5 = nil # MD5 object used for computation of md5 checksum for current_pack
|
133
|
+
@last_packs = Array.new # The packs we have dealt last with. Earlier packs are at the beginning of the queue
|
134
|
+
@request_timestamp = nil # The time the pack was requested
|
135
|
+
@delay_timestamp = nil # Timestamp when pack was delayed
|
136
|
+
@delay_timeout = nil # Timeout (secs) to pass by before requesting next pack
|
137
|
+
@current_download_path = nil # Path where to store the current pack
|
138
|
+
@current_request_cnt = 0 # Number of times this pack was requested
|
139
|
+
|
140
|
+
@local_pack_queue = Array.new # Locally queued packs. Each element is a 2 element array of [pack, downloadpath]
|
141
|
+
|
142
|
+
@server.connect_to_events(IRC_Server::ON_USER_MESSAGE |
|
143
|
+
IRC_Server::ON_USER_QUIT|
|
144
|
+
IRC_Server::ON_SERVER_DISCONNECTED,
|
145
|
+
self)
|
146
|
+
|
147
|
+
@server.dcc_parser.connect_to_events(DCC_Parser::ON_DCC_SEND, self)
|
148
|
+
# Only one TCP connection is used per bot
|
149
|
+
@dcc_con = DCC_File.new
|
150
|
+
@dcc_con.connect_to_events(DCC_File::ON_ALL_EVENTS, self)
|
151
|
+
@@timer.connect_to_events(Timer::ON_TIMER, self)
|
152
|
+
self.init_events
|
153
|
+
end
|
154
|
+
|
155
|
+
# Disconnect from events, close all file/socket handles
|
156
|
+
def shutdown
|
157
|
+
@dcc_con.close
|
158
|
+
@irc_user_bot.irc_server.disconnect_from_events(
|
159
|
+
IRC_Server::ON_USER_MESSAGE |
|
160
|
+
IRC_Server::ON_USER_QUIT|
|
161
|
+
IRC_Server::ON_SERVER_DISCONNECTED, self)
|
162
|
+
@server.dcc_parser.disconnect_from_events(DCC_Parser::ON_DCC_SEND, self)
|
163
|
+
@@timer.disconnect_from_events(Timer::ON_TIMER, self)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Add a pack to download and it's destination directory (without trailing deliminator)
|
167
|
+
def add_pack(xdcc_pack, path)
|
168
|
+
@mutex.synchronize do
|
169
|
+
if !@current_pack && @local_pack_queue.empty?
|
170
|
+
self.request_pack(xdcc_pack, path)
|
171
|
+
else
|
172
|
+
self.queue_pack(xdcc_pack, path)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Request the given pack and set internal stati
|
178
|
+
def request_pack(xdcc_pack, path)
|
179
|
+
@request_timestamp = Time.now
|
180
|
+
@current_request_cnt += 1
|
181
|
+
@current_pack = xdcc_pack
|
182
|
+
@current_pack_status = ON_PACK_REQUESTED
|
183
|
+
@current_download_path = path
|
184
|
+
@irc_user_bot.send("XDCC SEND ##{@current_pack.pack_nr}")
|
185
|
+
self.fire_event(ON_PACK_REQUESTED, @current_pack)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Queue pack locally
|
189
|
+
def queue_pack(xdcc_pack, path)
|
190
|
+
@local_pack_queue << [xdcc_pack, path]
|
191
|
+
self.local_queue_change
|
192
|
+
end
|
193
|
+
|
194
|
+
# Prepare next pack (if there is one) for download.
|
195
|
+
# If delay != 0, preparation of next pack will be delayed at least
|
196
|
+
# delay seconds (depending on the timer)
|
197
|
+
def next_pack(delay=0)
|
198
|
+
@mutex.synchronize do
|
199
|
+
# Enqueue all packs that have completed downloading and are waiting for
|
200
|
+
# an md5 checksum from bot
|
201
|
+
if $cfg.network.xdcc.enable_md5 && @current_pack_status == ON_DOWNLOAD_FINISHED && @current_pack_md5
|
202
|
+
@last_packs << [@current_pack, @current_pack_md5]
|
203
|
+
end
|
204
|
+
@current_pack_md5 = nil
|
205
|
+
end
|
206
|
+
if delay > 0
|
207
|
+
# Delayed request of next pack
|
208
|
+
@delay_timestamp = Time.now
|
209
|
+
@delay_timeout = delay
|
210
|
+
return
|
211
|
+
else
|
212
|
+
@delay_timestamp = nil
|
213
|
+
end
|
214
|
+
@current_request_cnt = 0
|
215
|
+
if !@local_pack_queue.empty?
|
216
|
+
pack, path = @local_pack_queue.delete_at(0)
|
217
|
+
self.request_pack(pack, path)
|
218
|
+
# Update remaining queue positions
|
219
|
+
self.local_queue_change
|
220
|
+
else
|
221
|
+
@mutex.synchronize do
|
222
|
+
@current_pack = nil
|
223
|
+
@current_pack_status = -1
|
224
|
+
@current_download_path = nil
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Reset handler to empty state
|
230
|
+
# There should not be any reason for this method to be called from outside
|
231
|
+
def empty_state!
|
232
|
+
@mutex.synchronize do
|
233
|
+
@current_pack = nil
|
234
|
+
@current_pack_status = -1
|
235
|
+
@current_download_path = nil
|
236
|
+
@delay_timestamp = nil
|
237
|
+
@local_pack_queue.clear
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Is the handler in empty state? (i.e contains no packs to download)
|
242
|
+
def empty_state?
|
243
|
+
@mutex.synchronize do
|
244
|
+
!@current_pack && @current_pack_status == -1
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# Inform all ON_QUEUED_LOCALLY listeners that there was
|
249
|
+
# an update in the local queue
|
250
|
+
def local_queue_change
|
251
|
+
length = @local_pack_queue.length
|
252
|
+
@local_pack_queue.each_with_index do |pack_info, index|
|
253
|
+
self.fire_event(ON_QUEUED_LOCALLY, pack_info[0], index + 1, length)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# Cancel the specified pack using the given reason.
|
258
|
+
# This works for packs that have one of the following stati:
|
259
|
+
# ON_QUEUED_LOCALLY, ON_QUEUED_REMOTELY, ON_DOWNLOAD_STARTED
|
260
|
+
def cancel_pack(xdcc_pack, reason=$cfg.text.network.xdcc.cancel_download_default)
|
261
|
+
pack = nil
|
262
|
+
nextpack = false
|
263
|
+
@mutex.synchronize do
|
264
|
+
if xdcc_pack == @current_pack
|
265
|
+
pack = @current_pack
|
266
|
+
# Check if remotely queued
|
267
|
+
if @current_pack_status == ON_QUEUED_REMOTELY
|
268
|
+
@irc_user_bot.send("XDCC REMOVE")
|
269
|
+
@current_pack_status = ON_DOWNLOAD_FAILED if pack
|
270
|
+
self.fire_event(ON_DOWNLOAD_FAILED, pack, reason) if pack
|
271
|
+
nextpack = true
|
272
|
+
# Check if download started
|
273
|
+
elsif @current_pack_status == ON_DOWNLOAD_STARTED
|
274
|
+
@dcc_con.close if pack
|
275
|
+
@current_pack_status = ON_DOWNLOAD_FAILED if pack
|
276
|
+
self.fire_event(ON_DOWNLOAD_FAILED, pack, reason) if pack
|
277
|
+
nextpack = true
|
278
|
+
elsif @current_pack_status == ON_PACK_REQUESTED
|
279
|
+
@dcc_con.close if pack
|
280
|
+
@current_pack_status = ON_DOWNLOAD_FAILED if pack
|
281
|
+
self.fire_event(ON_DOWNLOAD_FAILED, pack, reason) if pack
|
282
|
+
nextpack = true
|
283
|
+
end
|
284
|
+
else
|
285
|
+
# Check locally queued packs
|
286
|
+
@local_pack_queue.delete_if do |p|
|
287
|
+
ret = p[0] == xdcc_pack
|
288
|
+
pack = xdcc_pack if ret
|
289
|
+
self.fire_event(ON_DOWNLOAD_FAILED, pack, reason) if ret
|
290
|
+
ret
|
291
|
+
end
|
292
|
+
# Update local queue
|
293
|
+
self.local_queue_change if pack
|
294
|
+
end
|
295
|
+
end
|
296
|
+
if next_pack
|
297
|
+
self.next_pack(5)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Deal with delayed md5 checksum received from bot
|
302
|
+
def handle_delayed_md5(received_md5)
|
303
|
+
if !@last_packs.empty?
|
304
|
+
pack, md5 = @last_packs.delete_at(0)
|
305
|
+
return if !md5
|
306
|
+
md5_ok = (md5.hexdigest == received_md5)
|
307
|
+
self.fire_event(ON_MD5_STATUS, pack, md5_ok ? MD5_OK : MD5_FAILED)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# Event handler
|
312
|
+
def on_event(caller, event, eventargs)
|
313
|
+
case event
|
314
|
+
when IRC_Server::ON_USER_MESSAGE
|
315
|
+
# Check for private bot message
|
316
|
+
if (@irc_user_bot != eventargs[0] || !@server.me.has_name?(eventargs[2][0]))
|
317
|
+
return
|
318
|
+
end
|
319
|
+
irc_msg = eventargs[3]
|
320
|
+
message = eventargs[1]
|
321
|
+
# Prolly a status update of the bot
|
322
|
+
if status = $cfg.network.xdcc.queue_add_regexp.match(message)
|
323
|
+
# Pack has been added to the remote queue.
|
324
|
+
@current_pack_status = ON_QUEUED_REMOTELY
|
325
|
+
self.fire_event(ON_QUEUED_REMOTELY, @current_pack, status[1].to_i, nil)
|
326
|
+
elsif status = $cfg.network.xdcc.queue_full_regexp.match(message)
|
327
|
+
# Queue is full, enqueue current pack and wait before requesting next pack
|
328
|
+
self.add_pack(@current_pack, @current_download_path)
|
329
|
+
self.next_pack($cfg.network.xdcc.queue_full_wait)
|
330
|
+
elsif status = $cfg.network.xdcc.is_queued_regexp.match(message)
|
331
|
+
# This shouldn't ever occur...
|
332
|
+
@mutex.synchronize do
|
333
|
+
@current_pack_status = ON_DOWNLOAD_FAILED
|
334
|
+
end
|
335
|
+
self.fire_event(ON_DOWNLOAD_FAILED, @current_pack, $cfg.text.network.xdcc.err_pack_already_requested)
|
336
|
+
self.next_pack($cfg.network.xdcc.is_queued_wait)
|
337
|
+
elsif status = $cfg.network.xdcc.max_queued_regexp.match(message)
|
338
|
+
# As shouldn't this...
|
339
|
+
@mutex.synchronize do
|
340
|
+
@current_pack_status = ON_DOWNLOAD_FAILED
|
341
|
+
end
|
342
|
+
self.fire_event(ON_DOWNLOAD_FAILED, @current_pack, $cfg.text.network.xdcc.err_max_packs_requested)
|
343
|
+
self.next_pack($cfg.network.xdcc.max_queued_wait)
|
344
|
+
elsif status = $cfg.network.xdcc.queue_update_regexp.match(message)
|
345
|
+
# Remote queue position update
|
346
|
+
@mutex.synchronize do
|
347
|
+
@current_pack_status = ON_QUEUED_REMOTELY
|
348
|
+
end
|
349
|
+
self.fire_event(ON_QUEUED_REMOTELY, @current_pack, status[1].to_i, status[2].to_i)
|
350
|
+
elsif status = $cfg.network.xdcc.md5_regexp.match(message)
|
351
|
+
handle_delayed_md5(status[1])
|
352
|
+
elsif status = $cfg.network.xdcc.punish_slowness_regexp.match(message)
|
353
|
+
self.fire_event(ON_DOWNLOAD_FAILED, @current_pack, $cfg.text.network.xdcc.err_punish_slowness)
|
354
|
+
self.next_pack(5)
|
355
|
+
end
|
356
|
+
|
357
|
+
|
358
|
+
when DCC_File::ON_DCC_ESTABLISHED
|
359
|
+
@mutex.synchronize do
|
360
|
+
@current_pack_status = ON_DOWNLOAD_STARTED
|
361
|
+
end
|
362
|
+
self.fire_event(ON_DOWNLOAD_STARTED, @current_pack)
|
363
|
+
|
364
|
+
when DCC_File::ON_DCC_ERROR
|
365
|
+
@mutex.synchronize do
|
366
|
+
@current_pack_status = ON_DOWNLOAD_FAILED
|
367
|
+
end
|
368
|
+
self.fire_event(ON_DOWNLOAD_FAILED, @current_pack, eventargs[0])
|
369
|
+
# Give bot some time to close connection, before requesting next pack
|
370
|
+
self.next_pack($cfg.network.xdcc.con_error_wait)
|
371
|
+
|
372
|
+
when DCC_File::ON_DCC_COMPLETED
|
373
|
+
@mutex.synchronize do
|
374
|
+
@current_pack_status = ON_DOWNLOAD_FINISHED
|
375
|
+
@current_pack_md5 = eventargs[0]
|
376
|
+
end
|
377
|
+
self.fire_event(ON_DOWNLOAD_FINISHED, @current_pack)
|
378
|
+
self.fire_event(ON_MD5_STATUS, @current_pack, $cfg.network.xdcc.enable_md5 ? MD5_UNAVAILABLE : MD5_DISABLED)
|
379
|
+
self.next_pack
|
380
|
+
|
381
|
+
when DCC_File::ON_DCC_PROGRESS
|
382
|
+
self.fire_event(ON_DOWNLOAD_PROGRESS, @current_pack, eventargs[0], eventargs[1], eventargs[2])
|
383
|
+
|
384
|
+
when DCC_Parser::ON_DCC_SEND
|
385
|
+
if (eventargs[0].irc_user == @irc_user_bot && (@current_pack_status == ON_PACK_REQUESTED ||
|
386
|
+
@current_pack_status == ON_QUEUED_REMOTELY))
|
387
|
+
@dcc_con.get(eventargs[0], @current_download_path)
|
388
|
+
end
|
389
|
+
|
390
|
+
when Timer::ON_TIMER
|
391
|
+
if @delay_timestamp
|
392
|
+
# Next pack has been delayed. Check for end of delay.
|
393
|
+
self.next_pack if eventargs[0] - @delay_timestamp >= @delay_timeout
|
394
|
+
end
|
395
|
+
|
396
|
+
@mutex.synchronize do
|
397
|
+
if @current_pack_status == ON_PACK_REQUESTED
|
398
|
+
if (eventargs[0] - @request_timestamp > $cfg.network.xdcc.request_timeout)
|
399
|
+
if $cfg.network.xdcc.no_max_rerequests || (@current_request_cnt < $cfg.network.xdcc.max_rerequests)
|
400
|
+
# No XDCC answer within specified interval. Rerequest pack
|
401
|
+
self.request_pack(@current_pack, @current_download_path)
|
402
|
+
else
|
403
|
+
@current_pack_status = ON_DOWNLOAD_FAILED
|
404
|
+
self.fire_event(ON_DOWNLOAD_FAILED, @current_pack, $cfg.text.network.xdcc.err_no_answer)
|
405
|
+
self.next_pack(20)
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Copyright (c) 2004-2005, Christoph Heindl
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
# are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright notice, this list
|
8
|
+
# of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above copyright notice, this list
|
10
|
+
# of conditions and the following disclaimer in the documentation and/or other materials
|
11
|
+
# provided with the distribution.
|
12
|
+
# * Neither the name of Christoph Heindl nor the names of its contributors may be used to
|
13
|
+
# endorse or promote products derived from this software without specific prior written
|
14
|
+
# permission.
|
15
|
+
#
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
17
|
+
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
18
|
+
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
19
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
21
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
22
|
+
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
23
|
+
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
|
+
|
25
|
+
require 'src/Network/IRC_Message.rb'
|
26
|
+
|
27
|
+
# An XDCC_Pack represents a file to download in the XDCC pseudo protocol.
|
28
|
+
class XDCC_Pack
|
29
|
+
# Bot, which offered pack
|
30
|
+
attr_reader :irc_user_bot
|
31
|
+
# Pack number, number of downloads, size, and pack name
|
32
|
+
attr_accessor :pack_nr, :download_cnt, :size, :name
|
33
|
+
|
34
|
+
# Initialize with the bot, which offers the pack, irc_server the bot is on
|
35
|
+
def initialize(irc_user_bot)
|
36
|
+
@irc_user_bot = irc_user_bot
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns a human readable representation of this pack as string
|
40
|
+
def to_s
|
41
|
+
"#{@pack_nr} | #{@download_cnt} | #{@size} | #{@name}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns a xdcc representation of this pack as an IRC_Message.
|
45
|
+
# Channel is the target channel
|
46
|
+
def to_irc(channel)
|
47
|
+
IRC_Message.new("PRIVMSG", channel, "\002##{@pack_nr} \002 #{@download_cnt}x [#{@size}] #{@name}")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Equality based on irc_bot, pack number and pack name
|
51
|
+
# Download count is not included
|
52
|
+
def ==(pack)
|
53
|
+
return false unless pack
|
54
|
+
@irc_user_bot == pack.irc_user_bot &&
|
55
|
+
@pack_nr == pack.pack_nr &&
|
56
|
+
@name == pack.name
|
57
|
+
end
|
58
|
+
end
|