mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-05-12 16:59:50 +00:00
Add message purging functions to Thread
This commit is contained in:
parent
e13cbf4644
commit
5ae7940ec8
@ -23,12 +23,14 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from discord.types.threads import ThreadMember
|
from typing import Callable, Dict, Iterable, List, Optional, Sequence, TYPE_CHECKING
|
||||||
from typing import Dict, Optional, TYPE_CHECKING
|
import time
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from .mixins import Hashable
|
from .mixins import Hashable
|
||||||
from .abc import Messageable
|
from .abc import Messageable
|
||||||
from .enums import ChannelType, try_enum
|
from .enums import ChannelType, try_enum
|
||||||
|
from .errors import ClientException, NoMoreItems
|
||||||
from .utils import MISSING, parse_time, _get_as_snowflake
|
from .utils import MISSING, parse_time, _get_as_snowflake
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
@ -47,7 +49,7 @@ if TYPE_CHECKING:
|
|||||||
from .channel import TextChannel
|
from .channel import TextChannel
|
||||||
from .member import Member
|
from .member import Member
|
||||||
from .message import Message
|
from .message import Message
|
||||||
from .abc import Snowflake
|
from .abc import Snowflake, SnowflakeTime
|
||||||
from .state import ConnectionState
|
from .state import ConnectionState
|
||||||
|
|
||||||
|
|
||||||
@ -232,6 +234,175 @@ class Thread(Messageable, Hashable):
|
|||||||
"""
|
"""
|
||||||
return self._type is ChannelType.news_thread
|
return self._type is ChannelType.news_thread
|
||||||
|
|
||||||
|
async def delete_messages(self, messages: Iterable[Snowflake]) -> None:
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Deletes a list of messages. This is similar to :meth:`Message.delete`
|
||||||
|
except it bulk deletes multiple messages.
|
||||||
|
|
||||||
|
As a special case, if the number of messages is 0, then nothing
|
||||||
|
is done. If the number of messages is 1 then single message
|
||||||
|
delete is done. If it's more than two, then bulk delete is used.
|
||||||
|
|
||||||
|
You cannot bulk delete more than 100 messages or messages that
|
||||||
|
are older than 14 days old.
|
||||||
|
|
||||||
|
You must have the :attr:`~Permissions.manage_messages` permission to
|
||||||
|
use this.
|
||||||
|
|
||||||
|
Usable only by bot accounts.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
messages: Iterable[:class:`abc.Snowflake`]
|
||||||
|
An iterable of messages denoting which ones to bulk delete.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
ClientException
|
||||||
|
The number of messages to delete was more than 100.
|
||||||
|
Forbidden
|
||||||
|
You do not have proper permissions to delete the messages or
|
||||||
|
you're not using a bot account.
|
||||||
|
NotFound
|
||||||
|
If single delete, then the message was already deleted.
|
||||||
|
HTTPException
|
||||||
|
Deleting the messages failed.
|
||||||
|
"""
|
||||||
|
if not isinstance(messages, (list, tuple)):
|
||||||
|
messages = list(messages)
|
||||||
|
|
||||||
|
if len(messages) == 0:
|
||||||
|
return # do nothing
|
||||||
|
|
||||||
|
if len(messages) == 1:
|
||||||
|
message_id = messages[0].id
|
||||||
|
await self._state.http.delete_message(self.id, message_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(messages) > 100:
|
||||||
|
raise ClientException('Can only bulk delete messages up to 100 messages')
|
||||||
|
|
||||||
|
message_ids = [m.id for m in messages]
|
||||||
|
await self._state.http.delete_messages(self.id, message_ids)
|
||||||
|
|
||||||
|
async def purge(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
limit: int = 100,
|
||||||
|
check: Callable[[Message], bool] = MISSING,
|
||||||
|
before: Optional[SnowflakeTime] = None,
|
||||||
|
after: Optional[SnowflakeTime] = None,
|
||||||
|
around: Optional[SnowflakeTime] = None,
|
||||||
|
oldest_first: Optional[bool] = False,
|
||||||
|
bulk: bool = True,
|
||||||
|
) -> List[Message]:
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Purges a list of messages that meet the criteria given by the predicate
|
||||||
|
``check``. If a ``check`` is not provided then all messages are deleted
|
||||||
|
without discrimination.
|
||||||
|
|
||||||
|
You must have the :attr:`~Permissions.manage_messages` permission to
|
||||||
|
delete messages even if they are your own (unless you are a user
|
||||||
|
account). The :attr:`~Permissions.read_message_history` permission is
|
||||||
|
also needed to retrieve message history.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
---------
|
||||||
|
|
||||||
|
Deleting bot's messages ::
|
||||||
|
|
||||||
|
def is_me(m):
|
||||||
|
return m.author == client.user
|
||||||
|
|
||||||
|
deleted = await thread.purge(limit=100, check=is_me)
|
||||||
|
await thread.send(f'Deleted {len(deleted)} message(s)')
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
limit: Optional[:class:`int`]
|
||||||
|
The number of messages to search through. This is not the number
|
||||||
|
of messages that will be deleted, though it can be.
|
||||||
|
check: Callable[[:class:`Message`], :class:`bool`]
|
||||||
|
The function used to check if a message should be deleted.
|
||||||
|
It must take a :class:`Message` as its sole parameter.
|
||||||
|
before: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]]
|
||||||
|
Same as ``before`` in :meth:`history`.
|
||||||
|
after: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]]
|
||||||
|
Same as ``after`` in :meth:`history`.
|
||||||
|
around: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]]
|
||||||
|
Same as ``around`` in :meth:`history`.
|
||||||
|
oldest_first: Optional[:class:`bool`]
|
||||||
|
Same as ``oldest_first`` in :meth:`history`.
|
||||||
|
bulk: :class:`bool`
|
||||||
|
If ``True``, use bulk delete. Setting this to ``False`` is useful for mass-deleting
|
||||||
|
a bot's own messages without :attr:`Permissions.manage_messages`. When ``True``, will
|
||||||
|
fall back to single delete if messages are older than two weeks.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
-------
|
||||||
|
Forbidden
|
||||||
|
You do not have proper permissions to do the actions required.
|
||||||
|
HTTPException
|
||||||
|
Purging the messages failed.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
--------
|
||||||
|
List[:class:`.Message`]
|
||||||
|
The list of messages that were deleted.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if check is MISSING:
|
||||||
|
check = lambda m: True
|
||||||
|
|
||||||
|
iterator = self.history(limit=limit, before=before, after=after, oldest_first=oldest_first, around=around)
|
||||||
|
ret: List[Message] = []
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22
|
||||||
|
|
||||||
|
async def _single_delete_strategy(messages: Iterable[Message]):
|
||||||
|
for m in messages:
|
||||||
|
await m.delete()
|
||||||
|
|
||||||
|
strategy = self.delete_messages if bulk else _single_delete_strategy
|
||||||
|
|
||||||
|
async for message in iterator:
|
||||||
|
if count == 100:
|
||||||
|
to_delete = ret[-100:]
|
||||||
|
await strategy(to_delete)
|
||||||
|
count = 0
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
if not check(message):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if message.id < minimum_time:
|
||||||
|
# older than 14 days old
|
||||||
|
if count == 1:
|
||||||
|
await ret[-1].delete()
|
||||||
|
elif count >= 2:
|
||||||
|
to_delete = ret[-count:]
|
||||||
|
await strategy(to_delete)
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
strategy = _single_delete_strategy
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
ret.append(message)
|
||||||
|
|
||||||
|
# SOme messages remaining to poll
|
||||||
|
if count >= 2:
|
||||||
|
# more than 2 messages -> bulk delete
|
||||||
|
to_delete = ret[-count:]
|
||||||
|
await strategy(to_delete)
|
||||||
|
elif count == 1:
|
||||||
|
# delete a single message
|
||||||
|
await ret[-1].delete()
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
async def edit(
|
async def edit(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@ -386,6 +557,7 @@ class Thread(Messageable, Hashable):
|
|||||||
def _pop_member(self, member_id: int) -> Optional[ThreadMember]:
|
def _pop_member(self, member_id: int) -> Optional[ThreadMember]:
|
||||||
return self._members.pop(member_id, None)
|
return self._members.pop(member_id, None)
|
||||||
|
|
||||||
|
|
||||||
class ThreadMember(Hashable):
|
class ThreadMember(Hashable):
|
||||||
"""Represents a Discord thread member.
|
"""Represents a Discord thread member.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user