feat: add Activity presence models (#60)
This commit is contained in:
parent
c47a7e49f8
commit
39162b6543
@ -36,6 +36,7 @@ from .ext import loader as ext_loader
|
||||
from .interactions import Interaction, Snowflake
|
||||
from .error_handler import setup_global_error_handler
|
||||
from .voice_client import VoiceClient
|
||||
from .models import Activity
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .models import (
|
||||
@ -439,8 +440,7 @@ class Client:
|
||||
async def change_presence(
|
||||
self,
|
||||
status: str,
|
||||
activity_name: Optional[str] = None,
|
||||
activity_type: int = 0,
|
||||
activity: Optional[Activity] = None,
|
||||
since: int = 0,
|
||||
afk: bool = False,
|
||||
):
|
||||
@ -449,8 +449,7 @@ class Client:
|
||||
|
||||
Args:
|
||||
status (str): The new status for the client (e.g., "online", "idle", "dnd", "invisible").
|
||||
activity_name (Optional[str]): The name of the activity.
|
||||
activity_type (int): The type of the activity.
|
||||
activity (Optional[Activity]): Activity instance describing what the bot is doing.
|
||||
since (int): The timestamp (in milliseconds) of when the client went idle.
|
||||
afk (bool): Whether the client is AFK.
|
||||
"""
|
||||
@ -460,8 +459,7 @@ class Client:
|
||||
if self._gateway:
|
||||
await self._gateway.update_presence(
|
||||
status=status,
|
||||
activity_name=activity_name,
|
||||
activity_type=activity_type,
|
||||
activity=activity,
|
||||
since=since,
|
||||
afk=afk,
|
||||
)
|
||||
|
@ -14,6 +14,8 @@ import time
|
||||
import random
|
||||
from typing import Optional, TYPE_CHECKING, Any, Dict
|
||||
|
||||
from .models import Activity
|
||||
|
||||
from .enums import GatewayOpcode, GatewayIntent
|
||||
from .errors import GatewayException, DisagreementException, AuthenticationError
|
||||
from .interactions import Interaction
|
||||
@ -213,26 +215,17 @@ class GatewayClient:
|
||||
async def update_presence(
|
||||
self,
|
||||
status: str,
|
||||
activity_name: Optional[str] = None,
|
||||
activity_type: int = 0,
|
||||
activity: Optional[Activity] = None,
|
||||
*,
|
||||
since: int = 0,
|
||||
afk: bool = False,
|
||||
):
|
||||
) -> None:
|
||||
"""Sends the presence update payload to the Gateway."""
|
||||
payload = {
|
||||
"op": GatewayOpcode.PRESENCE_UPDATE,
|
||||
"d": {
|
||||
"since": since,
|
||||
"activities": (
|
||||
[
|
||||
{
|
||||
"name": activity_name,
|
||||
"type": activity_type,
|
||||
}
|
||||
]
|
||||
if activity_name
|
||||
else []
|
||||
),
|
||||
"activities": [activity.to_dict()] if activity else [],
|
||||
"status": status,
|
||||
"afk": afk,
|
||||
},
|
||||
@ -353,7 +346,10 @@ class GatewayClient:
|
||||
future._members.extend(raw_event_d_payload.get("members", [])) # type: ignore
|
||||
|
||||
# If this is the last chunk, resolve the future
|
||||
if raw_event_d_payload.get("chunk_index") == raw_event_d_payload.get("chunk_count", 1) - 1:
|
||||
if (
|
||||
raw_event_d_payload.get("chunk_index")
|
||||
== raw_event_d_payload.get("chunk_count", 1) - 1
|
||||
):
|
||||
future.set_result(future._members) # type: ignore
|
||||
del self._member_chunk_requests[nonce]
|
||||
|
||||
|
@ -2361,6 +2361,37 @@ class ThreadMember:
|
||||
return f"<ThreadMember user_id='{self.user_id}' thread_id='{self.id}'>"
|
||||
|
||||
|
||||
class Activity:
|
||||
"""Represents a user's presence activity."""
|
||||
|
||||
def __init__(self, name: str, type: int) -> None:
|
||||
self.name = name
|
||||
self.type = type
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {"name": self.name, "type": self.type}
|
||||
|
||||
|
||||
class Game(Activity):
|
||||
"""Represents a playing activity."""
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
super().__init__(name, 0)
|
||||
|
||||
|
||||
class Streaming(Activity):
|
||||
"""Represents a streaming activity."""
|
||||
|
||||
def __init__(self, name: str, url: str) -> None:
|
||||
super().__init__(name, 1)
|
||||
self.url = url
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
payload = super().to_dict()
|
||||
payload["url"] = self.url
|
||||
return payload
|
||||
|
||||
|
||||
class PresenceUpdate:
|
||||
"""Represents a PRESENCE_UPDATE event."""
|
||||
|
||||
@ -2371,7 +2402,17 @@ class PresenceUpdate:
|
||||
self.user = User(data["user"])
|
||||
self.guild_id: Optional[str] = data.get("guild_id")
|
||||
self.status: Optional[str] = data.get("status")
|
||||
self.activities: List[Dict[str, Any]] = data.get("activities", [])
|
||||
self.activities: List[Activity] = []
|
||||
for activity in data.get("activities", []):
|
||||
act_type = activity.get("type", 0)
|
||||
name = activity.get("name", "")
|
||||
if act_type == 0:
|
||||
obj = Game(name)
|
||||
elif act_type == 1:
|
||||
obj = Streaming(name, activity.get("url", ""))
|
||||
else:
|
||||
obj = Activity(name, act_type)
|
||||
self.activities.append(obj)
|
||||
self.client_status: Dict[str, Any] = data.get("client_status", {})
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Updating Presence
|
||||
|
||||
The `Client.change_presence` method allows you to update the bot's status and displayed activity.
|
||||
Pass an :class:`~disagreement.models.Activity` (such as :class:`~disagreement.models.Game` or :class:`~disagreement.models.Streaming`) to describe what your bot is doing.
|
||||
|
||||
## Status Strings
|
||||
|
||||
@ -22,8 +23,18 @@ An activity dictionary must include a `name` and a `type` field. The type value
|
||||
| `4` | Custom |
|
||||
| `5` | Competing |
|
||||
|
||||
Example:
|
||||
Example using the provided activity classes:
|
||||
|
||||
```python
|
||||
await client.change_presence(status="idle", activity={"name": "with Discord", "type": 0})
|
||||
from disagreement.models import Game
|
||||
|
||||
await client.change_presence(status="idle", activity=Game("with Discord"))
|
||||
```
|
||||
|
||||
You can also specify a streaming URL:
|
||||
|
||||
```python
|
||||
from disagreement.models import Streaming
|
||||
|
||||
await client.change_presence(status="online", activity=Streaming("My Stream", "https://twitch.tv/someone"))
|
||||
```
|
||||
|
@ -2,6 +2,7 @@ import pytest
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from disagreement.client import Client
|
||||
from disagreement.models import Game
|
||||
from disagreement.errors import DisagreementException
|
||||
|
||||
|
||||
@ -18,11 +19,11 @@ class DummyGateway(MagicMock):
|
||||
async def test_change_presence_passes_arguments():
|
||||
client = Client(token="t")
|
||||
client._gateway = DummyGateway()
|
||||
|
||||
await client.change_presence(status="idle", activity_name="hi", activity_type=0)
|
||||
game = Game("hi")
|
||||
await client.change_presence(status="idle", activity=game)
|
||||
|
||||
client._gateway.update_presence.assert_awaited_once_with(
|
||||
status="idle", activity_name="hi", activity_type=0, since=0, afk=False
|
||||
status="idle", activity=game, since=0, afk=False
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user