mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-02-20 21:41:06 +03:00
Update to v1.0
This commit is contained in:
parent
a1799ee74b
commit
72835dfb44
|
@ -26,7 +26,7 @@ Installing
|
||||||
|
|
||||||
.. code:: sh
|
.. code:: sh
|
||||||
|
|
||||||
pip3 install telethon-aio
|
pip3 install telethon
|
||||||
|
|
||||||
|
|
||||||
Creating a client
|
Creating a client
|
||||||
|
|
|
@ -13,9 +13,9 @@ Magic with asyncio
|
||||||
|
|
||||||
import telethon.sync
|
import telethon.sync
|
||||||
|
|
||||||
At the beginning of your main script and you will be good. If you
|
At the beginning of your main script and you will be good. If you do use
|
||||||
do use updates or events, keep reading, or use `a simpler version
|
updates or events, keep reading, or install the latest version using
|
||||||
<https://github.com/LonamiWebs/Telethon/tree/sync>`_ (discouraged).
|
threads and Python 3.4 support with ``pip install telethon==0.19.1.6``.
|
||||||
|
|
||||||
You might also want to check the :ref:`changelog`.
|
You might also want to check the :ref:`changelog`.
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ way, since your event handlers will be ``async def`` too.
|
||||||
|
|
||||||
There are two exceptions. Both `client.run_until_disconnected()
|
There are two exceptions. Both `client.run_until_disconnected()
|
||||||
<telethon.client.updates.UpdateMethods.run_until_disconnected>` and
|
<telethon.client.updates.UpdateMethods.run_until_disconnected>` and
|
||||||
`client.start() <telethon.client.updates.UpdateMethods.start>` work in
|
`client.start() <telethon.client.auth.AuthMethods.start>` work in
|
||||||
and outside of ``async def`` for convenience without importing the
|
and outside of ``async def`` for convenience without importing the
|
||||||
magic module. The rest of methods remain ``async`` unless you import it.
|
magic module. The rest of methods remain ``async`` unless you import it.
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,131 @@ it can take advantage of new goodies!
|
||||||
.. contents:: List of All Versions
|
.. contents:: List of All Versions
|
||||||
|
|
||||||
|
|
||||||
|
Synchronous magic (v1.0)
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
|
||||||
|
If you come from Telethon pre-1.0 you **really** want to read
|
||||||
|
:ref:`asyncio-magic` to port your scripts to the new version.
|
||||||
|
|
||||||
|
If you're not ready for this, you can ``pip install telethon==0.19.1.6``.
|
||||||
|
It's the latest version of the library using threads for Python 3.4+.
|
||||||
|
|
||||||
|
If you're interested in maintaining a Telethon version that supports
|
||||||
|
Python 3.4 and uses threads, please open an issue and let me know.
|
||||||
|
|
||||||
|
The library has been around for well over a year. A lot of improvements have
|
||||||
|
been made, a lot of user complaints have been fixed, and a lot of user desires
|
||||||
|
have been implemented. It's time to consider the public API as stable, and
|
||||||
|
remove some of the old methods that were around until now for compatibility
|
||||||
|
reasons. But there's one more surprise!
|
||||||
|
|
||||||
|
There is a new magic ``telethon.sync`` module to let you use **all** the
|
||||||
|
methods in the :ref:`TelegramClient <telethon-client>` (and the types returned
|
||||||
|
from its functions) in a synchronous way, while using ``asyncio`` behind
|
||||||
|
the scenes! This means you're now able to do both of the following:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await client.send_message('me', 'Hello!')
|
||||||
|
|
||||||
|
asyncio.get_event_loop().run_until_complete(main())
|
||||||
|
|
||||||
|
# ...can be rewritten as:
|
||||||
|
|
||||||
|
from telethon import sync
|
||||||
|
client.send_message('me', 'Hello!')
|
||||||
|
|
||||||
|
Both ways can coexist (you need to ``await`` if the loop is running).
|
||||||
|
|
||||||
|
You can also use the magic ``sync`` module in your own classes, and call
|
||||||
|
``sync.syncify(cls)`` to convert all their ``async def`` into magic variants.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Breaking Changes
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
- ``message.get_fwd_sender`` is now in `message.forward
|
||||||
|
<telethon.tl.custom.message.Message.forward>`.
|
||||||
|
- ``client.add_update_handler`` is now `client.add_event_handler
|
||||||
|
<telethon.client.updates.UpdateMethods.add_event_handler>`
|
||||||
|
- ``client.remove_update_handler`` is now `client.remove_event_handler
|
||||||
|
<telethon.client.updates.UpdateMethods.remove_event_handler>`
|
||||||
|
- ``client.list_update_handlers`` is now `client.list_event_handlers
|
||||||
|
<telethon.client.updates.UpdateMethods.list_event_handlers>`
|
||||||
|
- ``client.get_message_history`` is now `client.get_messages
|
||||||
|
<telethon.client.messages.MessageMethods.get_messages>`
|
||||||
|
- ``client.send_voice_note`` is now `client.send_file
|
||||||
|
<telethon.client.uploads.UploadMethods.send_file>` with ``is_voice=True``.
|
||||||
|
- ``client.invoke()`` is now ``client(...)``.
|
||||||
|
- ``report_errors`` has been removed since it's currently not used,
|
||||||
|
and ``flood_sleep_threshold`` is now part of the client.
|
||||||
|
- Methods with a lot of arguments can no longer be used without specifying
|
||||||
|
their argument. Instead you need to use named arguments. This improves
|
||||||
|
readability and not needing to learn the order of the arguments, which
|
||||||
|
can also change.
|
||||||
|
|
||||||
|
|
||||||
|
Additions
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
- `client.send_file <telethon.client.uploads.UploadMethods.send_file>` now
|
||||||
|
accepts external ``http://`` and ``https://`` URLs.
|
||||||
|
- You can use the :ref:`TelegramClient <telethon-client>` inside of ``with``
|
||||||
|
blocks, which will `client.start() <telethon.client.auth.AuthMethods.start>`
|
||||||
|
and `disconnect() <telethon.client.telegrambaseclient.TelegramBaseClient.disconnect>`
|
||||||
|
the client for you:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from telethon import TelegramClient, sync
|
||||||
|
|
||||||
|
with TelegramClient(name, api_id, api_hash) as client:
|
||||||
|
client.send_message('me', 'Hello!')
|
||||||
|
|
||||||
|
Convenience at its maximum! You can even chain the `.start()
|
||||||
|
<telethon.client.auth.AuthMethods.start>` method since
|
||||||
|
it returns the instance of the client:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
with TelegramClient(name, api_id, api_hash).star(bot_token=token) as bot:
|
||||||
|
bot.send_message(chat, 'Hello!')
|
||||||
|
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
- There were some ``@property async def`` left, and some ``await property``.
|
||||||
|
- "User joined" event was being treated as "User was invited".
|
||||||
|
- SQLite's cursor should not be closed properly after usage.
|
||||||
|
- ``await`` the updates task upon disconnection.
|
||||||
|
- Some bug in Python 3.5.2's ``asyncio`` causing 100% CPU load if you
|
||||||
|
forgot to call `client.disconnect()
|
||||||
|
<telethon.client.telegrambaseclient.TelegramBaseClient.disconnect>`.
|
||||||
|
The method is called for you on object destruction, but you still should
|
||||||
|
disconnect manually or use a ``with`` block.
|
||||||
|
- Some fixes regarding disconnecting on client deletion and properly
|
||||||
|
saving the authorization key.
|
||||||
|
- Passing a class to `message.get_entities_text
|
||||||
|
<telethon.tl.custom.message.Message.get_entities_text>` now works properly.
|
||||||
|
- Iterating messages from a specific user in private messages now works.
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
- Both `client.start() <telethon.client.auth.AuthMethods.start>` and
|
||||||
|
`client.run_until_disconnected()
|
||||||
|
<telethon.client.updates.UpdateMethods.run_until_disconnected>` can
|
||||||
|
be ran in both a synchronous way (without starting the loop manually)
|
||||||
|
or from an ``async def`` where they need to have an ``await``.
|
||||||
|
|
||||||
|
|
||||||
Core Rewrite in asyncio (v1.0-rc1)
|
Core Rewrite in asyncio (v1.0-rc1)
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -183,7 +183,7 @@ def main():
|
||||||
version = re.search(r"^__version__\s*=\s*'(.*)'.*$",
|
version = re.search(r"^__version__\s*=\s*'(.*)'.*$",
|
||||||
f.read(), flags=re.MULTILINE).group(1)
|
f.read(), flags=re.MULTILINE).group(1)
|
||||||
setup(
|
setup(
|
||||||
name='Telethon-aio',
|
name='Telethon',
|
||||||
version=version,
|
version=version,
|
||||||
description="Full-featured Telegram client library for Python 3",
|
description="Full-featured Telegram client library for Python 3",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
|
@ -206,7 +206,7 @@ def main():
|
||||||
# 3 - Alpha
|
# 3 - Alpha
|
||||||
# 4 - Beta
|
# 4 - Beta
|
||||||
# 5 - Production/Stable
|
# 5 - Production/Stable
|
||||||
'Development Status :: 3 - Alpha',
|
'Development Status :: 5 - Production/Stable',
|
||||||
|
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Topic :: Communications :: Chat',
|
'Topic :: Communications :: Chat',
|
||||||
|
|
|
@ -17,6 +17,7 @@ class AuthMethods(MessageParseMethods, UserMethods):
|
||||||
self,
|
self,
|
||||||
phone=lambda: input('Please enter your phone: '),
|
phone=lambda: input('Please enter your phone: '),
|
||||||
password=lambda: getpass.getpass('Please enter your password: '),
|
password=lambda: getpass.getpass('Please enter your password: '),
|
||||||
|
*,
|
||||||
bot_token=None, force_sms=False, code_callback=None,
|
bot_token=None, force_sms=False, code_callback=None,
|
||||||
first_name='New User', last_name='', max_attempts=3):
|
first_name='New User', last_name='', max_attempts=3):
|
||||||
"""
|
"""
|
||||||
|
@ -193,7 +194,7 @@ class AuthMethods(MessageParseMethods, UserMethods):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def sign_in(
|
async def sign_in(
|
||||||
self, phone=None, code=None, password=None,
|
self, phone=None, *, code=None, password=None,
|
||||||
bot_token=None, phone_code_hash=None):
|
bot_token=None, phone_code_hash=None):
|
||||||
"""
|
"""
|
||||||
Starts or completes the sign in process with the given phone number
|
Starts or completes the sign in process with the given phone number
|
||||||
|
@ -325,7 +326,7 @@ class AuthMethods(MessageParseMethods, UserMethods):
|
||||||
self._authorized = True
|
self._authorized = True
|
||||||
return result.user
|
return result.user
|
||||||
|
|
||||||
async def send_code_request(self, phone, force_sms=False):
|
async def send_code_request(self, phone, *, force_sms=False):
|
||||||
"""
|
"""
|
||||||
Sends a code request to the specified phone number.
|
Sends a code request to the specified phone number.
|
||||||
|
|
||||||
|
@ -382,8 +383,8 @@ class AuthMethods(MessageParseMethods, UserMethods):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def edit_2fa(
|
async def edit_2fa(
|
||||||
self, current_password=None, new_password=None, hint='',
|
self, current_password=None, new_password=None,
|
||||||
email=None):
|
*, hint='', email=None):
|
||||||
"""
|
"""
|
||||||
Changes the 2FA settings of the logged in user, according to the
|
Changes the 2FA settings of the logged in user, according to the
|
||||||
passed parameters. Take note of the parameter explanations.
|
passed parameters. Take note of the parameter explanations.
|
||||||
|
|
|
@ -13,7 +13,7 @@ class ChatMethods(UserMethods):
|
||||||
|
|
||||||
@async_generator
|
@async_generator
|
||||||
async def iter_participants(
|
async def iter_participants(
|
||||||
self, entity, limit=None, search='',
|
self, entity, limit=None, *, search='',
|
||||||
filter=None, aggressive=False, _total=None):
|
filter=None, aggressive=False, _total=None):
|
||||||
"""
|
"""
|
||||||
Iterator over the participants belonging to the specified chat.
|
Iterator over the participants belonging to the specified chat.
|
||||||
|
|
|
@ -14,7 +14,7 @@ class DialogMethods(UserMethods):
|
||||||
|
|
||||||
@async_generator
|
@async_generator
|
||||||
async def iter_dialogs(
|
async def iter_dialogs(
|
||||||
self, limit=None, offset_date=None, offset_id=0,
|
self, limit=None, *, offset_date=None, offset_id=0,
|
||||||
offset_peer=types.InputPeerEmpty(), ignore_migrated=False,
|
offset_peer=types.InputPeerEmpty(), ignore_migrated=False,
|
||||||
_total=None):
|
_total=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -16,7 +16,7 @@ class DownloadMethods(UserMethods):
|
||||||
# region Public methods
|
# region Public methods
|
||||||
|
|
||||||
async def download_profile_photo(
|
async def download_profile_photo(
|
||||||
self, entity, file=None, download_big=True):
|
self, entity, file=None, *, download_big=True):
|
||||||
"""
|
"""
|
||||||
Downloads the profile photo of the given entity (user/chat/channel).
|
Downloads the profile photo of the given entity (user/chat/channel).
|
||||||
|
|
||||||
|
@ -91,7 +91,8 @@ class DownloadMethods(UserMethods):
|
||||||
# Until there's a report for chats, no need to.
|
# Until there's a report for chats, no need to.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def download_media(self, message, file=None, progress_callback=None):
|
async def download_media(self, message, file=None,
|
||||||
|
*, progress_callback=None):
|
||||||
"""
|
"""
|
||||||
Downloads the given media, or the media from a specified Message.
|
Downloads the given media, or the media from a specified Message.
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ class DownloadMethods(UserMethods):
|
||||||
)
|
)
|
||||||
|
|
||||||
async def download_file(
|
async def download_file(
|
||||||
self, input_location, file=None, part_size_kb=None,
|
self, input_location, file=None, *, part_size_kb=None,
|
||||||
file_size=None, progress_callback=None):
|
file_size=None, progress_callback=None):
|
||||||
"""
|
"""
|
||||||
Downloads the given input location to a file.
|
Downloads the given input location to a file.
|
||||||
|
|
|
@ -22,7 +22,7 @@ class MessageMethods(UploadMethods, MessageParseMethods):
|
||||||
|
|
||||||
@async_generator
|
@async_generator
|
||||||
async def iter_messages(
|
async def iter_messages(
|
||||||
self, entity, limit=None, offset_date=None, offset_id=0,
|
self, entity, limit=None, *, offset_date=None, offset_id=0,
|
||||||
max_id=0, min_id=0, add_offset=0, search=None, filter=None,
|
max_id=0, min_id=0, add_offset=0, search=None, filter=None,
|
||||||
from_user=None, batch_size=100, wait_time=None, ids=None,
|
from_user=None, batch_size=100, wait_time=None, ids=None,
|
||||||
_total=None):
|
_total=None):
|
||||||
|
@ -285,7 +285,7 @@ class MessageMethods(UploadMethods, MessageParseMethods):
|
||||||
# region Message sending/editing/deleting
|
# region Message sending/editing/deleting
|
||||||
|
|
||||||
async def send_message(
|
async def send_message(
|
||||||
self, entity, message='', reply_to=None,
|
self, entity, message='', *, reply_to=None,
|
||||||
parse_mode=utils.Default, link_preview=True, file=None,
|
parse_mode=utils.Default, link_preview=True, file=None,
|
||||||
force_document=False, clear_draft=False):
|
force_document=False, clear_draft=False):
|
||||||
"""
|
"""
|
||||||
|
@ -403,7 +403,7 @@ class MessageMethods(UploadMethods, MessageParseMethods):
|
||||||
|
|
||||||
return self._get_response_message(request, result, entity)
|
return self._get_response_message(request, result, entity)
|
||||||
|
|
||||||
async def forward_messages(self, entity, messages, from_peer=None):
|
async def forward_messages(self, entity, messages, *, from_peer=None):
|
||||||
"""
|
"""
|
||||||
Forwards the given message(s) to the specified entity.
|
Forwards the given message(s) to the specified entity.
|
||||||
|
|
||||||
|
@ -469,8 +469,8 @@ class MessageMethods(UploadMethods, MessageParseMethods):
|
||||||
return result[0] if single else result
|
return result[0] if single else result
|
||||||
|
|
||||||
async def edit_message(
|
async def edit_message(
|
||||||
self, entity, message=None, text=None, parse_mode=utils.Default,
|
self, entity, message=None, text=None,
|
||||||
link_preview=True, file=None):
|
*, parse_mode=utils.Default, link_preview=True, file=None):
|
||||||
"""
|
"""
|
||||||
Edits the given message ID (to change its contents or disable preview).
|
Edits the given message ID (to change its contents or disable preview).
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ class MessageMethods(UploadMethods, MessageParseMethods):
|
||||||
self._cache_media(msg, file, file_handle)
|
self._cache_media(msg, file, file_handle)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
async def delete_messages(self, entity, message_ids, revoke=True):
|
async def delete_messages(self, entity, message_ids, *, revoke=True):
|
||||||
"""
|
"""
|
||||||
Deletes a message from a chat, optionally "for everyone".
|
Deletes a message from a chat, optionally "for everyone".
|
||||||
|
|
||||||
|
@ -586,8 +586,8 @@ class MessageMethods(UploadMethods, MessageParseMethods):
|
||||||
|
|
||||||
# region Miscellaneous
|
# region Miscellaneous
|
||||||
|
|
||||||
async def send_read_acknowledge(self, entity, message=None, max_id=None,
|
async def send_read_acknowledge(
|
||||||
clear_mentions=False):
|
self, entity, message=None, *, max_id=None, clear_mentions=False):
|
||||||
"""
|
"""
|
||||||
Sends a "read acknowledge" (i.e., notifying the given peer that we've
|
Sends a "read acknowledge" (i.e., notifying the given peer that we've
|
||||||
read their messages, also known as the "double check").
|
read their messages, also known as the "double check").
|
||||||
|
|
|
@ -27,7 +27,7 @@ class UploadMethods(MessageParseMethods, UserMethods):
|
||||||
# region Public methods
|
# region Public methods
|
||||||
|
|
||||||
async def send_file(
|
async def send_file(
|
||||||
self, entity, file, caption='', force_document=False,
|
self, entity, file, *, caption='', force_document=False,
|
||||||
progress_callback=None, reply_to=None, attributes=None,
|
progress_callback=None, reply_to=None, attributes=None,
|
||||||
thumb=None, allow_cache=True, parse_mode=utils.Default,
|
thumb=None, allow_cache=True, parse_mode=utils.Default,
|
||||||
voice_note=False, video_note=False, **kwargs):
|
voice_note=False, video_note=False, **kwargs):
|
||||||
|
@ -221,7 +221,7 @@ class UploadMethods(MessageParseMethods, UserMethods):
|
||||||
]
|
]
|
||||||
|
|
||||||
async def upload_file(
|
async def upload_file(
|
||||||
self, file, part_size_kb=None, file_name=None, use_cache=None,
|
self, file, *, part_size_kb=None, file_name=None, use_cache=None,
|
||||||
progress_callback=None):
|
progress_callback=None):
|
||||||
"""
|
"""
|
||||||
Uploads the specified file and returns a handle (an instance of
|
Uploads the specified file and returns a handle (an instance of
|
||||||
|
|
|
@ -14,7 +14,7 @@ class MessageRead(EventBuilder):
|
||||||
messages the event will be fired. By default (``False``) only
|
messages the event will be fired. By default (``False``) only
|
||||||
when messages you sent are read by someone else will fire it.
|
when messages you sent are read by someone else will fire it.
|
||||||
"""
|
"""
|
||||||
def __init__(self, inbox=False, chats=None, blacklist_chats=None):
|
def __init__(self, chats=None, *, blacklist_chats=None, inbox=False):
|
||||||
super().__init__(chats, blacklist_chats)
|
super().__init__(chats, blacklist_chats)
|
||||||
self.inbox = inbox
|
self.inbox = inbox
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ class UserUpdate(EventBuilder):
|
||||||
contact (`bool`):
|
contact (`bool`):
|
||||||
``True`` if what's being uploaded (selected) is a contact.
|
``True`` if what's being uploaded (selected) is a contact.
|
||||||
"""
|
"""
|
||||||
def __init__(self, user_id, status=None, typing=None):
|
def __init__(self, user_id, *, status=None, typing=None):
|
||||||
super().__init__(types.PeerUser(user_id))
|
super().__init__(types.PeerUser(user_id))
|
||||||
|
|
||||||
self.online = None if status is None else \
|
self.online = None if status is None else \
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# Versions should comply with PEP440.
|
# Versions should comply with PEP440.
|
||||||
# This line is parsed in setup.py:
|
# This line is parsed in setup.py:
|
||||||
__version__ = '1.0-rc1'
|
__version__ = '1.0'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user