XDCC-Fetch 1.386
Sign up to get free protection for your applications and to get access to all the features.
- 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,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
|
+
|
26
|
+
require 'src/Network/IRC_Message.rb'
|
27
|
+
|
28
|
+
# Represents a user on irc
|
29
|
+
class IRC_User
|
30
|
+
attr_accessor :name, :user, :host
|
31
|
+
attr_reader :irc_server
|
32
|
+
|
33
|
+
def initialize(name, irc_server)
|
34
|
+
@name = name
|
35
|
+
@user = nil
|
36
|
+
@host = nil
|
37
|
+
@irc_server = irc_server
|
38
|
+
end
|
39
|
+
|
40
|
+
# Send a private message to the user
|
41
|
+
def send(message)
|
42
|
+
@irc_server.send(IRC_Message.new("PRIVMSG", @name, message))
|
43
|
+
end
|
44
|
+
|
45
|
+
# Send a private notice to the user
|
46
|
+
def notice(message)
|
47
|
+
@irc_server.send(IRC_Message.new("NOTICE", @name, message))
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
"#{@name}!#{@user}@#{@host}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Equals the nick of this user the given string?
|
55
|
+
def has_name?(other_name)
|
56
|
+
self.name.downcase == other_name.downcase
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,168 @@
|
|
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 'socket'
|
27
|
+
require 'resolv-replace'
|
28
|
+
require 'src/Utilities/Events.rb'
|
29
|
+
require 'timeout'
|
30
|
+
|
31
|
+
# Provides businesslogic for handling a TCP client connection.
|
32
|
+
# Supports text based and binary based connections through wrapping the actual receive
|
33
|
+
# and send procedure.
|
34
|
+
class TCP_Connection
|
35
|
+
include Event_Publisher
|
36
|
+
|
37
|
+
attr_reader :address, :port
|
38
|
+
attr_accessor :proc_recv, :proc_send
|
39
|
+
|
40
|
+
|
41
|
+
# -- connectable events
|
42
|
+
|
43
|
+
# On socket connection established. Args: none
|
44
|
+
ON_CONNECTED = Event_Publisher.next_global_eventID
|
45
|
+
# On socket connection closed remotely. Args: none
|
46
|
+
ON_CLOSED = Event_Publisher.next_global_eventID
|
47
|
+
# On socket error. Args: error message
|
48
|
+
ON_ERROR = Event_Publisher.next_global_eventID
|
49
|
+
# On data received. Args: data
|
50
|
+
ON_DATA = Event_Publisher.next_global_eventID
|
51
|
+
# All events packaged in one
|
52
|
+
ON_ALL_EVENTS = ON_CONNECTED + ON_CLOSED + ON_DATA + ON_ERROR
|
53
|
+
|
54
|
+
def initialize(proc_recv, proc_send)
|
55
|
+
@proc_recv = proc_recv
|
56
|
+
@proc_send = proc_send
|
57
|
+
@socket = nil
|
58
|
+
@recv_thread = nil
|
59
|
+
init_events
|
60
|
+
end
|
61
|
+
|
62
|
+
# Open connection to the specified server and port
|
63
|
+
def open(address, port)
|
64
|
+
@address = address
|
65
|
+
@port = port
|
66
|
+
|
67
|
+
if !self.connected?
|
68
|
+
# Spawn a thread responsible for handling initial connection
|
69
|
+
# That way, the the main thread is not blocked if connection cannot be
|
70
|
+
# established
|
71
|
+
connect_thread = Thread.new do
|
72
|
+
if @address && @port
|
73
|
+
begin
|
74
|
+
timeout($cfg.network.tcp.connect_timeout) {
|
75
|
+
@socket = TCPSocket.new(@address, @port)
|
76
|
+
}
|
77
|
+
self.fire_event(ON_CONNECTED)
|
78
|
+
# Setup the required receive thread which reads from the connection
|
79
|
+
@recv_thread = Thread.new do
|
80
|
+
begin
|
81
|
+
while data = self.proc_recv.call(@socket)
|
82
|
+
self.fire_event(ON_DATA, data) unless data.length == 0
|
83
|
+
end
|
84
|
+
self.close
|
85
|
+
self.fire_event(ON_CLOSED)
|
86
|
+
rescue IOError, Errno::ECONNRESET, Errno::ENOTSOCK, SocketError => err
|
87
|
+
self.fire_event(ON_ERROR, err.to_s)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
rescue TimeoutError => err
|
91
|
+
self.fire_event(ON_ERROR, $cfg.text.network.tcp.err_con_timeout)
|
92
|
+
rescue IOError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ETIMEDOUT, SocketError => err
|
93
|
+
self.close
|
94
|
+
self.fire_event(ON_ERROR, err.to_s)
|
95
|
+
end
|
96
|
+
else
|
97
|
+
self.fire_event(ON_ERROR, $cfg.text.network.tcp.err_con_no_remote)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
else
|
101
|
+
# Already connected
|
102
|
+
self.fire_event(ON_ERROR, $cfg.text.network.tcp.err_con_active)
|
103
|
+
end
|
104
|
+
# Lower priority of connect thread. This may help higher level applications to increase there response time
|
105
|
+
connect_thread.priority = $cfg.network.tcp.connect_thread_priority
|
106
|
+
end
|
107
|
+
|
108
|
+
# Send data to socket
|
109
|
+
def send(data)
|
110
|
+
begin
|
111
|
+
@proc_send.call(@socket, data) if self.connected?
|
112
|
+
rescue Exception => err
|
113
|
+
self.fire_event(ON_ERROR, err.to_s)
|
114
|
+
self.close
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Immediate shutdown the connection
|
119
|
+
def close
|
120
|
+
begin
|
121
|
+
@socket.close
|
122
|
+
rescue Exception
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Wait for the connection to close
|
127
|
+
def wait
|
128
|
+
if self.connected?
|
129
|
+
@recv_thread.join
|
130
|
+
else
|
131
|
+
self.fire_event(ON_ERROR, $cfg.text.network.tcp.err_con_closed)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Is connection established?
|
136
|
+
def connected?
|
137
|
+
@socket && !@socket.closed?
|
138
|
+
end
|
139
|
+
|
140
|
+
# Generate a line based TCPConnection object. That is, data is received
|
141
|
+
# whenever \r\n is received.
|
142
|
+
def TCP_Connection.text
|
143
|
+
recv_proc = proc do |socket|
|
144
|
+
data = socket.gets("\r\n")
|
145
|
+
end
|
146
|
+
|
147
|
+
send_proc = proc do |socket, data|
|
148
|
+
socket.puts(data)
|
149
|
+
end
|
150
|
+
TCP_Connection.new(recv_proc, send_proc)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Generate a TCPConnection object, capable of handling binary data packets.
|
154
|
+
def TCP_Connection.binary
|
155
|
+
recv_proc = proc do |socket|
|
156
|
+
data = socket.recv(16384)
|
157
|
+
(data.length > 0) ? data : nil
|
158
|
+
end
|
159
|
+
|
160
|
+
send_proc = proc do |socket, data|
|
161
|
+
socket.print(data)
|
162
|
+
end
|
163
|
+
TCP_Connection.new(recv_proc, send_proc)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
|
@@ -0,0 +1,120 @@
|
|
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/XDCC_Pack.rb'
|
27
|
+
require 'src/Network/IRC_Message.rb'
|
28
|
+
|
29
|
+
# An XDCC_Announcement represents an complete offering of an xdcc bot. This includes info about the current bot status as
|
30
|
+
# well as the offered packs.
|
31
|
+
class XDCC_Announcement
|
32
|
+
|
33
|
+
# The irc_user offering
|
34
|
+
attr_reader :irc_user_bot
|
35
|
+
#nr of packs offered, nr of available slots, nr of slots open and the targets this announcement was found at
|
36
|
+
# Nr of packs in announcement
|
37
|
+
attr_accessor :pack_cnt
|
38
|
+
# Total number of slots
|
39
|
+
attr_accessor :slot_cnt
|
40
|
+
# Number of slots available
|
41
|
+
attr_accessor :openslot_cnt
|
42
|
+
# Total number of queue slots
|
43
|
+
attr_accessor :queue_cnt
|
44
|
+
# Number of open queue positions
|
45
|
+
attr_accessor :openqueue_cnt
|
46
|
+
# Array of channels or nicknames, this announcement was sent to
|
47
|
+
attr_accessor :targets
|
48
|
+
# Type of announcement (FULL or MEDIUM)
|
49
|
+
attr_reader :ann_type
|
50
|
+
# Array of XDCC_Packs belonging to this announcement
|
51
|
+
attr_reader :packs
|
52
|
+
|
53
|
+
# -- Constants
|
54
|
+
ANN_FULL = 0
|
55
|
+
ANN_MINIMAL = 1
|
56
|
+
|
57
|
+
# Initialize with the bot which offers
|
58
|
+
def initialize(irc_user_bot, type=ANN_FULL)
|
59
|
+
@pack_cnt = -1
|
60
|
+
@irc_user_bot = irc_user_bot
|
61
|
+
@packs = Array.new
|
62
|
+
@openslot_cnt = -1
|
63
|
+
@slot_cnt = -1
|
64
|
+
@queue_cnt = -1
|
65
|
+
@openqueue_cnt = -1
|
66
|
+
@ann_type = type
|
67
|
+
end
|
68
|
+
|
69
|
+
# Has parsing completed
|
70
|
+
def completed?
|
71
|
+
@packs.length == @pack_cnt
|
72
|
+
end
|
73
|
+
|
74
|
+
# Does this announcement contain queue information
|
75
|
+
def has_queue_info?
|
76
|
+
@queue_cnt != -1
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns a human readable representation of this announcement as string
|
80
|
+
def to_s
|
81
|
+
s = "XDCC_Announcement: #{@irc_user_bot.name} | nr of packs: #{@pack_cnt} | open slots: #{@openslot_cnt}/#{@slot_cnt} | queue: #{@openqueue_cnt}/#{@queue_cnt}\r\n"
|
82
|
+
@packs.each do |pack|
|
83
|
+
s += "#{pack}\r\n"
|
84
|
+
end
|
85
|
+
s
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns a xdcc representation of this announcement as array of irc_messages.
|
89
|
+
# If channel is not given, the channelname is taken from the targets.
|
90
|
+
def to_irc(channel=nil)
|
91
|
+
channel = @targets[0] unless channel
|
92
|
+
a = []
|
93
|
+
a << IRC_Message.new("PRIVMSG", channel, "\002**\002 #{@pack_cnt} packs \002\002 #{@openslot_cnt} of #{@slot_cnt} slots open")
|
94
|
+
a << IRC_Message.new("PRIVMSG", channel, "\002**\002 Bandwidth usage ...")
|
95
|
+
a << IRC_Message.new("PRIVMSG", channel, "\002**\002 To request a file, type \"/msg ....")
|
96
|
+
@packs.each do |pack|
|
97
|
+
a << pack.to_irc(channel)
|
98
|
+
end
|
99
|
+
a << IRC_Message.new("PRIVMSG", channel, "Total Offered: 1.1 MB Total Transferred: 2.13 MB")
|
100
|
+
end
|
101
|
+
|
102
|
+
# Determines equality of this xdcc_announcement and the given xdcc_announcement.
|
103
|
+
def ==(ann)
|
104
|
+
@irc_user_bot == ann.irc_user_bot &&
|
105
|
+
@pack_cnt == ann.pack_cnt &&
|
106
|
+
@slot_cnt == ann.pack_cnt &&
|
107
|
+
@openslot_cnt == ann.openslot_cnt &&
|
108
|
+
@packs == ann.packs
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
#<mybotDCC> ** 4 packs ** 20 of 20 slots open, Record: 3543.1KB/s
|
113
|
+
#<mybotDCC> ** Bandwidth Usage ** Current: 0.0KB/s, Record: 9.5KB/s
|
114
|
+
#<mybotDCC> ** To request a file, type "/msg mybotDCC xdcc send #x" **
|
115
|
+
#<mybotDCC> ** To request details, type "/msg mybotDCC xdcc info #x" **
|
116
|
+
#<mybotDCC> #1 2x [1.0M] Setup-NettalkIRCD.exe
|
117
|
+
#<mybotDCC> #2 1x [ 93K] XDCC-FetchGUI-nightly.zip
|
118
|
+
#<mybotDCC> #3 1x [ <1K] wscite162.zip
|
119
|
+
#<mybotDCC> #4 0x [ <1K] sometext.txt
|
120
|
+
#<mybotDCC> Total Offered: 1.1 MB Total Transferred: 2.13 MB
|
@@ -0,0 +1,167 @@
|
|
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 'thread'
|
27
|
+
require 'src/Utilities/Events.rb'
|
28
|
+
require 'src/Network/IRC_Server.rb'
|
29
|
+
require 'src/Network/XDCC_Parser.rb'
|
30
|
+
|
31
|
+
class XDCC_Announcement_Storage
|
32
|
+
include Event_Publisher
|
33
|
+
|
34
|
+
# -- Connectable events
|
35
|
+
|
36
|
+
# Whenever a new(unknown, updated) announcement is available. Args: xdcc_announcement
|
37
|
+
ON_ANNOUNCEMENT_NEW = Event_Publisher.next_global_eventID
|
38
|
+
# Whenever a known announcement is lost, due to user quit or announcement update. Args: xdcc_announcement
|
39
|
+
ON_ANNOUNCEMENT_LOST = Event_Publisher.next_global_eventID
|
40
|
+
|
41
|
+
# Initialize with the given XDCC_Parser
|
42
|
+
def initialize(xdcc_parser)
|
43
|
+
@mutex = Mutex.new
|
44
|
+
@bot_announcement = Hash.new
|
45
|
+
@irc_servers = Array.new
|
46
|
+
@parser = xdcc_parser
|
47
|
+
@parser.connect_to_events(XDCC_Parser::ON_ANNOUNCEMENT, self)
|
48
|
+
self.init_events
|
49
|
+
end
|
50
|
+
|
51
|
+
# Clear up, prepare for deallocation
|
52
|
+
def shutdown
|
53
|
+
@parser.disconnect_from_events(XDCC_Parser::ON_ANNOUNCEMENT, self)
|
54
|
+
self.shutdown_events
|
55
|
+
end
|
56
|
+
|
57
|
+
# Handle a XDCC_Announcement
|
58
|
+
# Basically decides, if it is unknown or known and based on this, takes the appropriate actions
|
59
|
+
def handle_announcement(ann)
|
60
|
+
@mutex.synchronize do
|
61
|
+
# Check if we've already subsribed at the irc_server the ann was broadcasted on
|
62
|
+
if !@irc_servers.include?(ann.irc_user_bot.irc_server)
|
63
|
+
@irc_servers.push(ann.irc_user_bot.irc_server)
|
64
|
+
ann.irc_user_bot.irc_server.connect_to_events(IRC_Server::ON_USER_QUIT|
|
65
|
+
IRC_Server::ON_USER_PART|
|
66
|
+
IRC_Server::ON_USER_KICK|
|
67
|
+
IRC_Server::ON_SERVER_DISCONNECTED,
|
68
|
+
self)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Check if it is an unknown bot
|
72
|
+
if !@bot_announcement.include?(ann.irc_user_bot)
|
73
|
+
self.handle_new_announcement(ann)
|
74
|
+
else
|
75
|
+
self.handle_existing_announcement(ann)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Handles an unknown XDCC_Announcement.
|
81
|
+
# Broadcasts an ON_ANNOUNCEMENT_NEW event
|
82
|
+
def handle_new_announcement(ann)
|
83
|
+
@bot_announcement[ann.irc_user_bot] = ann
|
84
|
+
self.fire_event(ON_ANNOUNCEMENT_NEW, ann)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Handles a known XDCC_Announcement.
|
88
|
+
# An ON_ANNOUNCEMENT_UPDATE is being broadcasted if the XDCC_Announcement changed.
|
89
|
+
def handle_existing_announcement(ann)
|
90
|
+
# Check if announcement has updated
|
91
|
+
if @bot_announcement[ann.irc_user_bot] != ann
|
92
|
+
self.fire_event(ON_ANNOUNCEMENT_LOST, @bot_announcement[ann.irc_user_bot])
|
93
|
+
self.fire_event(ON_ANNOUNCEMENT_NEW, ann)
|
94
|
+
@bot_announcement[ann.irc_user_bot] = ann
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Handles a user quit message.
|
99
|
+
# A ON_ANNOUNCEMENT_LOST is thrown, if the user quitting used to offer XDCC_Packs.
|
100
|
+
def handle_user_quit(irc_user)
|
101
|
+
@mutex.synchronize do
|
102
|
+
ann = @bot_announcement.delete(irc_user)
|
103
|
+
self.fire_event(ON_ANNOUNCEMENT_LOST, ann) if ann
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# When disconnected from server, all announcements found on this server
|
108
|
+
# are treated as lost. the server itself is not killed.
|
109
|
+
def handle_server_disconnect(irc_server)
|
110
|
+
@mutex.synchronize do
|
111
|
+
@bot_announcement.delete_if do |bot, ann|
|
112
|
+
ret = (bot.irc_server == irc_server)
|
113
|
+
self.fire_event(ON_ANNOUNCEMENT_LOST, ann) if ret
|
114
|
+
ret
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# When a user is kicked from a certain channel. Possible announcements
|
120
|
+
# belonging to that user are being treated as lost. If the user is
|
121
|
+
# ourself, all announcements found on that channel are being treated as lost
|
122
|
+
def handle_channel_left(irc_server, channelname, irc_user)
|
123
|
+
if irc_server.me.has_name?(irc_user.name)
|
124
|
+
# We have been forced to leave channel
|
125
|
+
chan = channelname.downcase
|
126
|
+
@mutex.synchronize do
|
127
|
+
@bot_announcement.delete_if do |bot, ann|
|
128
|
+
# Although announcement may be broadcasted in multiple channels,
|
129
|
+
# we only check the first so far
|
130
|
+
# TODO: check if announcement was broadcasted in other chans (we know)
|
131
|
+
# too. If we are in such a chan, don't kill announcement
|
132
|
+
ret = (ann.targets[0].downcase == chan)
|
133
|
+
self.fire_event(ON_ANNOUNCEMENT_LOST, ann) if ret
|
134
|
+
ret
|
135
|
+
end
|
136
|
+
end
|
137
|
+
else
|
138
|
+
# User (potential bot has been kicked)
|
139
|
+
username = irc_user.name.downcase
|
140
|
+
@mutex.synchronize do
|
141
|
+
@bot_announcement.delete_if do |bot, ann|
|
142
|
+
ret = (bot.name.downcase == username)
|
143
|
+
self.fire_event(ON_ANNOUNCEMENT_LOST, ann) if ret
|
144
|
+
ret
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Handle incoming events
|
151
|
+
def on_event(caller, event, eventargs)
|
152
|
+
case event
|
153
|
+
when XDCC_Parser::ON_ANNOUNCEMENT
|
154
|
+
self.handle_announcement(eventargs[0])
|
155
|
+
|
156
|
+
when IRC_Server::ON_USER_QUIT
|
157
|
+
self.handle_user_quit(eventargs[0])
|
158
|
+
|
159
|
+
when IRC_Server::ON_SERVER_DISCONNECTED
|
160
|
+
self.handle_server_disconnect(caller)
|
161
|
+
|
162
|
+
when IRC_Server::ON_USER_KICK, IRC_Server::ON_USER_PART
|
163
|
+
self.handle_channel_left(caller, eventargs[1], eventargs[0])
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|