Browse Source

Use X-Ratelimit-Reset-After header by default.

There is now an option to turn it off, of course.
pull/2327/head
Rapptz 6 years ago
parent
commit
ea3d119ca6
  1. 11
      discord/client.py
  2. 5
      discord/http.py
  3. 13
      discord/utils.py

11
discord/client.py

@ -185,6 +185,14 @@ class Client:
In short, this makes it so the only member you can reliably query is the In short, this makes it so the only member you can reliably query is the
message author. Useful for bots that do not require any state. message author. Useful for bots that do not require any state.
assume_unsync_clock: :class:`bool`
Whether to assume the system clock is unsynced. This applies to the ratelimit handling
code. If this is set to ``True``, the default, then the library uses the time to reset
a rate limit bucket given by Discord. If this is ``False`` then your system clock is
used to calculate how long to sleep for. If this is set to ``False`` it is recommended to
sync your system clock to Google's NTP server.
.. versionadded:: 1.3
Attributes Attributes
----------- -----------
@ -203,7 +211,8 @@ class Client:
connector = options.pop('connector', None) connector = options.pop('connector', None)
proxy = options.pop('proxy', None) proxy = options.pop('proxy', None)
proxy_auth = options.pop('proxy_auth', None) proxy_auth = options.pop('proxy_auth', None)
self.http = HTTPClient(connector, proxy=proxy, proxy_auth=proxy_auth, loop=self.loop) unsync_clock = options.pop('assume_unsync_clock', True)
self.http = HTTPClient(connector, proxy=proxy, proxy_auth=proxy_auth, unsync_clock=unsync_clock, loop=self.loop)
self._handlers = { self._handlers = {
'ready': self._handle_ready 'ready': self._handle_ready

5
discord/http.py

@ -86,7 +86,7 @@ class HTTPClient:
SUCCESS_LOG = '{method} {url} has received {text}' SUCCESS_LOG = '{method} {url} has received {text}'
REQUEST_LOG = '{method} {url} with {json} has returned {status}' REQUEST_LOG = '{method} {url} with {json} has returned {status}'
def __init__(self, connector=None, *, proxy=None, proxy_auth=None, loop=None): def __init__(self, connector=None, *, proxy=None, proxy_auth=None, loop=None, unsync_clock=True):
self.loop = asyncio.get_event_loop() if loop is None else loop self.loop = asyncio.get_event_loop() if loop is None else loop
self.connector = connector self.connector = connector
self.__session = None # filled in static_login self.__session = None # filled in static_login
@ -97,6 +97,7 @@ class HTTPClient:
self.bot_token = False self.bot_token = False
self.proxy = proxy self.proxy = proxy
self.proxy_auth = proxy_auth self.proxy_auth = proxy_auth
self.use_clock = not unsync_clock
user_agent = 'DiscordBot (https://github.com/Rapptz/discord.py {0}) Python/{1[0]}.{1[1]} aiohttp/{2}' user_agent = 'DiscordBot (https://github.com/Rapptz/discord.py {0}) Python/{1[0]}.{1[1]} aiohttp/{2}'
self.user_agent = user_agent.format(__version__, sys.version_info, aiohttp.__version__) self.user_agent = user_agent.format(__version__, sys.version_info, aiohttp.__version__)
@ -166,7 +167,7 @@ class HTTPClient:
remaining = r.headers.get('X-Ratelimit-Remaining') remaining = r.headers.get('X-Ratelimit-Remaining')
if remaining == '0' and r.status != 429: if remaining == '0' and r.status != 429:
# we've depleted our current bucket # we've depleted our current bucket
delta = utils._parse_ratelimit_header(r) delta = utils._parse_ratelimit_header(r, use_clock=self.use_clock)
log.debug('A rate limit bucket has been exhausted (bucket: %s, retry: %s).', bucket, delta) log.debug('A rate limit bucket has been exhausted (bucket: %s, retry: %s).', bucket, delta)
maybe_lock.defer() maybe_lock.defer()
self.loop.call_later(delta, lock.release) self.loop.call_later(delta, lock.release)

13
discord/utils.py

@ -302,10 +302,15 @@ def _bytes_to_base64_data(data):
def to_json(obj): def to_json(obj):
return json.dumps(obj, separators=(',', ':'), ensure_ascii=True) return json.dumps(obj, separators=(',', ':'), ensure_ascii=True)
def _parse_ratelimit_header(request): def _parse_ratelimit_header(request, *, use_clock=False):
now = parsedate_to_datetime(request.headers['Date']) reset_after = request.headers.get('X-Ratelimit-Reset-After')
reset = datetime.datetime.fromtimestamp(float(request.headers['X-Ratelimit-Reset']), datetime.timezone.utc) if use_clock or not reset_after:
return (reset - now).total_seconds() utc = datetime.timezone.utc
now = datetime.datetime.now(utc)
reset = datetime.datetime.fromtimestamp(float(request.headers['X-Ratelimit-Reset']), utc)
return (reset - now).total_seconds()
else:
return float(reset_after)
async def maybe_coroutine(f, *args, **kwargs): async def maybe_coroutine(f, *args, **kwargs):
value = f(*args, **kwargs) value = f(*args, **kwargs)

Loading…
Cancel
Save