Browse Source

Modernize Relationship class

pull/10109/head
dolfies 3 years ago
parent
commit
c46f24ca40
  1. 4
      discord/http.py
  2. 82
      discord/relationship.py
  3. 27
      discord/state.py

4
discord/http.py

@ -2167,9 +2167,7 @@ class HTTPClient:
return self.request(r, json=payload, context_properties=props) return self.request(r, json=payload, context_properties=props)
def change_friend_nickname(self, user_id, nickname): def edit_relationship(self, user_id, **payload): # TODO: return type
payload = {'nickname': nickname}
return self.request(Route('PATCH', '/users/@me/relationships/{user_id}', user_id=user_id), json=payload) return self.request(Route('PATCH', '/users/@me/relationships/{user_id}', user_id=user_id), json=payload)
# Connections # Connections

82
discord/relationship.py

@ -24,9 +24,12 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations from __future__ import annotations
import copy
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
from .enums import RelationshipAction, RelationshipType, try_enum from .enums import RelationshipAction, RelationshipType, try_enum
from .object import Object
from .utils import MISSING
if TYPE_CHECKING: if TYPE_CHECKING:
from .state import ConnectionState from .state import ConnectionState
@ -60,24 +63,38 @@ class Relationship:
Attributes Attributes
----------- -----------
nickname: Optional[:class:`str`] nick: Optional[:class:`str`]
The user's friend nickname (if applicable). The user's friend nickname (if applicable).
.. versionchanged:: 2.0
Renamed ``nickname`` to :attr:`nick`.
user: :class:`User` user: :class:`User`
The user you have the relationship with. The user you have the relationship with.
type: :class:`RelationshipType` type: :class:`RelationshipType`
The type of relationship you have. The type of relationship you have.
""" """
__slots__ = ('nickname', 'type', 'user', '_state') __slots__ = ('nick', 'type', 'user', '_state')
def __init__(self, *, state: ConnectionState, data) -> None: # TODO: type data def __init__(self, *, state: ConnectionState, data) -> None: # TODO: type data
self._state = state self._state = state
self._update(data)
def _update(self, data: dict) -> None:
self.type: RelationshipType = try_enum(RelationshipType, data['type']) self.type: RelationshipType = try_enum(RelationshipType, data['type'])
self.user: User = state.store_user(data['user']) self.nick: Optional[str] = data.get('nickname')
self.nickname: Optional[str] = data.get('nickname', None)
self.user: User
if (user := data.get('user')) is not None:
self.user = self._state.store_user(user)
elif self.user:
return
else:
user_id = int(data['id'])
self.user = self._state.get_user(user_id) or Object(id=user_id) # type: ignore # Lying for better developer UX
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<Relationship user={self.user!r} type={self.type!r}>' return f'<Relationship user={self.user!r} type={self.type!r} nick={self.nick!r}>'
def __eq__(self, other: object) -> bool: def __eq__(self, other: object) -> bool:
return isinstance(other, Relationship) and other.user.id == self.user.id return isinstance(other, Relationship) and other.user.id == self.user.id
@ -95,50 +112,81 @@ class Relationship:
Deletes the relationship. Deletes the relationship.
Depending on the type, this could mean unfriending or unblocking the user,
denying an incoming friend request, or discarding an outgoing friend request.
Raises Raises
------ ------
HTTPException HTTPException
Deleting the relationship failed. Deleting the relationship failed.
""" """
action = RelationshipAction.deny_request
if self.type is RelationshipType.friend: if self.type is RelationshipType.friend:
await self._state.http.remove_relationship(self.user.id, action=RelationshipAction.unfriend) action = RelationshipAction.unfriend
elif self.type is RelationshipType.blocked: elif self.type is RelationshipType.blocked:
await self._state.http.remove_relationship(self.user.id, action=RelationshipAction.unblock) action = RelationshipAction.unblock
elif self.type is RelationshipType.incoming_request: elif self.type is RelationshipType.incoming_request:
await self._state.http.remove_relationship(self.user.id, action=RelationshipAction.deny_request) action = RelationshipAction.deny_request
elif self.type is RelationshipType.outgoing_request: elif self.type is RelationshipType.outgoing_request:
await self._state.http.remove_relationship(self.user.id, action=RelationshipAction.remove_pending_request) action = RelationshipAction.remove_pending_request
async def accept(self) -> None: await self._state.http.remove_relationship(self.user.id, action=action)
async def accept(self) -> Relationship:
"""|coro| """|coro|
Accepts the relationship request. Only applicable for Accepts the relationship request. Only applicable for
type :class:`RelationshipType.incoming_request`. type :class:`RelationshipType.incoming_request`.
.. versionchanged:: 2.0
Changed the return type to :class:`Relationship`.
Raises Raises
------- -------
HTTPException HTTPException
Accepting the relationship failed. Accepting the relationship failed.
Returns
-------
:class:`Relationship`
The new relationship.
""" """
await self._state.http.add_relationship(self.user.id, action=RelationshipAction.accept_request) data = await self._state.http.add_relationship(self.user.id, action=RelationshipAction.accept_request)
return Relationship(state=self._state, data=data)
async def change_nickname(self, nick: Optional[str]) -> None: async def edit(self, nick: Optional[str] = MISSING) -> Relationship:
"""|coro| """|coro|
Changes a relationship's nickname. Only applicable for Edits the relationship.
type :class:`RelationshipType.friend`.
.. versionadded:: 1.9 .. versionadded:: 1.9
.. versionchanged:: 2.0
Changed the name of the method to :meth:`edit`.
The edit is no longer in-place.
Parameters Parameters
---------- ----------
nick: Optional[:class:`str`] nick: Optional[:class:`str`]
The nickname to change to. The nickname to change to. Can be ``None`` to denote no nickname.
Raises Raises
------- -------
HTTPException HTTPException
Changing the nickname failed. Changing the nickname failed.
Returns
-------
:class:`Relationship`
The new relationship.
""" """
await self._state.http.change_friend_nickname(self.user.id, nick) payload = {}
self.nickname = nick if nick is not MISSING:
payload['nick'] = nick
await self._state.http.edit_relationship(self.user.id, **payload)
# Emulate the return for consistency
new = copy.copy(self)
new.nick = nick if nick is not MISSING else self.nick
return new

