mirror of
https://github.com/stoatchat/python-client-sdk.git
synced 2026-07-21 01:55:23 -04:00
add docs
This commit is contained in:
@@ -3,3 +3,5 @@
|
||||
test.py
|
||||
dist
|
||||
*.egg-info
|
||||
docs/_build
|
||||
.vscode
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
requirements_file: docs_requirements.txt
|
||||
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -0,0 +1,90 @@
|
||||
.. currentmodule:: revolt
|
||||
|
||||
API Reference
|
||||
===============
|
||||
|
||||
|
||||
Client
|
||||
~~~~~~~
|
||||
|
||||
.. autoclass:: Client
|
||||
:members:
|
||||
|
||||
Asset
|
||||
~~~~~~
|
||||
|
||||
.. autoclass:: Asset
|
||||
:members:
|
||||
|
||||
Channel
|
||||
~~~~~~~~
|
||||
|
||||
.. autoclass:: Channel
|
||||
:members:
|
||||
|
||||
SavedMessageChannel
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: SavedMessageChannel
|
||||
:members:
|
||||
|
||||
DMChannel
|
||||
~~~~~~~~~~
|
||||
|
||||
.. autoclass:: DMChannel
|
||||
:members:
|
||||
|
||||
Embed
|
||||
~~~~~~~~~~
|
||||
|
||||
.. autoclass:: Embed
|
||||
:members:
|
||||
|
||||
|
||||
File
|
||||
~~~~~
|
||||
|
||||
.. autoclass:: File
|
||||
:members:
|
||||
|
||||
Member
|
||||
~~~~~~~
|
||||
|
||||
.. autoclass:: Member
|
||||
:members:
|
||||
|
||||
Message
|
||||
~~~~~~~
|
||||
|
||||
.. autoclass:: Message
|
||||
:members:
|
||||
|
||||
Messageable
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: Messageable
|
||||
:members:
|
||||
|
||||
Permissions
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: Permissions
|
||||
:members:
|
||||
|
||||
Role
|
||||
~~~~~
|
||||
|
||||
.. autoclass:: Role
|
||||
:members:
|
||||
|
||||
Server
|
||||
~~~~~~~~~~
|
||||
|
||||
.. autoclass:: Server
|
||||
:members:
|
||||
|
||||
User
|
||||
~~~~~~~~~~
|
||||
|
||||
.. autoclass:: User
|
||||
:members:
|
||||
@@ -0,0 +1,58 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import sphinx_nameko_theme
|
||||
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Revolt.py'
|
||||
copyright = '2021-present, Zomatree'
|
||||
author = 'Zomatree'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx.ext.autodoc",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
|
||||
html_theme = 'nameko'
|
||||
html_theme_path = [sphinx_nameko_theme.get_html_theme_path()]
|
||||
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
@@ -0,0 +1,7 @@
|
||||
Welcome to Revolt.py's documentation!
|
||||
====================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
api
|
||||
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -0,0 +1,2 @@
|
||||
Sphinx==4.1.2
|
||||
sphinx-nameko-theme==0.0.3
|
||||
+10
-2
@@ -1,5 +1,13 @@
|
||||
from .channel import TextChannel, VoiceChannel
|
||||
from .asset import Asset
|
||||
from .channel import DMChannel, Channel, GroupDMChannel, PartialTextChannel, SavedMessageChannel, VoiceChannel
|
||||
from .client import Client
|
||||
from .embed import Embed
|
||||
from .errors import HTTPError, RevoltError, ServerError
|
||||
from .file import File
|
||||
from .member import Member
|
||||
from .message import Message
|
||||
from .messageable import Messageable
|
||||
from .permissions import Permissions
|
||||
from .role import Role
|
||||
from .server import Server
|
||||
from .user import User
|
||||
from .message import Message
|
||||
|
||||
+29
-1
@@ -1,12 +1,32 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Union
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .types import File as FilePayload
|
||||
from .state import State
|
||||
from io import IOBase
|
||||
|
||||
class Asset:
|
||||
"""Represents a file on revolt
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: str
|
||||
The id of the asset
|
||||
tag: str
|
||||
The tag of the asset, this corrasponds to where the asset is used
|
||||
size: int
|
||||
Amount of bytes in the file
|
||||
filename: str
|
||||
The name of the file
|
||||
height: Optional[int]
|
||||
The height of the file if it is an image or video
|
||||
width: Optional[int]
|
||||
The width of the file if it is an image or video
|
||||
content_type: str
|
||||
The content type of the file
|
||||
"""
|
||||
def __init__(self, data: FilePayload, state: State):
|
||||
self.id = data['_id']
|
||||
self.tag = data['tag']
|
||||
@@ -25,7 +45,15 @@ class Asset:
|
||||
self.content_type = data["content_type"]
|
||||
|
||||
async def read(self) -> bytes:
|
||||
"""Reads the files content into bytes"""
|
||||
...
|
||||
|
||||
async def save(self, fp: IOBase):
|
||||
"""Reads the files content and saves it to a file
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
fp: IOBase
|
||||
The file to write too.
|
||||
"""
|
||||
fp.write(await self.read())
|
||||
|
||||
+28
-13
@@ -9,6 +9,17 @@ if TYPE_CHECKING:
|
||||
from .state import State
|
||||
|
||||
class Channel:
|
||||
"""Base class for all channels
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the channel
|
||||
channel_type: Literal['SavedMessage', 'DirectMessage', 'Group', 'TextChannel', 'VoiceChannel']
|
||||
The type of the channel
|
||||
server: Optional[:class:`Server`]
|
||||
The server the channel is part of
|
||||
"""
|
||||
def __init__(self, data: ChannelPayload, state: State):
|
||||
self.state = state
|
||||
self.id = data["_id"]
|
||||
@@ -16,23 +27,28 @@ class Channel:
|
||||
self.server = None
|
||||
|
||||
class SavedMessageChannel(Channel, Messageable):
|
||||
"""The Saved Message Channel"""
|
||||
def __init__(self, data: ChannelPayload, state: State):
|
||||
super().__init__(data, state)
|
||||
|
||||
class DMChannel(Channel, Messageable):
|
||||
"""A DM channel"""
|
||||
def __init__(self, data: ChannelPayload, state: State):
|
||||
super().__init__(data, state)
|
||||
|
||||
class GroupDMChannel(Channel, Messageable):
|
||||
"""A group DM channel"""
|
||||
def __init__(self, data: ChannelPayload, state: State):
|
||||
super().__init__(data, state)
|
||||
|
||||
class TextChannel(Channel, Messageable):
|
||||
"""A text channel"""
|
||||
def __init__(self, data: ChannelPayload, state: State):
|
||||
super().__init__(data, state)
|
||||
Messageable.__init__(self, state)
|
||||
|
||||
class PartialTextChannel(Messageable):
|
||||
"""A partial text channel, this will appear when the channel isnt cached"""
|
||||
def __init__(self, channel_id: str, state: State):
|
||||
super().__init__(state)
|
||||
|
||||
@@ -42,21 +58,20 @@ class PartialTextChannel(Messageable):
|
||||
self.server = None
|
||||
|
||||
class VoiceChannel(Channel):
|
||||
"""A voice channel"""
|
||||
def __init__(self, data: ChannelPayload, state: State):
|
||||
super().__init__(data, state)
|
||||
|
||||
def channel_factory(data: ChannelPayload) -> type[Channel]:
|
||||
channel_type = data["channel_type"]
|
||||
|
||||
if channel_type == "SavedMessage":
|
||||
return SavedMessageChannel
|
||||
elif channel_type == "DirectMessage":
|
||||
return DMChannel
|
||||
elif channel_type == "Group":
|
||||
return GroupDMChannel
|
||||
elif channel_type == "TextChannel":
|
||||
return TextChannel
|
||||
elif channel_type == "VoiceChannel":
|
||||
return VoiceChannel
|
||||
def channel_factory(data: ChannelPayload, state) -> Channel:
|
||||
if data["channel_type"] == "SavedMessage":
|
||||
return SavedMessageChannel(data, state)
|
||||
elif data["channel_type"] == "DirectMessage":
|
||||
return DMChannel(data, state)
|
||||
elif data["channel_type"] == "Group":
|
||||
return GroupDMChannel(data, state)
|
||||
elif data["channel_type"] == "TextChannel":
|
||||
return TextChannel(data, state)
|
||||
elif data["channel_type"] == "VoiceChannel":
|
||||
return VoiceChannel(data, state)
|
||||
else:
|
||||
raise Exception
|
||||
|
||||
+75
-2
@@ -23,6 +23,19 @@ if TYPE_CHECKING:
|
||||
logger = logging.getLogger("revolt")
|
||||
|
||||
class Client:
|
||||
"""The client for interacting with revolt
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
session: :class:`aiohttp.ClientSession`
|
||||
The aiohttp session to use for http request and the websocket
|
||||
token: :class:`str`
|
||||
The bots token
|
||||
api_url: :class:`str`
|
||||
The api url for the revolt instance you are connecting to, by default it uses the offical instance hosted at revolt.chat
|
||||
max_messages: :class:`int`
|
||||
The max amount of messages stored in the cache, by default this is 5k
|
||||
"""
|
||||
def __init__(self, session: aiohttp.ClientSession, token: str, api_url: str = "https://api.revolt.chat", max_messages: int = 5000):
|
||||
self.session = session
|
||||
self.token = token
|
||||
@@ -37,6 +50,15 @@ class Client:
|
||||
self.listeners: dict[str, list[tuple[Callable[..., bool], asyncio.Future[Any]]]] = {}
|
||||
|
||||
def dispatch(self, event: str, *args: Any):
|
||||
"""Dispatch an event, this is typically used for testing and internals.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
event: class:`str`
|
||||
The name of the event to dispatch, not including `on_`
|
||||
args: :class:`Any`
|
||||
The arguments passed to the event
|
||||
"""
|
||||
for check, future in self.listeners.pop(event, []):
|
||||
if check(*args):
|
||||
if len(args) == 1:
|
||||
@@ -53,6 +75,7 @@ class Client:
|
||||
return json.loads(await resp.text())
|
||||
|
||||
async def start(self):
|
||||
"""Starts the client"""
|
||||
api_info = await self.get_api_info()
|
||||
|
||||
self.api_info = api_info
|
||||
@@ -62,19 +85,69 @@ class Client:
|
||||
await self.websocket.start()
|
||||
|
||||
def get_user(self, id: str) -> Optional[User]:
|
||||
"""Gets a user from the cache
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the user
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`User`]
|
||||
The user if found
|
||||
"""
|
||||
self.state.get_user(id)
|
||||
|
||||
def get_channel(self, id: str) -> Optional[Channel]:
|
||||
"""Gets a channel from the cache
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the channel
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`Channel`]
|
||||
The channel if found
|
||||
"""
|
||||
self.state.get_channel(id)
|
||||
|
||||
def get_server(self, id: str) -> Optional[Server]:
|
||||
"""Gets a server from the cache
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the server
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`Server`]
|
||||
The server if found
|
||||
"""
|
||||
self.state.get_server(id)
|
||||
|
||||
def wait_for(self, event: str, *, check: Optional[Callable[..., bool]] = None) -> asyncio.Future[Any]:
|
||||
async def wait_for(self, event: str, *, check: Optional[Callable[..., bool]] = None) -> Any:
|
||||
"""Waits for an event
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
event: :class:`str`
|
||||
The name of the event to wait for, without the `on_`
|
||||
check: Optional[Callable[..., :class:`bool`]]
|
||||
A function that says what event to wait_for, this function takes the same parameters as the event you are waiting for and should return a bool saying if that is the event you want
|
||||
|
||||
Returns
|
||||
--------
|
||||
Any
|
||||
The parameters of the event
|
||||
"""
|
||||
if not check:
|
||||
check = lambda *_: True
|
||||
|
||||
future = asyncio.get_running_loop().create_future()
|
||||
self.listeners.setdefault(event, []).append((check, future))
|
||||
|
||||
return future
|
||||
return await future
|
||||
|
||||
@@ -4,6 +4,17 @@ import io
|
||||
import os
|
||||
|
||||
class File:
|
||||
"""Respresents a file about to be uploaded to revolt
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
file: Union[str, bytes]
|
||||
The name of the file or the content of the file in bytes, text files will be need to be encoded
|
||||
filename: Optional[str]
|
||||
The filename of the file when being uploaded, this will default to the name of the file if one exists
|
||||
spoiler: bool
|
||||
Determines if the file will be a spoiler, this prefexes the filename with `SPOILER_`
|
||||
"""
|
||||
def __init__(self, file: Union[str, bytes], *, filename: Optional[str] = None, spoiler: bool = False):
|
||||
if isinstance(file, str):
|
||||
self.f = open(file, "rb")
|
||||
|
||||
+19
-2
@@ -14,13 +14,30 @@ def flattern_user(member: Member, user: User):
|
||||
setattr(member, attr, getattr(user, attr))
|
||||
|
||||
class Member(User):
|
||||
"""Represents a member of a server, subclasses :class:`User`
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
nickname: Optional[:class:`str`]
|
||||
The nickname of the member if any
|
||||
roles: list[:class:`Role`]
|
||||
The roles of the member, ordered by the role's rank in decending order
|
||||
server: :class:`Server`
|
||||
The server the member belongs to
|
||||
"""
|
||||
def __init__(self, data: MemberPayload, server: Server, state: State):
|
||||
user = state.get_user(data["_id"]["user"])
|
||||
assert user
|
||||
flattern_user(self, user)
|
||||
|
||||
self._state = state
|
||||
self.id = data["_id"]["user"]
|
||||
self.nickname = data.get("nickname")
|
||||
self.roles = [server.get_role(role_id) for role_id in data.get("roles", [])]
|
||||
roles = []
|
||||
|
||||
for role in (server.get_role(role_id) for role_id in data.get("roles", [])):
|
||||
if role:
|
||||
roles.append(role)
|
||||
|
||||
self.roles = sorted(roles, key=lambda role: role.rank, reverse=True)
|
||||
|
||||
self.server = server
|
||||
|
||||
@@ -11,6 +11,25 @@ if TYPE_CHECKING:
|
||||
from .types import Message as MessagePayload
|
||||
|
||||
class Message:
|
||||
"""Represents a message
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the message
|
||||
content: :class:`str`
|
||||
The content of the message, this will not include system message's content
|
||||
attachments: list[:class:`Asset`]
|
||||
The attachments of the message
|
||||
embeds: list[:class:`Embed`]
|
||||
The embeds of the message
|
||||
channel: :class:`Messageable`
|
||||
The channel the message was sent in
|
||||
server: :class:`Server`
|
||||
The server the message was sent in
|
||||
author: Union[:class:`Member`, :class:`User`]
|
||||
The author of the message, will be :class:`User` in DMs
|
||||
"""
|
||||
def __init__(self, data: MessagePayload, state: State):
|
||||
self.state = state
|
||||
|
||||
|
||||
@@ -10,12 +10,35 @@ if TYPE_CHECKING:
|
||||
from .file import File
|
||||
|
||||
class Messageable:
|
||||
"""Base class for all channels that you can send messages in
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the channel
|
||||
"""
|
||||
id: str
|
||||
|
||||
def __init__(self, state: State):
|
||||
self.state = state
|
||||
|
||||
async def send(self, content: Optional[str] = None, embeds: Optional[list[Embed]] = None, embed: Optional[Embed] = None, attachments: Optional[list[File]] = None) -> Message:
|
||||
"""Sends a message in a channel, you must send at least one of either `content`, `embeds` or `attachments`
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
content: Optional[:class:`str`]
|
||||
The content of the message, this will not include system message's content
|
||||
attachments: Optional[list[:class:`File`]]
|
||||
The attachments of the message
|
||||
embeds: Optional[list[:class:`Embed`]]
|
||||
The embeds of the message
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`Message`
|
||||
The message that was just sent
|
||||
"""
|
||||
if embed:
|
||||
embeds = [embed]
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
@@ -6,6 +8,21 @@ if TYPE_CHECKING:
|
||||
from .types import Role as RolePayload
|
||||
|
||||
class Role:
|
||||
"""Represents a role
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the role
|
||||
name: :class:`str`
|
||||
The name of the role
|
||||
colour: :class:`str`
|
||||
The colour of the role
|
||||
hoist: :class:`bool`
|
||||
Whether members with the role will display seperate from everyone else
|
||||
rank: :class:`int`
|
||||
The position of the role in the role heirarchy
|
||||
"""
|
||||
def __init__(self, data: RolePayload, role_id: str, state: State):
|
||||
self.id = role_id
|
||||
self.name = data["name"]
|
||||
|
||||
+76
-4
@@ -2,6 +2,9 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from .permissions import Permissions
|
||||
from .channel import channel_factory
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .types import Server as ServerPayload
|
||||
from .state import State
|
||||
@@ -10,16 +13,85 @@ if TYPE_CHECKING:
|
||||
from .channel import Channel
|
||||
|
||||
class Server:
|
||||
"""Represents a server
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the server
|
||||
name: :class:`str`
|
||||
The name of the server
|
||||
owner: Optional[:class:`Member`]
|
||||
The owner of the server
|
||||
"""
|
||||
def __init__(self, data: ServerPayload, state: State):
|
||||
self.state = state
|
||||
self.id = data["_id"]
|
||||
self.name = data["name"]
|
||||
self.owner = state.get_member(self.id, data["owner"])
|
||||
self.default_permissions = Permissions(data["default_permissions"])
|
||||
|
||||
self._members: dict[str, Member] = {}
|
||||
self._roles: dict[str, Role] = {}
|
||||
self._channels: dict[str, Channel] = {}
|
||||
self._roles: dict[str, Role] = {role_id: Role(role, role_id, state) for role_id, role in data.get("roles", {}).items()}
|
||||
channels = [channel_factory(channel, state) for channel in data.get("channels", [])]
|
||||
self._channels: dict[str, Channel] = {channel.id: channel for channel in channels}
|
||||
|
||||
def get_role(self, role_id: str, /) -> Optional[Role]:
|
||||
@property
|
||||
def roles(self) -> list[Role]:
|
||||
"""list[:class:`Role`] Gets all roles in the server in decending order"""
|
||||
return list(self._roles.values())
|
||||
|
||||
@property
|
||||
def members(self) -> list[Member]:
|
||||
"""list[:class:`Member`] Gets all members in the server"""
|
||||
return list(self._members.values())
|
||||
|
||||
@property
|
||||
def channels(self) -> list[Channel]:
|
||||
"""list[:class:`Member`] Gets all channels in the server"""
|
||||
return list(self._channels.values())
|
||||
|
||||
def get_role(self, role_id: str) -> Optional[Role]:
|
||||
"""Gets a role from the cache
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the role
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`Role`]
|
||||
The role if found
|
||||
"""
|
||||
return self._roles.get(role_id)
|
||||
|
||||
def get_member(self, member_id: str, /) -> Optional[Member]:
|
||||
def get_member(self, member_id: str) -> Optional[Member]:
|
||||
"""Gets a member from the cache
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the member
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`Member`]
|
||||
The member if found
|
||||
"""
|
||||
return self._members.get(member_id)
|
||||
|
||||
def get_channel(self, channel_id: str) -> Optional[Channel]:
|
||||
"""Gets a channel from the cache
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The id of the channel
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`Channel`]
|
||||
The channel if found
|
||||
"""
|
||||
self._channels.get(channel_id)
|
||||
|
||||
+2
-3
@@ -56,10 +56,9 @@ class State:
|
||||
|
||||
server._members[member.id] = member
|
||||
return member
|
||||
|
||||
|
||||
def add_channel(self, payload: ChannelPayload) -> Channel:
|
||||
cls = channel_factory(payload)
|
||||
channel = cls(payload, self)
|
||||
channel = channel_factory(payload, self)
|
||||
self.channels[channel.id] = channel
|
||||
return channel
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from typing import TYPE_CHECKING, TypedDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .channel import Channel
|
||||
|
||||
class Category(TypedDict):
|
||||
id: str
|
||||
title: str
|
||||
channels: list[Channel]
|
||||
+24
-1
@@ -1,9 +1,32 @@
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
from typing import TYPE_CHECKING, TypedDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
from .role import Role, Permission
|
||||
from .file import File
|
||||
from .category import Category
|
||||
from .channel import Channel
|
||||
|
||||
class SystemMessagesConfig(TypedDict, total=False):
|
||||
user_joined: str
|
||||
user_left: str
|
||||
user_kicked: str
|
||||
user_banned: str
|
||||
|
||||
class _ServerOptional(TypedDict, total=False):
|
||||
nonce: str
|
||||
description: str
|
||||
categories: list[Category]
|
||||
system_messages: SystemMessagesConfig
|
||||
roles: list[Role]
|
||||
icon: File
|
||||
banner: File
|
||||
|
||||
class Server(TypedDict):
|
||||
_id: str
|
||||
owner: str
|
||||
name: str
|
||||
channels: list[Channel]
|
||||
default_permissions: Permission
|
||||
|
||||
+21
-2
@@ -7,7 +7,26 @@ if TYPE_CHECKING:
|
||||
from .types import User as UserPayload
|
||||
|
||||
class User:
|
||||
__flattern_attributes__ = ("name", "bot", "owner", "badges", "online", "flags")
|
||||
"""Represents a user
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: :class:`str`
|
||||
The users id
|
||||
name: :class:`str`
|
||||
The users name
|
||||
bot: :class:`bool`
|
||||
Whether or not the user is a bot
|
||||
owner: Optional[:class:`User`]
|
||||
The bot's owner if the user is a bot
|
||||
badges: :class:`int`
|
||||
The users badges
|
||||
online: :class:`bool`
|
||||
Whether or not the user is online
|
||||
flags: :class:`int`
|
||||
The user flags
|
||||
"""
|
||||
__flattern_attributes__ = ("id", "name", "bot", "owner", "badges", "online", "flags")
|
||||
|
||||
def __init__(self, data: UserPayload, state: State):
|
||||
self.state = state
|
||||
@@ -17,7 +36,7 @@ class User:
|
||||
bot = data.get("bot")
|
||||
if bot:
|
||||
self.bot = True
|
||||
self.owner = bot["owner"]
|
||||
self.owner = state.get_user(bot["owner"])
|
||||
else:
|
||||
self.bot = False
|
||||
self.owner = None
|
||||
|
||||
Reference in New Issue
Block a user