Skip to content

Commit 8c3a621

Browse files
Paillat-devDorukyumplun1331pre-commit-ci[bot]
authored
feat: ✨ Add MediaChannel and fix ForumChannel flags (#2641)
Signed-off-by: Dorukyum <[email protected]> Signed-off-by: Paillat <[email protected]> Co-authored-by: Dorukyum <[email protected]> Co-authored-by: plun1331 <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent dbd9f1b commit 8c3a621

File tree

9 files changed

+226
-10
lines changed

9 files changed

+226
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ These changes are available on the `master` branch, but have not yet been releas
3939
`Permissions.use_external_sounds`, and
4040
`Permissions.view_creator_monetization_analytics`.
4141
([#2620](https://github.com/Pycord-Development/pycord/pull/2620))
42+
- Added `MediaChannel` channel type.
43+
([#2641](https://github.com/Pycord-Development/pycord/pull/2641))
4244
- Added `Message._raw_data` attribute.
4345
([#2670](https://github.com/Pycord-Development/pycord/pull/2670))
4446
- Added helper methods to determine the authorizing party of an `Interaction`.
@@ -69,6 +71,8 @@ These changes are available on the `master` branch, but have not yet been releas
6971
([#2627](https://github.com/Pycord-Development/pycord/issues/2627))
7072
- Fixed `AttributeError` when sending polls with `PartialWebook`.
7173
([#2624](https://github.com/Pycord-Development/pycord/pull/2624))
74+
- Fixed editing `ForumChannel` flags not working.
75+
([#2641](https://github.com/Pycord-Development/pycord/pull/2641))
7276
- Fixed `AttributeError` when accessing `Member.guild_permissions` for user installed
7377
apps. ([#2650](https://github.com/Pycord-Development/pycord/pull/2650))
7478
- Fixed type annotations of cached properties.

discord/abc.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
from .enums import ChannelType
4747
from .errors import ClientException, InvalidArgument
4848
from .file import File, VoiceMessage
49-
from .flags import MessageFlags
49+
from .flags import ChannelFlags, MessageFlags
5050
from .invite import Invite
5151
from .iterators import HistoryIterator
5252
from .mentions import AllowedMentions
@@ -85,7 +85,6 @@
8585
from .client import Client
8686
from .embeds import Embed
8787
from .enums import InviteTarget
88-
from .flags import ChannelFlags
8988
from .guild import Guild
9089
from .member import Member
9190
from .message import Message, MessageReference, PartialMessage
@@ -419,8 +418,7 @@ async def _edit(
419418
pass
420419

421420
try:
422-
if options.pop("require_tag"):
423-
options["flags"] = ChannelFlags.require_tag.flag
421+
options["flags"] = options.pop("flags").value
424422
except KeyError:
425423
pass
426424

discord/channel.py

Lines changed: 199 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"GroupChannel",
6666
"PartialMessageable",
6767
"ForumChannel",
68+
"MediaChannel",
6869
"ForumTag",
6970
)
7071

@@ -853,7 +854,6 @@ async def edit(self, *, reason=None, **options):
853854
HTTPException
854855
Editing the channel failed.
855856
"""
856-
857857
payload = await self._edit(options, reason=reason)
858858
if payload is not None:
859859
# the payload will always be the proper channel payload
@@ -1056,7 +1056,7 @@ def guidelines(self) -> str | None:
10561056

10571057
@property
10581058
def requires_tag(self) -> bool:
1059-
"""Whether a tag is required to be specified when creating a thread in this forum channel.
1059+
"""Whether a tag is required to be specified when creating a thread in this forum or media channel.
10601060
10611061
Tags are specified in :attr:`applied_tags`.
10621062
@@ -1169,6 +1169,9 @@ async def edit(self, *, reason=None, **options):
11691169
HTTPException
11701170
Editing the channel failed.
11711171
"""
1172+
if "require_tag" in options:
1173+
options["flags"] = ChannelFlags._from_value(self.flags.value)
1174+
options["flags"].require_tag = options.pop("require_tag")
11721175

11731176
payload = await self._edit(options, reason=reason)
11741177
if payload is not None:
@@ -1351,6 +1354,196 @@ async def create_thread(
13511354
return ret
13521355

13531356

1357+
class MediaChannel(ForumChannel):
1358+
"""Represents a Discord media channel. Subclass of :class:`ForumChannel`.
1359+
1360+
.. container:: operations
1361+
1362+
.. describe:: x == y
1363+
1364+
Checks if two channels are equal.
1365+
1366+
.. describe:: x != y
1367+
1368+
Checks if two channels are not equal.
1369+
1370+
.. describe:: hash(x)
1371+
1372+
Returns the channel's hash.
1373+
1374+
.. describe:: str(x)
1375+
1376+
Returns the channel's name.
1377+
1378+
.. versionadded:: 2.7
1379+
1380+
Attributes
1381+
----------
1382+
name: :class:`str`
1383+
The channel name.
1384+
guild: :class:`Guild`
1385+
The guild the channel belongs to.
1386+
id: :class:`int`
1387+
The channel ID.
1388+
category_id: Optional[:class:`int`]
1389+
The category channel ID this channel belongs to, if applicable.
1390+
topic: Optional[:class:`str`]
1391+
The channel's topic. ``None`` if it doesn't exist.
1392+
1393+
.. note::
1394+
1395+
:attr:`guidelines` exists as an alternative to this attribute.
1396+
position: Optional[:class:`int`]
1397+
The position in the channel list. This is a number that starts at 0. e.g. the
1398+
top channel is position 0. Can be ``None`` if the channel was received in an interaction.
1399+
last_message_id: Optional[:class:`int`]
1400+
The last message ID of the message sent to this channel. It may
1401+
*not* point to an existing or valid message.
1402+
slowmode_delay: :class:`int`
1403+
The number of seconds a member must wait between sending messages
1404+
in this channel. A value of `0` denotes that it is disabled.
1405+
Bots and users with :attr:`~Permissions.manage_channels` or
1406+
:attr:`~Permissions.manage_messages` bypass slowmode.
1407+
nsfw: :class:`bool`
1408+
If the channel is marked as "not safe for work".
1409+
1410+
.. note::
1411+
1412+
To check if the channel or the guild of that channel are marked as NSFW, consider :meth:`is_nsfw` instead.
1413+
default_auto_archive_duration: :class:`int`
1414+
The default auto archive duration in minutes for threads created in this channel.
1415+
1416+
flags: :class:`ChannelFlags`
1417+
Extra features of the channel.
1418+
1419+
available_tags: List[:class:`ForumTag`]
1420+
The set of tags that can be used in a forum channel.
1421+
1422+
default_sort_order: Optional[:class:`SortOrder`]
1423+
The default sort order type used to order posts in this channel.
1424+
1425+
default_thread_slowmode_delay: Optional[:class:`int`]
1426+
The initial slowmode delay to set on newly created threads in this channel.
1427+
1428+
default_reaction_emoji: Optional[:class:`str` | :class:`discord.GuildEmoji`]
1429+
The default forum reaction emoji.
1430+
"""
1431+
1432+
@property
1433+
def media_download_options_hidden(self) -> bool:
1434+
"""Whether media download options are hidden in this media channel.
1435+
1436+
.. versionadded:: 2.7
1437+
"""
1438+
return self.flags.hide_media_download_options
1439+
1440+
@overload
1441+
async def edit(
1442+
self,
1443+
*,
1444+
reason: str | None = ...,
1445+
name: str = ...,
1446+
topic: str = ...,
1447+
position: int = ...,
1448+
nsfw: bool = ...,
1449+
sync_permissions: bool = ...,
1450+
category: CategoryChannel | None = ...,
1451+
slowmode_delay: int = ...,
1452+
default_auto_archive_duration: ThreadArchiveDuration = ...,
1453+
default_thread_slowmode_delay: int = ...,
1454+
default_sort_order: SortOrder = ...,
1455+
default_reaction_emoji: GuildEmoji | int | str | None = ...,
1456+
available_tags: list[ForumTag] = ...,
1457+
require_tag: bool = ...,
1458+
hide_media_download_options: bool = ...,
1459+
overwrites: Mapping[Role | Member | Snowflake, PermissionOverwrite] = ...,
1460+
) -> ForumChannel | None: ...
1461+
1462+
async def edit(self, *, reason=None, **options):
1463+
"""|coro|
1464+
1465+
Edits the channel.
1466+
1467+
You must have the :attr:`~Permissions.manage_channels` permission to
1468+
use this.
1469+
1470+
Parameters
1471+
----------
1472+
name: :class:`str`
1473+
The new channel name.
1474+
topic: :class:`str`
1475+
The new channel's topic.
1476+
position: :class:`int`
1477+
The new channel's position.
1478+
nsfw: :class:`bool`
1479+
To mark the channel as NSFW or not.
1480+
sync_permissions: :class:`bool`
1481+
Whether to sync permissions with the channel's new or pre-existing
1482+
category. Defaults to ``False``.
1483+
category: Optional[:class:`CategoryChannel`]
1484+
The new category for this channel. Can be ``None`` to remove the
1485+
category.
1486+
slowmode_delay: :class:`int`
1487+
Specifies the slowmode rate limit for user in this channel, in seconds.
1488+
A value of `0` disables slowmode. The maximum value possible is `21600`.
1489+
reason: Optional[:class:`str`]
1490+
The reason for editing this channel. Shows up on the audit log.
1491+
overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`~discord.abc.Snowflake`], :class:`PermissionOverwrite`]
1492+
The overwrites to apply to channel permissions. Useful for creating secret channels.
1493+
default_auto_archive_duration: :class:`int`
1494+
The new default auto archive duration in minutes for threads created in this channel.
1495+
Must be one of ``60``, ``1440``, ``4320``, or ``10080``.
1496+
default_thread_slowmode_delay: :class:`int`
1497+
The new default slowmode delay in seconds for threads created in this channel.
1498+
1499+
default_sort_order: Optional[:class:`SortOrder`]
1500+
The default sort order type to use to order posts in this channel.
1501+
1502+
default_reaction_emoji: Optional[:class:`discord.GuildEmoji` | :class:`int` | :class:`str`]
1503+
The default reaction emoji.
1504+
Can be a unicode emoji or a custom emoji in the forms:
1505+
:class:`GuildEmoji`, snowflake ID, string representation (e.g., '<a:emoji_name:emoji_id>').
1506+
1507+
available_tags: List[:class:`ForumTag`]
1508+
The set of tags that can be used in this channel. Must be less than `20`.
1509+
1510+
require_tag: :class:`bool`
1511+
Whether a tag should be required to be specified when creating a thread in this channel.
1512+
1513+
hide_media_download_options: :class:`bool`
1514+
Whether media download options should be hidden in this media channel.
1515+
1516+
Returns
1517+
-------
1518+
Optional[:class:`.MediaChannel`]
1519+
The newly edited media channel. If the edit was only positional
1520+
then ``None`` is returned instead.
1521+
1522+
Raises
1523+
------
1524+
InvalidArgument
1525+
If position is less than 0 or greater than the number of channels, or if
1526+
the permission overwrite information is not in proper form.
1527+
Forbidden
1528+
You do not have permissions to edit the channel.
1529+
HTTPException
1530+
Editing the channel failed.
1531+
"""
1532+
1533+
if "require_tag" in options or "hide_media_download_options" in options:
1534+
flags = ChannelFlags._from_value(self.flags.value)
1535+
flags.require_tag = options.pop("require_tag", flags.require_tag)
1536+
flags.hide_media_download_options = options.pop(
1537+
"hide_media_download_options", flags.hide_media_download_options
1538+
)
1539+
options["flags"] = flags
1540+
1541+
payload = await self._edit(options, reason=reason)
1542+
if payload is not None:
1543+
# the payload will always be the proper channel payload
1544+
return self.__class__(state=self._state, guild=self.guild, data=payload) # type: ignore
1545+
1546+
13541547
class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hashable):
13551548
__slots__ = (
13561549
"name",
@@ -3232,8 +3425,12 @@ def _guild_channel_factory(channel_type: int):
32323425
return TextChannel, value
32333426
elif value is ChannelType.stage_voice:
32343427
return StageChannel, value
3428+
elif value is ChannelType.directory:
3429+
return None, value # todo: Add DirectoryChannel when applicable
32353430
elif value is ChannelType.forum:
32363431
return ForumChannel, value
3432+
elif value is ChannelType.media:
3433+
return MediaChannel, value
32373434
else:
32383435
return None, value
32393436

discord/commands/options.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
CategoryChannel,
3535
DMChannel,
3636
ForumChannel,
37+
MediaChannel,
3738
StageChannel,
3839
TextChannel,
3940
Thread,
@@ -85,6 +86,7 @@
8586
CategoryChannel: ChannelType.category,
8687
Thread: ChannelType.public_thread,
8788
ForumChannel: ChannelType.forum,
89+
MediaChannel: ChannelType.media,
8890
DMChannel: ChannelType.private,
8991
}
9092

discord/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,7 @@ def from_datatype(cls, datatype):
825825
"ThreadOption",
826826
"Thread",
827827
"ForumChannel",
828+
"MediaChannel",
828829
"DMChannel",
829830
]:
830831
return cls.channel

discord/flags.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,14 @@ def require_tag(self):
15611561
"""
15621562
return 1 << 4
15631563

1564+
@flag_value
1565+
def hide_media_download_options(self):
1566+
""":class:`bool`: Returns ``True`` if the embedded media download options are hidden for the media channel posts.
1567+
1568+
.. versionadded:: 2.7
1569+
"""
1570+
return 1 << 15
1571+
15641572

15651573
@fill_with_flags()
15661574
class AttachmentFlags(BaseFlags):

discord/threads.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ def members(self) -> list[ThreadMember]:
300300
def applied_tags(self) -> list[ForumTag]:
301301
"""List[:class:`ForumTag`]: A list of tags applied to this thread.
302302
303-
This is only available for threads in forum channels.
303+
This is only available for threads in forum or media channels.
304304
"""
305305
from .channel import ForumChannel # to prevent circular import
306306

@@ -394,7 +394,7 @@ def starting_message(self) -> Message | None:
394394
return self._state._get_message(self.id)
395395

396396
def is_pinned(self) -> bool:
397-
"""Whether the thread is pinned to the top of its parent forum channel.
397+
"""Whether the thread is pinned to the top of its parent forum or media channel.
398398
399399
.. versionadded:: 2.3
400400
"""
@@ -638,7 +638,7 @@ async def edit(
638638
reason: Optional[:class:`str`]
639639
The reason for editing this thread. Shows up on the audit log.
640640
pinned: :class:`bool`
641-
Whether to pin the thread or not. This only works if the thread is part of a forum.
641+
Whether to pin the thread or not. This only works if the thread is part of a forum or media channel.
642642
applied_tags: List[:class:`ForumTag`]
643643
The set of tags to apply to the thread. Each tag object should have an ID set.
644644

docs/api/models.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,12 @@ Channels
428428
:members:
429429
:inherited-members:
430430

431+
.. attributetable:: MediaChannel
432+
433+
.. autoclass:: MediaChannel()
434+
:members:
435+
:inherited-members:
436+
431437
.. attributetable:: VoiceChannel
432438

433439
.. autoclass:: VoiceChannel()

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ def write_new():
493493
r".*/old_changelog.*",
494494
r"migrating_to_v1.*",
495495
r"migrating_to_v2.*",
496-
r"old_changelog.*"
496+
r"old_changelog.*",
497497
]
498498

499499
linkcheck_anchors_ignore_for_url = [r"https://github.com/Delitefully/DiscordLists"]

0 commit comments

Comments
 (0)