aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2016-09-26 19:54:52 -0400
committerRapptz <[email protected]>2016-09-26 19:55:42 -0400
commit7272190e2db6def1f8a6e153775b33c95d62e7bf (patch)
tree062d206d51b9abbeb8da42035b7c383a8eb91386
parentRemove unused endpoints.py file. (diff)
downloaddiscord.py-7272190e2db6def1f8a6e153775b33c95d62e7bf.tar.xz
discord.py-7272190e2db6def1f8a6e153775b33c95d62e7bf.zip
Add support for "Do Not Disturb" and "Invisible" statuses.
This deprecates Client.change_status in favour of the newer and more correct Client.change_presence.
-rw-r--r--discord/client.py42
-rw-r--r--discord/enums.py3
-rw-r--r--discord/gateway.py22
-rw-r--r--discord/utils.py16
-rw-r--r--docs/api.rst11
5 files changed, 86 insertions, 8 deletions
diff --git a/discord/client.py b/discord/client.py
index 0b0d9d5a..87cee11a 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -37,7 +37,7 @@ from .errors import *
from .state import ConnectionState
from .permissions import Permissions, PermissionOverwrite
from . import utils, compat
-from .enums import ChannelType, ServerRegion, VerificationLevel
+from .enums import ChannelType, ServerRegion, VerificationLevel, Status
from .voice_client import VoiceClient
from .iterators import LogsFromIterator
from .gateway import *
@@ -1526,6 +1526,7 @@ class Client:
self._update_cache(self.email, password)
@asyncio.coroutine
+ @utils.deprecated('change_presence')
def change_status(self, game=None, idle=False):
"""|coro|
@@ -1537,7 +1538,8 @@ class Client:
The idle parameter is a boolean parameter that indicates whether the
client should go idle or not.
- .. _game_list: https://gist.github.com/Rapptz/a82b82381b70a60c281b
+ .. deprecated:: v0.13.0
+ Use :meth:`change_status` instead.
Parameters
----------
@@ -1554,6 +1556,42 @@ class Client:
yield from self.ws.change_presence(game=game, idle=idle)
@asyncio.coroutine
+ def change_presence(self, *, game=None, status=None, afk=False):
+ """|coro|
+
+ Changes the client's presence.
+
+ The game parameter is a Game object (not a string) that represents
+ a game being played currently.
+
+ Parameters
+ ----------
+ game: Optional[:class:`Game`]
+ The game being played. None if no game is being played.
+ status: Optional[:class:`Status`]
+ Indicates what status to change to. If None, then
+ :attr:`Status.online` is used.
+ afk: bool
+ Indicates if you are going AFK. This allows the discord
+ client to know how to handle push notifications better
+ for you in case you are actually idle and not lying.
+
+ Raises
+ ------
+ InvalidArgument
+ If the ``game`` parameter is not :class:`Game` or None.
+ """
+
+ if status is None:
+ status = 'online'
+ elif status is Status.offline:
+ status = 'invisible'
+ else:
+ status = str(status)
+
+ yield from self.ws.change_presence(game=game, status=status, afk=afk)
+
+ @asyncio.coroutine
def change_nickname(self, member, nickname):
"""|coro|
diff --git a/discord/enums.py b/discord/enums.py
index 191728ee..37195cbb 100644
--- a/discord/enums.py
+++ b/discord/enums.py
@@ -78,6 +78,9 @@ class Status(Enum):
online = 'online'
offline = 'offline'
idle = 'idle'
+ dnd = 'dnd'
+ do_not_disturb = 'dnd'
+ invisible = 'invisible'
def __str__(self):
return self.value
diff --git a/discord/gateway.py b/discord/gateway.py
index ff6bc6a8..402a174b 100644
--- a/discord/gateway.py
+++ b/discord/gateway.py
@@ -29,7 +29,7 @@ import websockets
import asyncio
import aiohttp
from . import utils, compat
-from .enums import Status
+from .enums import Status, try_enum
from .game import Game
from .errors import GatewayNotFound, ConnectionClosed, InvalidArgument
import logging
@@ -406,18 +406,25 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol):
raise ConnectionClosed(e) from e
@asyncio.coroutine
- def change_presence(self, *, game=None, idle=None):
+ def change_presence(self, *, game=None, status=None, afk=False, since=0.0, idle=None):
if game is not None and not isinstance(game, Game):
raise InvalidArgument('game must be of Game or None')
- idle_since = None if idle == False else int(time.time() * 1000)
+ if idle:
+ status = 'idle'
+
+ if status == 'idle':
+ since = int(time.time() * 1000)
+
sent_game = dict(game) if game else None
payload = {
'op': self.PRESENCE,
'd': {
'game': sent_game,
- 'idle_since': idle_since
+ 'afk': afk,
+ 'since': since,
+ 'status': status
}
}
@@ -425,14 +432,17 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol):
log.debug('Sending "{}" to change status'.format(sent))
yield from self.send(sent)
+ status_enum = try_enum(Status, status)
+ if status_enum is Status.invisible:
+ status_enum = Status.offline
+
for server in self._connection.servers:
me = server.me
if me is None:
continue
me.game = game
- status = Status.idle if idle_since else Status.online
- me.status = status
+ me.status = status_enum
@asyncio.coroutine
def request_sync(self, guild_ids):
diff --git a/discord/utils.py b/discord/utils.py
index 55ee30a8..83129654 100644
--- a/discord/utils.py
+++ b/discord/utils.py
@@ -30,6 +30,7 @@ import datetime
from base64 import b64encode
import asyncio
import json
+import warnings, functools
DISCORD_EPOCH = 1420070400000
@@ -74,6 +75,21 @@ def parse_time(timestamp):
return datetime.datetime(*map(int, re_split(r'[^\d]', timestamp.replace('+00:00', ''))))
return None
+def deprecated(instead=None):
+ def actual_decorator(func):
+ @functools.wraps(func)
+ def decorated(*args, **kwargs):
+ warnings.simplefilter('always', DeprecationWarning) # turn off filter
+ if instead:
+ fmt = "{0.__name__} is deprecated, use {1} instead."
+ else:
+ fmt = '{0.__name__} is deprecated.'
+
+ warnings.warn(fmt.format(func, instead), stacklevel=3, category=DeprecationWarning)
+ warnings.simplefilter('default', DeprecationWarning) # reset filter
+ return func(*args, **kwargs)
+ return decorated
+ return actual_decorator
def oauth_url(client_id, permissions=None, server=None, redirect_uri=None):
"""A helper function that returns the OAuth2 URL for inviting the bot
diff --git a/docs/api.rst b/docs/api.rst
index 02572dd2..641331c4 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -549,6 +549,17 @@ All enumerations are subclasses of `enum`_.
.. attribute:: idle
The member is idle.
+ .. attribute:: dnd
+
+ The member is "Do Not Disturb".
+ .. attribute:: do_not_disturb
+
+ An alias for :attr:`dnd`.
+ .. attribute:: invisible
+
+ The member is "invisible". In reality, this is only used in sending
+ a presence a la :meth:`Client.change_presence`. When you receive a
+ user's presence this will be :attr:`offline` instead.
.. _discord_api_data: