py-tgcalls 2.2.3__py3-none-any.whl → 2.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-tgcalls
3
- Version: 2.2.3
3
+ Version: 2.2.5
4
4
  Summary: Async client API for the Telegram Calls.
5
5
  Author-email: Laky-64 <iraci.matteo@gmail.com>
6
6
  Project-URL: Homepage, https://pytgcalls.github.io/
@@ -20,7 +20,7 @@ Requires-Python: >=3.9
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: aiohttp>=3.9.3
23
- Requires-Dist: ntgcalls<3.0.0,>=2.0.3
23
+ Requires-Dist: ntgcalls<3.0.0,>=2.0.5
24
24
  Requires-Dist: deprecation
25
25
  Provides-Extra: pyrogram
26
26
  Requires-Dist: pyrogram>=1.2.20; extra == "pyrogram"
@@ -1,20 +1,21 @@
1
- py_tgcalls-2.2.3.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
1
+ py_tgcalls-2.2.5.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
2
2
  pytgcalls/__init__.py,sha256=qbfwN7rYwIdCegMOzdcbvwazeNjDzgmowgcqLFNqKIM,308
3
- pytgcalls/__version__.py,sha256=imyOcBgptJng0fWUAVwWSHYVE3csDgLCIYFSbnvEA-U,22
3
+ pytgcalls/__version__.py,sha256=btKTVVdL8jf2J-q4jm7Otknf3xzOoPGoGVBFald8zts,22
4
+ pytgcalls/chat_lock.py,sha256=u3t0G3EQ20zn89Sn5s-GWFFX9Xmu4gYWkAgzHJOk0Mc,762
4
5
  pytgcalls/environment.py,sha256=ctCHACvG6l8SdpPewSBhOvc70kbwpv18maC0TwLvZ08,1924
5
6
  pytgcalls/exceptions.py,sha256=Rijc-8T93WEWJxNW9jncU8_M6mYZZZcs8F2bqitEIeI,3787
6
7
  pytgcalls/ffmpeg.py,sha256=CZvSyuztc-TGKbKI9_2G7CLITe1ITf315YPyprWu_Pg,8645
7
8
  pytgcalls/filters.py,sha256=8Fq_gvHHdqhIk_XwMJ9wneeZOwrvBkSOKaMJ60r3bZU,6157
8
9
  pytgcalls/list_to_cmd.py,sha256=rGJLsejbAQdDb8pctMbLnwea5NkitlfVKc3IpoGi4V4,240
9
10
  pytgcalls/mtproto_required.py,sha256=6B-31p5qH_6oekUgypV4nK3hqPS6Nr-pA8S81wjnbaY,630
10
- pytgcalls/mutex.py,sha256=vWqji9IAHtAc61FUTVXncx5rZ3rVf5qG_7PI4LmuYmU,733
11
- pytgcalls/pytgcalls.py,sha256=DxCE0--mb53vyDXLLBAwy1cPrJgLsyC9rba_h2OzR2o,1608
11
+ pytgcalls/mutex.py,sha256=hs92-LcyIkt76cTWb-czuq1PyF89GSvxpmt3h1K8l3U,381
12
+ pytgcalls/pytgcalls.py,sha256=SZeslmHnPjCNOiC7_3imeXstM8VQwPSN3yRDn6t1v28,1512
12
13
  pytgcalls/pytgcalls_session.py,sha256=_BGJWvf7t3mki2DhlEPjh9cypvYuSFkMSxzTsfepwUk,2719
13
- pytgcalls/scaffold.py,sha256=Gahln5l70FJZwo1KGqv1A7K9Vn_ozAATpADGFJuPhKA,3162
14
+ pytgcalls/scaffold.py,sha256=1qSSTZ6Y-rXyQ65saq0yXzgeE_6iaeUjN76QQtIRb4g,3193
14
15
  pytgcalls/statictypes.py,sha256=CdlqgQNhTZ_uTE8-B8m01fJ7TlD2B42EI2QBPxDdAtA,3842
