Kode sumber untuk ehforwarderbot.chat

# coding=utf-8

import copy
import warnings
from abc import ABC, abstractmethod
from enum import Enum
from typing import Dict, Any, Optional, TypeVar, MutableSequence

from .channel import SlaveChannel
from .coordinator import translator
from .middleware import Middleware
from .types import ModuleID, ChatID

__all__ = ['BaseChat',
           'Chat', 'PrivateChat', 'SystemChat', 'GroupChat',
           'ChatMember', 'SelfChatMember', 'SystemChatMember',
           'ChatNotificationState']


[docs]class ChatNotificationState(Enum): """ Indicates the notifications settings of a chat in its slave channel or middleware. If an exact match is not available, choose the most similar one. """ NONE = 0 """No notification is sent to slave IM channel at all.""" MENTIONS = 1 """Notifications are sent only when the User is mentioned in the message, in the form of @-references or quote-reply (message target). """ ALL = -1 """All messages in the chat triggers notifications."""
[docs]class BaseChat(ABC): """ Base chat class, this is an abstract class sharing properties among all chats and members. No instance can be created directly from this class. Note: ``BaseChat`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. Attributes: module_id (:obj:`.ModuleID` (str)): Unique ID of the module. channel_emoji (str): Emoji of the channel, empty string if the chat is from a middleware. module_name (:obj:`.ModuleID` (str)): Name of the module. name (str): Name of the chat. alias (Optional[str]): Alternative name of the chat, usually set by user. uid (:obj:`.ChatID` (str)): Unique ID of the chat. This MUST be unique within the channel. description (str): A text description of the chat, usually known as “bio”, “description”, “purpose”, or “topic” of the chat. vendor_specific (Dict[str, Any]): Any vendor specific attributes. """ # Allow mypy to recognize subclass output for `return self` methods. _BaseChatSelf = TypeVar('_BaseChatSelf', bound='BaseChat', covariant=True)
[docs] def __init__(self, *, channel: Optional[SlaveChannel] = None, middleware: Optional[Middleware] = None, module_name: str = "", channel_emoji: str = "", module_id: ModuleID = ModuleID(""), name: str = "", alias: Optional[str] = None, uid: ChatID = ChatID(""), id: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = ""): """ Args: channel (Optional[:obj:`.SlaveChannel`]): Provide the channel object to fill :attr:`module_name`, :attr:`channel_emoji`, and :attr:`module_id` automatically. middleware (Optional[:obj:`.Middleware`]): Provide the middleware object to fill :attr:`module_name`, and :attr:`module_id` automatically. module_id: Unique ID of the module. channel_emoji (str): Emoji of the channel, empty string if the chat is from a middleware. module_name (str): Name of the module. name (str): Name of the chat. alias (Optional[str]): Alternative name of the chat, usually set by user. uid: Unique ID of the chat. This MUST be unique within the channel. description (str): A text description of the chat, usually known as “bio”, “description”, “purpose”, or “topic” of the chat. vendor_specific (Dict[str, Any]): Any vendor specific attributes. """ if channel: if isinstance(channel, SlaveChannel): self.module_name = channel.channel_name self.channel_emoji = channel.channel_emoji self.module_id = channel.channel_id else: raise ValueError( "channel value should be an SlaveChannel object") elif isinstance(middleware, Middleware): self.module_id = middleware.middleware_id self.module_name = middleware.middleware_name self.channel_emoji = "" else: self.module_name = module_name self.channel_emoji = channel_emoji self.module_id = module_id self.name: str = name self.alias: Optional[str] = alias if id: warnings.warn("`id` argument is deprecated, use `uid` instead.", DeprecationWarning) self.uid: ChatID = id else: self.uid = uid self.vendor_specific: Dict[str, Any] = vendor_specific if vendor_specific is not None else dict() self.description: str = description
@property def id(self) -> ChatID: warnings.warn("`id` property of a chat/member is deprecated, use `uid` instead.", DeprecationWarning) return self.uid @id.setter def id(self, val: ChatID): warnings.warn("`id` property of a chat/member is deprecated, use `uid` instead.", DeprecationWarning) self.uid = val @property def display_name(self) -> str: """Shortcut property, equivalent to ``alias or name``""" return self.alias or self.name @property def long_name(self) -> str: """ Shortcut property, if alias exists, this will provide the alias with name in parenthesis. Otherwise, this will return the name """ if self.alias: return "{0} ({1})".format(self.alias, self.name) else: return self.name
[docs] def copy(self: _BaseChatSelf) -> _BaseChatSelf: """Return a shallow copy of the object.""" return copy.copy(self)
[docs] @abstractmethod def verify(self): """ Verify the completeness of the data. Raises: AssertionError: When this chat is invalid. """ assert self.module_id, "Module ID should not be empty" assert isinstance(self.module_id, str), \ f"Module ID should be a string, {self.module_id!r} found." assert isinstance(self.module_name, str), \ f"Module Name should be a string, {self.module_name!r} found." assert isinstance(self.channel_emoji, str), \ f"Channel emoji should be a string, {self.channel_emoji!r} found." assert self.uid, "Entity ID should not be empty" assert isinstance(self.uid, str), \ f"Entity id should be a string, {self.uid!r} found." assert isinstance(self.name, str), \ f"Entity name should be a string, {self.name!r} found." assert isinstance(self.alias, (str, type(None))), \ f"Entity alias should be either a string or None, {self.name!r} found." assert isinstance(self.description, str), \ f"Entity description should be a string, {self.description!r} found."
def __eq__(self, other): return self.module_id == other.module_id and self.uid == other.uid def __str__(self): return f"<{self.__class__.__name__}: {self.long_name} ({self.uid}) @ {self.module_name}>" def __repr__(self): return ( f"{self.__class__.__name__}(" f"module_name={self.module_name!r}, " f"module_id={self.module_id!r}, " f"channel_emoji={self.channel_emoji!r}, " f"name={self.name!r}, " f"alias={self.alias!r}, " f"uid={self.uid!r}, " f"vendor_specific={self.vendor_specific!r}, " f"description={self.description!r}" f")" )
[docs]class ChatMember(BaseChat): """Member of a chat. Usually indicates a member in a group, or the other participant in a private chat. Chat bots created by the users of the IM platform is also considered as a plain :class:`.ChatMember`. To represent the User Themself, use :class:`.SelfChatMember`. To represent a chat member that is a part of the system, the slave channel, or a middleware, use :class:`.SystemChatMember`. :class:`.ChatMember`\\ s MUST be created with reference of the chat it belongs to. Different objects MUST be created even when the same person appears in different groups or in a private chat. :class:`.ChatMember`\\ s are RECOMMENDED to be created using :meth:`.Chat.add_member` method. Note: ``ChatMember`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. """
[docs] def __init__(self, chat: 'Chat', *, name: str = "", alias: Optional[str] = None, uid: ChatID = ChatID(""), id: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", middleware: Optional[Middleware] = None): """ Args: chat (:class:`~.chat.Chat`): Chat associated with this member. Keyword Args: name (str): Name of the member. alias (Optional[str]): Alternative name of the member, usually set by user. uid (:obj:`.ChatID` (str)): Unique ID of the member. This MUST be unique within the channel. This ID can be the same with a private chat of the same person. description (str): A text description of the member, usually known as “bio”, “description”, “summary” or “introduction” of the member. middleware (:class:`.Middleware`): Initialize this chat as a part of a middleware. """ if middleware: super().__init__(module_name=middleware.middleware_name, channel_emoji="", module_id=middleware.middleware_id, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description) else: super().__init__(module_name=chat.module_name, channel_emoji=chat.channel_emoji, module_id=chat.module_id, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description) self.chat: 'Chat' = chat
[docs] def verify(self): super().verify() assert isinstance(self.chat, Chat)
def __eq__(self, other): return ( isinstance(other, ChatMember) and other.uid == self.uid and other.chat == self.chat ) def __str__(self): return f"<{self.__class__.__name__}: {self.long_name} ({self.uid}) @ {self.chat}>" def __repr__(self): return ( f"{self.__class__.__name__}(" f"chat={self.chat}, " f"name={self.name!r}, " f"alias={self.alias!r}, " f"uid={self.uid!r}, " f"vendor_specific={self.vendor_specific!r}, " f"description={self.description!r}" f")" )
[docs]class SelfChatMember(ChatMember): """The User Themself as member of a chat. :class:`.SelfChatMember`\\ s are RECOMMENDED to be created together with a chat object by setting ``with_self`` value to ``True``. The created object is accessible at :attr:`.Chat.self`. The default ID of a :class:`.SelfChatMember` object is :attr:`.SelfChatMember.SELF_ID`, and the default name is a translated version of the word “You”. You are RECOMMENDED to change the ID of this object if provided by your IM platform, and you MAY change the name or alias of this object depending on your needs. Note: ``SelfChatMember`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. Attributes: SELF_ID: The default ID of a :class:`.SelfChatMember`. """ SELF_ID = ChatID("__self__")
[docs] def __init__(self, chat: 'Chat', *, name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", middleware: Optional[Middleware] = None): """ Args: chat (:class:`~.chat.Chat`): Chat associated with this member. Keyword Args: name (str): Name of the member. alias (Optional[str]): Alternative name of the member, usually set by user. uid (:obj:`.ChatID` (str)): Unique ID of the member. This MUST be unique within the channel. This ID can be the same with a private chat of the same person. description (str): A text description of the member, usually known as “bio”, “description”, “summary” or “introduction” of the member. middleware (:class:`.Middleware`): Initialize this chat as a part of a middleware. """ name = name or translator.gettext("You") uid = uid or id or self.SELF_ID super().__init__(chat, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description, middleware=middleware)
[docs]class SystemChatMember(ChatMember): """A system account/prompt as member of a chat. Use this chat to send messages that is not from any specific member. Middlewares are RECOMMENDED to use this member type to communicate with the User in an existing chat. Chat bots created by the users of the IM platform SHOULD NOT be created as a :class:`.SystemChatMember`, but a plain :class:`.ChatMember` instead. :class:`.SystemChatMember`\\ s are RECOMMENDED to be created using :meth:`.Chat.add_system_member` or :meth:`.Chat.make_system_member` method. Note: ``SystemChatMember`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. Attributes: SYSTEM_ID: The default ID of a :class:`.SystemChatMember`. """ SYSTEM_ID = ChatID("__system__")
[docs] def __init__(self, chat: 'Chat', *, name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", middleware: Optional[Middleware] = None): """ Args: chat (:class:`~.chat.Chat`): Chat associated with this member. Keyword Args: name (str): Name of the member. alias (Optional[str]): Alternative name of the member, usually set by user. uid (:obj:`.ChatID` (str)): Unique ID of the member. This MUST be unique within the channel. This ID can be the same with a private chat of the same person. description (str): A text description of the member, usually known as “bio”, “description”, “summary” or “introduction” of the member. middleware (:class:`.Middleware`): Initialize this chat as a part of a middleware. """ name = name or translator.gettext("System") uid = uid or id or self.SYSTEM_ID super().__init__(chat, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description, middleware=middleware)
[docs]class Chat(BaseChat, ABC): # lgtm [py/missing-equals] """ A chat object, indicates a user, a group, or a system chat. This class is abstract. No instance can be created directly from this class. If your IM platform is providing an ID of the User Themself, and it is using this ID to indicate the author of a message, you SHOULD update :attr:`Chat.self.uid <.BaseChat.uid>` accordingly. .. code-block:: python >>> channel.my_chat_id "david_divad" >>> chat = Chat(channel=channel, name="Alice", uid=ChatID("alice123")) >>> chat.self.uid = channel.my_chat_id By doing so, you can get the author in one step: .. code-block:: python author = chat.get_member(author_id) ... instead of using a condition check: .. code-block:: python if author_id == channel.my_chat_id: author = chat.self else: author = chat.get_member(author_id) Note: ``Chat`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. Attributes: module_id (:obj:`.ModuleID` (str)): Unique ID of the module. channel_emoji (str): Emoji of the channel, empty string if the chat is from a middleware. module_name (str): Name of the module. name (str): Name of the chat. alias (Optional[str]): Alternative name of the chat, usually set by user. uid (:obj:`~.ChatID` (str)): Unique ID of the chat. This MUST be unique within the channel. description (str): A text description of the chat, usually known as “bio”, “description”, “purpose”, or “topic” of the chat. notification (:class:`ChatNotificationState`): Indicate the notification settings of the chat in its slave channel (or middleware), defaulted to :const:`~.ChatNotificationState.ALL`. members (list of :obj:`.ChatMember`): Provide a list of members in the chat. Defaulted to an empty ``list``. You can extend this object and implement a ``@property`` method set for loading members on demand. Note that this list may include members created by middlewares when the object is a part of a message, and these members MAY not appear when trying to retrieve from the slave channel directly. These members would have a different :attr:`~.BaseChat.module_id` specified from the chat. vendor_specific (Dict[str, Any]): Any vendor specific attributes. self (Optional[:obj:`SelfChatMember`]): the User as a member of the chat (if available). """ self: Optional[SelfChatMember] """The user as a member of the chat (if available)."""
[docs] def __init__(self, *, channel: Optional[SlaveChannel] = None, middleware: Optional[Middleware] = None, module_name: str = "", channel_emoji: str = "", module_id: ModuleID = ModuleID(""), name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", members: MutableSequence[ChatMember] = None, notification: ChatNotificationState = ChatNotificationState.ALL, with_self: bool = True): """ Keyword Args: module_id (str): Unique ID of the module. channel_emoji (str): Emoji of the channel, empty string if the chat is from a middleware. module_name: Name of the module. name (str): Name of the chat. alias (Optional[str]): Alternative name of the chat, usually set by user. id: Unique ID of the chat. This MUST be unique within the channel. description (str): A text description of the chat, usually known as “bio”, “description”, “purpose”, or “topic” of the chat. notification (ChatNotificationState): Indicate the notification settings of the chat in its slave channel (or middleware), defaulted to ``ALL``. members (MutableSequence[:obj:`.ChatMember`]): Provide a list of members of the chat. Defaulted to an empty :obj:`list`. vendor_specific (Dict[str, Any]): Any vendor specific attributes. with_self (bool): Initialize the chat with the User Themself as a member. """ super().__init__(channel=channel, middleware=middleware, module_name=module_name, channel_emoji=channel_emoji, module_id=module_id, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description) self.members: MutableSequence[ChatMember] = members if members is not None else [] if with_self: self.self = self.add_self() else: self.self = None self.notification: ChatNotificationState = notification
@property def has_self(self) -> bool: """Indicate if this chat has yourself.""" return any(isinstance(member, SelfChatMember) for member in self.members)
[docs] def add_self(self) -> SelfChatMember: """Add self to the list of members. Raises: AssertionError: When there is already a self in the list of members. """ if getattr(self, 'self', None) and isinstance(self.self, SelfChatMember): return self.self assert not any(isinstance(i, SelfChatMember) for i in self.members) s = SelfChatMember(self) self.members.append(s) return s
[docs] def add_member(self, name: str, uid: ChatID, alias: Optional[str] = None, id: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", middleware: Optional[Middleware] = None) -> ChatMember: """Add a member to the chat. Tip: This method does not check for duplicates. Only add members with this method if you are sure that they are not added yet. To check if the member is already added before adding, you can do something like this: .. code-block:: python with contextlib.suppress(KeyError): return chat.get_member(uid) return chat.add_member(name, uid, alias=..., vendor_specific=...) Args: name (str): Name of the member. uid: ID of the member. Keyword Args: alias (Optional[str]): Alias of the member. vendor_specific (Dict[str, Any]): Any vendor specific attributes. description (str): A text description of the chat, usually known as “bio”, “description”, “purpose”, or “topic” of the chat. middleware (Optional[:class:`.Middleware`]): Initialize this chat as a part of a middleware. """ if id: warnings.warn("`id` argument is deprecated, use `uid` instead.", DeprecationWarning) uid = uid or id member = ChatMember(self, name=name, alias=alias, uid=uid, vendor_specific=vendor_specific, description=description, middleware=middleware) self.members.append(member) return member
[docs] def make_system_member(self, name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", middleware: Optional[Middleware] = None) -> SystemChatMember: """Make a system member for this chat. Useful for slave channels and middlewares to create an author of a message from a system member when the “system” member is NOT intended to become a member of the chat. Keyword Args: name (str): Name of the member. uid: ID of the member. alias (Optional[str]): Alias of the member. vendor_specific (Dict[str, Any]): Any vendor specific attributes. description (str): A text description of the chat, usually known as “bio”, “description”, “purpose”, or “topic” of the chat. middleware (Optional[:class:`.Middleware`]): Initialize this chat as a part of a middleware. """ return SystemChatMember(self, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description, middleware=middleware)
[docs] def add_system_member(self, name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", middleware: Optional[Middleware] = None) -> SystemChatMember: """Add a system member to the chat. Useful for slave channels and middlewares to create an author of a message from a system member when the “system” member is intended to become a member of the chat. Tip: This method does not check for duplicates. Only add members with this method if you are sure that they are not added yet. Keyword Args: name (str): Name of the member. uid: ID of the member. alias (Optional[str]): Alias of the member. vendor_specific (Dict[str, Any]): Any vendor specific attributes. description (str): A text description of the chat, usually known as “bio”, “description”, “purpose”, or “topic” of the chat. middleware (Optional[:class:`.Middleware`]): Initialize this chat as a part of a middleware. """ member = self.make_system_member(name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description, middleware=middleware) self.members.append(member) return member
[docs] def get_member(self, member_id: ChatID) -> ChatMember: """Find a member of chat by its ID. Args: member_id: ID of the chat member. Returns: the chat member. Raises: KeyError: when the ID provided is not found. """ for i in self.members: if i.uid == member_id: return i raise KeyError
def __str__(self): return f"<{self.__class__.__name__}: {self.long_name} ({self.uid}) @ {self.channel_emoji}{self.module_name} ({self.module_id})>" def __repr__(self): return ( f"{self.__class__.__name__}(" f"module_name={self.module_name!r}, " f"module_id={self.module_id!r}, " f"channel_emoji={self.channel_emoji!r}, " f"name={self.name!r}, " f"alias={self.alias!r}, " f"uid={self.uid!r}, " f"vendor_specific={self.vendor_specific!r}, " f"members={self.members!r}, " f"notification={self.notification!r}, " f"description={self.description!r}" f")" )
[docs]class PrivateChat(Chat): """A private chat, where usually only the User Themself and the other participant are in the chat. Chat bots SHOULD also be categorized under this type. There SHOULD only be at most one non-system member of the chat apart from the User Themself, otherwise it might lead to unintended behavior. This object is by default initialized with the other participant as its member. If the ``with_self`` argument is ``True`` (which is the default setting), the User Themself would also be initialized as a member of the chat. Args: other: the other participant of the chat as a member Note: ``PrivateChat`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. """ other: ChatMember def __init__(self, *, channel: Optional[SlaveChannel] = None, middleware: Optional[Middleware] = None, module_name: str = "", channel_emoji: str = "", module_id: ModuleID = ModuleID(""), name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", notification: ChatNotificationState = ChatNotificationState.ALL, with_self: bool = True, other_is_self: bool = False): super().__init__(channel=channel, middleware=middleware, module_name=module_name, channel_emoji=channel_emoji, module_id=module_id, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description, notification=notification, with_self=with_self) if other_is_self and with_self: assert self.self is not None self.other = self.self else: self.other = self.add_member(name=name, alias=alias, uid=uid, vendor_specific=vendor_specific, description=description) self.verify()
[docs] def verify(self): super().verify() assert all(isinstance(member, ChatMember) for member in self.members), \ f"Some members of this chat is not a valid one: {self.members!r}"
[docs]class SystemChat(Chat): """A system chat, where usually only the User Themself and the other participant (system chat member) are in the chat. This object is used to represent system chat where the other participant is neither a user nor a chat bot of the remote IM. Middlewares are RECOMMENDED to create chats with this type when they want to send messages in this type. This object is by default initialized with the system participant as its member. If the ``with_self`` argument is ``True`` (which is the default setting), the User Themself would also be initialized as a member of the chat. Args: other: the other participant of the chat as a member Note: ``SystemChat`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. """ other: SystemChatMember def __init__(self, *, channel: Optional[SlaveChannel] = None, middleware: Optional[Middleware] = None, module_name: str = "", channel_emoji: str = "", module_id: ModuleID = ModuleID(""), name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", notification: ChatNotificationState = ChatNotificationState.ALL, with_self: bool = True): super().__init__(channel=channel, middleware=middleware, module_name=module_name, channel_emoji=channel_emoji, module_id=module_id, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description, notification=notification, with_self=with_self) self.other = self.add_system_member(name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description) self.verify()
[docs] def verify(self): super().verify() assert all(isinstance(member, ChatMember) for member in self.members)
[docs]class GroupChat(Chat): """A group chat, where there are usually multiple members present. Members can be added with the :meth:`.add_member` method. If the ``with_self`` argument is ``True`` (which is the default setting), the User Themself would also be initialized as a member of the chat. Examples: >>> group = GroupChat(channel=slave_channel, name="Wonderland", uid=ChatID("wonderland001")) >>> group.add_member(name="Alice", uid=ChatID("alice")) ChatMember(chat=<GroupChat: Wonderland (wonderland001) @ Example slave channel>, name='Alice', alias=None, uid='alice', vendor_specific={}, description='') >>> group.add_member(name="bob", alias="Bob James", uid=ChatID("bob")) ChatMember(chat=<GroupChat: Wonderland (wonderland001) @ Example slave channel>, name='bob', alias='Bob James', uid='bob', vendor_specific={}, description='') >>> from pprint import pprint >>> pprint(group.members) [SelfChatMember(chat=<GroupChat: Wonderland (wonderland001) @ Example slave channel>, name='You', alias=None, uid='__self__', vendor_specific={}, description=''), ChatMember(chat=<GroupChat: Wonderland (wonderland001) @ Example slave channel>, name='Alice', alias=None, uid='alice', vendor_specific={}, description=''), ChatMember(chat=<GroupChat: Wonderland (wonderland001) @ Example slave channel>, name='bob', alias='Bob James', uid='bob', vendor_specific={}, description='')] Note: ``GroupChat`` objects are picklable, thus it is RECOMMENDED to keep any object of its subclass also picklable. """ def __init__(self, *, channel: Optional[SlaveChannel] = None, middleware: Optional[Middleware] = None, module_name: str = "", channel_emoji: str = "", module_id: ModuleID = ModuleID(""), name: str = "", alias: Optional[str] = None, id: ChatID = ChatID(""), uid: ChatID = ChatID(""), vendor_specific: Dict[str, Any] = None, description: str = "", notification: ChatNotificationState = ChatNotificationState.ALL, with_self: bool = True): super().__init__(channel=channel, middleware=middleware, module_name=module_name, channel_emoji=channel_emoji, module_id=module_id, name=name, alias=alias, id=id, uid=uid, vendor_specific=vendor_specific, description=description, notification=notification, with_self=with_self) self.verify()
[docs] def verify(self): super().verify() assert all(isinstance(member, ChatMember) for member in self.members)