# Copyright (c) 2018 Tulir Asokan
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from typing import Any, Dict
import json
from attr import dataclass
import attr
from .....api import JSON
from ..primitive import RoomID, UserID, EventID
from ..util import SerializableEnum, Serializable, Obj
[docs]class EventType(Serializable):
"""An event type."""
by_event_type: Dict[str, 'EventType'] = {}
class Class(SerializableEnum):
UNKNOWN = "unknown"
STATE = "state"
MESSAGE = "message"
ACCOUNT_DATA = "account_data"
EPHEMERAL = "ephemeral"
ROOM_CANONICAL_ALIAS: 'EventType'
ROOM_ALIASES: 'EventType'
ROOM_CREATE: 'EventType'
ROOM_JOIN_RULES: 'EventType'
ROOM_MEMBER: 'EventType'
ROOM_POWER_LEVELS: 'EventType'
ROOM_NAME: 'EventType'
ROOM_TOPIC: 'EventType'
ROOM_AVATAR: 'EventType'
ROOM_PINNED_EVENTS: 'EventType'
ROOM_TOMBSTONE: 'EventType'
ROOM_REDACTION: 'EventType'
ROOM_MESSAGE: 'EventType'
ROOM_ENCRYPTED: 'EventType'
STICKER: 'EventType'
REACTION: 'EventType'
RECEIPT: 'EventType'
TYPING: 'EventType'
PRESENCE: 'EventType'
DIRECT: 'EventType'
PUSH_RULES: 'EventType'
TAG: 'EventType'
IGNORED_USER_LIST: 'EventType'
ALL: 'EventType'
def __init__(self, t: str, t_class: Class = Class.UNKNOWN):
self.t = t
self.t_class = t_class
self.by_event_type[t] = self
[docs] def serialize(self) -> JSON:
return self.t
[docs] @classmethod
def deserialize(cls, raw: JSON) -> Any:
return cls.find(raw)
[docs] @classmethod
def find(cls, t: str) -> 'EventType':
try:
return cls.by_event_type[t]
except KeyError:
return EventType(t)
[docs] def json(self) -> str:
return json.dumps(self.serialize())
[docs] @classmethod
def parse_json(cls, data: str) -> 'EventType':
return cls.deserialize(json.loads(data))
def __str__(self):
return self.t
def __repr__(self):
return f"EventType(\"{self.t}\", EventType.Class.{self.t_class.name})"
@property
def is_message(self) -> bool:
"""Whether or not the event is a message event."""
return self.t_class == EventType.Class.MESSAGE
@property
def is_state(self) -> bool:
"""Whether or not the event is a state event."""
return self.t_class == EventType.Class.STATE
@property
def is_ephemeral(self) -> bool:
"""Whether or not the event is ephemeral."""
return self.t_class == EventType.Class.EPHEMERAL
@property
def is_account_data(self) -> bool:
"""Whether or not the event is an account data event."""
return self.t_class == EventType.Class.ACCOUNT_DATA
_standard_types = {
EventType.Class.STATE: {
"m.room.aliases": "ROOM_ALIASES",
"m.room.canonical_alias": "ROOM_CANONICAL_ALIAS",
"m.room.create": "ROOM_CREATE",
"m.room.join_rules": "ROOM_JOIN_RULES",
"m.room.member": "ROOM_MEMBER",
"m.room.power_levels": "ROOM_POWER_LEVELS",
"m.room.name": "ROOM_NAME",
"m.room.topic": "ROOM_TOPIC",
"m.room.avatar": "ROOM_AVATAR",
"m.room.pinned_events": "ROOM_PINNED_EVENTS",
"m.room.tombstone": "ROOM_TOMBSTONE",
},
EventType.Class.MESSAGE: {
"m.room.redaction": "ROOM_REDACTION",
"m.room.message": "ROOM_MESSAGE",
"m.room.encrypted": "ROOM_ENCRYPTED",
"m.sticker": "STICKER",
"m.reaction": "REACTION",
},
EventType.Class.EPHEMERAL: {
"m.receipt": "RECEIPT",
"m.typing": "TYPING",
"m.presence": "PRESENCE",
},
EventType.Class.ACCOUNT_DATA: {
"m.direct": "DIRECT",
"m.push_rules": "PUSH_RULES",
"m.tag": "TAG",
"m.ignored_user_list": "IGNORED_USER_LIST",
},
}
for _t_class, _types in _standard_types.items():
for _t, _name in _types.items():
_event_type = EventType(_t, _t_class)
EventType.by_event_type[_t] = _event_type
setattr(EventType, _name, _event_type)
EventType.ALL = EventType("__ALL__")
EventType.by_event_type["__ALL__"] = EventType.ALL
[docs]@dataclass
class BaseUnsigned:
"""Base unsigned information."""
age: int = None
[docs]@dataclass
class BaseEvent:
"""Base event class. The only things an event **must** have are content and event type."""
content: Obj
type: EventType
[docs]@dataclass
class BaseRoomEvent(BaseEvent):
"""Base room event class. Room events must have a room ID, event ID, sender and timestamp in
addition to the content and type in the base event."""
room_id: RoomID
event_id: EventID
sender: UserID
timestamp: int = attr.ib(metadata={"json": "origin_server_ts"})