Periodically send ping/getState

This commit is contained in:
Lonami Exo 2018-06-18 13:22:25 +02:00
parent 94d6c339c4
commit 374f5e2aab
4 changed files with 42 additions and 1 deletions

View File

@ -2,6 +2,7 @@ import abc
import asyncio
import logging
import platform
import time
import warnings
from datetime import timedelta, datetime
@ -192,6 +193,8 @@ class TelegramBaseClient(abc.ABC):
self._last_state = datetime.now()
self._state_delay = timedelta(hours=1)
self._state = None
self._updates_handle = None
self._last_request = time.time()
# Some further state for subclasses
self._event_builders = []
@ -241,6 +244,8 @@ class TelegramBaseClient(abc.ABC):
await self._sender.send(self._init_with(
functions.help.GetConfigRequest()))
self._updates_handle = self._loop.create_task(self._update_loop())
if not had_auth:
self.session.auth_key = self._sender.state.auth_key
self.session.save()
@ -386,4 +391,8 @@ class TelegramBaseClient(abc.ABC):
def _handle_update(self, update):
raise NotImplementedError
@abc.abstractmethod
def _update_loop(self):
raise NotImplementedError
# endregion

View File

@ -1,6 +1,8 @@
import asyncio
import itertools
import logging
import random
import time
import warnings
from .users import UserMethods
@ -170,6 +172,35 @@ class UpdateMethods(UserMethods):
update._entities = {}
self._loop.create_task(self._dispatch_update(update))
async def _update_loop(self):
# Pings' ID don't really need to be secure, just "random"
rnd = lambda: random.randrange(-2**63, 2**63)
while self.is_connected():
try:
await asyncio.wait_for(self.disconnected, timeout=60)
continue # We actually just want to act upon timeout
except asyncio.TimeoutError:
pass
except:
continue # Any disconnected exception should be ignored
# We also don't really care about their result.
# Just send them periodically.
self._sender.send(functions.PingRequest(rnd()))
# We need to send some content-related request at least hourly
# for Telegram to keep delivering updates, otherwise they will
# just stop even if we're connected. Do so every 30 minutes.
#
# TODO Call getDifference instead since it's more relevant
if time.time() - self._last_request > 30 * 60:
if not await self.is_user_authorized():
# What can be the user doing for so
# long without being logged in...?
continue
await self(functions.updates.GetStateRequest())
async def _dispatch_update(self, update):
if self._events_pending_resolve:
if self._event_resolve_lock.locked():

View File

@ -1,5 +1,6 @@
import asyncio
import itertools
import time
from .telegrambaseclient import TelegramBaseClient
from .. import errors, utils
@ -16,6 +17,7 @@ class UserMethods(TelegramBaseClient):
raise _NOT_A_REQUEST
await r.resolve(self, utils)
self._last_request = time.time()
for _ in range(retries):
try:
future = self._sender.send(request, ordered=ordered)

View File

@ -384,7 +384,6 @@ class MTProtoSender:
__log__.debug('Receiving items from the network...')
body = await self._connection.recv()
except asyncio.TimeoutError:
# TODO If nothing is received for a minute, send a request
continue
except Exception as e:
if isinstance(e, ConnectionError):