15
16
  pytgcalls/sync.py,sha256=IsOH3TD7cxUg_-zdGt12HoS8sBlXvcGayPZAoxxKM48,3396
16
17
  pytgcalls/version_manager.py,sha256=egeGgvb66zWlLTMuw2U-b0x8MfnRzMm1xAEVN87HF5c,296
17
- pytgcalls/wait_counter_lock.py,sha256=J-KCWUBCt7ktKQKyIseNG0RfXDVRh-h0wKhaZlf4aFs,437
18
+ pytgcalls/wait_counter_lock.py,sha256=dA_FbmHS1wCwtGhSAEfQrA94J9OUVhPRNcaX4vK8NRA,622
18
19
  pytgcalls/ytdlp.py,sha256=MEPkVlFdbexbgqVRMt7C1YadPIER2R-4oN03osl5vq8,2473
19
20
  pytgcalls/custom_api/__init__.py,sha256=ZT8d0lc2YrDuw_YSFAXXHHMewoXGFZ-ANOBIAr0vGFQ,60
20
21
  pytgcalls/custom_api/custom_api.py,sha256=Ko3aS6psrwPmOhRPxvG0fepXt4STrA0StvINSxz4Cj8,1890
@@ -35,11 +36,11 @@ pytgcalls/methods/decorators/__init__.py,sha256=TCGaEVZnHjtOwv-3PNfaCVm0kyFhJApU
35
36
  pytgcalls/methods/decorators/on_update.py,sha256=ZTL4YcQk0N4Ru56a5WItUvkSN5SAqr6_RDZvXmZMIHs,316
36
37
  pytgcalls/methods/internal/__init__.py,sha256=fcgIxUJKT6QJD30ltnOfzKsLhzTTTklD2qxKlwCvyv0,1057
37
38
  pytgcalls/methods/internal/clear_cache.py,sha256=IbcDOGiBJbmqOnGJWkIe8c6P_Y6e0YPkui4Hg4PAZlA,334
38
- pytgcalls/methods/internal/clear_call.py,sha256=u84SdZb5z6lGRxf7dbrcAcf-xObGVgMsHqSmvdzoAbQ,487
39
- pytgcalls/methods/internal/connect_call.py,sha256=fRQYfDzpwyCXHDOTDSxPdzFu8bmeNf9hvP6c6lpNS-k,5739
39
+ pytgcalls/methods/internal/clear_call.py,sha256=r9v2oPGrDfplxqlfKxT95JjOijm6daIpQjisOyKDBrA,542
40
+ pytgcalls/methods/internal/connect_call.py,sha256=wgRtcY-YxGDFCJcLkSIqgc81DdoA9osQ_iEErqbBH7E,5770
40
41
  pytgcalls/methods/internal/emit_sig_data.py,sha256=ucIsknhJHB-0x7lcymXvwQ647AJQ852zH2W6MdlC3ws,216
41
42
  pytgcalls/methods/internal/handle_connection_changed.py,sha256=_1u3J6_Pjl1Gs1u_WkhG2FAUl_hxlHUiflaMkKkJDsc,866
42
- pytgcalls/methods/internal/handle_mtproto_updates.py,sha256=mdj8N4GXX1J650dE7OThSAVCmtB4wwByqd95P6vmbU8,7461
43
+ pytgcalls/methods/internal/handle_mtproto_updates.py,sha256=I8l9n4t2haN3wR3cCWqynIBsilN1XazuLC9l8aS7Rhw,7812
43
44
  pytgcalls/methods/internal/handle_stream_ended.py,sha256=DllD1ZfGQbwVh-S0neocwnN-8lQtwwyrzWl9teSrZbY,561
44
45
  pytgcalls/methods/internal/handle_stream_frame.py,sha256=_FA782qlOT3tUqnySm7RBpjbgfEEzt1oEBDm-iADsbQ,1145
