359 lines
13 KiB
Python
359 lines
13 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import datetime
|
|
from enum import Enum, IntFlag
|
|
|
|
|
|
class FileMime(Enum):
|
|
AUDIO_OGG = 'audio/ogg'
|
|
IMAGE_JPEG = 'image/jpeg'
|
|
IMAGE_PNG = 'image/png'
|
|
IMAGE_SVG = 'image/svg'
|
|
JSON = 'application/json'
|
|
PDF = 'application/pdf'
|
|
TEXT_CSV = 'text/csv'
|
|
TEXT_HTML = 'text/html'
|
|
TEXT_MARKDOWN = 'text/markdown'
|
|
TEXT_PLAIN = 'text/plain'
|
|
VIDEO_MP4 = 'video/mp4'
|
|
VIDEO_MPEG = 'video/mpeg'
|
|
VIDEO_WEBM = 'video/webm'
|
|
ZIP = 'application/zip'
|
|
|
|
|
|
class ChannelType(Enum):
|
|
GUILD_TEXT = 0
|
|
DM = 1
|
|
GUILD_VOICE = 2
|
|
GROUP_DM = 3
|
|
GUILD_CATEGORY = 4
|
|
GUILD_ANNOUNCEMENT = 5
|
|
ANNOUNCEMENT_THREAD = 10
|
|
PUBLIC_THREAD = 11
|
|
PRIVATE_THREAD = 12
|
|
GUILD_STAGE_VOICE = 13
|
|
GUILD_DIRECTORY = 14
|
|
GUILD_FORUM = 15
|
|
GUILD_MEDIA = 16
|
|
|
|
|
|
class ChannelFlags(IntFlag):
|
|
# this thread is pinned to the top of its parent GUILD_FORUM or GUILD_MEDIA channel
|
|
PINNED = 1 << 1
|
|
# whether a tag is required to be specified when creating a thread in a GUILD_FORUM or a GUILD_MEDIA channel.
|
|
# Tags are specified in the applied_tags field.
|
|
REQUIRE_TAG = 1 << 4
|
|
# when set hides the embedded media download options. Available only for media channels
|
|
HIDE_MEDIA_DOWNLOAD_OPTIONS = 1 << 15
|
|
|
|
|
|
class OverwriteType(Enum):
|
|
ROLE = 0
|
|
MEMBER = 1
|
|
|
|
|
|
class Permissions(IntFlag):
|
|
NONE = 0
|
|
# Allows creation of instant invites
|
|
CREATE_INSTANT_INVITE = 1
|
|
# Allows kicking members
|
|
KICK_MEMBERS = 1 << 1
|
|
# Allows banning members
|
|
BAN_MEMBERS = 1 << 2
|
|
# Allows all permissions and bypasses channel permission overwrites
|
|
ADMINISTRATOR = 1 << 3
|
|
# Allows management and editing of channels
|
|
MANAGE_CHANNELS = 1 << 4
|
|
# Allows management and editing of the guild
|
|
MANAGE_GUILD = 1 << 5
|
|
# Allows for adding new reactions to messages.
|
|
# This permission does not apply to reacting with an existing reaction on a message.
|
|
ADD_REACTIONS = 1 << 6
|
|
# Allows for viewing of audit logs
|
|
VIEW_AUDIT_LOG = 1 << 7
|
|
# Allows for using priority speaker in a voice channel
|
|
PRIORITY_SPEAKER = 1 << 8
|
|
# Allows the user to go live
|
|
STREAM = 1 << 9
|
|
# Allows guild members to view a channel,
|
|
# which includes reading messages in text channels and joining voice channels
|
|
VIEW_CHANNEL = 1 << 10
|
|
# Allows for sending messages in a channel and creating threads in a forum
|
|
# (does not allow sending messages in threads)
|
|
SEND_MESSAGES = 1 << 11
|
|
# Allows for sending of /tts messages
|
|
SEND_TTS_MESSAGES = 1 << 12
|
|
# Allows for deletion of other users messages
|
|
MANAGE_MESSAGES = 1 << 13
|
|
# Links sent by users with this permission will be auto-embedded
|
|
EMBED_LINKS = 1 << 14
|
|
# Allows for uploading images and files
|
|
ATTACH_FILES = 1 << 15
|
|
# Allows for reading of message history
|
|
READ_MESSAGE_HISTORY = 1 << 16
|
|
# Allows for using the @everyone tag to notify all users in a channel,
|
|
# and the @here tag to notify all online users in a channel
|
|
MENTION_EVERYONE = 1 << 17
|
|
# Allows the usage of custom emojis from other servers
|
|
USE_EXTERNAL_EMOJIS = 1 << 18
|
|
# Allows for viewing guild insights
|
|
VIEW_GUILD_INSIGHTS = 1 << 19
|
|
# Allows for joining of a voice channel
|
|
CONNECT = 1 << 20
|
|
# Allows for speaking in a voice channel
|
|
SPEAK = 1 << 21
|
|
# Allows for muting members in a voice channel
|
|
MUTE_MEMBERS = 1 << 22
|
|
# Allows for deafening of members in a voice channel
|
|
DEAFEN_MEMBERS = 1 << 23
|
|
# Allows for moving of members between voice channels
|
|
MOVE_MEMBERS = 1 << 24
|
|
# Allows for using voice-activity-detection in a voice channel
|
|
USE_VAD = 1 << 25
|
|
# Allows for modification of own nickname
|
|
CHANGE_NICKNAME = 1 << 26
|
|
# Allows for modification of other users nicknames
|
|
MANAGE_NICKNAMES = 1 << 27
|
|
# Allows management and editing of roles
|
|
MANAGE_ROLES = 1 << 28
|
|
# Allows management and editing of webhooks
|
|
MANAGE_WEBHOOKS = 1 << 29
|
|
# Allows for editing and deleting emojis, stickers, and soundboard sounds created by all users
|
|
MANAGE_GUILD_EXPRESSIONS = 1 << 30
|
|
# Allows members to use application commands, including slash commands and context menu commands.
|
|
USE_APPLICATION_COMMANDS = 1 << 31
|
|
# Allows for requesting to speak in stage channels. (This permission is under active development
|
|
# and may be changed or removed.)
|
|
REQUEST_TO_SPEAK = 1 << 32
|
|
# Allows for editing and deleting scheduled events created by all users
|
|
MANAGE_EVENTS = 1 << 33
|
|
# Allows for deleting and archiving threads, and viewing all private threads
|
|
MANAGE_THREADS = 1 << 34
|
|
# Allows for creating public and announcement threads
|
|
CREATE_PUBLIC_THREADS = 1 << 35
|
|
# Allows for creating private threads
|
|
CREATE_PRIVATE_THREADS = 1 << 36
|
|
# Allows the usage of custom stickers from other servers
|
|
USE_EXTERNAL_STICKERS = 1 << 37
|
|
# Allows for sending messages in threads
|
|
SEND_MESSAGES_IN_THREADS = 1 << 38
|
|
# Allows for using Activities (applications with the EMBEDDED flag)
|
|
USE_EMBEDDED_ACTIVITIES = 1 << 39
|
|
# Allows for timing out users to prevent them from sending or reacting to messages in chat and threads,
|
|
# and from speaking in voice and stage channels
|
|
MODERATE_MEMBERS = 1 << 40
|
|
# Allows for viewing role subscription insights
|
|
VIEW_CREATOR_MONETIZATION_ANALYTICS = 1 << 41
|
|
# Allows for using soundboard in a voice channel
|
|
USE_SOUNDBOARD = 1 << 42
|
|
# Allows for creating emojis, stickers, and soundboard sounds, and editing and deleting those created
|
|
# by the current user. Not yet available to developers, see changelog.
|
|
CREATE_GUILD_EXPRESSIONS = 1 << 43
|
|
# Allows for creating scheduled events, and editing and deleting those created by the current user.
|
|
# Not yet available to developers, see changelog.
|
|
CREATE_EVENTS = 1 << 44
|
|
# Allows the usage of custom soundboard sounds from other servers
|
|
USE_EXTERNAL_SOUNDS = 1 << 45
|
|
# Allows sending voice messages
|
|
SEND_VOICE_MESSAGES = 1 << 46
|
|
# Allows sending polls
|
|
SEND_POLLS = 1 << 49
|
|
# Allows user-installed apps to send public responses. When disabled, users will still be allowed to use their apps
|
|
# but the responses will be ephemeral. This only applies to apps not also installed to the server.
|
|
USE_EXTERNAL_APPS = 1 << 50
|
|
# Allows pinning and unpinning messages
|
|
PIN_MESSAGES = 1 << 51
|
|
|
|
|
|
@dataclass
|
|
class Overwrite:
|
|
id: int
|
|
type: OverwriteType
|
|
allow: Permissions
|
|
deny: Permissions
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> Overwrite:
|
|
return Overwrite(
|
|
id=int(info['id']),
|
|
type=OverwriteType(info['type']),
|
|
allow=Permissions(int(info['allow'])),
|
|
deny=Permissions(int(info['deny'])))
|
|
|
|
|
|
@dataclass
|
|
class ChannelCategory:
|
|
id: int
|
|
guild_id: int
|
|
position: int
|
|
permission_overwrites: list[Overwrite]
|
|
name: str | None
|
|
parent_id: int | None
|
|
flags: ChannelFlags
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> ChannelCategory:
|
|
parent_id: str | None = info.get('parent_id')
|
|
return ChannelCategory(
|
|
id=int(info['id']),
|
|
guild_id=int(info['guild_id']),
|
|
position=int(info['position']),
|
|
permission_overwrites=[Overwrite.from_dict(o) for o in info['permission_overwrites']],
|
|
name=info.get('name'),
|
|
parent_id=int(parent_id) if parent_id is not None else None,
|
|
flags=ChannelFlags(info['flags']))
|
|
|
|
|
|
@dataclass
|
|
class TextChannel:
|
|
id: int
|
|
guild_id: int
|
|
position: int
|
|
permission_overwrites: list[Overwrite]
|
|
name: str | None
|
|
topic: str | None
|
|
nsfw: bool
|
|
last_message_id: int | None
|
|
rate_limit_per_user: int
|
|
parent_id: int | None
|
|
last_pin_timestamp: datetime | None
|
|
flags: ChannelFlags
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> TextChannel:
|
|
parent_id: str | None = info.get('parent_id')
|
|
last_message_id: str | None = info.get('last_message_id')
|
|
last_pin_timestamp: str | None = info.get('last_pin_timestamp')
|
|
return TextChannel(
|
|
id=int(info['id']),
|
|
guild_id=int(info['guild_id']),
|
|
position=int(info['position']),
|
|
permission_overwrites=[Overwrite.from_dict(o) for o in info['permission_overwrites']],
|
|
name=info.get('name'),
|
|
topic=info.get('topic'),
|
|
nsfw=info['nsfw'],
|
|
last_message_id=int(last_message_id) if last_message_id is not None else None,
|
|
rate_limit_per_user=int(info['rate_limit_per_user']),
|
|
parent_id=int(parent_id) if parent_id is not None else None,
|
|
last_pin_timestamp=(datetime.fromisoformat(last_pin_timestamp) if last_pin_timestamp is not None else None),
|
|
flags=ChannelFlags(info['flags']))
|
|
|
|
|
|
@dataclass
|
|
class User: # TODO : complete attributes
|
|
id: int
|
|
username: str
|
|
discriminator: str
|
|
global_name: str | None
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> User:
|
|
return User(
|
|
id=int(info['id']),
|
|
username=info['username'],
|
|
discriminator=info['discriminator'],
|
|
global_name=info.get('global_name'))
|
|
|
|
|
|
@dataclass
|
|
class Message: # TODO : complete attributes
|
|
id: int
|
|
channel_id: int
|
|
author: User
|
|
content: str
|
|
timestamp: datetime
|
|
edited_timestamp: datetime | None
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> Message:
|
|
edited_timestamp: str | None = info.get('edited_timestamp')
|
|
return Message(
|
|
id=int(info['id']),
|
|
channel_id=int(info['channel_id']),
|
|
author=(User.from_dict(info['author']) if info.get('webhook_id') is None else User(
|
|
id=info['webhook_id'], username='webhook', discriminator='webhook', global_name=None)),
|
|
content=info['content'],
|
|
timestamp=datetime.fromisoformat(info['timestamp']),
|
|
edited_timestamp=datetime.fromisoformat(edited_timestamp) if edited_timestamp is not None else None)
|
|
|
|
|
|
@dataclass
|
|
class RoleColors:
|
|
primary_color: int
|
|
seconday_color: int | None
|
|
tertiary_color: int | None
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> RoleColors:
|
|
seconday_color = info.get('secondary_color')
|
|
tertiary_color = info.get('tertiary_color')
|
|
return RoleColors(
|
|
primary_color=int(info['primary_color']),
|
|
seconday_color=int(seconday_color) if seconday_color is not None else None,
|
|
tertiary_color=int(tertiary_color) if tertiary_color is not None else None)
|
|
|
|
|
|
class RoleFlags(IntFlag):
|
|
NONE = 0
|
|
# role can be selected by members in an onboarding prompt
|
|
IN_PROMPT = 1
|
|
|
|
|
|
@dataclass
|
|
class RoleTags:
|
|
bot_id: int | None
|
|
intergration_id: int | None
|
|
premium_subscriber: bool
|
|
subcription_listing_id: int | None
|
|
available_for_purchase: bool
|
|
guild_connections: bool
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> RoleTags:
|
|
bot_id = info.get('bot_id')
|
|
intergration_id = info.get('intergration_id')
|
|
subcription_listing_id = info.get('subcription_listing_id')
|
|
return RoleTags(
|
|
bot_id=int(bot_id) if bot_id is not None else None,
|
|
intergration_id=int(intergration_id) if intergration_id is not None else None,
|
|
premium_subscriber='premium_subscriber' in info,
|
|
subcription_listing_id=int(subcription_listing_id) if subcription_listing_id is not None else None,
|
|
available_for_purchase='available_for_purchase' in info,
|
|
guild_connections='guild_connections' in info)
|
|
|
|
|
|
@dataclass
|
|
class Role:
|
|
id: int # role id
|
|
name: str # role name
|
|
color: int # Deprecated integer representation of hexadecimal color code
|
|
colors: RoleColors # the role's colors
|
|
hoist: bool # if this role is pinned in the user listing
|
|
icon: str | None # role icon hash
|
|
unicode_emoji: str | None # role unicode emoji
|
|
position: int # position of this role (roles with the same position are sorted by id)
|
|
permissions: Permissions # permission bit set
|
|
managed: bool # whether this role is managed by an integration
|
|
mentionable: bool # whether this role is mentionable
|
|
tags: RoleTags | None # the tags this role has
|
|
flags: int # role flags combined as a bitfield
|
|
|
|
@staticmethod
|
|
def from_dict(info: dict) -> Role:
|
|
tags = info.get('tags')
|
|
return Role(
|
|
id=int(info['id']),
|
|
name=info['name'],
|
|
color=int(info['color']),
|
|
colors=RoleColors.from_dict(info['colors']),
|
|
hoist=info['hoist'],
|
|
icon=info.get('icon'),
|
|
unicode_emoji=info.get('unicode_emoji'),
|
|
position=int(info['position']),
|
|
permissions=Permissions(int(info['permissions'])),
|
|
managed=info['managed'],
|
|
mentionable=info['mentionable'],
|
|
tags=RoleTags.from_dict(tags) if tags is not None else None,
|
|
flags=RoleFlags(int(info['flags']))
|
|
)
|