27
discord/state.py

@ -2167,23 +2167,36 @@ class ConnectionState:
def parse_relationship_add(self, data) -> None: def parse_relationship_add(self, data) -> None:
key = int(data['id']) key = int(data['id'])
old = self.user.get_relationship(key) # type: ignore # self.user is always present here new = self._relationships.get(key)
new = Relationship(state=self, data=data) if new is None:
self._relationships[key] = new relationship = Relationship(state=self, data=data)
if old is not None: self._relationships[key] = relationship
self.dispatch('relationship_update', old, new) self.dispatch('relationship_add', relationship)
else: else:
self.dispatch('relationship_add', new) old = copy.copy(new)
new._update(data)
self.dispatch('relationship_update', old, new)
def parse_relationship_remove(self, data) -> None: def parse_relationship_remove(self, data) -> None:
key = int(data['id']) key = int(data['id'])
try: try:
old = self._relationships.pop(key) old = self._relationships.pop(key)
except KeyError: except KeyError:
pass _log.warning('Relationship_remove referencing unknown relationship ID: %s. Discarding.', key)
else: else:
self.dispatch('relationship_remove', old) self.dispatch('relationship_remove', old)
def parse_relationship_update(self, data) -> None:
key = int(data['id'])
new = self._relationships.get(key)
if new is None:
relationship = Relationship(state=self, data=data)
self._relationships[key] = relationship
else:
old = copy.copy(new)
new._update(data)
self.dispatch('relationship_update', old, new)
def parse_interaction_create(self, data) -> None: def parse_interaction_create(self, data) -> None:
type, name, channel = self._interaction_cache.pop(data['nonce'], (0, None, None)) type, name, channel = self._interaction_cache.pop(data['nonce'], (0, None, None))
i = Interaction._from_self(channel, type=type, user=self.user, name=name, **data) # type: ignore # self.user is always present here i = Interaction._from_self(channel, type=type, user=self.user, name=name, **data) # type: ignore # self.user is always present here

Loading…
Cancel
Save