9 changed files with 462 additions and 9 deletions
@ -0,0 +1,125 @@ |
|||||
|
""" |
||||
|
The MIT License (MIT) |
||||
|
|
||||
|
Copyright (c) 2015-present Rapptz |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||
|
copy of this software and associated documentation files (the "Software"), |
||||
|
to deal in the Software without restriction, including without limitation |
||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||
|
Software is furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in |
||||
|
all copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
|
DEALINGS IN THE SOFTWARE. |
||||
|
""" |
||||
|
from __future__ import annotations |
||||
|
|
||||
|
from typing import TYPE_CHECKING, Literal, Optional, TypeVar, Union |
||||
|
|
||||
|
from .item import Item |
||||
|
from ..components import FileComponent, UnfurledMediaItem |
||||
|
from ..enums import ComponentType |
||||
|
|
||||
|
if TYPE_CHECKING: |
||||
|
from typing_extensions import Self |
||||
|
|
||||
|
from .view import View |
||||
|
|
||||
|
V = TypeVar('V', bound='View', covariant=True) |
||||
|
|
||||
|
__all__ = ('File',) |
||||
|
|
||||
|
|
||||
|
class File(Item[V]): |
||||
|
"""Represents a UI file component. |
||||
|
|
||||
|
.. versionadded:: 2.6 |
||||
|
|
||||
|
Parameters |
||||
|
---------- |
||||
|
media: Union[:class:`str`, :class:`UnfurledMediaItem`] |
||||
|
This file's media. If this is a string itmust point to a local |
||||
|
file uploaded within the parent view of this item, and must |
||||
|
meet the ``attachment://file-name.extension`` structure. |
||||
|
spoiler: :class:`bool` |
||||
|
Whether to flag this file as a spoiler. Defaults to ``False``. |
||||
|
row: Optional[:class:`int`] |
||||
|
The relative row this file component belongs to. By default |
||||
|
items are arranged automatically into those rows. If you'd |
||||
|
like to control the relative positioning of the row then |
||||
|
passing an index is advised. For example, row=1 will show |
||||
|
up before row=2. Defaults to ``None``, which is automatic |
||||
|
ordering. The row number must be between 0 and 9 (i.e. zero indexed) |
||||
|
""" |
||||
|
|
||||
|
def __init__( |
||||
|
self, |
||||
|
media: Union[str, UnfurledMediaItem], |
||||
|
*, |
||||
|
spoiler: bool = False, |
||||
|
row: Optional[int] = None, |
||||
|
) -> None: |
||||
|
super().__init__() |
||||
|
self._underlying = FileComponent._raw_construct( |
||||
|
media=UnfurledMediaItem(media) if isinstance(media, str) else media, |
||||
|
spoiler=spoiler, |
||||
|
) |
||||
|
|
||||
|
self.row = row |
||||
|
|
||||
|
def _is_v2(self): |
||||
|
return True |
||||
|
|
||||
|
@property |
||||
|
def width(self): |
||||
|
return 5 |
||||
|
|
||||
|
@property |
||||
|
def type(self) -> Literal[ComponentType.file]: |
||||
|
return self._underlying.type |
||||
|
|
||||
|
@property |
||||
|
def media(self) -> UnfurledMediaItem: |
||||
|
""":class:`UnfurledMediaItem`: Returns this file media.""" |
||||
|
return self._underlying.media |
||||
|
|
||||
|
@media.setter |
||||
|
def media(self, value: UnfurledMediaItem) -> None: |
||||
|
self._underlying.media = value |
||||
|
|
||||
|
@property |
||||
|
def url(self) -> str: |
||||
|
""":class:`str`: Returns this file's url.""" |
||||
|
return self._underlying.media.url |
||||
|
|
||||
|
@url.setter |
||||
|
def url(self, value: str) -> None: |
||||
|
self._underlying.media = UnfurledMediaItem(value) |
||||
|
|
||||
|
@property |
||||
|
def spoiler(self) -> bool: |
||||
|
""":class:`bool`: Returns whether this file should be flagged as a spoiler.""" |
||||
|
return self._underlying.spoiler |
||||
|
|
||||
|
@spoiler.setter |
||||
|
def spoiler(self, value: bool) -> None: |
||||
|
self._underlying.spoiler = value |
||||
|
|
||||
|
def to_component_dict(self): |
||||
|
return self._underlying.to_dict() |
||||
|
|
||||
|
@classmethod |
||||
|
def from_component(cls, component: FileComponent) -> Self: |
||||
|
return cls( |
||||
|
media=component.media, |
||||
|
spoiler=component.spoiler, |
||||
|
) |
@ -0,0 +1,177 @@ |
|||||
|
""" |
||||
|
The MIT License (MIT) |
||||
|
|
||||
|
Copyright (c) 2015-present Rapptz |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||
|
copy of this software and associated documentation files (the "Software"), |
||||
|
to deal in the Software without restriction, including without limitation |
||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||
|
Software is furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in |
||||
|
all copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
|
DEALINGS IN THE SOFTWARE. |
||||
|
""" |
||||
|
from __future__ import annotations |
||||
|
|
||||
|
from typing import TYPE_CHECKING, List, Literal, Optional, TypeVar |
||||
|
|
||||
|
from .item import Item |
||||
|
from ..enums import ComponentType |
||||
|
from ..components import ( |
||||
|
MediaGalleryItem, |
||||
|
MediaGalleryComponent, |
||||
|
) |
||||
|
|
||||
|
if TYPE_CHECKING: |
||||
|
from typing_extensions import Self |
||||
|
|
||||
|
from .view import View |
||||
|
|
||||
|
V = TypeVar('V', bound='View', covariant=True) |
||||
|
|
||||
|
__all__ = ('MediaGallery',) |
||||
|
|
||||
|
|
||||
|
class MediaGallery(Item[V]): |
||||
|
"""Represents a UI media gallery. |
||||
|
|
||||
|
This can contain up to 10 :class:`MediaGalleryItem`s. |
||||
|
|
||||
|
.. versionadded:: 2.6 |
||||
|
|
||||
|
Parameters |
||||
|
---------- |
||||
|
items: List[:class:`MediaGalleryItem`] |
||||
|
The initial items of this gallery. |
||||
|
row: Optional[:class:`int`] |
||||
|
The relative row this media gallery belongs to. By default |
||||
|
items are arranged automatically into those rows. If you'd |
||||
|
like to control the relative positioning of the row then |
||||
|
passing an index is advised. For example, row=1 will show |
||||
|
up before row=2. Defaults to ``None``, which is automatic |
||||
|
ordering. The row number must be between 0 and 9 (i.e. zero indexed) |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, items: List[MediaGalleryItem], *, row: Optional[int] = None) -> None: |
||||
|
super().__init__() |
||||
|
|
||||
|
self._underlying = MediaGalleryComponent._raw_construct( |
||||
|
items=items, |
||||
|
) |
||||
|
|
||||
|
self.row = row |
||||
|
|
||||
|
@property |
||||
|
def items(self) -> List[MediaGalleryItem]: |
||||
|
"""List[:class:`MediaGalleryItem`]: Returns a read-only list of this gallery's items.""" |
||||
|
return self._underlying.items.copy() |
||||
|
|
||||
|
@items.setter |
||||
|
def items(self, value: List[MediaGalleryItem]) -> None: |
||||
|
if len(value) > 10: |
||||
|
raise ValueError('media gallery only accepts up to 10 items') |
||||
|
|
||||
|
self._underlying.items = value |
||||
|
|
||||
|
def to_component_dict(self): |
||||
|
return self._underlying.to_dict() |
||||
|
|
||||
|
def _is_v2(self) -> bool: |
||||
|
return True |
||||
|
|
||||
|
def add_item(self, item: MediaGalleryItem) -> Self: |
||||
|
"""Adds an item to this gallery. |
||||
|
|
||||
|
This function returns the class instance to allow for fluent-style |
||||
|
chaining. |
||||
|
|
||||
|
Parameters |
||||
|
---------- |
||||
|
item: :class:`MediaGalleryItem` |
||||
|
The item to add to the gallery. |
||||
|
|
||||
|
Raises |
||||
|
------ |
||||
|
TypeError |
||||
|
A :class:`MediaGalleryItem` was not passed. |
||||
|
ValueError |
||||
|
Maximum number of items has been exceeded (10). |
||||
|
""" |
||||
|
|
||||
|
if len(self._underlying.items) >= 10: |
||||
|
raise ValueError('maximum number of items has been exceeded') |
||||
|
|
||||
|
if not isinstance(item, MediaGalleryItem): |
||||
|
raise TypeError(f'expected MediaGalleryItem not {item.__class__.__name__}') |
||||
|
|
||||
|
self._underlying.items.append(item) |
||||
|
return self |
||||
|
|
||||
|
def remove_item(self, item: MediaGalleryItem) -> Self: |
||||
|
"""Removes an item from the gallery. |
||||
|
|
||||
|
This function returns the class instance to allow for fluent-style |
||||
|
chaining. |
||||
|
|
||||
|
Parameters |
||||
|
---------- |
||||
|
item: :class:`MediaGalleryItem` |
||||
|
The item to remove from the gallery. |
||||
|
""" |
||||
|
|
||||
|
try: |
||||
|
self._underlying.items.remove(item) |
||||
|
except ValueError: |
||||
|
pass |
||||
|
return self |
||||
|
|
||||
|
def insert_item_at(self, index: int, item: MediaGalleryItem) -> Self: |
||||
|
"""Inserts an item before a specified index to the gallery. |
||||
|
|
||||
|
This function returns the class instance to allow for fluent-style |
||||
|
chaining. |
||||
|
|
||||
|
Parameters |
||||
|
---------- |
||||
|
index: :class:`int` |
||||
|
The index of where to insert the item. |
||||
|
item: :class:`MediaGalleryItem` |
||||
|
The item to insert. |
||||
|
""" |
||||
|
|
||||
|
self._underlying.items.insert(index, item) |
||||
|
return self |
||||
|
|
||||
|
def clear_items(self) -> Self: |
||||
|
"""Removes all items from the gallery. |
||||
|
|
||||
|
This function returns the class instance to allow for fluent-style |
||||
|
chaining. |
||||
|
""" |
||||
|
|
||||
|
self._underlying.items.clear() |
||||
|
return self |
||||
|
|
||||
|
@property |
||||
|
def type(self) -> Literal[ComponentType.media_gallery]: |
||||
|
return self._underlying.type |
||||
|
|
||||
|
@property |
||||
|
def width(self): |
||||
|
return 5 |
||||
|
|
||||
|
@classmethod |
||||
|
def from_component(cls, component: MediaGalleryComponent) -> Self: |
||||
|
return cls( |
||||
|
items=component.items, |
||||
|
) |
@ -0,0 +1,110 @@ |
|||||
|
""" |
||||
|
The MIT License (MIT) |
||||
|
|
||||
|
Copyright (c) 2015-present Rapptz |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||
|
copy of this software and associated documentation files (the "Software"), |
||||
|
to deal in the Software without restriction, including without limitation |
||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||
|
Software is furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in |
||||
|
all copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
|
DEALINGS IN THE SOFTWARE. |
||||
|
""" |
||||
|
from __future__ import annotations |
||||
|
|
||||
|
from typing import TYPE_CHECKING, Literal, Optional, TypeVar |
||||
|
|
||||
|
from .item import Item |
||||
|
from ..components import SeparatorComponent |
||||
|
from ..enums import SeparatorSize, ComponentType |
||||
|
|
||||
|
if TYPE_CHECKING: |
||||
|
from .view import View |
||||
|
|
||||
|
V = TypeVar('V', bound='View', covariant=True) |
||||
|
|
||||
|
__all__ = ('Separator',) |
||||
|
|
||||
|
|
||||
|
class Separator(Item[V]): |
||||
|
"""Represents a UI separator. |
||||
|
|
||||
|
.. versionadded:: 2.6 |
||||
|
|
||||
|
Parameters |
||||
|
---------- |
||||
|
visible: :class:`bool` |
||||
|
Whether this separator is visible. On the client side this |
||||
|
is whether a divider line should be shown or not. |
||||
|
spacing: :class:`SeparatorSize` |
||||
|
The spacing of this separator. |
||||
|
row: Optional[:class:`int`] |
||||
|
The relative row this separator belongs to. By default |
||||
|
items are arranged automatically into those rows. If you'd |
||||
|
like to control the relative positioning of the row then |
||||
|
passing an index is advised. For example, row=1 will show |
||||
|
up before row=2. Defaults to ``None``, which is automatic |
||||
|
ordering. The row number must be between 0 and 9 (i.e. zero indexed) |
||||
|
""" |
||||
|
|
||||
|
def __init__( |
||||
|
self, |
||||
|
*, |
||||
|
visible: bool = True, |
||||
|
spacing: SeparatorSize = SeparatorSize.small, |
||||
|
row: Optional[int] = None, |
||||
|
) -> None: |
||||
|
super().__init__() |
||||
|
self._underlying = SeparatorComponent._raw_construct( |
||||
|
spacing=spacing, |
||||
|
visible=visible, |
||||
|
) |
||||
|
|
||||
|
self.row = row |
||||
|
|
||||
|
def _is_v2(self): |
||||
|
return True |
||||
|
|
||||
|
@property |
||||
|
def visible(self) -> bool: |
||||
|
""":class:`bool`: Whether this separator is visible. |
||||
|
|
||||
|
On the client side this is whether a divider line should |
||||
|
be shown or not. |
||||
|
""" |
||||
|
return self._underlying.visible |
||||
|
|
||||
|
@visible.setter |
||||
|
def visible(self, value: bool) -> None: |
||||
|
self._underlying.visible = value |
||||
|
|
||||
|
@property |
||||
|
def spacing(self) -> SeparatorSize: |
||||
|
""":class:`SeparatorSize`: The spacing of this separator.""" |
||||
|
return self._underlying.spacing |
||||
|
|
||||
|
@spacing.setter |
||||
|
def spacing(self, value: SeparatorSize) -> None: |
||||
|
self._underlying.spacing = value |
||||
|
|
||||
|
@property |
||||
|
def width(self): |
||||
|
return 5 |
||||
|
|
||||
|
@property |
||||
|
def type(self) -> Literal[ComponentType.separator]: |
||||
|
return self._underlying.type |
||||
|
|
||||
|
def to_component_dict(self): |
||||
|
return self._underlying.to_dict() |
Loading…
Reference in new issue