1 from __future__
import absolute_import
2 import socket
, random
, time
, nil
.thread
7 def do_nothing(*arguments
):
10 def strip_tags(input):
14 last_index
= len(input) - 1
15 while i
<= last_index
:
16 current_char
= input[i
]
17 if ord(current_char
) < ord(' '):
18 if current_char
== '\x03' and last_index
- i
>= 2:
19 next_char
= input[i
+ 1]
20 next_char_value
= ord(next_char
)
23 second_digit
= ord(input[i
+ 1])
24 if second_digit
>= ord('0') and second_digit
<= ord('5'):
26 elif next_char
== '0':
28 elif next_char_value
>= ord('2') and next_char_value
<= ord('9'):
31 output
+= current_char
36 def __init__(self
, input):
40 tokens
= input[1 : ].split('!')
47 tokens
= tokens
[1].split('@')
52 self
.ident
= tokens
[0]
53 self
.address
= tokens
[1]
57 self
.on_raw_packet
= do_nothing
58 self
.on_failed_connect
= do_nothing
59 self
.on_connect
= do_nothing
60 self
.on_disconnect
= do_nothing
61 self
.on_entry
= do_nothing
62 self
.on_notice
= do_nothing
63 self
.on_join
= do_nothing
64 self
.on_invite
= do_nothing
65 self
.on_channel_message
= do_nothing
66 self
.on_private_message
= do_nothing
67 self
.on_nick_name_in_use
= self
.change_nick
68 self
.on_quit
= do_nothing
70 self
.auto_reconnect
= True
71 self
.auto_reconnect_delay
= 5
77 self
.maximum_ping_count
= None
79 nil
.thread
.create_thread(lambda: self
.timeout_thread())
81 def timeout_thread(self
):
83 if self
.last_line
!= None and time
.time() - self
.last_line
> self
.timeout
:
84 print 'Timeout occured'
85 nil
.thread
.create_thread(lambda: self
.perform_reconnect())
86 time
.sleep(self
.auto_reconnect_delay
)
90 def connect(self
, server
, port
, nick
, user
, local_host
, real_name
):
95 self
.local_host
= local_host
96 self
.real_name
= real_name
99 self
.socket
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
, socket
.IPPROTO_TCP
)
101 self
.socket
.connect((server
, port
))
105 self
.on_failed_connect()
106 if self
.auto_reconnect
:
107 time
.sleep(self
.auto_reconnect_delay
)
111 self
.send_line('NICK %s' % nick
)
112 self
.send_line('USER %s "%s" "%s" :%s' % (user
, local_host
, server
, real_name
))
116 self
.connect(self
.server
, self
.port
, self
.nick
, self
.user
, self
.local_host
, self
.real_name
)
118 def send_line(self
, line
):
119 self
.socket
.send('%s\r\n' % line
)
121 def join(self
, channel
):
122 self
.send_line('JOIN %s' % channel
)
124 def message(self
, target
, message
):
125 self
.send_line('PRIVMSG %s :%s' % (target
, message
))
127 def got_disconnected(self
):
129 time
.sleep(self
.auto_reconnect_delay
)
132 def perform_reconnect(self
):
137 self
.got_disconnected()
139 def receive_data(self
):
143 new_data
= self
.socket
.recv(self
.read_size
)
144 self
.last_line
= time
.time()
146 self
.perform_reconnect()
148 if len(new_data
) == 0:
149 self
.perform_reconnect()
151 self
.buffer += new_data
152 self
.process_new_data()
154 def process_new_data(self
):
156 offset
= self
.buffer.find('\n')
159 line
= self
.buffer[0 : offset
].replace('\r', '')
160 self
.buffer = self
.buffer[offset
+ 1 : ]
161 self
.process_line(line
)
163 def process_line(self
, line
):
164 self
.on_raw_packet(line
)
168 offset
= line
.find(colon
, 1)
170 tokens
= line
.split(delimiter
)
172 tokens
= line
[0 : offset
- 1].split(delimiter
)
173 tokens
.append(line
[offset
+ 1 : ])
175 self
.process_command(tokens
)
177 def process_command(self
, tokens
):
179 ('376', self
.event_end_of_motd
),
180 ('422', self
.event_end_of_motd
),
181 ('433', self
.event_nick_name_in_use
),
182 ('NOTICE', self
.event_notice
),
183 ('INVITE', self
.event_invite
),
184 ('JOIN', self
.event_join
),
185 ('PRIVMSG', self
.event_message
),
186 ('MODE', self
.event_mode
),
187 ('QUIT', self
.event_quit
)
190 if tokens
[0] == 'PING' and len(tokens
) == 2:
191 self
.send_line('PONG %s' % tokens
[1])
192 self
.ping_counter
+= 1
193 if self
.maximum_ping_count
!= None and self
.ping_counter
>= self
.maximum_ping_count
:
194 print 'Exceeded maximum ping count, reconnecting'
195 self
.perform_reconnect()
201 self
.ping_counter
= 0
203 for command
, function
in commands
:
204 if command
== tokens
[1]:
208 def change_nick(self
):
209 new_nick
= '%s%d' % (self
.nick
, random
.randint(10, 99))
210 self
.send_line('NICK %s' % new_nick
)
212 def event_end_of_motd(self
, tokens
):
213 self
.nick
= tokens
[2]
216 def event_nick_name_in_use(self
, tokens
):
217 self
.on_nick_name_in_use()
219 def event_notice(self
, tokens
):
220 user
= irc_user(tokens
[0])
224 self
.on_notice(user
, text
)
226 def event_invite(self
, tokens
):
227 user
= irc_user(tokens
[0])
231 self
.on_invite(user
, channel
)
233 def event_join(self
, tokens
):
234 user
= irc_user(tokens
[0])
237 own_join
= (user
.nick
== self
.nick
)
239 self
.on_join(channel
, user
, own_join
)
241 def event_message(self
, tokens
):
242 user
= irc_user(tokens
[0])
247 if target
== self
.nick
:
248 self
.on_private_message(user
, message
)
250 self
.on_channel_message(target
, user
, message
)
252 def event_mode(self
, tokens
):
255 def event_quit(self
, tokens
):
256 user
= irc_user(tokens
[0])
260 self
.on_quit(user
, message
)