summaryrefslogtreecommitdiff
path: root/asciifarm/common/messages.py
blob: 059094e6e8469b42f5d5c83c8368592ab52dca36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

import re
import unicodedata

class InvalidMessageError(Exception):
    errType = "invalidmessage"
    description = ""
    
    def __init__(self, description="", errType=None):
        self.description = description
        if errType is not None:
            self.errType = errType

class InvalidNameError(InvalidMessageError):
    errType = "invalidname"

class Message:
    
    @classmethod
    def msgType(cls):
        return cls.typename
    
    def to_json(self):
        raise NotImplementedError
    
    @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"
    nameRegex = re.compile("(~|\w)\w*")
    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")
        for char in name if name[0] != "~" else name[1:]:
            category = unicodedata.category(char)
            assert category in self.categories, InvalidNameError("all name caracters must be in these unicode categories: " + "|".join(self.categories) + " (except the tilde in a tildename)")
            
        #assert (name.rfind("~") < 1), InvalidNameError("tilde character may only occur at start of name")
        #assert (self.nameRegex.match(name) is not None), InvalidNameError("name must match the following regex: {}".format(self.nameRegex.pattern))
        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



messages = {message.msgType(): message for message in [
    NameMessage,
    InputMessage,
    ChatMessage
]}