Source code for defectio.models.server

from __future__ import annotations
from defectio.types.payloads import IconPayload
from defectio.models.permission import ChannelPermission, ServerPermission
from defectio.models.colour import Colour

from typing import Optional
from typing import TYPE_CHECKING

from .mixins import Hashable

if TYPE_CHECKING:
    from ..types.payloads import (
        ServerPayload,
        CategoryPayload,
        SystemMessagePayload,
        RolePayload,
    )
    from ..state import ConnectionState
    from ..types.websocket import ServerUpdate, ServerRoleUpdate
    from .member import Member
    from .channel import MessageableChannel


class Icon:
    __slots__ = (
        "id",
        "tag",
        "size",
        "filename",
        "content_type",
        "metadata",
        "_state",
    )

    def __init__(self, payload: IconPayload, state: ConnectionState) -> None:
        self.id = payload["_id"]
        self._state = state
        self.tag = payload["tag"]
        self.size = payload["size"]
        self.filename = payload["filename"]
        self.content_type = payload["content_type"]
        self.metadata = payload["metadata"]

    @property
    def url(self) -> str:
        return f"{self._state.http.api_info.features.autumn.url}/icons/{self.id}"


class SystemMessages:

    __slots__ = (
        "_user_joined",
        "_user_left",
        "_user_kicked",
        "_user_banned",
        "_state",
        "server",
    )

    def __init__(
        self, data: SystemMessagePayload, server: Server, state: ConnectionState
    ) -> None:
        self._state = state
        self.server = server
        self._user_joined = data.get("user_joined")
        self._user_left = data.get("user_left")
        self._user_kicked = data.get("user_kicked")
        self._user_banned = data.get("user_banned")

    @property
    def user_joined(self) -> Optional[MessageableChannel]:
        return self._state.get_channel(self._user_joined)

    @property
    def user_left(self) -> Optional[MessageableChannel]:
        return self._state.get_channel(self._user_left)

    @property
    def user_kicked(self) -> Optional[MessageableChannel]:
        return self._state.get_channel(self._user_kicked)

    @property
    def user_banned(self) -> Optional[MessageableChannel]:
        return self._state.get_channel(self._user_banned)

    def __repr__(self) -> str:
        return (
            f"<SystemMessages server={self.server.id} "
            f"user_joined={self.user_joined} "
            f"user_left={self.user_left} "
            f"user_kicked={self.user_kicked} "
            f"user_banned={self.user_banned}>"
        )

    def __str__(self) -> str:
        return self.__repr__()


[docs]class Role(Hashable): def __init__(self, id: str, data: RolePayload, state: ConnectionState) -> None: self.id = id self._state = state self.name = data.get("name") if "colour" in data: self.colour = Colour.from_hex(data["colour"]) else: self.colour = None self.hoist = data.get("hoist", False) self.rank = data.get("rank") self.default_server_permissions = ServerPermission(data.get("permissions")[0]) self.default_channel_permissions = ChannelPermission(data.get("permissions")[1]) def _update(self, event: ServerRoleUpdate) -> None: if event.get("clear") == "Colour": self.colour = None self.name = event.get("name", self.name) self.hoist = event.get("hoist", self.hoist) self.rank = event.get("rank", self.rank) @property def color(self) -> Optional[Colour]: return self.colour def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return f"<Role server={self.server.id} name={self.name} colour={self.colour}>"
class Category(Hashable): def __init__(self, data: CategoryPayload, state: ConnectionState) -> None: self._state = state self.channels: list[MessageableChannel] = [] self._from_data(data) def _from_data(self, data: CategoryPayload) -> None: self.id = data.get("id") self.title = data.get("title") for channel in data.get("channels", []): self.channels.append(self._state.get_channel(channel))
[docs]class Server(Hashable): def __init__(self, data: ServerPayload, state: ConnectionState): self.channel_ids: list[str] = [] self.member_ids: list[str] = [] self._categories: dict[str, Category] = {} self._state: ConnectionState = state self._from_data(data) def _from_data(self, data: ServerPayload) -> None: self.id = data.get("_id") self.owner = data.get("owner") self.name = data.get("name") self.description = data.get("description") self.channel_ids = data.get("channels") self.member_ids = data.get("members") for category in data.get("categories", []): self._categories[category["id"]] = Category(category, self._state) self.roles: list[Role] = [] for key, value in data.get("roles", {}).items(): self.roles.append(Role(key, value, self._state)) self.banner = data.get("banner") self.system_message = SystemMessages( data.get("system_messages"), self, self._state ) self.server_permissions = ServerPermission(data.get("default_permissions")[0]) self.channel_permissions = ChannelPermission(data.get("default_permissions")[1]) if "icon" in data: self.icon = Icon(data["icon"], self._state) else: self.icon = None def __str__(self) -> str: return self.name def __repr__(self) -> str: attrs = ( ("id", self.id), ("name", self.name), ("description", self.description or ""), ) inner = " ".join("%s=%r" % t for t in attrs) return f"<Server {inner}>" def _update(self, payload: ServerUpdate): """[summary] Parameters ---------- payload : ServerUpdate [description] """ self.owner = payload.get("owner", self.owner) self.name = payload.get("name", self.name) self.description = payload.get("description", self.description) if "icon" in payload: self.icon = Icon(payload["icon"], self._state) else: self.icon = None def get_role(self, role_id: str) -> Optional[Role]: for role in self.roles: if role.id == role_id: return role return None def create_text_channel( self, name: str, *, description: Optional[str] = None ) -> MessageableChannel: channel = self._state.http.create_channel(self.id, name, "Text", description) self._state.add_channel(channel) self.channel_ids.append(channel["_id"]) def create_voice_channel(self, name: str): channel = self._state.http.create_channel(self.id, name, "Voice") self._state.add_channel(channel) self.channel_ids.append(channel["_id"]) def get_member_named(self, name: str): for member in self.members: if member.name == name: return member return None def get_category_channel(self, channel_id: str) -> Optional[Category]: for category in self._categories.values(): for channel in category.channels: if channel.id == channel_id: return category return None def get_channel(self, id: str) -> Optional[MessageableChannel]: for channel in self.channels: if channel.id == id: return channel return None @property def channels(self): """All channels in the server Returns ------- [type] list of all channels """ return [self._state.get_channel(channel_id) for channel_id in self.channel_ids] @property def text_channels(self): """All text channels in the server Returns ------- [type] list of all text channels """ from .channel import TextChannel return [i for i in self.channels if isinstance(i, TextChannel)] @property def voice_channels(self): """All voice channels in the server Returns ------- [type] list of all voice channels """ from .channel import VoiceChannel return [i for i in self.channels if isinstance(i, VoiceChannel)] @property def members(self) -> list[Member]: """All cached members in the server. Returns ------- list[Member] list of all cached members in the server. """ return [self._state.get_member(member_id) for member_id in self.member_ids] @property def categories(self) -> list[Category]: """All categories in the server Returns ------- list[Category] list of all categories """ return list(self._categories.values())