comparison irclib.py @ 260:9a2302e8382b

(irclib) created a "Channel" class Signed-off-by: Charly COSTE <changaco@changaco.net>
author Charly COSTE <changaco@changaco.net>
date Sat, 13 Mar 2010 17:38:47 +0100
parents e64b574afa8f
children 53f4d9aa2b52
comparison
equal deleted inserted replaced
259:3b318108e9e0 260:9a2302e8382b
408 if connection in self.connections: 408 if connection in self.connections:
409 self.connections.remove(connection) 409 self.connections.remove(connection)
410 if self.fn_to_remove_socket: 410 if self.fn_to_remove_socket:
411 self.fn_to_remove_socket(connection._get_socket()) 411 self.fn_to_remove_socket(connection._get_socket())
412 412
413
414 LEFT, LEAVING, NOT_IN, JOINING, JOINED = range(5)
415
416 class Channel:
417
418 def __init__(self, connection, channel_name):
419 self.connection = connection
420 self.channel_name = channel_name
421 self.callbacks = []
422 self.state = NOT_IN
423
424 def _callback(self, error):
425 if not error:
426 self.state = JOINED
427 else:
428 self.state = NOT_IN
429 m = 'channel "'+self.channel_name+'" on connection "'+str(self.connection)+'"'
430 if len(self.callbacks) == 0:
431 self.connection.irclibobj.bot.error(1, 'no join callback for '+m, debug=True)
432 else:
433 self.connection.irclibobj.bot.error(1, 'calling '+str(len(self.callbacks))+' join callback(s) for '+m, debug=True)
434 for f in self.callbacks:
435 f(self.channel_name, error)
436
437 def add_callback(self, callback):
438 if callback and not callback in self.callbacks:
439 self.callbacks.append(callback)
440
441 def join(self, key=None, callback=None):
442 self.state = JOINING
443 self.key = key
444 self.add_callback(callback)
445 self.connection.send_raw("JOIN %s%s" % (self.channel_name, (key and (" " + key))))
446
447 def part(self, message=None):
448 if self.state <= NOT_IN:
449 return
450 self.state = LEAVING
451 self.connection.send_raw("PART " + self.channel_name + (message and (" " + message)))
452
453 def rejoin(self):
454 self.join(key=self.key)
455
456 def remove_callback(self, callback):
457 try:
458 self.callbacks.remove(callback)
459 except ValueError:
460 pass
461
462
413 _rfc_1459_command_regexp = re.compile("^(:(?P<prefix>[^ ]+) +)?(?P<command>[^ ]+)( *(?P<argument> .+))?") 463 _rfc_1459_command_regexp = re.compile("^(:(?P<prefix>[^ ]+) +)?(?P<command>[^ ]+)( *(?P<argument> .+))?")
414 464
415 class Connection: 465 class Connection:
416 """Base class for IRC connections. 466 """Base class for IRC connections.
417 467
462 self.port = port 512 self.port = port
463 self.nickname = nickname 513 self.nickname = nickname
464 self.nick_callbacks = [] 514 self.nick_callbacks = []
465 self.join_callbacks = {} 515 self.join_callbacks = {}
466 self.lock = threading.RLock() 516 self.lock = threading.RLock()
467 self.left_channels = [] 517 self.channels = {}
468 self.channels = []
469 self.channels_keys = {}
470 self.irc_id = None 518 self.irc_id = None
471 self.previous_buffer = "" 519 self.previous_buffer = ""
472 self.handlers = {} 520 self.handlers = {}
473 self.real_server_name = "" 521 self.real_server_name = ""
474 self.new_nickname = None 522 self.new_nickname = None
592 if self.nick(self.nickname): 640 if self.nick(self.nickname):
593 self.user(self.username, self.ircname) 641 self.user(self.username, self.ircname)
594 642
595 # Rejoin channels 643 # Rejoin channels
596 if len(self.channels) > 0: 644 if len(self.channels) > 0:
597 for channel in self.channels: 645 for channel in self.channels.itervalues():
598 if self.channels_keys.has_key(channel): 646 channel.rejoin()
599 key = self.channels_keys[channel]
600 else:
601 key = ''
602 self.join(channel, key=key)
603 647
604 self.lock.release() 648 self.lock.release()
605 return self 649 return self
606 650
607 651
611 else: 655 else:
612 self.irclibobj.bot.error(1, 'calling '+str(len(self.nick_callbacks))+' nick callback(s) for "'+self.__str__()+'"', debug=True) 656 self.irclibobj.bot.error(1, 'calling '+str(len(self.nick_callbacks))+' nick callback(s) for "'+self.__str__()+'"', debug=True)
613 for f in self.nick_callbacks: 657 for f in self.nick_callbacks:
614 f(error, arguments=arguments) 658 f(error, arguments=arguments)
615 self.nick_callbacks = [] 659 self.nick_callbacks = []
616
617
618 def _call_join_callbacks(self, channel, error):
619 self.lock.acquire()
620 m = 'channel "'+channel+'" on connection "'+str(self)+'"'
621 if not self.join_callbacks.has_key(channel) or len(self.join_callbacks[channel]) == 0:
622 self.irclibobj.bot.error(1, 'no join callback for '+m, debug=True)
623 else:
624 self.irclibobj.bot.error(1, 'calling '+str(len(self.join_callbacks[channel]))+' join callback(s) for '+m, debug=True)
625 for f in self.join_callbacks[channel]:
626 f(channel, error)
627 self.join_callbacks.pop(channel, None)
628 self.lock.release()
629 660
630 661
631 def add_nick_callback(self, callback): 662 def add_nick_callback(self, callback):
632 self.nick_callbacks.append(callback) 663 self.nick_callbacks.append(callback)
633 664
795 if self.irc_id != prefix: 826 if self.irc_id != prefix:
796 self.irc_id = prefix 827 self.irc_id = prefix
797 if DEBUG: 828 if DEBUG:
798 print "irc_id: %s" % (prefix) 829 print "irc_id: %s" % (prefix)
799 channel = target.lower() 830 channel = target.lower()
800 if not channel in self.channels: 831 if self.channels[channel].state != JOINED:
801 self.channels.append(channel) 832 self.channels[channel]._callback(None)
802 if channel in self.left_channels:
803 self.left_channels.remove(channel)
804 self._call_join_callbacks(channel, None)
805 833
806 if command in ['inviteonlychan', 'bannedfromchan', 'channelisfull', 'badchannelkey']: 834 if command in ['inviteonlychan', 'bannedfromchan', 'channelisfull', 'badchannelkey']:
807 self._call_join_callbacks(arguments[0].lower(), command) 835 self.channels[arguments[0].lower()]._callback(command)
808 836
809 if DEBUG: 837 if DEBUG:
810 print "command: %s, source: %s, target: %s, arguments: %s" % ( 838 print "command: %s, source: %s, target: %s, arguments: %s" % (
811 command, prefix, target, arguments) 839 command, prefix, target, arguments)
812 840
912 940
913 nicks -- List of nicks. 941 nicks -- List of nicks.
914 """ 942 """
915 self.send_raw("ISON " + " ".join(nicks)) 943 self.send_raw("ISON " + " ".join(nicks))
916 944
917 def join(self, channel, callback=None, key=""): 945 def join(self, channel_name, callback=None, key=""):
918 """Send a JOIN command.""" 946 """Send a JOIN command."""
919 if callback: 947 if not self.channels.has_key(channel_name):
920 self.add_join_callback(channel, callback) 948 self.channels[channel_name] = Channel(self, channel_name)
921 if key: 949 self.channels[channel_name].join(key=key, callback=callback)
922 self.channels_keys[channel] = key
923 self.send_raw("JOIN %s%s" % (channel, (key and (" " + key))))
924 950
925 def kick(self, channel, nick, comment=""): 951 def kick(self, channel, nick, comment=""):
926 """Send a KICK command.""" 952 """Send a KICK command."""
927 self.send_raw("KICK %s %s%s" % (channel, nick, (comment and (" :" + comment)))) 953 self.send_raw("KICK %s %s%s" % (channel, nick, (comment and (" :" + comment))))
928 954
982 self.send_raw("NOTICE %s :%s" % (target, text)) 1008 self.send_raw("NOTICE %s :%s" % (target, text))
983 1009
984 def oper(self, nick, password): 1010 def oper(self, nick, password):
985 """Send an OPER command.""" 1011 """Send an OPER command."""
986 self.send_raw("OPER %s %s" % (nick, password)) 1012 self.send_raw("OPER %s %s" % (nick, password))
987
988 def _remove_channel(self, channel):
989 if channel in self.channels:
990 self.channels.remove(channel)
991 if not channel in self.left_channels:
992 self.left_channels.append(channel)
993 1013
994 def part(self, channels, message=""): 1014 def part(self, channels, message=""):
995 """Send a PART command.""" 1015 """Send a PART command."""
996 try: 1016 try:
997 if isinstance(channels, basestring): 1017 if isinstance(channels, basestring):
998 self._remove_channel(channels) 1018 self.channels[channels].part(message=message)
999 self.send_raw("PART " + channels + (message and (" " + message)))
1000 else: 1019 else:
1001 for channel in channels: 1020 for channel in channels:
1002 self._remove_channel(channel) 1021 self.channels[channel].part(message=message)
1003 self.send_raw("PART " + ",".join(channels) + (message and (" " + message)))
1004 except ServerNotConnectedError: 1022 except ServerNotConnectedError:
1005 self.disconnect(volontary=True) 1023 self.disconnect(volontary=True)
1006 self.connect() 1024 self.connect()
1007 1025
1008 def pass_(self, password): 1026 def pass_(self, password):