45
46
  pytgcalls/methods/internal/join_presentation.py,sha256=sXhmzbLWwVFi3gFl1rv0OgJsRJBrvjzRcl60N6ydNW8,2184
@@ -116,7 +117,7 @@ pytgcalls/types/stream/record_stream.py,sha256=f4VQ6MY8HtOxt7vz0hWBFmbbAIvTRHpAI
116
117
  pytgcalls/types/stream/stream_ended.py,sha256=xR_kZwFf03hA6rw_nvI7Be7GwoCKzQf_1MKaGpPDXqY,716
117
118
  pytgcalls/types/stream/stream_frames.py,sha256=028ZhNV-mN3BGqMlmxusAV1xDQpXRYCeM0WXBZhRUhA,446
118
119
  pytgcalls/types/stream/video_quality.py,sha256=eMCBFPwh5meX3UVEaozcGlwmgaujfpiTa3vBVSBBP_8,275
119
- py_tgcalls-2.2.3.dist-info/METADATA,sha256=F0k9s4eJBmRk4UcmwLMBwuEFx6UG-1Od7pJLf2KemCU,5280
120
- py_tgcalls-2.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
121
- py_tgcalls-2.2.3.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
122
- py_tgcalls-2.2.3.dist-info/RECORD,,
120
+ py_tgcalls-2.2.5.dist-info/METADATA,sha256=z5H1ZrBVTaaYMqaL4L__jniTrocWWAkdUcnF-FOCEPs,5280
121
+ py_tgcalls-2.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
122
+ py_tgcalls-2.2.5.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
123
+ py_tgcalls-2.2.5.dist-info/RECORD,,
pytgcalls/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '2.2.3'
1
+ __version__ = '2.2.5'
pytgcalls/chat_lock.py ADDED
@@ -0,0 +1,25 @@
1
+ import asyncio
2
+ from typing import Dict
3
+
4
+ from .wait_counter_lock import WaitCounterLock
5
+
6
+
7
+ class ChatLock:
8
+ def __init__(self):
9
+ self._main_lock = asyncio.Lock()
10
+ self._chat_lock: Dict[int, WaitCounterLock] = {}
11
+
12
+ async def _remove_callback(self, chat_id: int):
13
+ async with self._main_lock:
14
+ if not self._chat_lock[chat_id].waiters():
15
+ self._chat_lock.pop(chat_id, None)
16
+
17
+ async def acquire(self, chat_id: int) -> WaitCounterLock:
18
+ async with self._main_lock:
19
+ self._chat_lock[chat_id] = self._chat_lock.get(
20
+ chat_id,
21
+ ) or WaitCounterLock(
22
+ self._remove_callback,
23
+ chat_id,
24
+ )
25
+ return self._chat_lock[chat_id]
@@ -6,7 +6,8 @@ from ...scaffold import Scaffold
6
6
 
7
7
  class ClearCall(Scaffold):
8
8
  async def _clear_call(self, chat_id: int):
9
- if chat_id in self._wait_connect:
9
+ if chat_id in self._wait_connect and \
10
+ chat_id not in self._p2p_configs:
10
11
  self._wait_connect[chat_id].set_exception(
11
12
  TelegramServerError(),
12
13
  )
@@ -131,6 +131,7 @@ class ConnectCall(Scaffold):
131
131
  if retries == 3 or chat_id > 0:
132
132
  raise
133
133
  self._log_retries(retries)
134
+ payload = None
134
135
  except Exception:
135
136
  try:
136
137
  await self._binding.stop(chat_id)
@@ -43,7 +43,8 @@ class HandleMTProtoUpdates(Scaffold):
43
43
  ),
44
44
  )
45
45
  if chat_id in self._wait_connect and \
46
- not self._wait_connect[chat_id].done():
46
+ not self._wait_connect[chat_id].done() and \
47
+ chat_id not in self._p2p_configs:
47
48
  if isinstance(update, ChatUpdate):
48
49
  if update.status & ChatUpdate.Status.DISCARDED_CALL:
