mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-08-10 18:59:33 +00:00
Stop auto-accepting ToS on sign_up, add get_tos instead
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import getpass
|
||||
import inspect
|
||||
import os
|
||||
@@ -235,7 +236,7 @@ async def sign_in(
|
||||
|
||||
if isinstance(result, _tl.auth.AuthorizationSignUpRequired):
|
||||
# The method must return the User but we don't have it, so raise instead (matches pre-layer 104 behaviour)
|
||||
self._tos = result.terms_of_service
|
||||
self._tos = (result.terms_of_service, None)
|
||||
raise errors.SignUpRequired()
|
||||
|
||||
return await _update_session_state(self, result.user)
|
||||
@@ -258,15 +259,10 @@ async def sign_up(
|
||||
# because the user already tried to sign in.
|
||||
#
|
||||
# We're emulating pre-layer 104 behaviour so except the right error:
|
||||
if not self._tos:
|
||||
try:
|
||||
return await self.sign_in(code=code)
|
||||
except errors.SignUpRequired:
|
||||
pass # code is correct and was used, now need to sign in
|
||||
|
||||
if self._tos and self._tos.text:
|
||||
sys.stderr.write("{}\n".format(self._tos.text))
|
||||
sys.stderr.flush()
|
||||
try:
|
||||
return await self.sign_in(code=code)
|
||||
except errors.SignUpRequired:
|
||||
pass # code is correct and was used, now need to sign in
|
||||
|
||||
result = await self(_tl.fn.auth.SignUp(
|
||||
phone_number=phone,
|
||||
@@ -275,12 +271,23 @@ async def sign_up(
|
||||
last_name=last_name
|
||||
))
|
||||
|
||||
if self._tos:
|
||||
await self(_tl.fn.help.AcceptTermsOfService(self._tos.id))
|
||||
|
||||
return await _update_session_state(self, result.user)
|
||||
|
||||
|
||||
async def get_tos(self):
|
||||
first_time = self._tos is None
|
||||
no_tos = self._tos and self._tos[0] is None
|
||||
tos_expired = self._tos and self._tos[1] is not None and asyncio.get_running_loop().time() >= self._tos[1]
|
||||
|
||||
if first_time or no_tos or tos_expired:
|
||||
result = await self(_tl.fn.help.GetTermsOfServiceUpdate())
|
||||
tos = getattr(result, 'terms_of_service', None)
|
||||
self._tos = (tos, asyncio.get_running_loop().time() + result.expires)
|
||||
|
||||
# not stored in the client to prevent a cycle
|
||||
return _custom.TermsOfService._new(self, *self._tos)
|
||||
|
||||
|
||||
async def _update_session_state(self, user, save=True):
|
||||
"""
|
||||
Callback called whenever the login or sign up process completes.
|
||||
|
@@ -142,6 +142,7 @@ def init(
|
||||
self.flood_sleep_threshold = flood_sleep_threshold
|
||||
self._flood_waited_requests = {} # prevent calls that would floodwait entirely
|
||||
self._phone_code_hash = None # used during login to prevent exposing the hash to end users
|
||||
self._tos = None # used during signup and when fetching tos (tos/expiry)
|
||||
|
||||
# Update handling.
|
||||
self._catch_up = catch_up
|
||||
|
@@ -455,10 +455,15 @@ class TelegramClient:
|
||||
|
||||
You must call `send_code_request` first.
|
||||
|
||||
**By using this method you're agreeing to Telegram's
|
||||
Terms of Service. This is required and your account
|
||||
will be banned otherwise.** See https://telegram.org/tos
|
||||
and https://core.telegram.org/api/terms.
|
||||
.. important::
|
||||
|
||||
When creating a new account, you must be sure to show the Terms of Service
|
||||
to the user, and only after they approve, the code can accept the Terms of
|
||||
Service. If not, they must be declined, in which case the account **will be
|
||||
deleted**.
|
||||
|
||||
Make sure to use `client.get_tos` to fetch the Terms of Service, and to
|
||||
use `tos.accept()` or `tos.decline()` after the user selects an option.
|
||||
|
||||
Arguments
|
||||
first_name (`str`):
|
||||
@@ -481,6 +486,16 @@ class TelegramClient:
|
||||
|
||||
code = input('enter code: ')
|
||||
await client.sign_up('Anna', 'Banana', code=code)
|
||||
|
||||
# IMPORTANT: you MUST retrieve the Terms of Service and accept
|
||||
# them, or Telegram has every right to delete the account.
|
||||
tos = await client.get_tos()
|
||||
print(tos.html)
|
||||
|
||||
if code('accept (y/n)?: ') == 'y':
|
||||
await tos.accept()
|
||||
else:
|
||||
await tos.decline() # deletes the account!
|
||||
"""
|
||||
|
||||
@forward_call(auth.send_code_request)
|
||||
@@ -628,6 +643,42 @@ class TelegramClient:
|
||||
await client.edit_2fa(current_password='I_<3_Telethon')
|
||||
"""
|
||||
|
||||
@forward_call(auth.get_tos)
|
||||
async def get_tos(self: 'TelegramClient') -> '_custom.TermsOfService':
|
||||
"""
|
||||
Fetch `Telegram's Terms of Service`_, which every user must accept in order to use
|
||||
Telegram, or they must otherwise `delete their account`_.
|
||||
|
||||
This method **must** be called after sign up, and **should** be called again
|
||||
after it expires (at the risk of having the account terminated otherwise).
|
||||
|
||||
See the documentation of `TermsOfService` for more information.
|
||||
|
||||
The library cannot automate this process because the user must read the Terms of Service.
|
||||
Automating its usage without reading the terms would be done at the developer's own risk.
|
||||
|
||||
Example
|
||||
.. code-block:: python
|
||||
|
||||
# Fetch the ToS, forever (this could be a separate task, for example)
|
||||
while True:
|
||||
tos = await client.get_tos()
|
||||
|
||||
if tos:
|
||||
# There's an update or they must be accepted (you could show a popup)
|
||||
print(tos.html)
|
||||
if code('accept (y/n)?: ') == 'y':
|
||||
await tos.accept()
|
||||
else:
|
||||
await tos.decline() # deletes the account!
|
||||
|
||||
# after tos.timeout expires, the method should be called again!
|
||||
await asyncio.sleep(tos.timeout)
|
||||
|
||||
_Telegram's Terms of Service: https://telegram.org/tos
|
||||
_delete their account: https://core.telegram.org/api/config#terms-of-service
|
||||
"""
|
||||
|
||||
async def __aenter__(self):
|
||||
await self.connect()
|
||||
return self
|
||||
|
@@ -10,6 +10,7 @@ from ..errors._rpcbase import RpcError, ServerError, FloodError, InvalidDcError,
|
||||
from .._misc import helpers, utils, hints
|
||||
from .._sessions.types import Entity
|
||||
from .. import errors, _tl
|
||||
from ..types import _custom
|
||||
from .account import ignore_takeout
|
||||
|
||||
_NOT_A_REQUEST = lambda: TypeError('You can only invoke requests, not types!')
|
||||
@@ -134,7 +135,7 @@ async def _call(self: 'TelegramClient', sender, request, ordered=False, flood_sl
|
||||
async def get_me(self: 'TelegramClient') \
|
||||
-> 'typing.Union[_tl.User, _tl.InputPeerUser]':
|
||||
try:
|
||||
return (await self(_tl.fn.users.GetUsers([_tl.InputUserSelf()])))[0]
|
||||
return _custom.User._new(self, (await self(_tl.fn.users.GetUsers([_tl.InputUserSelf()])))[0])
|
||||
except UnauthorizedError:
|
||||
return None
|
||||
|
||||
|
Reference in New Issue
Block a user