Browse Source

Implement friend tokens

pull/10109/head
Dolfies 4 months ago
parent
commit
92912ea81a
  1. 41
      discord/client.py
  2. 5
      discord/guild.py
  3. 15
      discord/http.py
  4. 4
      discord/member.py
  5. 12
      discord/relationship.py
  6. 4
      discord/types/user.py
  7. 25
      discord/user.py

41
discord/client.py

@ -2431,14 +2431,15 @@ class Client:
with_mutual_guilds: bool = True, with_mutual_guilds: bool = True,
with_mutual_friends_count: bool = False, with_mutual_friends_count: bool = False,
with_mutual_friends: bool = True, with_mutual_friends: bool = True,
friend_token: str = MISSING,
) -> UserProfile: ) -> UserProfile:
"""|coro| """|coro|
Retrieves a :class:`.UserProfile` based on their user ID. Retrieves a :class:`.UserProfile` based on their user ID.
You must share a guild, be friends with this user, You must provide a valid ``friend_token``, share a guild with,
or have an incoming friend request from them to be friends with, or have an incoming friend request from this
get this information (unless the user is a bot). user to get this information, unless the user is a bot.
.. versionchanged:: 2.0 .. versionchanged:: 2.0
@ -2463,13 +2464,16 @@ class Client:
This fills in :attr:`.UserProfile.mutual_friends` and :attr:`.UserProfile.mutual_friends_count`. This fills in :attr:`.UserProfile.mutual_friends` and :attr:`.UserProfile.mutual_friends_count`.
.. versionadded:: 2.0 .. versionadded:: 2.0
friend_token: :class:`str`
The friend token to use for fetching the profile.
.. versionadded:: 2.1
Raises Raises
------- -------
NotFound NotFound
A user with this ID does not exist. A user with this ID does not exist.
Forbidden You do not have a mutual with this user and the user is not a bot.
You do not have a mutual with this user, and the user is not a bot.
HTTPException HTTPException
Fetching the profile failed. Fetching the profile failed.
@ -2484,6 +2488,7 @@ class Client:
with_mutual_guilds=with_mutual_guilds, with_mutual_guilds=with_mutual_guilds,
with_mutual_friends_count=with_mutual_friends_count, with_mutual_friends_count=with_mutual_friends_count,
with_mutual_friends=with_mutual_friends, with_mutual_friends=with_mutual_friends,
friend_token=friend_token or None,
) )
return UserProfile(state=state, data=data) return UserProfile(state=state, data=data)
@ -3020,6 +3025,32 @@ class Client:
data = await state.http.get_friend_suggestions() data = await state.http.get_friend_suggestions()
return [FriendSuggestion(state=state, data=d) for d in data] return [FriendSuggestion(state=state, data=d) for d in data]
async def friend_token(self) -> str:
"""|coro|
Retrieves your friend token.
These can be used to fetch the user's profile without a mutual
and add the user as a friend regardless of their friend request settings.
To share, append it to the user's URL like so:
``https://discord.com/users/{user.id}?friend_token={friend_token}``.
.. versionadded:: 2.1
Raises
-------
HTTPException
Retrieving your friend token failed.
Returns
--------
:class:`str`
Your friend token.
"""
data = await self.http.get_friend_token()
return data['friend_token']
async def fetch_country_code(self) -> str: async def fetch_country_code(self) -> str:
"""|coro| """|coro|

5
discord/guild.py

@ -2683,6 +2683,7 @@ class Guild(Hashable):
with_mutual_guilds: bool = True, with_mutual_guilds: bool = True,
with_mutual_friends_count: bool = False, with_mutual_friends_count: bool = False,
with_mutual_friends: bool = True, with_mutual_friends: bool = True,
friend_token: str = MISSING,
) -> MemberProfile: ) -> MemberProfile:
"""|coro| """|coro|
@ -2708,8 +2709,7 @@ class Guild(Hashable):
------- -------
NotFound NotFound
A user with this ID does not exist. A user with this ID does not exist.
Forbidden You do not have a mutual with this user and the user is not a bot.
You do not have a mutual with this user, and and the user is not a bot.
HTTPException HTTPException
Fetching the profile failed. Fetching the profile failed.
InvalidData InvalidData
@ -2727,6 +2727,7 @@ class Guild(Hashable):
with_mutual_guilds=with_mutual_guilds, with_mutual_guilds=with_mutual_guilds,
with_mutual_friends_count=with_mutual_friends_count, with_mutual_friends_count=with_mutual_friends_count,
with_mutual_friends=with_mutual_friends, with_mutual_friends=with_mutual_friends,
friend_token=friend_token or None,
) )
if 'guild_member_profile' not in data: if 'guild_member_profile' not in data:
raise InvalidData('Member is not in this guild') raise InvalidData('Member is not in this guild')

