Remove userbot functionality
This has a lot of legacy and cruft so there may be some stuff I've missed but this first pass is enough to get a clear separation.
This commit is contained in:
parent
59aa1a0e5f
commit
54288879e2
@ -22,19 +22,17 @@ import logging
|
||||
|
||||
from .client import Client
|
||||
from .appinfo import AppInfo
|
||||
from .user import User, ClientUser, Profile
|
||||
from .user import User, ClientUser
|
||||
from .emoji import Emoji
|
||||
from .partial_emoji import PartialEmoji
|
||||
from .activity import *
|
||||
from .channel import *
|
||||
from .guild import Guild
|
||||
from .flags import *
|
||||
from .relationship import Relationship
|
||||
from .member import Member, VoiceState
|
||||
from .message import *
|
||||
from .asset import Asset
|
||||
from .errors import *
|
||||
from .calls import CallMessage, GroupCall
|
||||
from .permissions import Permissions, PermissionOverwrite
|
||||
from .role import Role, RoleTags
|
||||
from .file import File
|
||||
|
174
discord/calls.py
174
discord/calls.py
@ -1,174 +0,0 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
from . import utils
|
||||
from .enums import VoiceRegion, try_enum
|
||||
from .member import VoiceState
|
||||
|
||||
class CallMessage:
|
||||
"""Represents a group call message from Discord.
|
||||
|
||||
This is only received in cases where the message type is equivalent to
|
||||
:attr:`MessageType.call`.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
ended_timestamp: Optional[:class:`datetime.datetime`]
|
||||
A naive UTC datetime object that represents the time that the call has ended.
|
||||
participants: List[:class:`User`]
|
||||
The list of users that are participating in this call.
|
||||
message: :class:`Message`
|
||||
The message associated with this call message.
|
||||
"""
|
||||
|
||||
def __init__(self, message, **kwargs):
|
||||
self.message = message
|
||||
self.ended_timestamp = utils.parse_time(kwargs.get('ended_timestamp'))
|
||||
self.participants = kwargs.get('participants')
|
||||
|
||||
@property
|
||||
def call_ended(self):
|
||||
""":class:`bool`: Indicates if the call has ended.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
"""
|
||||
return self.ended_timestamp is not None
|
||||
|
||||
@property
|
||||
def channel(self):
|
||||
r""":class:`GroupChannel`\: The private channel associated with this message.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
"""
|
||||
return self.message.channel
|
||||
|
||||
@property
|
||||
def duration(self):
|
||||
"""Queries the duration of the call.
|
||||
|
||||
If the call has not ended then the current duration will
|
||||
be returned.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Returns
|
||||
---------
|
||||
:class:`datetime.timedelta`
|
||||
The timedelta object representing the duration.
|
||||
"""
|
||||
if self.ended_timestamp is None:
|
||||
return datetime.datetime.utcnow() - self.message.created_at
|
||||
else:
|
||||
return self.ended_timestamp - self.message.created_at
|
||||
|
||||
class GroupCall:
|
||||
"""Represents the actual group call from Discord.
|
||||
|
||||
This is accompanied with a :class:`CallMessage` denoting the information.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
call: :class:`CallMessage`
|
||||
The call message associated with this group call.
|
||||
unavailable: :class:`bool`
|
||||
Denotes if this group call is unavailable.
|
||||
ringing: List[:class:`User`]
|
||||
A list of users that are currently being rung to join the call.
|
||||
region: :class:`VoiceRegion`
|
||||
The guild region the group call is being hosted on.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.call = kwargs.get('call')
|
||||
self.unavailable = kwargs.get('unavailable')
|
||||
self._voice_states = {}
|
||||
|
||||
for state in kwargs.get('voice_states', []):
|
||||
self._update_voice_state(state)
|
||||
|
||||
self._update(**kwargs)
|
||||
|
||||
def _update(self, **kwargs):
|
||||
self.region = try_enum(VoiceRegion, kwargs.get('region'))
|
||||
lookup = {u.id: u for u in self.call.channel.recipients}
|
||||
me = self.call.channel.me
|
||||
lookup[me.id] = me
|
||||
self.ringing = list(filter(None, map(lookup.get, kwargs.get('ringing', []))))
|
||||
|
||||
def _update_voice_state(self, data):
|
||||
user_id = int(data['user_id'])
|
||||
# left the voice channel?
|
||||
if data['channel_id'] is None:
|
||||
self._voice_states.pop(user_id, None)
|
||||
else:
|
||||
self._voice_states[user_id] = VoiceState(data=data, channel=self.channel)
|
||||
|
||||
@property
|
||||
def connected(self):
|
||||
"""List[:class:`User`]: A property that returns all users that are currently in this call.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
"""
|
||||
ret = [u for u in self.channel.recipients if self.voice_state_for(u) is not None]
|
||||
me = self.channel.me
|
||||
if self.voice_state_for(me) is not None:
|
||||
ret.append(me)
|
||||
|
||||
return ret
|
||||
|
||||
@property
|
||||
def channel(self):
|
||||
r""":class:`GroupChannel`\: Returns the channel the group call is in.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
"""
|
||||
return self.call.channel
|
||||
|
||||
@utils.deprecated()
|
||||
def voice_state_for(self, user):
|
||||
"""Retrieves the :class:`VoiceState` for a specified :class:`User`.
|
||||
|
||||
If the :class:`User` has no voice state then this function returns
|
||||
``None``.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Parameters
|
||||
------------
|
||||
user: :class:`User`
|
||||
The user to retrieve the voice state for.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`VoiceState`]
|
||||
The voice state associated with this user.
|
||||
"""
|
||||
|
||||
return self._voice_states.get(user.id)
|
@ -311,10 +311,6 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
||||
account). The :attr:`~Permissions.read_message_history` permission is
|
||||
also needed to retrieve message history.
|
||||
|
||||
Internally, this employs a different number of strategies depending
|
||||
on the conditions met such as if a bulk delete is possible or if
|
||||
the account is a user bot or not.
|
||||
|
||||
Examples
|
||||
---------
|
||||
|
||||
@ -345,8 +341,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
||||
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 current account is a user bot (now deprecated), or if messages are
|
||||
older than two weeks.
|
||||
fall back to single delete if messages are older than two weeks.
|
||||
|
||||
Raises
|
||||
-------
|
||||
@ -369,7 +364,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
||||
count = 0
|
||||
|
||||
minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22
|
||||
strategy = self.delete_messages if self._state.is_bot and bulk else _single_delete_strategy
|
||||
strategy = self.delete_messages if bulk else _single_delete_strategy
|
||||
|
||||
while True:
|
||||
try:
|
||||
@ -1442,95 +1437,6 @@ class GroupChannel(discord.abc.Messageable, Hashable):
|
||||
|
||||
return base
|
||||
|
||||
@utils.deprecated()
|
||||
async def add_recipients(self, *recipients):
|
||||
r"""|coro|
|
||||
|
||||
Adds recipients to this group.
|
||||
|
||||
A group can only have a maximum of 10 members.
|
||||
Attempting to add more ends up in an exception. To
|
||||
add a recipient to the group, you must have a relationship
|
||||
with the user of type :attr:`RelationshipType.friend`.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
\*recipients: :class:`User`
|
||||
An argument list of users to add to this group.
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Adding a recipient to this group failed.
|
||||
"""
|
||||
|
||||
# TODO: wait for the corresponding WS event
|
||||
|
||||
req = self._state.http.add_group_recipient
|
||||
for recipient in recipients:
|
||||
await req(self.id, recipient.id)
|
||||
|
||||
@utils.deprecated()
|
||||
async def remove_recipients(self, *recipients):
|
||||
r"""|coro|
|
||||
|
||||
Removes recipients from this group.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
\*recipients: :class:`User`
|
||||
An argument list of users to remove from this group.
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Removing a recipient from this group failed.
|
||||
"""
|
||||
|
||||
# TODO: wait for the corresponding WS event
|
||||
|
||||
req = self._state.http.remove_group_recipient
|
||||
for recipient in recipients:
|
||||
await req(self.id, recipient.id)
|
||||
|
||||
@utils.deprecated()
|
||||
async def edit(self, **fields):
|
||||
"""|coro|
|
||||
|
||||
Edits the group.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
name: Optional[:class:`str`]
|
||||
The new name to change the group to.
|
||||
Could be ``None`` to remove the name.
|
||||
icon: Optional[:class:`bytes`]
|
||||
A :term:`py:bytes-like object` representing the new icon.
|
||||
Could be ``None`` to remove the icon.
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Editing the group failed.
|
||||
"""
|
||||
|
||||
try:
|
||||
icon_bytes = fields['icon']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if icon_bytes is not None:
|
||||
fields['icon'] = utils._bytes_to_base64_data(icon_bytes)
|
||||
|
||||
data = await self._state.http.edit_group(self.id, **fields)
|
||||
self._update_group(data)
|
||||
|
||||
async def leave(self):
|
||||
"""|coro|
|
||||
|
||||
|
@ -30,7 +30,7 @@ import traceback
|
||||
|
||||
import aiohttp
|
||||
|
||||
from .user import User, Profile
|
||||
from .user import User
|
||||
from .invite import Invite
|
||||
from .template import Template
|
||||
from .widget import Widget
|
||||
@ -245,10 +245,7 @@ class Client:
|
||||
|
||||
def _get_state(self, **options):
|
||||
return ConnectionState(dispatch=self.dispatch, handlers=self._handlers,
|
||||
hooks=self._hooks, syncer=self._syncer, http=self.http, loop=self.loop, **options)
|
||||
|
||||
async def _syncer(self, guilds):
|
||||
await self.ws.request_sync(guilds)
|
||||
hooks=self._hooks, http=self.http, loop=self.loop, **options)
|
||||
|
||||
def _handle_ready(self):
|
||||
self._ready.set()
|
||||
@ -454,7 +451,7 @@ class Client:
|
||||
|
||||
# login state management
|
||||
|
||||
async def login(self, token, *, bot=True):
|
||||
async def login(self, token):
|
||||
"""|coro|
|
||||
|
||||
Logs in the client with the specified credentials.
|
||||
@ -473,11 +470,6 @@ class Client:
|
||||
token: :class:`str`
|
||||
The authentication token. Do not prefix this token with
|
||||
anything as the library will do it for you.
|
||||
bot: :class:`bool`
|
||||
Keyword argument that specifies if the account logging on is a bot
|
||||
token or not.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Raises
|
||||
------
|
||||
@ -490,8 +482,7 @@ class Client:
|
||||
"""
|
||||
|
||||
log.info('logging in using static token')
|
||||
await self.http.static_login(token.strip(), bot=bot)
|
||||
self._connection.is_bot = bot
|
||||
await self.http.static_login(token.strip())
|
||||
|
||||
@utils.deprecated('Client.close')
|
||||
async def logout(self):
|
||||
@ -628,7 +619,7 @@ class Client:
|
||||
self._connection.clear()
|
||||
self.http.recreate()
|
||||
|
||||
async def start(self, *args, **kwargs):
|
||||
async def start(self, token, *, reconnect=True):
|
||||
"""|coro|
|
||||
|
||||
A shorthand coroutine for :meth:`login` + :meth:`connect`.
|
||||
@ -638,13 +629,7 @@ class Client:
|
||||
TypeError
|
||||
An unexpected keyword argument was received.
|
||||
"""
|
||||
bot = kwargs.pop('bot', True)
|
||||
reconnect = kwargs.pop('reconnect', True)
|
||||
|
||||
if kwargs:
|
||||
raise TypeError(f"unexpected keyword argument(s) {list(kwargs.keys())}")
|
||||
|
||||
await self.login(*args, bot=bot)
|
||||
await self.login(token)
|
||||
await self.connect(reconnect=reconnect)
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
@ -1364,51 +1349,6 @@ class Client:
|
||||
data = await self.http.get_user(user_id)
|
||||
return User(state=self._connection, data=data)
|
||||
|
||||
@utils.deprecated()
|
||||
async def fetch_user_profile(self, user_id):
|
||||
"""|coro|
|
||||
|
||||
Gets an arbitrary user's profile.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Parameters
|
||||
------------
|
||||
user_id: :class:`int`
|
||||
The ID of the user to fetch their profile for.
|
||||
|
||||
Raises
|
||||
-------
|
||||
:exc:`.Forbidden`
|
||||
Not allowed to fetch profiles.
|
||||
:exc:`.HTTPException`
|
||||
Fetching the profile failed.
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`.Profile`
|
||||
The profile of the user.
|
||||
"""
|
||||
|
||||
state = self._connection
|
||||
data = await self.http.get_user_profile(user_id)
|
||||
|
||||
def transform(d):
|
||||
return state._get_guild(int(d['id']))
|
||||
|
||||
since = data.get('premium_since')
|
||||
mutual_guilds = list(filter(None, map(transform, data.get('mutual_guilds', []))))
|
||||
user = data['user']
|
||||
return Profile(flags=user.get('flags', 0),
|
||||
premium_since=utils.parse_time(since),
|
||||
mutual_guilds=mutual_guilds,
|
||||
user=User(data=user, state=state),
|
||||
connected_accounts=data['connected_accounts'])
|
||||
|
||||
async def fetch_channel(self, channel_id):
|
||||
"""|coro|
|
||||
|
||||
|
@ -35,18 +35,12 @@ __all__ = (
|
||||
'ContentFilter',
|
||||
'Status',
|
||||
'DefaultAvatar',
|
||||
'RelationshipType',
|
||||
'AuditLogAction',
|
||||
'AuditLogActionCategory',
|
||||
'UserFlags',
|
||||
'ActivityType',
|
||||
'HypeSquadHouse',
|
||||
'NotificationLevel',
|
||||
'PremiumType',
|
||||
'UserContentFilter',
|
||||
'FriendFlags',
|
||||
'TeamMembershipState',
|
||||
'Theme',
|
||||
'WebhookType',
|
||||
'ExpireBehaviour',
|
||||
'ExpireBehavior',
|
||||
@ -242,22 +236,6 @@ class ContentFilter(Enum):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class UserContentFilter(Enum):
|
||||
disabled = 0
|
||||
friends = 1
|
||||
all_messages = 2
|
||||
|
||||
class FriendFlags(Enum):
|
||||
noone = 0
|
||||
mutual_guilds = 1
|
||||
mutual_friends = 2
|
||||
guild_and_friends = 3
|
||||
everyone = 4
|
||||
|
||||
class Theme(Enum):
|
||||
light = 'light'
|
||||
dark = 'dark'
|
||||
|
||||
class Status(Enum):
|
||||
online = 'online'
|
||||
offline = 'offline'
|
||||
@ -280,12 +258,6 @@ class DefaultAvatar(Enum):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class RelationshipType(Enum):
|
||||
friend = 1
|
||||
blocked = 2
|
||||
incoming_request = 3
|
||||
outgoing_request = 4
|
||||
|
||||
class NotificationLevel(Enum):
|
||||
all_messages = 0
|
||||
only_mentions = 1
|
||||
@ -427,15 +399,6 @@ class ActivityType(Enum):
|
||||
def __int__(self):
|
||||
return self.value
|
||||
|
||||
class HypeSquadHouse(Enum):
|
||||
bravery = 1
|
||||
brilliance = 2
|
||||
balance = 3
|
||||
|
||||
class PremiumType(Enum):
|
||||
nitro_classic = 1
|
||||
nitro = 2
|
||||
|
||||
class TeamMembershipState(Enum):
|
||||
invited = 1
|
||||
accepted = 2
|
||||
|
@ -378,9 +378,6 @@ class DiscordWebSocket:
|
||||
}
|
||||
}
|
||||
|
||||
if not self._connection.is_bot:
|
||||
payload['d']['synced_guilds'] = []
|
||||
|
||||
if self.shard_id is not None and self.shard_count is not None:
|
||||
payload['d']['shard'] = [self.shard_id, self.shard_count]
|
||||
|
||||
@ -622,13 +619,6 @@ class DiscordWebSocket:
|
||||
log.debug('Sending "%s" to change status', sent)
|
||||
await self.send(sent)
|
||||
|
||||
async def request_sync(self, guild_ids):
|
||||
payload = {
|
||||
'op': self.GUILD_SYNC,
|
||||
'd': list(guild_ids)
|
||||
}
|
||||
await self.send_as_json(payload)
|
||||
|
||||
async def request_chunks(self, guild_id, query=None, *, limit, user_ids=None, presences=False, nonce=None):
|
||||
payload = {
|
||||
'op': self.REQUEST_MEMBERS,
|
||||
|
@ -2090,29 +2090,6 @@ class Guild(Hashable):
|
||||
payload['max_age'] = 0
|
||||
return Invite(state=self._state, data=payload)
|
||||
|
||||
@utils.deprecated()
|
||||
def ack(self):
|
||||
"""|coro|
|
||||
|
||||
Marks every message in this guild as read.
|
||||
|
||||
The user must not be a bot user.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Acking failed.
|
||||
ClientException
|
||||
You must not be a bot user.
|
||||
"""
|
||||
|
||||
state = self._state
|
||||
if state.is_bot:
|
||||
raise ClientException('Must not be a bot account to ack messages.')
|
||||
return state.http.ack_guild(self.id)
|
||||
|
||||
def audit_logs(self, *, limit=100, before=None, after=None, oldest_first=None, user=None, action=None):
|
||||
"""Returns an :class:`AsyncIterator` that enables receiving the guild's audit logs.
|
||||
|
||||
|
@ -147,7 +147,7 @@ class HTTPClient:
|
||||
}
|
||||
|
||||
if self.token is not None:
|
||||
headers['Authorization'] = 'Bot ' + self.token if self.bot_token else self.token
|
||||
headers['Authorization'] = 'Bot ' + self.token
|
||||
# some checking if it's a JSON request
|
||||
if 'json' in kwargs:
|
||||
headers['Content-Type'] = 'application/json'
|
||||
@ -281,23 +281,18 @@ class HTTPClient:
|
||||
if self.__session:
|
||||
await self.__session.close()
|
||||
|
||||
def _token(self, token, *, bot=True):
|
||||
self.token = token
|
||||
self.bot_token = bot
|
||||
self._ack_token = None
|
||||
|
||||
# login management
|
||||
|
||||
async def static_login(self, token, *, bot):
|
||||
async def static_login(self, token):
|
||||
# Necessary to get aiohttp to stop complaining about session creation
|
||||
self.__session = aiohttp.ClientSession(connector=self.connector, ws_response_class=DiscordClientWebSocketResponse)
|
||||
old_token, old_bot = self.token, self.bot_token
|
||||
self._token(token, bot=bot)
|
||||
old_token = self.token
|
||||
self.token = token
|
||||
|
||||
try:
|
||||
data = await self.request(Route('GET', '/users/@me'))
|
||||
except HTTPException as exc:
|
||||
self._token(old_token, bot=old_bot)
|
||||
self.token = old_token
|
||||
if exc.response.status == 401:
|
||||
raise LoginFailure('Improper token has been passed.') from exc
|
||||
raise
|
||||
@ -319,25 +314,6 @@ class HTTPClient:
|
||||
def leave_group(self, channel_id):
|
||||
return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id))
|
||||
|
||||
def add_group_recipient(self, channel_id, user_id):
|
||||
r = Route('PUT', '/channels/{channel_id}/recipients/{user_id}', channel_id=channel_id, user_id=user_id)
|
||||
return self.request(r)
|
||||
|
||||
def remove_group_recipient(self, channel_id, user_id):
|
||||
r = Route('DELETE', '/channels/{channel_id}/recipients/{user_id}', channel_id=channel_id, user_id=user_id)
|
||||
return self.request(r)
|
||||
|
||||
def edit_group(self, channel_id, **options):
|
||||
valid_keys = ('name', 'icon')
|
||||
payload = {
|
||||
k: v for k, v in options.items() if k in valid_keys
|
||||
}
|
||||
|
||||
return self.request(Route('PATCH', '/channels/{channel_id}', channel_id=channel_id), json=payload)
|
||||
|
||||
def convert_group(self, channel_id):
|
||||
return self.request(Route('POST', '/channels/{channel_id}/convert', channel_id=channel_id))
|
||||
|
||||
# Message management
|
||||
|
||||
def start_private_message(self, user_id):
|
||||
@ -410,14 +386,6 @@ class HTTPClient:
|
||||
|
||||
return self.request(r, form=form, files=files)
|
||||
|
||||
async def ack_message(self, channel_id, message_id):
|
||||
r = Route('POST', '/channels/{channel_id}/messages/{message_id}/ack', channel_id=channel_id, message_id=message_id)
|
||||
data = await self.request(r, json={'token': self._ack_token})
|
||||
self._ack_token = data['token']
|
||||
|
||||
def ack_guild(self, guild_id):
|
||||
return self.request(Route('POST', '/guilds/{guild_id}/ack', guild_id=guild_id))
|
||||
|
||||
def delete_message(self, channel_id, message_id, *, reason=None):
|
||||
r = Route('DELETE', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id, message_id=message_id)
|
||||
return self.request(r, reason=reason)
|
||||
@ -543,18 +511,12 @@ class HTTPClient:
|
||||
|
||||
return self.request(r, json=payload, reason=reason)
|
||||
|
||||
def edit_profile(self, password, username, avatar, **fields):
|
||||
payload = {
|
||||
'password': password,
|
||||
'username': username,
|
||||
'avatar': avatar
|
||||
}
|
||||
|
||||
if 'email' in fields:
|
||||
payload['email'] = fields['email']
|
||||
|
||||
if 'new_password' in fields:
|
||||
payload['new_password'] = fields['new_password']
|
||||
def edit_profile(self, username, avatar):
|
||||
payload = {}
|
||||
if avatar is not None:
|
||||
payload['avatar'] = avatar
|
||||
if username is not None:
|
||||
payload['username'] = username
|
||||
|
||||
return self.request(Route('PATCH', '/users/@me'), json=payload)
|
||||
|
||||
@ -933,28 +895,6 @@ class HTTPClient:
|
||||
def move_member(self, user_id, guild_id, channel_id, *, reason=None):
|
||||
return self.edit_member(guild_id=guild_id, user_id=user_id, channel_id=channel_id, reason=reason)
|
||||
|
||||
# Relationship related
|
||||
|
||||
def remove_relationship(self, user_id):
|
||||
r = Route('DELETE', '/users/@me/relationships/{user_id}', user_id=user_id)
|
||||
return self.request(r)
|
||||
|
||||
def add_relationship(self, user_id, type=None):
|
||||
r = Route('PUT', '/users/@me/relationships/{user_id}', user_id=user_id)
|
||||
payload = {}
|
||||
if type is not None:
|
||||
payload['type'] = type
|
||||
|
||||
return self.request(r, json=payload)
|
||||
|
||||
def send_friend_request(self, username, discriminator):
|
||||
r = Route('POST', '/users/@me/relationships')
|
||||
payload = {
|
||||
'username': username,
|
||||
'discriminator': int(discriminator)
|
||||
}
|
||||
return self.request(r, json=payload)
|
||||
|
||||
# Misc
|
||||
|
||||
def application_info(self):
|
||||
@ -985,19 +925,3 @@ class HTTPClient:
|
||||
|
||||
def get_user(self, user_id):
|
||||
return self.request(Route('GET', '/users/{user_id}', user_id=user_id))
|
||||
|
||||
def get_user_profile(self, user_id):
|
||||
return self.request(Route('GET', '/users/{user_id}/profile', user_id=user_id))
|
||||
|
||||
def get_mutual_friends(self, user_id):
|
||||
return self.request(Route('GET', '/users/{user_id}/relationships', user_id=user_id))
|
||||
|
||||
def change_hypesquad_house(self, house_id):
|
||||
payload = {'house_id': house_id}
|
||||
return self.request(Route('POST', '/hypesquad/online'), json=payload)
|
||||
|
||||
def leave_hypesquad_house(self):
|
||||
return self.request(Route('DELETE', '/hypesquad/online'))
|
||||
|
||||
def edit_settings(self, **payload):
|
||||
return self.request(Route('PATCH', '/users/@me/settings'), json=payload)
|
||||
|
@ -31,7 +31,6 @@ from . import utils
|
||||
from .reaction import Reaction
|
||||
from .emoji import Emoji
|
||||
from .partial_emoji import PartialEmoji
|
||||
from .calls import CallMessage
|
||||
from .enums import MessageType, ChannelType, try_enum
|
||||
from .errors import InvalidArgument, ClientException, HTTPException
|
||||
from .embeds import Embed
|
||||
@ -453,12 +452,6 @@ class Message(Hashable):
|
||||
channel: Union[:class:`abc.Messageable`]
|
||||
The :class:`TextChannel` that the message was sent from.
|
||||
Could be a :class:`DMChannel` or :class:`GroupChannel` if it's a private message.
|
||||
call: Optional[:class:`CallMessage`]
|
||||
The call that the message refers to. This is only applicable to messages of type
|
||||
:attr:`MessageType.call`.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
reference: Optional[:class:`~discord.MessageReference`]
|
||||
The message that this message references. This is only applicable to messages of
|
||||
type :attr:`MessageType.pins_add`, crossposted messages created by a
|
||||
@ -534,7 +527,7 @@ class Message(Hashable):
|
||||
'mention_everyone', 'embeds', 'id', 'mentions', 'author',
|
||||
'_cs_channel_mentions', '_cs_raw_mentions', 'attachments',
|
||||
'_cs_clean_content', '_cs_raw_channel_mentions', 'nonce', 'pinned',
|
||||
'role_mentions', '_cs_raw_role_mentions', 'type', 'call', 'flags',
|
||||
'role_mentions', '_cs_raw_role_mentions', 'type', 'flags',
|
||||
'_cs_system_content', '_cs_guild', '_state', 'reactions', 'reference',
|
||||
'application', 'activity', 'stickers')
|
||||
|
||||
@ -548,7 +541,6 @@ class Message(Hashable):
|
||||
self.application = data.get('application')
|
||||
self.activity = data.get('activity')
|
||||
self.channel = channel
|
||||
self.call = None
|
||||
self._edited_timestamp = utils.parse_time(data['edited_timestamp'])
|
||||
self.type = try_enum(MessageType, data['type'])
|
||||
self.pinned = data['pinned']
|
||||
@ -581,7 +573,7 @@ class Message(Hashable):
|
||||
|
||||
ref.resolved = self.__class__(channel=chan, data=resolved, state=state)
|
||||
|
||||
for handler in ('author', 'member', 'mentions', 'mention_roles', 'call', 'flags'):
|
||||
for handler in ('author', 'member', 'mentions', 'mention_roles', 'flags'):
|
||||
try:
|
||||
getattr(self, f'_handle_{handler}')(data[handler])
|
||||
except KeyError:
|
||||
@ -749,26 +741,6 @@ class Message(Hashable):
|
||||
if role is not None:
|
||||
self.role_mentions.append(role)
|
||||
|
||||
def _handle_call(self, call):
|
||||
if call is None or self.type is not MessageType.call:
|
||||
self.call = None
|
||||
return
|
||||
|
||||
# we get the participant source from the mentions array or
|
||||
# the author
|
||||
|
||||
participants = []
|
||||
for uid in map(int, call.get('participants', [])):
|
||||
if uid == self.author.id:
|
||||
participants.append(self.author)
|
||||
else:
|
||||
user = utils.find(lambda u: u.id == uid, self.mentions)
|
||||
if user is not None:
|
||||
participants.append(user)
|
||||
|
||||
call['participants'] = participants
|
||||
self.call = CallMessage(message=self, **call)
|
||||
|
||||
def _rebind_channel_reference(self, new_channel):
|
||||
self.channel = new_channel
|
||||
|
||||
@ -937,19 +909,6 @@ class Message(Hashable):
|
||||
created_at_ms = int((self.created_at - datetime.datetime(1970, 1, 1)).total_seconds() * 1000)
|
||||
return formats[created_at_ms % len(formats)].format(self.author.name)
|
||||
|
||||
if self.type is MessageType.call:
|
||||
# we're at the call message type now, which is a bit more complicated.
|
||||
# we can make the assumption that Message.channel is a PrivateChannel
|
||||
# with the type ChannelType.group or ChannelType.private
|
||||
call_ended = self.call.ended_timestamp is not None
|
||||
|
||||
if self.channel.me in self.call.participants:
|
||||
return f'{self.author.name} started a call.'
|
||||
elif call_ended:
|
||||
return f'You missed a call from {self.author.name}'
|
||||
else:
|
||||
return '{0.author.name} started a call \N{EM DASH} Join the call.'.format(self)
|
||||
|
||||
if self.type is MessageType.premium_guild_subscription:
|
||||
return f'{self.author.name} just boosted the server!'
|
||||
|
||||
@ -1303,29 +1262,6 @@ class Message(Hashable):
|
||||
"""
|
||||
await self._state.http.clear_reactions(self.channel.id, self.id)
|
||||
|
||||
@utils.deprecated()
|
||||
async def ack(self):
|
||||
"""|coro|
|
||||
|
||||
Marks this message as read.
|
||||
|
||||
The user must not be a bot user.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Acking failed.
|
||||
ClientException
|
||||
You must not be a bot user.
|
||||
"""
|
||||
|
||||
state = self._state
|
||||
if state.is_bot:
|
||||
raise ClientException('Must not be a bot account to ack messages.')
|
||||
return await state.http.ack_message(self.channel.id, self.id)
|
||||
|
||||
async def reply(self, content=None, **kwargs):
|
||||
"""|coro|
|
||||
|
||||
|
@ -1,85 +0,0 @@
|
||||
"""
|
||||
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 .enums import RelationshipType, try_enum
|
||||
from . import utils
|
||||
|
||||
class Relationship:
|
||||
"""Represents a relationship in Discord.
|
||||
|
||||
A relationship is like a friendship, a person who is blocked, etc.
|
||||
Only non-bot accounts can have relationships.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
user: :class:`User`
|
||||
The user you have the relationship with.
|
||||
type: :class:`RelationshipType`
|
||||
The type of relationship you have.
|
||||
"""
|
||||
|
||||
__slots__ = ('type', 'user', '_state')
|
||||
|
||||
def __init__(self, *, state, data):
|
||||
self._state = state
|
||||
self.type = try_enum(RelationshipType, data['type'])
|
||||
self.user = state.store_user(data['user'])
|
||||
|
||||
def __repr__(self):
|
||||
return '<Relationship user={0.user!r} type={0.type!r}>'.format(self)
|
||||
|
||||
@utils.deprecated()
|
||||
async def delete(self):
|
||||
"""|coro|
|
||||
|
||||
Deletes the relationship.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Raises
|
||||
------
|
||||
HTTPException
|
||||
Deleting the relationship failed.
|
||||
"""
|
||||
|
||||
await self._state.http.remove_relationship(self.user.id)
|
||||
|
||||
@utils.deprecated()
|
||||
async def accept(self):
|
||||
"""|coro|
|
||||
|
||||
Accepts the relationship request. e.g. accepting a
|
||||
friend request.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Accepting the relationship failed.
|
||||
"""
|
||||
|
||||
await self._state.http.add_relationship(self.user.id)
|
@ -317,7 +317,7 @@ class AutoShardedClient(Client):
|
||||
|
||||
def _get_state(self, **options):
|
||||
return AutoShardedConnectionState(dispatch=self.dispatch,
|
||||
handlers=self._handlers, syncer=self._syncer,
|
||||
handlers=self._handlers,
|
||||
hooks=self._hooks, http=self.http, loop=self.loop, **options)
|
||||
|
||||
@property
|
||||
|
122
discord/state.py
122
discord/state.py
@ -42,7 +42,6 @@ from .emoji import Emoji
|
||||
from .mentions import AllowedMentions
|
||||
from .partial_emoji import PartialEmoji
|
||||
from .message import Message
|
||||
from .relationship import Relationship
|
||||
from .channel import *
|
||||
from .raw_models import *
|
||||
from .member import Member
|
||||
@ -102,7 +101,7 @@ async def logging_coroutine(coroutine, *, info):
|
||||
log.exception('Exception occurred during %s', info)
|
||||
|
||||
class ConnectionState:
|
||||
def __init__(self, *, dispatch, handlers, hooks, syncer, http, loop, **options):
|
||||
def __init__(self, *, dispatch, handlers, hooks, http, loop, **options):
|
||||
self.loop = loop
|
||||
self.http = http
|
||||
self.max_messages = options.get('max_messages', 1000)
|
||||
@ -110,8 +109,6 @@ class ConnectionState:
|
||||
self.max_messages = 1000
|
||||
|
||||
self.dispatch = dispatch
|
||||
self.syncer = syncer
|
||||
self.is_bot = None
|
||||
self.handlers = handlers
|
||||
self.hooks = hooks
|
||||
self.shard_count = None
|
||||
@ -196,7 +193,6 @@ class ConnectionState:
|
||||
self.user = None
|
||||
self._users = weakref.WeakValueDictionary()
|
||||
self._emojis = {}
|
||||
self._calls = {}
|
||||
self._guilds = {}
|
||||
self._voice_clients = {}
|
||||
|
||||
@ -338,7 +334,7 @@ class ConnectionState:
|
||||
channel_id = channel.id
|
||||
self._private_channels[channel_id] = channel
|
||||
|
||||
if self.is_bot and len(self._private_channels) > 128:
|
||||
if len(self._private_channels) > 128:
|
||||
_, to_remove = self._private_channels.popitem(last=False)
|
||||
if isinstance(to_remove, DMChannel):
|
||||
self._private_channels_by_user.pop(to_remove.recipient.id, None)
|
||||
@ -403,36 +399,34 @@ class ConnectionState:
|
||||
|
||||
async def _delay_ready(self):
|
||||
try:
|
||||
# only real bots wait for GUILD_CREATE streaming
|
||||
if self.is_bot:
|
||||
states = []
|
||||
while True:
|
||||
# this snippet of code is basically waiting N seconds
|
||||
# until the last GUILD_CREATE was sent
|
||||
try:
|
||||
guild = await asyncio.wait_for(self._ready_state.get(), timeout=self.guild_ready_timeout)
|
||||
except asyncio.TimeoutError:
|
||||
break
|
||||
states = []
|
||||
while True:
|
||||
# this snippet of code is basically waiting N seconds
|
||||
# until the last GUILD_CREATE was sent
|
||||
try:
|
||||
guild = await asyncio.wait_for(self._ready_state.get(), timeout=self.guild_ready_timeout)
|
||||
except asyncio.TimeoutError:
|
||||
break
|
||||
else:
|
||||
if self._guild_needs_chunking(guild):
|
||||
future = await self.chunk_guild(guild, wait=False)
|
||||
states.append((guild, future))
|
||||
else:
|
||||
if self._guild_needs_chunking(guild):
|
||||
future = await self.chunk_guild(guild, wait=False)
|
||||
states.append((guild, future))
|
||||
if guild.unavailable is False:
|
||||
self.dispatch('guild_available', guild)
|
||||
else:
|
||||
if guild.unavailable is False:
|
||||
self.dispatch('guild_available', guild)
|
||||
else:
|
||||
self.dispatch('guild_join', guild)
|
||||
self.dispatch('guild_join', guild)
|
||||
|
||||
for guild, future in states:
|
||||
try:
|
||||
await asyncio.wait_for(future, timeout=5.0)
|
||||
except asyncio.TimeoutError:
|
||||
log.warning('Shard ID %s timed out waiting for chunks for guild_id %s.', guild.shard_id, guild.id)
|
||||
for guild, future in states:
|
||||
try:
|
||||
await asyncio.wait_for(future, timeout=5.0)
|
||||
except asyncio.TimeoutError:
|
||||
log.warning('Shard ID %s timed out waiting for chunks for guild_id %s.', guild.shard_id, guild.id)
|
||||
|
||||
if guild.unavailable is False:
|
||||
self.dispatch('guild_available', guild)
|
||||
else:
|
||||
self.dispatch('guild_join', guild)
|
||||
if guild.unavailable is False:
|
||||
self.dispatch('guild_available', guild)
|
||||
else:
|
||||
self.dispatch('guild_join', guild)
|
||||
|
||||
# remove the state
|
||||
try:
|
||||
@ -440,10 +434,6 @@ class ConnectionState:
|
||||
except AttributeError:
|
||||
pass # already been deleted somehow
|
||||
|
||||
# call GUILD_SYNC after we're done chunking
|
||||
if not self.is_bot:
|
||||
log.info('Requesting GUILD_SYNC for %s guilds', len(self.guilds))
|
||||
await self.syncer([s.id for s in self.guilds])
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
else:
|
||||
@ -465,18 +455,6 @@ class ConnectionState:
|
||||
for guild_data in data['guilds']:
|
||||
self._add_guild_from_data(guild_data)
|
||||
|
||||
for relationship in data.get('relationships', []):
|
||||
try:
|
||||
r_id = int(relationship['id'])
|
||||
except KeyError:
|
||||
continue
|
||||
else:
|
||||
user._relationships[r_id] = Relationship(state=self, data=relationship)
|
||||
|
||||
for pm in data.get('private_channels', []):
|
||||
factory, _ = _channel_factory(pm['type'])
|
||||
self._add_private_channel(factory(me=user, data=pm, state=self))
|
||||
|
||||
self.dispatch('connect')
|
||||
self._ready_task = asyncio.ensure_future(self._delay_ready(), loop=self.loop)
|
||||
|
||||
@ -722,22 +700,6 @@ class ConnectionState:
|
||||
else:
|
||||
self.dispatch('guild_channel_pins_update', channel, last_pin)
|
||||
|
||||
def parse_channel_recipient_add(self, data):
|
||||
channel = self._get_private_channel(int(data['channel_id']))
|
||||
user = self.store_user(data['user'])
|
||||
channel.recipients.append(user)
|
||||
self.dispatch('group_join', channel, user)
|
||||
|
||||
def parse_channel_recipient_remove(self, data):
|
||||
channel = self._get_private_channel(int(data['channel_id']))
|
||||
user = self.store_user(data['user'])
|
||||
try:
|
||||
channel.recipients.remove(user)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
self.dispatch('group_remove', channel, user)
|
||||
|
||||
def parse_guild_member_add(self, data):
|
||||
guild = self._get_guild(int(data['guild_id']))
|
||||
if guild is None:
|
||||
@ -875,10 +837,6 @@ class ConnectionState:
|
||||
else:
|
||||
self.dispatch('guild_join', guild)
|
||||
|
||||
def parse_guild_sync(self, data):
|
||||
guild = self._get_guild(int(data['id']))
|
||||
guild._sync(data)
|
||||
|
||||
def parse_guild_update(self, data):
|
||||
guild = self._get_guild(int(data['id']))
|
||||
if guild is not None:
|
||||
@ -1024,11 +982,6 @@ class ConnectionState:
|
||||
self.dispatch('voice_state_update', member, before, after)
|
||||
else:
|
||||
log.debug('VOICE_STATE_UPDATE referencing an unknown member ID: %s. Discarding.', data['user_id'])
|
||||
else:
|
||||
# in here we're either at private or group calls
|
||||
call = self._calls.get(channel_id)
|
||||
if call is not None:
|
||||
call._update_voice_state(data)
|
||||
|
||||
def parse_voice_server_update(self, data):
|
||||
try:
|
||||
@ -1062,25 +1015,6 @@ class ConnectionState:
|
||||
timestamp = datetime.datetime.utcfromtimestamp(data.get('timestamp'))
|
||||
self.dispatch('typing', channel, member, timestamp)
|
||||
|
||||
def parse_relationship_add(self, data):
|
||||
key = int(data['id'])
|
||||
old = self.user.get_relationship(key)
|
||||
new = Relationship(state=self, data=data)
|
||||
self.user._relationships[key] = new
|
||||
if old is not None:
|
||||
self.dispatch('relationship_update', old, new)
|
||||
else:
|
||||
self.dispatch('relationship_add', new)
|
||||
|
||||
def parse_relationship_remove(self, data):
|
||||
key = int(data['id'])
|
||||
try:
|
||||
old = self.user._relationships.pop(key)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
self.dispatch('relationship_remove', old)
|
||||
|
||||
def _get_reaction_user(self, channel, user_id):
|
||||
if isinstance(channel, TextChannel):
|
||||
return channel.guild.get_member(user_id)
|
||||
@ -1224,10 +1158,6 @@ class AutoShardedConnectionState(ConnectionState):
|
||||
if self._messages:
|
||||
self._update_message_references()
|
||||
|
||||
for pm in data.get('private_channels', []):
|
||||
factory, _ = _channel_factory(pm['type'])
|
||||
self._add_private_channel(factory(me=user, data=pm, state=self))
|
||||
|
||||
self.dispatch('connect')
|
||||
self.dispatch('shard_connect', data['__shard_id__'])
|
||||
|
||||
|
@ -41,10 +41,6 @@ class _PartialTemplateState:
|
||||
self.__state = state
|
||||
self.http = _FriendlyHttpAttributeErrorHelper()
|
||||
|
||||
@property
|
||||
def is_bot(self):
|
||||
return self.__state.is_bot
|
||||
|
||||
@property
|
||||
def shard_count(self):
|
||||
return self.__state.shard_count
|
||||
@ -125,7 +121,7 @@ class Template:
|
||||
source_serialised['id'] = id
|
||||
state = _PartialTemplateState(state=self._state)
|
||||
guild = Guild(data=source_serialised, state=state)
|
||||
|
||||
|
||||
self.source_guild = guild
|
||||
|
||||
def __repr__(self):
|
||||
|
558
discord/user.py
558
discord/user.py
@ -22,62 +22,12 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
import discord.abc
|
||||
from .flags import PublicUserFlags
|
||||
from .utils import snowflake_time, _bytes_to_base64_data, parse_time
|
||||
from .enums import DefaultAvatar, RelationshipType, UserFlags, HypeSquadHouse, PremiumType, try_enum
|
||||
from .errors import ClientException
|
||||
from .utils import snowflake_time, _bytes_to_base64_data
|
||||
from .enums import DefaultAvatar, try_enum
|
||||
from .colour import Colour
|
||||
from .asset import Asset
|
||||
from .utils import deprecated
|
||||
|
||||
class Profile(namedtuple('Profile', 'flags user mutual_guilds connected_accounts premium_since')):
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def nitro(self):
|
||||
return self.premium_since is not None
|
||||
|
||||
premium = nitro
|
||||
|
||||
def _has_flag(self, o):
|
||||
v = o.value
|
||||
return (self.flags & v) == v
|
||||
|
||||
@property
|
||||
def staff(self):
|
||||
return self._has_flag(UserFlags.staff)
|
||||
|
||||
@property
|
||||
def partner(self):
|
||||
return self._has_flag(UserFlags.partner)
|
||||
|
||||
@property
|
||||
def bug_hunter(self):
|
||||
return self._has_flag(UserFlags.bug_hunter)
|
||||
|
||||
@property
|
||||
def early_supporter(self):
|
||||
return self._has_flag(UserFlags.early_supporter)
|
||||
|
||||
@property
|
||||
def hypesquad(self):
|
||||
return self._has_flag(UserFlags.hypesquad)
|
||||
|
||||
@property
|
||||
def hypesquad_houses(self):
|
||||
flags = (UserFlags.hypesquad_bravery, UserFlags.hypesquad_brilliance, UserFlags.hypesquad_balance)
|
||||
return [house for house, flag in zip(HypeSquadHouse, flags) if self._has_flag(flag)]
|
||||
|
||||
@property
|
||||
def team_user(self):
|
||||
return self._has_flag(UserFlags.team_user)
|
||||
|
||||
@property
|
||||
def system(self):
|
||||
return self._has_flag(UserFlags.system)
|
||||
|
||||
_BaseUser = discord.abc.User
|
||||
|
||||
@ -314,32 +264,16 @@ class ClientUser(BaseUser):
|
||||
|
||||
verified: :class:`bool`
|
||||
Specifies if the user is a verified account.
|
||||
email: Optional[:class:`str`]
|
||||
The email the user used when registering.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
locale: Optional[:class:`str`]
|
||||
The IETF language tag used to identify the language the user is using.
|
||||
mfa_enabled: :class:`bool`
|
||||
Specifies if the user has MFA turned on and working.
|
||||
premium: :class:`bool`
|
||||
Specifies if the user is a premium user (e.g. has Discord Nitro).
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
premium_type: Optional[:class:`PremiumType`]
|
||||
Specifies the type of premium a user has (e.g. Nitro or Nitro Classic). Could be None if the user is not premium.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
"""
|
||||
__slots__ = BaseUser.__slots__ + \
|
||||
('email', 'locale', '_flags', 'verified', 'mfa_enabled',
|
||||
'premium', 'premium_type', '_relationships', '__weakref__')
|
||||
('locale', '_flags', 'verified', 'mfa_enabled', '__weakref__')
|
||||
|
||||
def __init__(self, *, state, data):
|
||||
super().__init__(state=state, data=data)
|
||||
self._relationships = {}
|
||||
|
||||
def __repr__(self):
|
||||
return '<ClientUser id={0.id} name={0.name!r} discriminator={0.discriminator!r}' \
|
||||
@ -349,83 +283,16 @@ class ClientUser(BaseUser):
|
||||
super()._update(data)
|
||||
# There's actually an Optional[str] phone field as well but I won't use it
|
||||
self.verified = data.get('verified', False)
|
||||
self.email = data.get('email')
|
||||
self.locale = data.get('locale')
|
||||
self._flags = data.get('flags', 0)
|
||||
self.mfa_enabled = data.get('mfa_enabled', False)
|
||||
self.premium = data.get('premium', False)
|
||||
self.premium_type = try_enum(PremiumType, data.get('premium_type', None))
|
||||
|
||||
@deprecated()
|
||||
def get_relationship(self, user_id):
|
||||
"""Retrieves the :class:`Relationship` if applicable.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
user_id: :class:`int`
|
||||
The user ID to check if we have a relationship with them.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`Relationship`]
|
||||
The relationship if available or ``None``.
|
||||
"""
|
||||
return self._relationships.get(user_id)
|
||||
|
||||
@property
|
||||
def relationships(self):
|
||||
"""List[:class:`User`]: Returns all the relationships that the user has.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
"""
|
||||
return list(self._relationships.values())
|
||||
|
||||
@property
|
||||
def friends(self):
|
||||
r"""List[:class:`User`]: Returns all the users that the user is friends with.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
"""
|
||||
return [r.user for r in self._relationships.values() if r.type is RelationshipType.friend]
|
||||
|
||||
@property
|
||||
def blocked(self):
|
||||
r"""List[:class:`User`]: Returns all the users that the user has blocked.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
"""
|
||||
return [r.user for r in self._relationships.values() if r.type is RelationshipType.blocked]
|
||||
|
||||
async def edit(self, **fields):
|
||||
async def edit(self, *, username=None, avatar=None):
|
||||
"""|coro|
|
||||
|
||||
Edits the current profile of the client.
|
||||
|
||||
If a bot account is used then a password field is optional,
|
||||
otherwise it is required.
|
||||
|
||||
.. warning::
|
||||
|
||||
The user account-only fields are deprecated.
|
||||
|
||||
.. note::
|
||||
|
||||
To upload an avatar, a :term:`py:bytes-like object` must be passed in that
|
||||
@ -437,19 +304,6 @@ class ClientUser(BaseUser):
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
password: :class:`str`
|
||||
The current password for the client's account.
|
||||
Only applicable to user accounts.
|
||||
new_password: :class:`str`
|
||||
The new password you wish to change to.
|
||||
Only applicable to user accounts.
|
||||
email: :class:`str`
|
||||
The new email you wish to change to.
|
||||
Only applicable to user accounts.
|
||||
house: Optional[:class:`HypeSquadHouse`]
|
||||
The hypesquad house you wish to change to.
|
||||
Could be ``None`` to leave the current house.
|
||||
Only applicable to user accounts.
|
||||
username: :class:`str`
|
||||
The new username you wish to change to.
|
||||
avatar: :class:`bytes`
|
||||
@ -462,218 +316,14 @@ class ClientUser(BaseUser):
|
||||
Editing your profile failed.
|
||||
InvalidArgument
|
||||
Wrong image format passed for ``avatar``.
|
||||
ClientException
|
||||
Password is required for non-bot accounts.
|
||||
House field was not a HypeSquadHouse.
|
||||
"""
|
||||
|
||||
try:
|
||||
avatar_bytes = fields['avatar']
|
||||
except KeyError:
|
||||
avatar = self.avatar
|
||||
else:
|
||||
if avatar_bytes is not None:
|
||||
avatar = _bytes_to_base64_data(avatar_bytes)
|
||||
else:
|
||||
avatar = None
|
||||
|
||||
not_bot_account = not self.bot
|
||||
password = fields.get('password')
|
||||
if not_bot_account and password is None:
|
||||
raise ClientException('Password is required for non-bot accounts.')
|
||||
|
||||
args = {
|
||||
'password': password,
|
||||
'username': fields.get('username', self.name),
|
||||
'avatar': avatar
|
||||
}
|
||||
|
||||
if not_bot_account:
|
||||
args['email'] = fields.get('email', self.email)
|
||||
|
||||
if 'new_password' in fields:
|
||||
args['new_password'] = fields['new_password']
|
||||
|
||||
http = self._state.http
|
||||
|
||||
if 'house' in fields:
|
||||
house = fields['house']
|
||||
if house is None:
|
||||
await http.leave_hypesquad_house()
|
||||
elif not isinstance(house, HypeSquadHouse):
|
||||
raise ClientException('`house` parameter was not a HypeSquadHouse')
|
||||
else:
|
||||
value = house.value
|
||||
|
||||
await http.change_hypesquad_house(value)
|
||||
|
||||
data = await http.edit_profile(**args)
|
||||
if not_bot_account:
|
||||
self.email = data['email']
|
||||
try:
|
||||
http._token(data['token'], bot=False)
|
||||
except KeyError:
|
||||
pass
|
||||
if avatar is not None:
|
||||
avatar = _bytes_to_base64_data(avatar)
|
||||
|
||||
data = await self._state.http.edit_profile(username=username, avatar=avatar)
|
||||
self._update(data)
|
||||
|
||||
@deprecated()
|
||||
async def create_group(self, *recipients):
|
||||
r"""|coro|
|
||||
|
||||
Creates a group direct message with the recipients
|
||||
provided. These recipients must be have a relationship
|
||||
of type :attr:`RelationshipType.friend`.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
\*recipients: :class:`User`
|
||||
An argument :class:`list` of :class:`User` to have in
|
||||
your group.
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Failed to create the group direct message.
|
||||
ClientException
|
||||
Attempted to create a group with only one recipient.
|
||||
This does not include yourself.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`GroupChannel`
|
||||
The new group channel.
|
||||
"""
|
||||
|
||||
from .channel import GroupChannel
|
||||
|
||||
if len(recipients) < 2:
|
||||
raise ClientException('You must have two or more recipients to create a group.')
|
||||
|
||||
users = [str(u.id) for u in recipients]
|
||||
data = await self._state.http.start_group(self.id, users)
|
||||
return GroupChannel(me=self, data=data, state=self._state)
|
||||
|
||||
@deprecated()
|
||||
async def edit_settings(self, **kwargs):
|
||||
"""|coro|
|
||||
|
||||
Edits the client user's settings.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Parameters
|
||||
-------
|
||||
afk_timeout: :class:`int`
|
||||
How long (in seconds) the user needs to be AFK until Discord
|
||||
sends push notifications to your mobile device.
|
||||
animate_emojis: :class:`bool`
|
||||
Whether or not to animate emojis in the chat.
|
||||
convert_emoticons: :class:`bool`
|
||||
Whether or not to automatically convert emoticons into emojis.
|
||||
e.g. :-) -> 😃
|
||||
default_guilds_restricted: :class:`bool`
|
||||
Whether or not to automatically disable DMs between you and
|
||||
members of new guilds you join.
|
||||
detect_platform_accounts: :class:`bool`
|
||||
Whether or not to automatically detect accounts from services
|
||||
like Steam and Blizzard when you open the Discord client.
|
||||
developer_mode: :class:`bool`
|
||||
Whether or not to enable developer mode.
|
||||
disable_games_tab: :class:`bool`
|
||||
Whether or not to disable the showing of the Games tab.
|
||||
enable_tts_command: :class:`bool`
|
||||
Whether or not to allow tts messages to be played/sent.
|
||||
explicit_content_filter: :class:`UserContentFilter`
|
||||
The filter for explicit content in all messages.
|
||||
friend_source_flags: :class:`FriendFlags`
|
||||
Who can add you as a friend.
|
||||
gif_auto_play: :class:`bool`
|
||||
Whether or not to automatically play gifs that are in the chat.
|
||||
guild_positions: List[:class:`abc.Snowflake`]
|
||||
A list of guilds in order of the guild/guild icons that are on
|
||||
the left hand side of the UI.
|
||||
inline_attachment_media: :class:`bool`
|
||||
Whether or not to display attachments when they are uploaded in chat.
|
||||
inline_embed_media: :class:`bool`
|
||||
Whether or not to display videos and images from links posted in chat.
|
||||
locale: :class:`str`
|
||||
The :rfc:`3066` language identifier of the locale to use for the language
|
||||
of the Discord client.
|
||||
message_display_compact: :class:`bool`
|
||||
Whether or not to use the compact Discord display mode.
|
||||
render_embeds: :class:`bool`
|
||||
Whether or not to render embeds that are sent in the chat.
|
||||
render_reactions: :class:`bool`
|
||||
Whether or not to render reactions that are added to messages.
|
||||
restricted_guilds: List[:class:`abc.Snowflake`]
|
||||
A list of guilds that you will not receive DMs from.
|
||||
show_current_game: :class:`bool`
|
||||
Whether or not to display the game that you are currently playing.
|
||||
status: :class:`Status`
|
||||
The clients status that is shown to others.
|
||||
theme: :class:`Theme`
|
||||
The theme of the Discord UI.
|
||||
timezone_offset: :class:`int`
|
||||
The timezone offset to use.
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Editing the settings failed.
|
||||
Forbidden
|
||||
The client is a bot user and not a user account.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`dict`
|
||||
The client user's updated settings.
|
||||
"""
|
||||
payload = {}
|
||||
|
||||
content_filter = kwargs.pop('explicit_content_filter', None)
|
||||
if content_filter:
|
||||
payload.update({'explicit_content_filter': content_filter.value})
|
||||
|
||||
friend_flags = kwargs.pop('friend_source_flags', None)
|
||||
if friend_flags:
|
||||
dicts = [{}, {'mutual_guilds': True}, {'mutual_friends': True},
|
||||
{'mutual_guilds': True, 'mutual_friends': True}, {'all': True}]
|
||||
payload.update({'friend_source_flags': dicts[friend_flags.value]})
|
||||
|
||||
guild_positions = kwargs.pop('guild_positions', None)
|
||||
if guild_positions:
|
||||
guild_positions = [str(x.id) for x in guild_positions]
|
||||
payload.update({'guild_positions': guild_positions})
|
||||
|
||||
restricted_guilds = kwargs.pop('restricted_guilds', None)
|
||||
if restricted_guilds:
|
||||
restricted_guilds = [str(x.id) for x in restricted_guilds]
|
||||
payload.update({'restricted_guilds': restricted_guilds})
|
||||
|
||||
status = kwargs.pop('status', None)
|
||||
if status:
|
||||
payload.update({'status': status.value})
|
||||
|
||||
theme = kwargs.pop('theme', None)
|
||||
if theme:
|
||||
payload.update({'theme': theme.value})
|
||||
|
||||
payload.update(kwargs)
|
||||
|
||||
data = await self._state.http.edit_settings(**payload)
|
||||
return data
|
||||
|
||||
class User(BaseUser, discord.abc.Messageable):
|
||||
"""Represents a Discord user.
|
||||
|
||||
@ -761,197 +411,3 @@ class User(BaseUser, discord.abc.Messageable):
|
||||
state = self._state
|
||||
data = await state.http.start_private_message(self.id)
|
||||
return state.add_dm_channel(data)
|
||||
|
||||
@property
|
||||
def relationship(self):
|
||||
"""Optional[:class:`Relationship`]: Returns the :class:`Relationship` with this user if applicable, ``None`` otherwise.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
"""
|
||||
return self._state.user.get_relationship(self.id)
|
||||
|
||||
@deprecated()
|
||||
async def mutual_friends(self):
|
||||
"""|coro|
|
||||
|
||||
Gets all mutual friends of this user.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
Not allowed to get mutual friends of this user.
|
||||
HTTPException
|
||||
Getting mutual friends failed.
|
||||
|
||||
Returns
|
||||
-------
|
||||
List[:class:`User`]
|
||||
The users that are mutual friends.
|
||||
"""
|
||||
state = self._state
|
||||
mutuals = await state.http.get_mutual_friends(self.id)
|
||||
return [User(state=state, data=friend) for friend in mutuals]
|
||||
|
||||
@deprecated()
|
||||
def is_friend(self):
|
||||
""":class:`bool`: Checks if the user is your friend.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
"""
|
||||
r = self.relationship
|
||||
if r is None:
|
||||
return False
|
||||
return r.type is RelationshipType.friend
|
||||
|
||||
@deprecated()
|
||||
def is_blocked(self):
|
||||
""":class:`bool`: Checks if the user is blocked.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
"""
|
||||
r = self.relationship
|
||||
if r is None:
|
||||
return False
|
||||
return r.type is RelationshipType.blocked
|
||||
|
||||
@deprecated()
|
||||
async def block(self):
|
||||
"""|coro|
|
||||
|
||||
Blocks the user.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
Not allowed to block this user.
|
||||
HTTPException
|
||||
Blocking the user failed.
|
||||
"""
|
||||
|
||||
await self._state.http.add_relationship(self.id, type=RelationshipType.blocked.value)
|
||||
|
||||
@deprecated()
|
||||
async def unblock(self):
|
||||
"""|coro|
|
||||
|
||||
Unblocks the user.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
Not allowed to unblock this user.
|
||||
HTTPException
|
||||
Unblocking the user failed.
|
||||
"""
|
||||
await self._state.http.remove_relationship(self.id)
|
||||
|
||||
@deprecated()
|
||||
async def remove_friend(self):
|
||||
"""|coro|
|
||||
|
||||
Removes the user as a friend.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
Not allowed to remove this user as a friend.
|
||||
HTTPException
|
||||
Removing the user as a friend failed.
|
||||
"""
|
||||
await self._state.http.remove_relationship(self.id)
|
||||
|
||||
@deprecated()
|
||||
async def send_friend_request(self):
|
||||
"""|coro|
|
||||
|
||||
Sends the user a friend request.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
Not allowed to send a friend request to the user.
|
||||
HTTPException
|
||||
Sending the friend request failed.
|
||||
"""
|
||||
await self._state.http.send_friend_request(username=self.name, discriminator=self.discriminator)
|
||||
|
||||
@deprecated()
|
||||
async def profile(self):
|
||||
"""|coro|
|
||||
|
||||
Gets the user's profile.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This can only be used by non-bot accounts.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
Not allowed to fetch profiles.
|
||||
HTTPException
|
||||
Fetching the profile failed.
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`Profile`
|
||||
The profile of the user.
|
||||
"""
|
||||
|
||||
state = self._state
|
||||
data = await state.http.get_user_profile(self.id)
|
||||
|
||||
def transform(d):
|
||||
return state._get_guild(int(d['id']))
|
||||
|
||||
since = data.get('premium_since')
|
||||
mutual_guilds = list(filter(None, map(transform, data.get('mutual_guilds', []))))
|
||||
return Profile(flags=data['user'].get('flags', 0),
|
||||
premium_since=parse_time(since),
|
||||
mutual_guilds=mutual_guilds,
|
||||
user=self,
|
||||
connected_accounts=data['connected_accounts'])
|
||||
|
@ -403,10 +403,6 @@ class _PartialWebhookState:
|
||||
def store_user(self, data):
|
||||
return BaseUser(state=self, data=data)
|
||||
|
||||
@property
|
||||
def is_bot(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
def http(self):
|
||||
if self.parent is not None:
|
||||
|
235
docs/api.rst
235
docs/api.rst
@ -897,29 +897,6 @@ to handle it, which defaults to print a traceback and ignoring the exception.
|
||||
:param user: The user that joined or left.
|
||||
:type user: :class:`User`
|
||||
|
||||
.. function:: on_relationship_add(relationship)
|
||||
on_relationship_remove(relationship)
|
||||
|
||||
Called when a :class:`Relationship` is added or removed from the
|
||||
:class:`ClientUser`.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
:param relationship: The relationship that was added or removed.
|
||||
:type relationship: :class:`Relationship`
|
||||
|
||||
.. function:: on_relationship_update(before, after)
|
||||
|
||||
Called when a :class:`Relationship` is updated, e.g. when you
|
||||
block a friend or a friendship is accepted.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
:param before: The previous relationship status.
|
||||
:type before: :class:`Relationship`
|
||||
:param after: The updated relationship status.
|
||||
:type after: :class:`Relationship`
|
||||
|
||||
.. _discord-api-utils:
|
||||
|
||||
Utility Functions
|
||||
@ -945,97 +922,6 @@ Utility Functions
|
||||
|
||||
.. autofunction:: discord.utils.sleep_until
|
||||
|
||||
Profile
|
||||
---------
|
||||
|
||||
.. class:: Profile
|
||||
|
||||
A namedtuple representing a user's Discord public profile.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. attribute:: user
|
||||
|
||||
The :class:`User` the profile belongs to.
|
||||
|
||||
:type: :class:`User`
|
||||
.. attribute:: premium
|
||||
|
||||
A boolean indicating if the user has premium (i.e. Discord Nitro).
|
||||
|
||||
:type: :class:`bool`
|
||||
.. attribute:: nitro
|
||||
|
||||
An alias for :attr:`premium`.
|
||||
.. attribute:: premium_since
|
||||
|
||||
A naive UTC datetime indicating how long the user has been premium since.
|
||||
This could be ``None`` if not applicable.
|
||||
|
||||
:type: :class:`datetime.datetime`
|
||||
.. attribute:: staff
|
||||
|
||||
A boolean indicating if the user is Discord Staff.
|
||||
|
||||
:type: :class:`bool`
|
||||
.. attribute:: partner
|
||||
|
||||
A boolean indicating if the user is a Discord Partner.
|
||||
|
||||
:type: :class:`bool`
|
||||
.. attribute:: bug_hunter
|
||||
|
||||
A boolean indicating if the user is a Bug Hunter.
|
||||
|
||||
:type: :class:`bool`
|
||||
.. attribute:: early_supporter
|
||||
|
||||
A boolean indicating if the user has had premium before 10 October, 2018.
|
||||
|
||||
:type: :class:`bool`
|
||||
.. attribute:: hypesquad
|
||||
|
||||
A boolean indicating if the user is in Discord HypeSquad.
|
||||
|
||||
:type: :class:`bool`
|
||||
.. attribute:: hypesquad_houses
|
||||
|
||||
A list of :class:`HypeSquadHouse` that the user is in.
|
||||
|
||||
:type: List[:class:`HypeSquadHouse`]
|
||||
.. attribute:: team_user
|
||||
|
||||
A boolean indicating if the user is in part of a team.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
:type: :class:`bool`
|
||||
|
||||
.. attribute:: system
|
||||
|
||||
A boolean indicating if the user is officially part of the Discord urgent message system.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
:type: :class:`bool`
|
||||
|
||||
.. attribute:: mutual_guilds
|
||||
|
||||
A list of :class:`Guild` that the :class:`ClientUser` shares with this
|
||||
user.
|
||||
|
||||
:type: List[:class:`Guild`]
|
||||
|
||||
.. attribute:: connected_accounts
|
||||
|
||||
A list of dict objects indicating the accounts the user has connected.
|
||||
|
||||
An example entry can be seen below: ::
|
||||
|
||||
{"type": "twitch", "id": "92473777", "name": "discordapp"}
|
||||
|
||||
:type: List[Dict[:class:`str`, :class:`str`]]
|
||||
|
||||
.. _discord-api-enums:
|
||||
|
||||
Enumerations
|
||||
@ -1940,127 +1826,6 @@ of :class:`enum.Enum`.
|
||||
|
||||
The action is the update of something.
|
||||
|
||||
.. class:: RelationshipType
|
||||
|
||||
Specifies the type of :class:`Relationship`.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This only applies to users, *not* bots.
|
||||
|
||||
.. attribute:: friend
|
||||
|
||||
You are friends with this user.
|
||||
|
||||
.. attribute:: blocked
|
||||
|
||||
You have blocked this user.
|
||||
|
||||
.. attribute:: incoming_request
|
||||
|
||||
The user has sent you a friend request.
|
||||
|
||||
.. attribute:: outgoing_request
|
||||
|
||||
You have sent a friend request to this user.
|
||||
|
||||
|
||||
.. class:: UserContentFilter
|
||||
|
||||
Represents the options found in ``Settings > Privacy & Safety > Safe Direct Messaging``
|
||||
in the Discord client.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This only applies to users, *not* bots.
|
||||
|
||||
.. attribute:: all_messages
|
||||
|
||||
Scan all direct messages from everyone.
|
||||
|
||||
.. attribute:: friends
|
||||
|
||||
Scan all direct messages that aren't from friends.
|
||||
|
||||
.. attribute:: disabled
|
||||
|
||||
Don't scan any direct messages.
|
||||
|
||||
|
||||
.. class:: FriendFlags
|
||||
|
||||
Represents the options found in ``Settings > Privacy & Safety > Who Can Add You As A Friend``
|
||||
in the Discord client.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This only applies to users, *not* bots.
|
||||
|
||||
.. attribute:: noone
|
||||
|
||||
This allows no-one to add you as a friend.
|
||||
|
||||
.. attribute:: mutual_guilds
|
||||
|
||||
This allows guild members to add you as a friend.
|
||||
|
||||
.. attribute:: mutual_friends
|
||||
|
||||
This allows friends of friends to add you as a friend.
|
||||
|
||||
.. attribute:: guild_and_friends
|
||||
|
||||
This is a superset of :attr:`mutual_guilds` and :attr:`mutual_friends`.
|
||||
|
||||
.. attribute:: everyone
|
||||
|
||||
This allows everyone to add you as a friend.
|
||||
|
||||
|
||||
.. class:: PremiumType
|
||||
|
||||
Represents the user's Discord Nitro subscription type.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This only applies to users, *not* bots.
|
||||
|
||||
.. attribute:: nitro
|
||||
|
||||
Represents the Discord Nitro with Nitro-exclusive games.
|
||||
|
||||
.. attribute:: nitro_classic
|
||||
|
||||
Represents the Discord Nitro with no Nitro-exclusive games.
|
||||
|
||||
|
||||
.. class:: Theme
|
||||
|
||||
Represents the theme synced across all Discord clients.
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
.. note::
|
||||
|
||||
This only applies to users, *not* bots.
|
||||
|
||||
.. attribute:: light
|
||||
|
||||
Represents the Light theme on Discord.
|
||||
|
||||
.. attribute:: dark
|
||||
|
||||
Represents the Dark theme on Discord.
|
||||
|
||||
|
||||
.. class:: TeamMembershipState
|
||||
|
||||
Represents the membership state of a team member retrieved through :func:`Bot.application_info`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user