diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..a0032bb2
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..ef79d401
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..085b279e
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/telethon-opensource.iml b/.idea/telethon-opensource.iml
new file mode 100644
index 00000000..67116063
--- /dev/null
+++ b/.idea/telethon-opensource.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..94a25f7f
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 00000000..80272da0
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,679 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.session.
+ f =
+ set_update
+ self.session
+ set_dc
+ auth_key_call
+ mtprot
+ set_
+ AsyncClass
+ Connection
+
+
+ D:\projects\telethon-opensource\telethon
+ D:\projects\telethon-opensource
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1537880100846
+
+
+ 1537880100846
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/telethon/client/users.py
+ 290
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ x,y=(*args,)
+ Python
+ EXPRESSION
+
+
+ x,y=*args
+ Python
+ EXPRESSION
+
+
+ x=(*args,)
+ Python
+ EXPRESSION
+
+
+ x=(*args)
+ Python
+ EXPRESSION
+
+
+ args
+ Python
+ EXPRESSION
+
+
+ x=*args
+ Python
+ EXPRESSION
+
+
+ *args
+ Python
+ EXPRESSION
+
+
+ w
+ Python
+ EXPRESSION
+
+
+ w()
+ Python
+ EXPRESSION
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/telethon/client/auth.py b/telethon/client/auth.py
index de380de3..7c1ed6b6 100644
--- a/telethon/client/auth.py
+++ b/telethon/client/auth.py
@@ -399,7 +399,7 @@ class AuthMethods(MessageParseMethods, UserMethods):
return False
await self.disconnect()
- self.session.delete()
+ await self.session.delete()
self._authorized = False
return True
diff --git a/telethon/client/downloads.py b/telethon/client/downloads.py
index 4c0e1239..f8ab4ffc 100644
--- a/telethon/client/downloads.py
+++ b/telethon/client/downloads.py
@@ -223,9 +223,9 @@ class DownloadMethods(UserMethods):
config = await self(functions.help.GetConfigRequest())
for option in config.dc_options:
if option.ip_address == self.session.server_address:
- self.session.set_dc(
+ await self.session.set_dc(
option.id, option.ip_address, option.port)
- self.session.save()
+ await self.session.save()
break
# TODO Figure out why the session may have the wrong DC ID
diff --git a/telethon/client/telegrambaseclient.py b/telethon/client/telegrambaseclient.py
index 2a36d6ce..3ac80419 100644
--- a/telethon/client/telegrambaseclient.py
+++ b/telethon/client/telegrambaseclient.py
@@ -16,7 +16,7 @@ from ..network.mtprotostate import MTProtoState
from ..sessions import Session, SQLiteSession, MemorySession
from ..tl import TLObject, functions, types
from ..tl.alltlobjects import LAYER
-
+from ..utils import AsyncClassWrapper
DEFAULT_DC_ID = 4
DEFAULT_IPV4_IP = '149.154.167.51'
DEFAULT_IPV6_IP = '[2001:67c:4e8:f002::a]'
@@ -197,8 +197,7 @@ class TelegramBaseClient(abc.ABC):
DEFAULT_PORT
)
- self.flood_sleep_threshold = flood_sleep_threshold
- self.session = session
+ self.session = AsyncClassWrapper(session)
self.api_id = int(api_id)
self.api_hash = api_hash
@@ -330,8 +329,8 @@ class TelegramBaseClient(abc.ABC):
await self._disconnect()
if getattr(self, 'session', None):
if getattr(self, '_state', None):
- self.session.set_update_state(0, self._state)
- self.session.close()
+ f = await self.session.set_update_state(0, self._state)
+ await self.session.close()
async def _disconnect(self):
"""
@@ -369,7 +368,7 @@ class TelegramBaseClient(abc.ABC):
__log__.info('Reconnecting to new data center %s', new_dc)
dc = await self._get_dc(new_dc)
- self.session.set_dc(dc.id, dc.ip_address, dc.port)
+ await self.session.set_dc(dc.id, dc.ip_address, dc.port)
# auth_key's are associated with a server, which has now changed
# so it's not valid anymore. Set to None to force recreating it.
self.session.auth_key = self._sender.state.auth_key = None
@@ -377,14 +376,14 @@ class TelegramBaseClient(abc.ABC):
await self._disconnect()
return await self.connect()
- def _auth_key_callback(self, auth_key):
+ async def _auth_key_callback(self, auth_key):
"""
Callback from the sender whenever it needed to generate a
new authorization key. This means we are not authorized.
"""
self._authorized = None
self.session.auth_key = auth_key
- self.session.save()
+ await self.session.save()
# endregion
@@ -472,7 +471,7 @@ class TelegramBaseClient(abc.ABC):
session = self._exported_sessions.get(cdn_redirect.dc_id)
if not session:
dc = await self._get_dc(cdn_redirect.dc_id, cdn=True)
- session = self.session.clone()
+ session = await self.session.clone()
session.set_dc(dc.id, dc.ip_address, dc.port)
self._exported_sessions[cdn_redirect.dc_id] = session
diff --git a/telethon/client/updates.py b/telethon/client/updates.py
index 1e40a715..d6400d7d 100644
--- a/telethon/client/updates.py
+++ b/telethon/client/updates.py
@@ -137,7 +137,7 @@ class UpdateMethods(UserMethods):
This can also be used to forcibly fetch new updates if there are any.
"""
- state = self.session.get_update_state(0)
+ state = await self.session.get_update_state(0)
if not state or not state.pts:
state = await self(functions.updates.GetStateRequest())
@@ -172,15 +172,15 @@ class UpdateMethods(UserMethods):
state.pts = d.pts
break
finally:
- self.session.set_update_state(0, state)
+ await self.session.set_update_state(0, state)
self.session.catching_up = False
# endregion
# region Private methods
- def _handle_update(self, update):
- self.session.process_entities(update)
+ async def _handle_update(self, update):
+ await self.session.process_entities(update)
if isinstance(update, (types.Updates, types.UpdatesCombined)):
entities = {utils.get_peer_id(x): x for x in
itertools.chain(update.users, update.chats)}
@@ -236,7 +236,7 @@ class UpdateMethods(UserMethods):
# inserted because this is a rather expensive operation
# (default's sqlite3 takes ~0.1s to commit changes). Do
# it every minute instead. No-op if there's nothing new.
- self.session.save()
+ await self.session.save()
# We need to send some content-related request at least hourly
# for Telegram to keep delivering updates, otherwise they will
diff --git a/telethon/client/uploads.py b/telethon/client/uploads.py
index 6854a669..df6e7a1d 100644
--- a/telethon/client/uploads.py
+++ b/telethon/client/uploads.py
@@ -211,7 +211,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
entity, media=types.InputMediaUploadedPhoto(fh)
))
input_photo = utils.get_input_photo(r.photo)
- self.session.cache_file(fh.md5, fh.size, input_photo)
+ await self.session.cache_file(fh.md5, fh.size, input_photo)
fh = input_photo
if captions:
@@ -326,7 +326,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
file = stream.read()
hash_md5.update(file)
if use_cache:
- cached = self.session.get_file(
+ cached = await self.session.get_file(
hash_md5.digest(), file_size, cls=use_cache
)
if cached:
@@ -446,7 +446,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
)
return file_handle, media
- def _cache_media(self, msg, file, file_handle,
+ async def _cache_media(self, msg, file, file_handle,
force_document=False):
if file and msg and isinstance(file_handle,
custom.InputSizedFile):
@@ -457,6 +457,6 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
to_cache = utils.get_input_photo(msg.media.photo)
else:
to_cache = utils.get_input_document(msg.media.document)
- self.session.cache_file(md5, size, to_cache)
+ await self.session.cache_file(md5, size, to_cache)
# endregion
diff --git a/telethon/client/users.py b/telethon/client/users.py
index fa0c3015..b59f7ae7 100644
--- a/telethon/client/users.py
+++ b/telethon/client/users.py
@@ -48,7 +48,7 @@ class UserMethods(TelegramBaseClient):
exceptions.append(e)
results.append(None)
continue
- self.session.process_entities(result)
+ await self.session.process_entities(result)
exceptions.append(None)
results.append(result)
request_index += 1
@@ -58,7 +58,7 @@ class UserMethods(TelegramBaseClient):
return results
else:
result = await future
- self.session.process_entities(result)
+ await self.session.process_entities(result)
return result
except (errors.ServerError, errors.RpcCallFailError) as e:
__log__.warning('Telegram is having internal issues %s: %s',
@@ -288,7 +288,7 @@ class UserMethods(TelegramBaseClient):
try:
# First try to get the entity from cache, otherwise figure it out
- return self.session.get_input_entity(peer)
+ return await self.session.get_input_entity(peer)
except ValueError:
pass
@@ -393,7 +393,7 @@ class UserMethods(TelegramBaseClient):
try:
# Nobody with this username, maybe it's an exact name/title
return await self.get_entity(
- self.session.get_input_entity(string))
+ await self.session.get_input_entity(string))
except ValueError:
pass
diff --git a/telethon/network/__init__.py b/telethon/network/__init__.py
index e8070b21..b0d8674a 100644
--- a/telethon/network/__init__.py
+++ b/telethon/network/__init__.py
@@ -7,5 +7,5 @@ from .authenticator import do_authentication
from .mtprotosender import MTProtoSender
from .connection import (
ConnectionTcpFull, ConnectionTcpAbridged, ConnectionTcpObfuscated,
- ConnectionTcpIntermediate, ConnectionHttp
+ ConnectionTcpIntermediate, ConnectionHttp,Connection
)
diff --git a/telethon/network/connection/__init__.py b/telethon/network/connection/__init__.py
index 262aaa3a..af2f3af8 100644
--- a/telethon/network/connection/__init__.py
+++ b/telethon/network/connection/__init__.py
@@ -3,3 +3,4 @@ from .tcpabridged import ConnectionTcpAbridged
from .tcpobfuscated import ConnectionTcpObfuscated
from .tcpintermediate import ConnectionTcpIntermediate
from .http import ConnectionHttp
+from .common import Connection
diff --git a/telethon/network/mtprotosender.py b/telethon/network/mtprotosender.py
index 15f459d9..12fee1a4 100644
--- a/telethon/network/mtprotosender.py
+++ b/telethon/network/mtprotosender.py
@@ -15,7 +15,7 @@ from ..tl.types import (
MsgNewDetailedInfo, NewSessionCreated, MsgDetailedInfo, MsgsStateReq,
MsgsStateInfo, MsgsAllInfo, MsgResendReq, upload
)
-
+from ..utils import AsyncClassWrapper
__log__ = logging.getLogger(__name__)
@@ -262,7 +262,7 @@ class MTProtoSender:
await authenticator.do_authentication(plain)
if self._auth_key_callback:
- self._auth_key_callback(self.state.auth_key)
+ await self._auth_key_callback(self.state.auth_key)
break
except (SecurityError, AssertionError) as e:
@@ -570,7 +570,7 @@ class MTProtoSender:
__log__.debug('Handling update {}'
.format(message.obj.__class__.__name__))
if self._update_callback:
- self._update_callback(message.obj)
+ await self._update_callback(message.obj)
async def _handle_pong(self, message):
"""
diff --git a/telethon/test.py b/telethon/test.py
new file mode 100644
index 00000000..e5a64005
--- /dev/null
+++ b/telethon/test.py
@@ -0,0 +1,47 @@
+import inspect
+import asyncio
+from telethon.utils import AsyncClassWrapper
+
+class session:
+ test1='test1'
+ async def test2(self,arg):
+ print(arg)
+
+ def test3(self,arg):
+ print("test3")
+
+ @property
+ def test4(self):
+ return "test4"
+
+async def t():
+ s = AsyncClassWrapper(session())
+ print(s.test1)
+ await s.test2("test2")
+ await s.test3("k")
+ print(s.test4)
+ s.test5 = "hey"
+ print(s.test5)
+
+
+
+asyncio.get_event_loop().run_until_complete(t())
+import inspect
+import asyncio
+from telethon.client import TelegramClient
+
+
+
+api_hash = ""
+api_id = 12345
+async def main():
+ client = TelegramClient(None, api_id, api_hash)
+ await client.session.set_dc(2, '149.154.167.40', 443)
+ await client.start(
+ phone='9996621234', code_callback=lambda: '22222'
+ )
+ print(await client.get_dialogs())
+ await client.send_message("me","heyh")
+
+
+asyncio.get_event_loop().run_until_complete(main())
\ No newline at end of file
diff --git a/telethon/utils.py b/telethon/utils.py
index 60e4c990..20223bbd 100644
--- a/telethon/utils.py
+++ b/telethon/utils.py
@@ -16,6 +16,7 @@ from types import GeneratorType
from .extensions import markdown, html
from .helpers import add_surrogate, del_surrogate
from .tl import types
+import inspect
try:
import hachoir
@@ -970,3 +971,20 @@ def get_appropriated_part_size(file_size):
return 512
raise ValueError('File size too large')
+
+class AsyncClassWrapper:
+ def __init__(self, wrapped):
+ self.wrapped = wrapped
+
+ def __getattr__(self, item):
+ w = getattr(self.wrapped, item)
+ async def wrapper(*args,**kwargs):
+ val = w(*args, **kwargs)
+ return await val if inspect.isawaitable(val) else val
+
+ if inspect.isfunction(w) or inspect.ismethod(w):
+ return wrapper
+ elif isinstance(w,property):
+ return w.fget(self.wrapped)
+ else:
+ return w