from typing import TYPE_CHECKING, Optional, Dict, Any, List from abc import ABCMeta, abstractmethod from .models import User, Contact, OIM, Circle, CircleRole, MessageData, TextWithData, Substatus, LoginOption from util.misc import MultiDict if TYPE_CHECKING: from .backend import BackendSession, Chat, ChatSession class BackendEventHandler(metaclass = ABCMeta): __slots__ = ('bs',) bs: 'BackendSession' # Note to subclassers, regarding `__init__`: # `bs` is assigned in `Backend.login`, before `BackendEventHandler.on_open` is called, # because of circular references. # Therefore, your `__init__` should be conspicuously missing an assignment to `bs`. def on_open(self) -> None: pass def on_close(self) -> None: pass def on_maintenance_message(self, *args: Any, **kwargs: Any) -> None: pass def on_client_alert(self, icon_url: Optional[str], url: Optional[str], message: str = '') -> None: pass def on_maintenance_boot(self) -> None: pass @abstractmethod def on_presence_notification( self, ctc: Contact, on_contact_add: bool, old_substatus: Substatus, *, trid: Optional[str] = None, update_status: bool = True, update_info_other: bool = True, send_status_on_bl: bool = False, sess_id: Optional[int] = None, updated_phone_info: Optional[Dict[str, Any]] = None, ) -> None: pass @abstractmethod def on_presence_self_notification(self, old_substatus: Substatus, *, update_status: bool = True, update_info: bool = True) -> None: pass @abstractmethod def on_chat_invite( self, chat: 'Chat', inviter: User, *, circle: bool = False, inviter_id: Optional[str] = None, invite_msg: str = '', ) -> None: pass @abstractmethod def on_declined_chat_invite(self, chat: 'Chat', circle: bool = False) -> None: pass # `user` added me to their FL, and they're now on my RL. @abstractmethod def on_added_me(self, user: User, *, adder_id: Optional[str] = None, message: Optional[TextWithData] = None) -> None: pass @abstractmethod def on_removed_me(self, user: User) -> None: pass # `user` didn't accept contact request @abstractmethod def on_contact_request_denied(self, user_added: User, message: str, *, contact_id: Optional[str] = None) -> None: pass @abstractmethod def on_login_elsewhere(self, option: LoginOption) -> None: pass @abstractmethod def on_oim_sent(self, oim: OIM) -> None: pass @abstractmethod def on_circle_created(self, circle: Circle) -> None: pass @abstractmethod def on_circle_invite_revoked(self, chat_id: str) -> None: pass @abstractmethod def on_accepted_circle_invite(self, circle: Circle) -> None: pass @abstractmethod def on_circle_updated(self, circle: Circle) -> None: pass @abstractmethod def on_left_circle(self, circle: Circle) -> None: pass @abstractmethod def on_circle_role_updated(self, chat_id: str, role: CircleRole) -> None: pass # TODO: Make these non-frontend-specific to allow interop def msn_on_oim_deletion(self, oims_deleted: int) -> None: pass def msn_on_uun_sent( self, sender: User, type: int, data: Optional[bytes], *, pop_id_sender: Optional[str] = None, pop_id: Optional[str] = None, ) -> None: pass def msn_on_notify_ab(self) -> None: pass def msn_on_notify_circle_ab(self, chat_id: str) -> None: pass def ymsg_on_p2p_msg_request(self, sess_id: int, yahoo_data: MultiDict[bytes, bytes]) -> None: pass def ymsg_on_xfer_init(self, sess_id: int, yahoo_data: MultiDict[bytes, bytes]) -> None: pass def ymsg_on_sent_ft_http(self, yahoo_id_sender: str, url_path: str, upload_time: float, message: str) -> None: pass def ymsg_on_upload_file_ft(self, recipient: str, message: str) -> None: pass class ChatEventHandler(metaclass = ABCMeta): __slots__ = ('cs',) cs: 'ChatSession' # Note to subclassers, regarding `__init__`: # `cs` is assigned in `Chat.join`, before `ChatEventHandler.on_open` is called, # because of circular references. # Therefore, your `__init__` should be conspicuously missing an assignment to `cs`. def on_open(self) -> None: pass def on_close(self) -> None: pass @abstractmethod def on_participant_joined(self, cs_other: 'ChatSession', first_pop: bool, initial_join: bool) -> None: pass @abstractmethod def on_participant_left(self, cs_other: 'ChatSession', last_pop: bool) -> None: pass @abstractmethod def on_chat_invite_declined( self, chat: 'Chat', invitee: User, *, invitee_id: Optional[str] = None, message: Optional[str] = None, circle: bool = False, ) -> None: pass @abstractmethod def on_chat_updated(self) -> None: pass @abstractmethod def on_chat_roster_updated(self) -> None: pass @abstractmethod def on_participant_status_updated(self, cs_other: 'ChatSession', first_pop: bool, initial: bool, old_substatus: Substatus) -> None: pass @abstractmethod def on_message(self, data: MessageData) -> None: pass