def pkt_part(self, event): """ Received a part packet. Similar to ``pkt_join``. This method determines whether or not the client is being kicked off the server. """ if event.arguments['ns'] in self.channel.keys(): del self.channel[event.arguments['ns']] if len(self.channel) > 0: return if 'r' in event.arguments: if event.arguments['r'] in ('bad data', 'bad msg', 'msg too big' ) or 'killed:' in event.arguments['r']: self.handle_pkt( Packet('disconnect{0}e={1}{2}{3}'.format( "\n", event.arguments['r'], "\n", "\n")), time.time()) return if event.arguments['e'] != 'ok': return if self.channel or self.flag.disconnecting or self.flag.quitting: return self.handle_pkt(Packet('disconnect\ne=no joined channels\n\n'), time.time())
def process_property(self, data): """ Called when receive a property packet for the channel. This method makes sure that the data is stored in the right places in the object. """ if data.arguments['p'] == 'title': self.title.content = data.arguments['value'] self.title.by = data.arguments['by'] self.title.ts = data.arguments['ts'] if data.arguments['p'] == 'topic': self.topic.content = data.arguments['value'] self.topic.by = data.arguments['by'] self.topic.ts = data.arguments['ts'] if data.arguments['p'] == 'privclasses': self.pc = Packet(data.arguments['value'], ':').args self.pc_order = sorted(self.pc.keys(), key=int) self.pc_order.reverse() if data.arguments['p'] == 'members': member = Packet(data.arguments['value']) while member.cmd != None and len(member.args) > 0: self.register_user(member) member = Packet(member.body)
def dataReceived(self, data): """ Called by twisted when data is received. The data received is added to out buffer. If there are any full packets in the buffer, these packets are sent to the :py:class:`ChatClient <dAmnViper.base.ChatClient>` instance to be parsed properly. Any event handling relating to specific packets is done in the ``ChatClient`` instance. """ # Tell the client some data has arrived. Woo... self.client.dataReceived(data) # Split on null. self.__buffer += data raw = self.__buffer.split('\0') self.__buffer = raw.pop() for chunk in raw: packet = Packet(chunk) # If it's a ping packet, send a pong straight away! if packet.cmd == 'ping': self.send_packet('pong\n') # Let the client do whatever it needs to with the packet. self.client.handle_pkt(packet, time.time())
class Channel: """ Objects representing dAmn channels. Information about the channels are stored in here. """ class header: def __init__(self): self.content = '' self.by = '' self.ts = 0.0 def __init__(self, namespace, shorthand): """Set up all our variables.""" self.title = Channel.header() self.topic = Channel.header() self.pc = {} self.pc_order = [] self.member = {} self.namespace = namespace self.shorthand = shorthand self.type = '<dAmn channel \''+self.namespace+'\'>' def process_property(self, data): if data['p'] == 'title': self.title.content = data['value'] self.title.by = data['by'] self.title.ts = data['ts'] if data['p'] == 'topic': self.topic.content = data['value'] self.topic.by = data['by'] self.topic.ts = data['ts'] if data['p'] == 'privclasses': self.pc = Packet(data['value'], ':').args self.pc_order = sorted(self.pc.keys(), key=int) self.pc_order.reverse() if data['p'] == 'members': member = Packet(data['value']) while member.cmd != None and len(member.args) > 0: self.register_user(member) member = Packet(member.body) def register_user(self, info, user = None): user = user if user != None else info.param if user in self.member: self.member[user]['con']+= 1 else: self.member[user] = info.args self.member[user]['con'] = 1 def __str__(self): return self.namespace # EOF
def pkt_recv_join(self, event): """ Received a recv_join packet. This happens when a user joins a channel in which the client is also present. This method simply stores information about the user that just joined. """ self.channel[event.arguments['ns']].register_user( Packet(event.arguments['info']), event.arguments['user'])
def process_property(self, data): if data['p'] == 'title': self.title.content = data['value'] self.title.by = data['by'] self.title.ts = data['ts'] if data['p'] == 'topic': self.topic.content = data['value'] self.topic.by = data['by'] self.topic.ts = data['ts'] if data['p'] == 'privclasses': self.pc = Packet(data['value'], ':').args self.pc_order = sorted(self.pc.keys(), key=int) self.pc_order.reverse() if data['p'] == 'members': member = Packet(data['value']) while member.cmd != None and len(member.args) > 0: self.register_user(member) member = Packet(member.body)
def test_construct_packet(self): """ Test constructing packets using the packet object. """ packet = Packet() packet.cmd = 'command' packet.param = 'parameter' packet.args['argument'] = 'value' packet.body = 'body' raw = packet.compile() self.failIf(raw != 'command parameter\nargument=value\n\nbody', 'Packet object failed to correctly construct the raw packet')
def pkt_kicked(self, event): """ Received a kicked packet. This happens when the client is kicked from a channel. Here we automatically rejoin the channel if we are permitted to do so. """ del self.channel[event.arguments['ns']] if self.flag.disconnecting or self.flag.quitting: return if 'r' in event.arguments: if 'autokicked' in event.arguments['r'].lower( ) or 'not privileged' in event.arguments['r'].lower(): if len(self.channel) > 0: return self.handle_pkt(Packet('disconnect\ne=no joined channels\n\n'), time.time()) return if self.flag.autorejoin: self.join(event.arguments['ns'])
def pkt_join(self, event): """ Received a join packet. This is sent by the server when the client tries to join a channel on the server. If the join was successful, a :py:class:`Channel object <dAmnViper.data.Channel>` is created for the channel and stored in the ``channel`` attribute of the client. If the join failed, the client disconnects if there are no other joined channels. (``naive``) """ if event.arguments['e'] == 'ok': ns = event.arguments['ns'] self.channel[ns] = Channel(ns, self.deform_ns(ns)) return if len(self.channel) > 0: return self.handle_pkt(Packet('disconnect\ne=no joined channels\n\n'), time.time())
class Channel(object): """ Objects representing dAmn channels. Information about the channels are stored in here. The different attributes of the object are as follows: * ``title`` - This is an instance of the class ``Channel.header``, and stores information about the title of the channel. The object has the attributes ``content``, ``by`` and ``ts``. These store the content of the title, the person who set the title, and the timestamp from when they set it, respectively. * ``topic`` - Similar to the ``title`` attribute, but it stores information about the channel's topic, as opposed to the channel's title. * ``pc`` - Stores information about the channel's privclasses. * ``pc_order`` - A list storing the the privclass names in order of hierarchy. This is to allow applications to display information more easily if needed. * ``member`` - A dictionary storing information about each user currently in the channel. * ``namespace`` - The channel's full namespace. This is usually a string in the form ``chat:channel_name``. This can differ depending on the type of channel the object represents. * ``shorthand`` - The shorthand form of the channel ``namespace``. This is usually a string in the format ``#channel_name`` if the namespace is of the format ``chat:channel_name``. This can differ depending on the type of channel the object represents. * ``type`` - A string in for format ``<dAmn channel 'namespace'>`` where ``namespace`` is the same as the object's ``namespace`` attribute. Calling ``str(channel)``, where ``channel`` is an instance of the ``Channel`` class, returns the ``namespace`` attribute. As an example, here is what some of the attributes would look like for the **#Botdom** channel when the object is created:: >>> channel = Channel('chat:Botdom', '#Botdom') >>> channel.namespace 'chat:Botdom' >>> channel.shorthand '#Botdom' >>> str(channel) 'chat:Botdom' The other attributes would be empty objects of their respective types until the appropriate data is received from the server. """ class Header: def __init__(self): self.content = '' self.by = '' self.ts = 0.0 def __init__(self, namespace, shorthand): """Set up all our variables.""" self.title = Channel.Header() self.topic = Channel.Header() self.pc = {} self.pc_order = [] self.member = {} self.namespace = namespace self.shorthand = shorthand self.type = '<dAmn channel \''+self.namespace+'\'>' def process_property(self, data): """ Called when receive a property packet for the channel. This method makes sure that the data is stored in the right places in the object. """ if data.arguments['p'] == 'title': self.title.content = data.arguments['value'] self.title.by = data.arguments['by'] self.title.ts = data.arguments['ts'] if data.arguments['p'] == 'topic': self.topic.content = data.arguments['value'] self.topic.by = data.arguments['by'] self.topic.ts = data.arguments['ts'] if data.arguments['p'] == 'privclasses': self.pc = Packet(data.arguments['value'], ':').args self.pc_order = sorted(self.pc.keys(), key=int) self.pc_order.reverse() if data.arguments['p'] == 'members': member = Packet(data.arguments['value']) while member.cmd != None and len(member.args) > 0: self.register_user(member) member = Packet(member.body) def register_user(self, info, user = None): """ Called when a user joins the channel. Simply store their information in the ``member`` dictionary. """ user = user if user != None else info.param if user in self.member: self.member[user]['con']+= 1 else: self.member[user] = info.args self.member[user]['con'] = 1 def __str__(self): return self.namespace