15
discord/http.py

@ -2894,11 +2894,18 @@ class HTTPClient:
return self.request(Route('DELETE', '/users/@me/relationships/{user_id}', user_id=user_id), context_properties=props) return self.request(Route('DELETE', '/users/@me/relationships/{user_id}', user_id=user_id), context_properties=props)
def add_relationship( def add_relationship(
self, user_id: Snowflake, type: Optional[int] = None, *, action: RelationshipAction self,
user_id: Snowflake,
type: Optional[int] = None,
*,
friend_token: Optional[str] = None,
action: RelationshipAction,
) -> Response[None]: ) -> Response[None]:
payload = {} payload = {}
if type is not None: if type is not None:
payload['type'] = type payload['type'] = type
if friend_token:
payload['friend_token'] = friend_token
if action is RelationshipAction.accept_request: # User Profile, Friends, DM Channel if action is RelationshipAction.accept_request: # User Profile, Friends, DM Channel
props = choice( props = choice(
@ -2949,6 +2956,9 @@ class HTTPClient:
def delete_friend_suggestion(self, user_id: Snowflake) -> Response[None]: def delete_friend_suggestion(self, user_id: Snowflake) -> Response[None]:
return self.request(Route('DELETE', '/friend-suggestions/{user_id}', user_id=user_id)) return self.request(Route('DELETE', '/friend-suggestions/{user_id}', user_id=user_id))
def get_friend_token(self) -> Response[user.FriendToken]:
return self.request(Route('GET', '/users/@me/friend-token'))
# Connections # Connections
def get_connections(self) -> Response[List[user.Connection]]: def get_connections(self) -> Response[List[user.Connection]]:
@ -4389,6 +4399,7 @@ class HTTPClient:
with_mutual_guilds: bool = True, with_mutual_guilds: bool = True,
with_mutual_friends: bool = False, with_mutual_friends: bool = False,
with_mutual_friends_count: bool = False, with_mutual_friends_count: bool = False,
friend_token: Optional[str] = None,
) -> Response[profile.Profile]: ) -> Response[profile.Profile]:
params: Dict[str, Any] = { params: Dict[str, Any] = {
'with_mutual_guilds': str(with_mutual_guilds).lower(), 'with_mutual_guilds': str(with_mutual_guilds).lower(),
@ -4397,6 +4408,8 @@ class HTTPClient:
} }
if guild_id: if guild_id:
params['guild_id'] = guild_id params['guild_id'] = guild_id
if friend_token:
params['friend_token'] = friend_token
return self.request(Route('GET', '/users/{user_id}/profile', user_id=user_id), params=params) return self.request(Route('GET', '/users/{user_id}/profile', user_id=user_id), params=params)

4
discord/member.py

@ -1113,6 +1113,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
with_mutual_guilds: bool = True, with_mutual_guilds: bool = True,
with_mutual_friends_count: bool = False, with_mutual_friends_count: bool = False,
with_mutual_friends: bool = True, with_mutual_friends: bool = True,
friend_token: str = MISSING,
) -> MemberProfile: ) -> MemberProfile:
"""|coro| """|coro|
@ -1138,7 +1139,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
Raises Raises
------- -------
Forbidden NotFound
Not allowed to fetch this profile. Not allowed to fetch this profile.
HTTPException HTTPException
Fetching the profile failed. Fetching the profile failed.
@ -1155,4 +1156,5 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
with_mutual_guilds=with_mutual_guilds, with_mutual_guilds=with_mutual_guilds,
with_mutual_friends_count=with_mutual_friends_count, with_mutual_friends_count=with_mutual_friends_count,
with_mutual_friends=with_mutual_friends, with_mutual_friends=with_mutual_friends,
friend_token=friend_token,
) )

12
discord/relationship.py

