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