"""Handle Client-to-Client protocol per the `best availablespec <http://www.irchelp.org/irchelp/rfc/ctcpspec.html>`_."""importreLOW_LEVEL_QUOTE='\x10'LEVEL_QUOTE="\\"DELIMITER='\x01'low_level_mapping={"0":'\x00',"n":"\n","r":"\r",LEVEL_QUOTE:LEVEL_QUOTE}low_level_regexp=re.compile(LOW_LEVEL_QUOTE+"(.)")def_low_level_replace(match_obj):ch=match_obj.group(1)# If low_level_mapping doesn't have the character as key, we# should just return the character.returnlow_level_mapping.get(ch,ch)
[docs]defdequote(message):""" Dequote a message according to CTCP specifications. The function returns a list where each element can be either a string (normal message) or a tuple of one or two strings (tagged messages). If a tuple has only one element (ie is a singleton), that element is the tag; otherwise the tuple has two elements: the tag and the data. Arguments: message -- The message to be decoded. """# Perform the substitutionmessage=low_level_regexp.sub(_low_level_replace,message)ifDELIMITERnotinmessage:return[message]# Split it into parts.chunks=message.split(DELIMITER)returnlist(_gen_messages(chunks))
def_gen_messages(chunks):i=0whilei<len(chunks)-1:# Add message if it's non-empty.iflen(chunks[i])>0:yieldchunks[i]ifi<len(chunks)-2:# Aye! CTCP tagged data ahead!yieldtuple(chunks[i+1].split(" ",1))i=i+2iflen(chunks)%2==0:# Hey, a lonely _CTCP_DELIMITER at the end! This means# that the last chunk, including the delimiter, is a# normal message! (This is according to the CTCP# specification.)yieldDELIMITER+chunks[-1]