6464 from ..guild import Guild
6565 from ..channel import TextChannel
6666 from ..abc import Snowflake
67+ from ..ui .view import View
6768 import datetime
6869
6970MISSING = utils .MISSING
@@ -423,6 +424,7 @@ def handle_message_parameters(
423424 files : List [File ] = MISSING ,
424425 embed : Optional [Embed ] = MISSING ,
425426 embeds : List [Embed ] = MISSING ,
427+ view : Optional [View ] = MISSING ,
426428 allowed_mentions : Optional [AllowedMentions ] = MISSING ,
427429 previous_allowed_mentions : Optional [AllowedMentions ] = None ,
428430) -> ExecuteWebhookParameters :
@@ -449,6 +451,12 @@ def handle_message_parameters(
449451 else :
450452 payload ['content' ] = None
451453
454+ if view is not MISSING :
455+ if view is not None :
456+ payload ['components' ] = view .to_components ()
457+ else :
458+ payload ['components' ] = []
459+
452460 payload ['tts' ] = tts
453461 if avatar_url :
454462 payload ['avatar_url' ] = str (avatar_url )
@@ -621,6 +629,7 @@ async def edit(
621629 embed : Optional [Embed ] = MISSING ,
622630 file : File = MISSING ,
623631 files : List [File ] = MISSING ,
632+ view : Optional [View ] = MISSING ,
624633 allowed_mentions : Optional [AllowedMentions ] = None ,
625634 ):
626635 """|coro|
@@ -646,6 +655,9 @@ async def edit(
646655 allowed_mentions: :class:`AllowedMentions`
647656 Controls the mentions being processed in this message.
648657 See :meth:`.abc.Messageable.send` for more information.
658+ view: Optional[:class:`~discord.ui.View`]
659+ The updated view to update this message with. If ``None`` is passed then
660+ the view is removed.
649661
650662 Raises
651663 -------
@@ -667,6 +679,7 @@ async def edit(
667679 embed = embed ,
668680 file = file ,
669681 files = files ,
682+ view = view ,
670683 allowed_mentions = allowed_mentions ,
671684 )
672685
@@ -1148,6 +1161,7 @@ async def send(
11481161 embed : Embed = MISSING ,
11491162 embeds : List [Embed ] = MISSING ,
11501163 allowed_mentions : AllowedMentions = MISSING ,
1164+ view : View = MISSING ,
11511165 wait : Literal [True ],
11521166 ) -> WebhookMessage :
11531167 ...
@@ -1166,6 +1180,7 @@ async def send(
11661180 embed : Embed = MISSING ,
11671181 embeds : List [Embed ] = MISSING ,
11681182 allowed_mentions : AllowedMentions = MISSING ,
1183+ view : View = MISSING ,
11691184 wait : Literal [False ] = ...,
11701185 ) -> None :
11711186 ...
@@ -1183,6 +1198,7 @@ async def send(
11831198 embed : Embed = MISSING ,
11841199 embeds : List [Embed ] = MISSING ,
11851200 allowed_mentions : AllowedMentions = MISSING ,
1201+ view : View = MISSING ,
11861202 wait : bool = False ,
11871203 ) -> Optional [WebhookMessage ]:
11881204 """|coro|
@@ -1218,6 +1234,8 @@ async def send(
12181234 ephemeral: :class:`bool`
12191235 Indicates if the message should only be visible to the user.
12201236 This is only available to :attr:`WebhookType.application` webhooks.
1237+ If a view is sent with an ephemeral message and it has no timeout set
1238+ then the timeout is set to 15 minutes.
12211239 file: :class:`File`
12221240 The file to upload. This cannot be mixed with ``files`` parameter.
12231241 files: List[:class:`File`]
@@ -1231,8 +1249,11 @@ async def send(
12311249 be mixed with the ``embed`` parameter.
12321250 allowed_mentions: :class:`AllowedMentions`
12331251 Controls the mentions being processed in this message.
1234-
1235- .. versionadded:: 1.4
1252+ view: :class:`discord.ui.View`
1253+ The view to send with the message. You can only send a view
1254+ if this webhook is not partial and has state attached. A
1255+ webhook has state attached if the webhook is managed by the
1256+ library.
12361257
12371258 Raises
12381259 --------
@@ -1248,7 +1269,8 @@ async def send(
12481269 The length of ``embeds`` was invalid.
12491270 InvalidArgument
12501271 There was no token associated with this webhook or ``ephemeral``
1251- was passed with the improper webhook type.
1272+ was passed with the improper webhook type or there was no state
1273+ attached with this webhook when giving it a view.
12521274
12531275 Returns
12541276 ---------
@@ -1270,6 +1292,12 @@ async def send(
12701292 if application_webhook :
12711293 wait = True
12721294
1295+ if view is not MISSING :
1296+ if isinstance (self ._state , _WebhookState ):
1297+ raise InvalidArgument ('Webhook views require an associated state with the webhook' )
1298+ if ephemeral is True and view .timeout is None :
1299+ view .timeout = 15 * 60.0
1300+
12731301 params = handle_message_parameters (
12741302 content = content ,
12751303 username = username ,
@@ -1280,6 +1308,7 @@ async def send(
12801308 embed = embed ,
12811309 embeds = embeds ,
12821310 ephemeral = ephemeral ,
1311+ view = view ,
12831312 allowed_mentions = allowed_mentions ,
12841313 previous_allowed_mentions = previous_mentions ,
12851314 )
@@ -1293,8 +1322,16 @@ async def send(
12931322 files = params .files ,
12941323 wait = wait ,
12951324 )
1325+
1326+ msg = None
12961327 if wait :
1297- return self ._create_message (data )
1328+ msg = self ._create_message (data )
1329+
1330+ if view is not MISSING :
1331+ message_id = None if msg is None else msg .id
1332+ self ._state .store_view (view , message_id )
1333+
1334+ return msg
12981335
12991336 async def fetch_message (self , id : int ) -> WebhookMessage :
13001337 """|coro|
@@ -1346,6 +1383,7 @@ async def edit_message(
13461383 embed : Optional [Embed ] = MISSING ,
13471384 file : File = MISSING ,
13481385 files : List [File ] = MISSING ,
1386+ view : Optional [View ] = MISSING ,
13491387 allowed_mentions : Optional [AllowedMentions ] = None ,
13501388 ):
13511389 """|coro|
@@ -1376,6 +1414,10 @@ async def edit_message(
13761414 allowed_mentions: :class:`AllowedMentions`
13771415 Controls the mentions being processed in this message.
13781416 See :meth:`.abc.Messageable.send` for more information.
1417+ view: Optional[:class:`~discord.ui.View`]
1418+ The updated view to update this message with. If ``None`` is passed then
1419+ the view is removed. The webhook must have state attached, similar to
1420+ :meth:`send`.
13791421
13801422 Raises
13811423 -------
@@ -1388,19 +1430,24 @@ async def edit_message(
13881430 ValueError
13891431 The length of ``embeds`` was invalid
13901432 InvalidArgument
1391- There was no token associated with this webhook.
1433+ There was no token associated with this webhook or the webhook had
1434+ no state.
13921435 """
13931436
13941437 if self .token is None :
13951438 raise InvalidArgument ('This webhook does not have a token associated with it' )
13961439
1440+ if view is not MISSING and isinstance (self ._state , _WebhookState ):
1441+ raise InvalidArgument ('This webhook does not have state associated with it' )
1442+
13971443 previous_mentions : Optional [AllowedMentions ] = getattr (self ._state , 'allowed_mentions' , None )
13981444 params = handle_message_parameters (
13991445 content = content ,
14001446 file = file ,
14011447 files = files ,
14021448 embed = embed ,
14031449 embeds = embeds ,
1450+ view = view ,
14041451 allowed_mentions = allowed_mentions ,
14051452 previous_allowed_mentions = previous_mentions ,
14061453 )
@@ -1415,6 +1462,9 @@ async def edit_message(
14151462 files = params .files ,
14161463 )
14171464
1465+ if view :
1466+ self ._state .store_view (view , message_id )
1467+
14181468 async def delete_message (self , message_id : int ):
14191469 """|coro|
14201470
0 commit comments