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,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
|
+
|