2019-09-26 16:30:14 +00:00
import re
import unicodedata
2019-09-26 18:19:26 +00:00
import json
2019-09-26 16:30:14 +00:00
class InvalidMessageError ( Exception ) :
errType = " invalidmessage "
description = " "
def __init__ ( self , description = " " , errType = None ) :
self . description = description
if errType is not None :
self . errType = errType
2019-09-26 18:19:26 +00:00
def toMessage ( self ) :
2019-09-26 20:04:50 +00:00
return ErrorMessage ( self . errType , self . description )
2019-09-26 16:30:14 +00:00
class InvalidNameError ( InvalidMessageError ) :
errType = " invalidname "
class Message :
@classmethod
def msgType ( cls ) :
return cls . typename
def to_json ( self ) :
raise NotImplementedError
2019-09-26 18:19:26 +00:00
def to_json_bytes ( self ) :
return bytes ( json . dumps ( self . to_json ( ) ) , " utf-8 " )
2019-09-26 16:30:14 +00:00
@classmethod
def from_json ( cls , jsonobj ) :
raise NotImplementedError
class ClientToServerMessage ( Message ) :
def body ( self ) :
raise NotImplementedError
def to_json ( self ) :
return [ self . typename , self . body ( ) ]
@classmethod
def from_json ( cls , jsonlist ) :
assert len ( jsonlist ) == 2 , InvalidMessageError
typename , body = jsonlist
assert typename == cls . msgType ( ) , InvalidMessageError
return cls ( body )
class NameMessage ( ClientToServerMessage ) :
typename = " name "
categories = { " Lu " , " Ll " , " Lt " , " Lm " , " Lo " , " Nd " , " Nl " , " No " , " Pc " }
def __init__ ( self , name ) :
assert isinstance ( name , str ) , InvalidNameError ( " name must be a string " )
assert ( len ( name ) > 0 ) , InvalidNameError ( " name needs at least one character " )
assert ( len ( bytes ( name , " utf-8 " ) ) < = 256 ) , InvalidNameError ( " name may not be longer than 256 utf8 bytes " )
2019-09-27 13:30:27 +00:00
if name [ 0 ] != " ~ " :
for char in name :
category = unicodedata . category ( char )
assert category in self . categories , InvalidNameError ( " all name caracters must be in these unicode categories: " + " | " . join ( self . categories ) + " (except for tildenames) " )
2019-09-26 16:30:14 +00:00
self . name = name
def body ( self ) :
return self . name
class InputMessage ( ClientToServerMessage ) :
typename = " input "
def __init__ ( self , inp ) :
self . inp = inp
def body ( self ) :
return self . inp
class ChatMessage ( ClientToServerMessage ) :
typename = " chat "
def __init__ ( self , text ) :
assert isinstance ( text , str ) , InvalidMessageError ( " chat message must be a string " )
assert text . isprintable ( ) , InvalidMessageError ( " chat messages may only contain printable unicode characters " )
self . text = text
def body ( self ) :
return self . text
2019-09-26 18:19:26 +00:00
class ServerToClientMessage ( Message ) :
msglen = 0
@classmethod
def from_json ( cls , jsonlist ) :
assert len ( jsonlist ) == cls . msglen , InvalidMessageError
assert jsonlist [ 0 ] == cls . msgType ( ) , InvalidMessageError
return cls ( * jsonlist [ 1 : ] )
class MessageMessage ( ServerToClientMessage ) : # this name feels stupid
""" A message to inform the client. This is meant to be read by the user """
typename = " message "
msglen = 3
def __init__ ( self , text , type = " " ) :
self . text = text
self . type = type
def to_json ( self ) :
return [ self . typename , self . text , self . type ]
class WorldMessage ( ServerToClientMessage ) :
""" A message about the world state """
typename = " world "
msglen = 2
def __init__ ( self , updates ) :
assert isinstance ( updates , list ) , InvalidMessageError
self . updates = updates
def to_json ( self ) :
return [ self . typename , self . updates ]
class ErrorMessage ( ServerToClientMessage ) :
typename = " error "
msglen = 3
def __init__ ( self , errType , description = " " ) :
self . errType = errType
self . description = description
def to_json ( self ) :
return [ self . typename , self . errType , self . description ]
2019-09-26 16:30:14 +00:00
messages = { message . msgType ( ) : message for message in [
NameMessage ,
InputMessage ,
2019-09-26 18:19:26 +00:00
ChatMessage ,
WorldMessage ,
ErrorMessage ,
MessageMessage
2019-09-26 16:30:14 +00:00
] }