@ -399,18 +399,26 @@ class FriendSuggestion(Hashable):
f'<FriendSuggestion user={self.user!r} reasons={self.reasons!r} from_user_contacts={self.from_user_contacts!r}>' f'<FriendSuggestion user={self.user!r} reasons={self.reasons!r} from_user_contacts={self.from_user_contacts!r}>'
) )
async def accept(self) -> None: async def accept(self, *, friend_token: str = MISSING) -> None:
"""|coro| """|coro|
Accepts the friend suggestion. Accepts the friend suggestion.
This creates a :class:`Relationship` of type :class:`RelationshipType.outgoing_request`. This creates a :class:`Relationship` of type :class:`RelationshipType.outgoing_request`.
Parameters
----------
friend_token: :class:`str`
The friend token to accept the friend suggestion with.
This will bypass the user's friend request settings.
Raises Raises
------- -------
HTTPException HTTPException
Accepting the relationship failed. Accepting the relationship failed.
""" """
await self._state.http.add_relationship(self.user.id, action=RelationshipAction.friend_suggestion) await self._state.http.add_relationship(
self.user.id, friend_token=friend_token or None, action=RelationshipAction.friend_suggestion
)
async def delete(self) -> None: async def delete(self) -> None:
"""|coro| """|coro|

4
discord/types/user.py

@ -248,5 +248,9 @@ class FriendSuggestion(TypedDict):
from_suggested_user_contacts: NotRequired[bool] from_suggested_user_contacts: NotRequired[bool]
class FriendToken(TypedDict):
friend_token: str
class Report(TypedDict): class Report(TypedDict):
report_id: Snowflake report_id: Snowflake

25
discord/user.py

@ -613,6 +613,7 @@ class BaseUser(_UserTag):
with_mutual_guilds: bool = True, with_mutual_guilds: bool = True,
with_mutual_friends_count: bool = False, with_mutual_friends_count: bool = False,
with_mutual_friends: bool = True, with_mutual_friends: bool = True,
friend_token: str = MISSING,
) -> UserProfile: ) -> UserProfile:
"""|coro| """|coro|
@ -635,11 +636,16 @@ class BaseUser(_UserTag):
This fills in :attr:`UserProfile.mutual_friends` and :attr:`UserProfile.mutual_friends_count`. This fills in :attr:`UserProfile.mutual_friends` and :attr:`UserProfile.mutual_friends_count`.
.. versionadded:: 2.0 .. versionadded:: 2.0
friend_token: :class:`str`
The friend token to use for fetching the profile.
.. versionadded:: 2.1
Raises Raises
------- -------
Forbidden NotFound
Not allowed to fetch this profile. A user with this ID does not exist.
You do not have a mutual with this user, and the user is not a bot.
HTTPException HTTPException
Fetching the profile failed. Fetching the profile failed.
@ -653,6 +659,7 @@ class BaseUser(_UserTag):
with_mutual_guilds=with_mutual_guilds, with_mutual_guilds=with_mutual_guilds,
with_mutual_friends_count=with_mutual_friends_count, with_mutual_friends_count=with_mutual_friends_count,
with_mutual_friends=with_mutual_friends, with_mutual_friends=with_mutual_friends,
friend_token=friend_token,
) )
async def fetch_mutual_friends(self) -> List[User]: async def fetch_mutual_friends(self) -> List[User]:
@ -1236,11 +1243,19 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
""" """
await self._state.http.remove_relationship(self.id, action=RelationshipAction.unfriend) await self._state.http.remove_relationship(self.id, action=RelationshipAction.unfriend)
async def send_friend_request(self) -> None: async def send_friend_request(self, *, friend_token: str = MISSING) -> None:
"""|coro| """|coro|
Sends the user a friend request. Sends the user a friend request.
Parameters
-----------
friend_token: :class:`str`
The friend token to use for sending the friend request.
This will bypass the user's friend request settings.
.. versionadded:: 2.1
Raises Raises
------- -------
Forbidden Forbidden
@ -1248,4 +1263,6 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
HTTPException HTTPException
Sending the friend request failed. Sending the friend request failed.
""" """
await self._state.http.add_relationship(self.id, action=RelationshipAction.send_friend_request) await self._state.http.add_relationship(
self.id, friend_token=friend_token or None, action=RelationshipAction.send_friend_request
)

Loading…
Cancel
Save