49
50
  self._wait_connect[chat_id].set_exception(
@@ -79,66 +80,68 @@ class HandleMTProtoUpdates(Scaffold):
79
80
  action = update.action
80
81
  chat_peer = self._cache_user_peer.get(chat_id)
81
82
  user_id = participant.user_id
82
- if chat_id in self._call_sources:
83
- call_sources = self._call_sources[chat_id]
84
- was_camera = user_id in call_sources.camera
85
- was_screen = user_id in call_sources.presentation
86
83
 
87
- if was_camera != participant.video_camera:
88
- if participant.video_info:
89
- self._call_sources[chat_id].camera[
90
- user_id
91
- ] = participant.video_info.endpoint
92
- try:
93
- await self._binding.add_incoming_video(
94
- chat_id,
95
- participant.video_info.endpoint,
96
- participant.video_info.sources,
97
- )
98
- except (ConnectionNotFound, ConnectionError):
99
- pass
100
- elif user_id in self._call_sources[chat_id].camera:
101
- try:
102
- await self._binding.remove_incoming_video(
103
- chat_id,
104
- self._call_sources[
105
- chat_id
106
- ].camera[user_id],
107
- )
108
- except (ConnectionNotFound, ConnectionError):
109
- pass
110
- self._call_sources[chat_id].camera.pop(
111
- user_id, None,
112
- )
84
+ async with await self._chat_lock.acquire(chat_id):
85
+ if chat_id in self._call_sources:
86
+ call_sources = self._call_sources[chat_id]
87
+ was_camera = user_id in call_sources.camera
88
+ was_screen = user_id in call_sources.presentation
113
89
 
114
- if was_screen != participant.screen_sharing:
115
- if participant.presentation_info:
116
- self._call_sources[chat_id].presentation[
117
- user_id
118
- ] = participant.presentation_info.endpoint
119
- try:
120
- await self._binding.add_incoming_video(
121
- chat_id,
122
- participant.presentation_info.endpoint,
123
- participant.presentation_info.sources,
90
+ if was_camera != participant.video_camera:
91
+ if participant.video_info:
92
+ self._call_sources[chat_id].camera[
93
+ user_id
94
+ ] = participant.video_info.endpoint
95
+ try:
96
+ await self._binding.add_incoming_video(
97
+ chat_id,
98
+ participant.video_info.endpoint,
99
+ participant.video_info.sources,
100
+ )
101
+ except (ConnectionNotFound, ConnectionError):
102
+ pass
103
+ elif user_id in self._call_sources[chat_id].camera:
104
+ try:
105
+ await self._binding.remove_incoming_video(
106
+ chat_id,
107
+ self._call_sources[
108
+ chat_id
109
+ ].camera[user_id],
110
+ )
111
+ except (ConnectionNotFound, ConnectionError):
112
+ pass
113
+ self._call_sources[chat_id].camera.pop(
114
+ user_id, None,
124
115
  )
125
- except (ConnectionNotFound, ConnectionError):
126
- pass
127
- elif user_id in self._call_sources[
128
- chat_id
129
- ].presentation:
130
- try:
131
- await self._binding.remove_incoming_video(
132
- chat_id,
133
- self._call_sources[
134
- chat_id
135
- ].presentation[user_id],
116
+
117
+ if was_screen != participant.screen_sharing:
118
+ if participant.presentation_info:
119
+ self._call_sources[chat_id].presentation[
120
+ user_id
121
+ ] = participant.presentation_info.endpoint
122
+ try:
123
+ await self._binding.add_incoming_video(
124
+ chat_id,
125
+ participant.presentation_info.endpoint,
126
+ participant.presentation_info.sources,
127
+ )
128
+ except (ConnectionNotFound, ConnectionError):
129
+ pass
130
+ elif user_id in self._call_sources[
131
+ chat_id
132
+ ].presentation:
133
+ try:
134
+ await self._binding.remove_incoming_video(
135
+ chat_id,
136
+ self._call_sources[
137
+ chat_id
138
+ ].presentation[user_id],
139
+ )
140
+ except (ConnectionNotFound, ConnectionError):
141
+ pass
142
+ self._call_sources[chat_id].presentation.pop(
143
+ user_id, None,
136
144
  )
137
- except (ConnectionNotFound, ConnectionError):
138
- pass
139
- self._call_sources[chat_id].presentation.pop(
140
- user_id, None,
141
- )
142
145
 
143
146
  if chat_peer:
144
147
  is_self = BridgedClient.chat_id(
pytgcalls/mutex.py CHANGED
@@ -1,7 +1,5 @@
1
1
  from functools import wraps
2
2
 
3
- from .wait_counter_lock import WaitCounterLock
4
-
5
3
 
6
4
  def mutex(func):
7
5
  @wraps(func)
@@ -10,15 +8,6 @@ def mutex(func):
10
8
  chat_id = await self.resolve_chat_id(
11
9
  args[1] if len(args) > 1 else kwargs['chat_id'],
12
10
  )
13
- async with self._lock:
14
- self._calls_lock[chat_id] = self._calls_lock.get(
15
- chat_id,
16
- ) or WaitCounterLock()
17
- async with self._calls_lock[chat_id]:
18
- result = await func(*args, **kwargs)
19
-
20
- async with self._lock:
21
- if not self._calls_lock[chat_id].waiters():
22
- self._calls_lock.pop(chat_id, None)
23
- return result
11
+ async with await self._chat_lock.acquire(chat_id):
12
+ return await func(*args, **kwargs)
24
13
  return async_wrapper
pytgcalls/pytgcalls.py CHANGED
@@ -2,17 +2,16 @@ import asyncio
2
2
  import os
3
3
  from concurrent.futures import ThreadPoolExecutor
4
4
  from typing import Any
5
- from typing import Dict
6
5
 
7
6
  from ntgcalls import NTgCalls
8
7
 
8
+ from .chat_lock import ChatLock
9
9
  from .environment import Environment
10
10
  from .methods import Methods
11
11
  from .mtproto import MtProtoClient
12
12
  from .scaffold import Scaffold
13
13
  from .statictypes import statictypes
14
14
  from .types import Cache
15
- from .wait_counter_lock import WaitCounterLock
16
15
 
17
16
 
18
17
  class PyTgCalls(Methods, Scaffold):
@@ -43,8 +42,7 @@ class PyTgCalls(Methods, Scaffold):
43
42
  self._binding = NTgCalls()
44
43
  self.loop = asyncio.get_event_loop()
45
44
  self.workers = workers
46
- self._lock = asyncio.Lock()
47
- self._calls_lock: Dict[str, WaitCounterLock] = {}
45
+ self._chat_lock = ChatLock()
48
46
  self.executor = ThreadPoolExecutor(
49
47
  self.workers,
50
48
  thread_name_prefix='Handler',
pytgcalls/scaffold.py CHANGED
@@ -40,6 +40,7 @@ class Scaffold(HandlersHolder):
40
40
  self._wait_connect = dict()
41
41
  self._presentations = set()
42
42
  self._pending_connections = dict()
43
+ self._chat_lock = None
43
44
 
44
45
  def _handle_mtproto(self):
45
46
  pass
@@ -1,10 +1,13 @@
1
1
  import asyncio
2
+ from typing import Callable
2
3
 
3
4
 
4
5
  class WaitCounterLock:
5
- def __init__(self):
6
+ def __init__(self, remove_callback: Callable, *args):
6
7
  self._lock = asyncio.Lock()
7
8
  self._waiters = 0
9
+ self._remove_callback = remove_callback
10
+ self._args = args
8
11
 
9
12
  def waiters(self):
10
13
  return self._waiters
@@ -18,3 +21,4 @@ class WaitCounterLock:
18
21
  async def __aexit__(self, exc_type, exc, tb):
19
22
  if self._lock.locked():
20
23
  self._lock.release()
24
+ await self._remove_callback(*self._args)