Sessions as sqlite databases
In the beginning, session files used to be pickle. This proved to be bad as soon as one wanted to add more fields. For this reason, they were migrated to use JSON instead. But this proved to be bad as soon as one wanted to save things like entities (usernames, their ID and hash), so now it properly uses
sqlite3, which has been well tested, to save the session files! Calling
.get_input_entity using a
username no longer will need to fetch it first, so it's really 0 calls again. Calling
.get_entity will always fetch the most up to date version.
Furthermore, nearly everything has been documented, thus preparing the library for Read the Docs (although there are a few things missing I'd like to polish first), and the
logging are now better placed.
.get_dialogs()now returns a single list instead a tuple consisting of a custom class that should make everything easier to work with.
.get_message_history()also returns a single list instead a tuple, with the
Messageinstances modified to make them more convenient.
Both lists have a
.total attribute so you can still know how many dialogs/messages are in total.
- The mentioned use of
sqlite3for the session file.
.get_entity()now supports lists too, and it will make as little API calls as possible if you feed it
InputPeertypes. Usernames will always be resolved, since they may have changed.
.set_proxy()method, to avoid having to create a new
datetypes supported to represent a date parameter.
- Empty strings weren't working when they were a flag parameter (e.g., setting no last name).
- Fix invalid assertion regarding flag parameters as well.
- Avoid joining the background thread on disconnect, as it would be
Nonedue to a race condition.
- Correctly handle
Nonedates when downloading media.
.download_profile_photowas failing for some channels.
datewas being serialized as local date, but that was wrong.
datewas being represented as a
floatinstead of an
.tlparser wasn't stripping inline comments.
- Removed some redundant checks on
- Use a synchronized queue instead a hand crafted version.
- Use signed integers consistently (e.g.
- Always read the corresponding
TLObjectfrom API responses, except for some special cases still.
- A few more
exceptlow level to correctly wrap errors.
- More accurate exception types.
invokeWithLayer(initConnection(X))now wraps every first request after
As always, report if you have issues with some of the changes!
|Scheme layer used: |
It's here, it has come! The library now supports IPv6! Just pass
use_ipv6=True when creating a
TelegramClient. Note that I could not test this feature because my machine doesn't have IPv6 setup. If you know IPv6 works in your machine but the library doesn't, please refer to #425.
- IPv6 support.
- New method to extract the text surrounded by
MessageEntity's, in the
- Markdown parsing is Done Right.
- Reconnection on failed invoke. Should avoid "number of retries reached 0" (#270).
- Some missing autocast to
- The library uses the
loggingas it should have always done.
TcpClient.is_connected()is now more reliable.
- Getting an entity using their phone wasn't actually working.
- Full entities aren't saved unless they have an
access_hash, to avoid some
.get_message_historywas failing when retrieving items that had messages forwarded from a channel.
|Scheme layer used: |
This update brings a few general enhancements that are enough to deserve a new release, with a new feature: beta markdown-like parsing for
parse_mode='md'for Markdown! It works in a similar fashion to the official clients (defaults to double underscore/asterisk, like
**this**). Please report any issues with emojies or enhancements for the parser!
.idle()method so your main thread can do useful job (listen for updates).
- Add missing
- The list of known peers could end "corrupted" and have users with
access_hash=None, resulting in
structerror for it not being an integer. You shouldn't encounter this issue anymore.
- The warning for "added update handler but no workers set" wasn't actually working.
.get_input_peerwas ignoring a case for
- There used to be an exception when logging exceptions (whoops) on update handlers.
- "Downloading contacts" would produce strange output if they had semicolons (
;) in their name.
- Fix some cyclic imports and installing dependencies from the
- Code generation was using f-strings, which are only supported on Python ≥3.6.
auth_keygeneration has been moved from
.invoke(). There were some issues were
.connect()failed and the
Noneso this will ensure to have a valid
auth_keywhen needed, even if
- Support for higher limits on
- Much faster integer factorization when generating the required
auth_key. Thanks @delivrance for making me notice this, and for the pull request.
Bug fixes with updates
Hopefully a very ungrateful bug has been removed. When you used to invoke some request through update handlers, it could potentially enter an infinite loop. This has been mitigated and it's now safe to invoke things again! A lot of updates were being dropped (all those gzipped), and this has been fixed too.
More bug fixes include a correct parsing of certain TLObjects thanks to @stek29, and some wrong calls that would cause the library to crash thanks to @andr-04, and the
ReadThread not re-starting if you were already authorized.
.to_bytes() function has been replaced with
__bytes__ so now you can do
Bug fixes and new small features
This release primarly focuses on a few bug fixes and enhancements. Although more stuff may have broken along the way.
.get_input_entitywas failing for IDs and other cases, also making more requests than it should.
abspathwhen sending a file. You can now also override the attributes.
.send_message()was failing with channels.
.get_dialogs(limit=None)should now return all the dialogs correctly.
- Temporary fix for abusive duplicated updates.
- You will be warned if you call
- New customizable threshold value on the session to determine when to automatically sleep on flood waits. See
.get_drafts()method with a custom
Draftclass by @JosXa.
- Join all threads when calling
.disconnect(), to assert no dangling thread is left alive.
- Larger chunk when downloading files should result in faster downloads.
- You can use a callable key for the
EntityDatabase, so it can be any filter you need.
- MsgsAck is now sent in a container rather than its own request.
.get_input_photois now used in the generated code.
.process_entitieswas being called from more places than only
MtProtoSendernow relies more on the generated code to read responses.
Custom Entity Database
The main feature of this release is that Telethon now has a custom database for all the entities you encounter, instead depending on
@lru_cache on the
EntityDatabase will, by default, cache all the users, chats and channels you find in memory for as long as the program is running. The session will, by default, save all key-value pairs of the entity identifiers and their hashes (since Telegram may send an ID that it thinks you already know about, we need to save this information).
You can prevent the
EntityDatabase from saving users by setting
client.session.entities.enabled = False, and prevent the
Session from saving input entities at all by setting
client.session.save_entities = False. You can also clear the cache for a certain user through
client.session.entities.clear_cache(entity=None), which will clear all if no entity is given.
.sign_inaccepts phones as integers.
.get_dialogs()doesn't fail on Windows anymore, and returns the right amount of dialogs.
- New method to
- Changing the IP to which you connect to is as simple as
client.session.server_address = 'ip', since now the server address is always queried from the session.
GeneralProxyErrorshould be passed to the main thread again, so that you can handle it.
Updates Overhaul Update
After hundreds of lines changed on a major refactor, it's finally here. It's the Updates Overhaul Update; let's get right into it!
New stuff and enhancements
- You can invoke requests from update handlers. And any other thread. A new temporary will be made, so that you can be sending even several requests at the same time!
- Several worker threads for your updates! By default,
Nonewill spawn. I recommend you to work with
update_workers=4to get started, these will be polling constantly for updates.
- You can also change the number of workers at any given time.
- The library can now run in a single thread again, if you don't need to spawn any at all. Simply set
spawn_read_thread=Falsewhen creating the
- You can specify
.get_dialogs()to get all of them.
- Updates are expanded, so you don't need to check if the update has
.updatesor an inner
InputPeerentities are saved in the session file, but you can disable this by setting
.get_input_entitymethod, which makes use of the above feature. You should use this when a request needs a
InputPeer, rather than the whole entity (although both work).
Less important enhancements
- Assert that either all or None dependent-flag parameters are set before sending the request.
- Phone numbers can have dashes, spaces, or parenthesis. They'll be removed before making the request.
- You can override the phone and its hash on
.sign_in(), if you're creating a new
TelegramClienton two different places.
.create_new_connection()is gone for good. No need to deal with this manually since new connections are now handled on demand by the library itself.
.log_out()was consuming all retries. It should work just fine now.
- The session would fail to load if the
auth_keyhad been removed manually.
Updates.check_errorwas popping wrong side, although it's been completely removed.
ServerError's will be ignored, and the request will immediately be retried.
- Cross-thread safety when saving the session file.
- Some things changed on a matter of when to reconnect, so please report any bugs!
TelegramClientis now only an abstraction over the
TelegramBareClient, which can only do basic things, such as invoking requests, working with files, etc. If you don't need any of the abstractions the
TelegramClient, you can now use the
TelegramBareClientin a much more comfortable way.
MtProtoSenderis not thread-safe, but it doesn't need to be since a new connection will be spawned when needed.
- New connections used to be cached and then reused. Now only their sessions are saved, as temporary connections are spawned only when needed.
- Added more RPC errors to the list.
: Broken due to a condition which should had been the opposite (sigh), fixed 4 commits ahead on 62ea77c.
That's pretty much it, although there's more work to be done to make the overall experience of working with updates even better. Stay tuned!
Serialization bug fixes
Two bug fixes, one of them quite important, related to the serialization. Every object or request that had to serialize a
True/False type was always being serialized as
Another bug that didn't allow you to leave as
None flag parameters that needed a list has been fixed.
Other internal changes include a somewhat more readable
.to_bytes() function and pre-computing the flag instead using bit shifting. The
TLObject.constructor_id has been renamed to
.subclass_of_id is also uppercase now.
v0.14 had started working on the new
.to_bytes() method to dump the
BinaryWriter and its usage on the
.on_send() when serializing TLObjects, and this release finally removes it. The speed up when serializing things to bytes should now be over twice as fast wherever it's needed.
Other internal changes include using proper classes (including the generated code) for generating authorization keys and to write out
For bug fixes, this version is again compatible with Python 3.x versions below 3.5 (there was a method call that was Python 3.5 and above).