py-tgcalls 1.2.7__py3-none-any.whl → 1.2.8__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.1
2
2
  Name: py-tgcalls
3
- Version: 1.2.7
3
+ Version: 1.2.8
4
4
  Summary: UNKNOWN
5
5
  Home-page: https://github.com/pytgcalls/pytgcalls
6
6
  Author: Laky-64
@@ -22,9 +22,10 @@ Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
23
  Requires-Dist: aiohttp (>=3.9.3)
24
24
  Requires-Dist: deprecation
25
- Requires-Dist: ntgcalls (>=1.1.0)
25
+ Requires-Dist: ntgcalls (>=1.1.2)
26
26
  Requires-Dist: psutil
27
27
  Requires-Dist: screeninfo
28
+ Requires-Dist: setuptools
28
29
 
29
30
  <img src="https://raw.githubusercontent.com/pytgcalls/pytgcalls/master/.github/images/banner.png" alt="pytgcalls logo" />
30
31
  <p align="center">
@@ -1,18 +1,19 @@
1
1
  pytgcalls/__init__.py,sha256=MRF45fC5EHvNRJgMHKZEiytlfOidmShTvi5loWD9GPw,261
2
- pytgcalls/__version__.py,sha256=ZPIeIspmBptDYG5CCWeXrMEitl5VFLx13DZa9qaB4EA,22
2
+ pytgcalls/__version__.py,sha256=qGbXFEJiAOnWJQBRuZoZtO2VVVauuuZtAP1iQd2Gnq4,22
3
3
  pytgcalls/environment.py,sha256=ctCHACvG6l8SdpPewSBhOvc70kbwpv18maC0TwLvZ08,1924
4
4
  pytgcalls/exceptions.py,sha256=7BBRRD_lejYE8bcppkef8I1kiKPnx-O7G6IGDKg0R3Y,3532
5
5
  pytgcalls/ffmpeg.py,sha256=-y2Ce-qR8U4vgRD116aWSLFHggRZqxwrjyYb_7s3W8s,8442
6
- pytgcalls/mtproto_required.py,sha256=04outJTCtqW4B0200NPlO83S4KLheveCxw-cWyh1i74,781
6
+ pytgcalls/mtproto_required.py,sha256=0OJGKrUusF7Z4seYAZpr_xavnux1XWhbgC2szJ_yPPU,494
7
+ pytgcalls/mutex.py,sha256=RfkG2UI-kEzo57P0KHSuU6fgS8BE0UySpWqie5qhMy4,1160
7
8
  pytgcalls/pytgcalls.py,sha256=GUKpl3UN0JsvahbJW9oOgUdtMx0-Q_gNSLdV9fdvzRs,930
8
9
  pytgcalls/pytgcalls_session.py,sha256=BfqTEWDxH5VC3CHnu5RVVq2y9rUDq57EhNvPkk5wa08,2707
9
- pytgcalls/scaffold.py,sha256=fjoz6YK4M0UoBlm6se-P83RlBgDnBQncjyHsyRko5wg,794
10
+ pytgcalls/scaffold.py,sha256=-RImO5R-ZAMbieCUktf3REUOu4jEBGsroRMZo5IPKBE,822
10
11
  pytgcalls/statictypes.py,sha256=CdlqgQNhTZ_uTE8-B8m01fJ7TlD2B42EI2QBPxDdAtA,3842
11
12
  pytgcalls/stream_type.py,sha256=-6U3Rbh0Dfr12ZcmU9PVeBQr4AbdJsW2mP74h3SKFG4,733
12
13
  pytgcalls/sync.py,sha256=dADzbB94gDZrNIWv3JlVa6u1Ak-TXk3bbr6T7KOVcL0,3252
13
14
  pytgcalls/to_async.py,sha256=5aRU2rttq7n_gSFM-nhinVGj15MnnIezKg9OsW8PmjI,531
14
15
  pytgcalls/version_manager.py,sha256=egeGgvb66zWlLTMuw2U-b0x8MfnRzMm1xAEVN87HF5c,296
15
- pytgcalls/ytdlp.py,sha256=JsQWS5mYKJ88_8-zuxn8EnagrcASNrNHNES1xHunDjU,1806
16
+ pytgcalls/ytdlp.py,sha256=TyiorAgg8k6Nx04iv-tYK-3AGHdDl_BIFTZgbXHr5ME,1835
16
17
  pytgcalls/custom_api/__init__.py,sha256=ZT8d0lc2YrDuw_YSFAXXHHMewoXGFZ-ANOBIAr0vGFQ,60
17
18
  pytgcalls/custom_api/custom_api.py,sha256=Ko3aS6psrwPmOhRPxvG0fepXt4STrA0StvINSxz4Cj8,1890
18
19
  pytgcalls/handlers/__init__.py,sha256=pubbxI4pLqQpAKf8-toD6ija4cpSvbCJOQFjTiDjX1E,75
@@ -32,10 +33,10 @@ pytgcalls/methods/decorators/on_stream_end.py,sha256=IHsGgrWXWS6kg2K6x6u2aZMpo2a
32
33
  pytgcalls/methods/groups/__init__.py,sha256=GX1LPgUKEZOrSz7zWD9pR0OPWHO_4jcMdqXTDGQf5JA,293
33
34
  pytgcalls/methods/groups/change_volume_call.py,sha256=1qciR48hRdDwERomOPEUGcQ43Q2zRtNdBgF2JDs-w6c,720
34
35
  pytgcalls/methods/groups/get_participants.py,sha256=Tjpb9ZWRJGJZioZ7Z7dpOcmEexwEqfgUfvcsqxMNW2Y,631
35
- pytgcalls/methods/groups/join_group_call.py,sha256=4J-IpyedSIQNN3mg68homyv6MNdYaJQ1V8ARrbKhTpw,3240
36
- pytgcalls/methods/groups/leave_group_call.py,sha256=BmpKSAo3vaYXIpEIu1jaYUdo2TUb4XEJYKVEzXbOs4s,985
36
+ pytgcalls/methods/groups/join_group_call.py,sha256=-A0iKqCKsDm3pUhl5bPJ3NVnSy3JIF9zLNaO_zZ77ro,3705
37
+ pytgcalls/methods/groups/leave_group_call.py,sha256=Mu3PHw5s1v7rmeqwngqR3IwamddIa3Q_NmR6_cWC0iY,1023
37
38
  pytgcalls/methods/stream/__init__.py,sha256=Go0xKnzPLfB8c3lwCqyifk496E7jkcIZBmzYO0XbH0A,368
38
- pytgcalls/methods/stream/change_stream.py,sha256=KdquY2feZdjhtHQeJtWJO2cuIYvYvMkk6Sjykio7XZ8,997
39
+ pytgcalls/methods/stream/change_stream.py,sha256=UmolBavQdzbY1YS3t_aT-tEK3EvFbTlQguonUa4cVzc,1035
39
40
  pytgcalls/methods/stream/mute_stream.py,sha256=9R8ctu8zeMmqkdrbUq01Ni7tm0cM6Y8bM6auP8NIXqI,669
40
41
  pytgcalls/methods/stream/pause_stream.py,sha256=9a-P3HZOkxbnesi4f-pPIeUQaGhlFlJIPN7pqZljo2g,672
41
42
  pytgcalls/methods/stream/played_time.py,sha256=zkuGgEg8DmovnIf-vddv3A0m5fMv_goX6n8N2RP-fyk,669
@@ -50,7 +51,7 @@ pytgcalls/methods/utilities/mtproto_handler.py,sha256=pdX29BJDPsdB9xFLRZt41Lc1OX
50
51
  pytgcalls/methods/utilities/ping.py,sha256=pIraQyVd-fJDAdEnuD5MHBgFhXxN8-6yl2TV68aw6AA,295
51
52
  pytgcalls/methods/utilities/resolve_chat_id.py,sha256=6m-oXfJy1_iHz_7UWsmRYgDLK6IFoO1-I2I7CC9ytks,383
52
53
  pytgcalls/methods/utilities/run.py,sha256=cnYQd2xB5Cr_WS0Q2cXJZPGiN6JOCULzj1r4xXVyrlg,152
53
- pytgcalls/methods/utilities/start.py,sha256=l_hOnswgxIP5uSLGOwePepoM3ghd9fWGxq1Rk8Vt020,4626
54
+ pytgcalls/methods/utilities/start.py,sha256=9f4IIliv1sPlwlm8tr-ABaIfXwobh6YOITClaJXeS9Q,4492
54
55
  pytgcalls/methods/utilities/stream_params.py,sha256=hYcNxx__McmPeHgOUDEuNcN7ThgDjukejQYHrfmWm-A,1519
55
56
  pytgcalls/mtproto/__init__.py,sha256=X4zvzFG7km7qHyE0fdvA550WcOVO_xl_p__gvIfDGmw,130
56
57
  pytgcalls/mtproto/bridged_client.py,sha256=EW379VjMadbMm7gle35OWIfXdpPrF0ZszMc8r5YZi5k,4746
@@ -104,8 +105,8 @@ pytgcalls/types/stream/legacy/quality/low_quality_audio.py,sha256=sa7SpkDa17SIql
104
105
  pytgcalls/types/stream/legacy/quality/low_quality_video.py,sha256=87_c1ULPqkrafNxD1YOSlQZFJSty6PqkuT0arFRgXAo,342
105
106
  pytgcalls/types/stream/legacy/quality/medium_quality_audio.py,sha256=vcMX4c4MA0t56Ch89lIFEeLe4nlFtI6_DllYlZAVbwM,344
106
107
  pytgcalls/types/stream/legacy/quality/medium_quality_video.py,sha256=xUZf2Uclipd1IWgX0rE82kNt5vBqoVwqRdoxQiTL7yA,345
107
- py_tgcalls-1.2.7.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
108
- py_tgcalls-1.2.7.dist-info/METADATA,sha256=cFXimZ6bmz1_lXGRhWlhRzSPnqCKZf5xavTsZ17YNU8,4854
109
- py_tgcalls-1.2.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
110
- py_tgcalls-1.2.7.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
111
- py_tgcalls-1.2.7.dist-info/RECORD,,
108
+ py_tgcalls-1.2.8.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
109
+ py_tgcalls-1.2.8.dist-info/METADATA,sha256=sCyK2i9woc46OCbuACCKFI-J6Qy1Vr45qiX-P7-FVDk,4880
110
+ py_tgcalls-1.2.8.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
111
+ py_tgcalls-1.2.8.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
112
+ py_tgcalls-1.2.8.dist-info/RECORD,,
pytgcalls/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '1.2.7'
1
+ __version__ = '1.2.8'
@@ -4,6 +4,7 @@ from typing import Optional
4
4
  from typing import Union
5
5
 
6
6
  from ntgcalls import ConnectionError
7
+ from ntgcalls import ConnectionNotFound
7
8
  from ntgcalls import FileError
8
9
  from ntgcalls import InvalidParams
9
10
  from ntgcalls import TelegramServerError
@@ -13,6 +14,7 @@ from ...exceptions import NoActiveGroupCall
13
14
  from ...exceptions import UnMuteNeeded
14
15
  from ...mtproto import BridgedClient
15
16
  from ...mtproto_required import mtproto_required
17
+ from ...mutex import mutex
16
18
  from ...scaffold import Scaffold
17
19
  from ...statictypes import statictypes
18
20
  from ...to_async import ToAsync
@@ -23,6 +25,7 @@ py_logger = logging.getLogger('pytgcalls')
23
25
 
24
26
 
25
27
  class JoinGroupCall(Scaffold):
28
+ @mutex
26
29
  @statictypes
27
30
  @mtproto_required
28
31
  async def join_group_call(
@@ -78,11 +81,19 @@ class JoinGroupCall(Scaffold):
78
81
  except TelegramServerError:
79
82
  if retries == 3:
80
83
  raise
81
- if retries >= 1:
82
- py_logger.warning(
83
- f'Telegram is having some internal server issues. '
84
- f'Retrying {retries + 1} of 3',
84
+ (py_logger.warning if retries >= 1 else py_logger.info)(
85
+ f'Telegram is having some internal server issues. '
86
+ f'Retrying {retries + 1} of 3',
87
+ )
88
+ except Exception:
89
+ try:
90
+ await ToAsync(
91
+ self._binding.stop,
92
+ chat_id,
85
93
  )
94
+ except ConnectionNotFound:
95
+ pass
96
+ raise
86
97
 
87
98
  participants = await self._app.get_group_call_participants(
88
99
  chat_id,
@@ -99,3 +110,6 @@ class JoinGroupCall(Scaffold):
99
110
  raise AlreadyJoinedError()
100
111
  except InvalidParams:
101
112
  raise UnMuteNeeded()
113
+ except Exception:
114
+ self._cache_user_peer.pop(chat_id)
115
+ raise
@@ -5,12 +5,14 @@ from ntgcalls import ConnectionNotFound
5
5
  from ...exceptions import NoActiveGroupCall
6
6
  from ...exceptions import NotInGroupCallError
7
7
  from ...mtproto_required import mtproto_required
8
+ from ...mutex import mutex
8
9
  from ...scaffold import Scaffold
9
10
  from ...statictypes import statictypes
10
11
  from ...to_async import ToAsync
11
12
 
12
13
 
13
14
  class LeaveGroupCall(Scaffold):
15
+ @mutex
14
16
  @statictypes
15
17
  @mtproto_required
16
18
  async def leave_group_call(
@@ -6,6 +6,7 @@ from ntgcalls import FileError
6
6
 
7
7
  from ...exceptions import NotInGroupCallError
8
8
  from ...mtproto_required import mtproto_required
9
+ from ...mutex import mutex
9
10
  from ...scaffold import Scaffold
10
11
  from ...statictypes import statictypes
11
12
  from ...to_async import ToAsync
@@ -14,6 +15,7 @@ from ..utilities.stream_params import StreamParams
14
15
 
15
16
 
16
17
  class ChangeStream(Scaffold):
18
+ @mutex
17
19
  @statictypes
18
20
  @mtproto_required
19
21
  async def change_stream(
@@ -36,13 +36,7 @@ class Start(Scaffold):
36
36
  ) == participant.user_id if chat_peer else False
37
37
  if is_self:
38
38
  if just_left:
39
- try:
40
- await ToAsync(
41
- self._binding.stop,
42
- chat_id,
43
- )
44
- except ConnectionNotFound:
45
- pass
39
+ await clear_call(chat_id)
46
40
  if chat_id in self._need_unmute and \
47
41
  not just_joined and \
48
42
  not just_left and \
@@ -71,8 +65,7 @@ class Start(Scaffold):
71
65
  )
72
66
  except ConnectionNotFound:
73
67
  pass
74
- self._cache_user_peer.pop(chat_id)
75
- self._need_unmute.discard(chat_id)
68
+ await clear_cache(chat_id)
76
69
 
77
70
  async def update_status(chat_id: int, state: MediaState):
78
71
  try:
@@ -98,6 +91,10 @@ class Start(Scaffold):
98
91
  ),
99
92
  )
100
93
 
94
+ async def clear_cache(chat_id: int):
95
+ self._cache_user_peer.pop(chat_id)
96
+ self._need_unmute.discard(chat_id)
97
+
101
98
  if not self._is_running:
102
99
  self._is_running = True
103
100
  self._env_checker.check_environment()
@@ -126,7 +123,7 @@ class Start(Scaffold):
126
123
  )
127
124
  self._binding.on_disconnect(
128
125
  lambda chat_id: asyncio.run_coroutine_threadsafe(
129
- self._need_unmute.discard(chat_id),
126
+ clear_cache(chat_id),
130
127
  loop,
131
128
  ),
132
129
  )
@@ -1,4 +1,3 @@
1
- import inspect
2
1
  from functools import wraps
3
2
 
4
3
  from .exceptions import ClientNotStarted
@@ -6,7 +5,7 @@ from .exceptions import NoMTProtoClientSet
6
5
 
7
6
 
8
7
  def mtproto_required(func):
9
- def check_mtproto(*args, **_):
8
+ def check_mtproto(*args):
10
9
  self = args[0]
11
10
  if not self._app:
12
11
  raise NoMTProtoClientSet()
@@ -16,16 +15,7 @@ def mtproto_required(func):
16
15
 
17
16
  @wraps(func)
18
17
  async def async_wrapper(*args, **kwargs):
19
- check_mtproto(*args, **kwargs)
18
+ check_mtproto(*args)
20
19
  return await func(*args, **kwargs)
21
20
 
22
- @wraps(func)
23
- def wrapper(*args, **kwargs):
24
- check_mtproto(*args, **kwargs)
25
- return func(*args, **kwargs)
26
-
27
- if inspect.iscoroutinefunction(func) or \
28
- inspect.isasyncgenfunction(func):
29
- return async_wrapper
30
- else:
31
- return wrapper
21
+ return async_wrapper
pytgcalls/mutex.py ADDED
@@ -0,0 +1,38 @@
1
+ import asyncio
2
+ import logging
3
+ from functools import wraps
4
+ from inspect import signature
5
+ from typing import Optional
6
+
7
+
8
+ def mutex(func):
9
+ sig = signature(func)
10
+
11
+ @wraps(func)
12
+ async def async_wrapper(*args, **kwargs):
13
+ self = args[0]
14
+ bound = sig.bind(*args, **kwargs)
15
+
16
+ if 'chat_id' in bound.arguments:
17
+ chat_id: Optional[int] = None
18
+ try:
19
+ chat_id = await self._resolve_chat_id(
20
+ bound.arguments['chat_id'],
21
+ )
22
+ except Exception as e:
23
+ logging.debug(
24
+ 'Error occurred while resolving chat_id. Reason: ' +
25
+ str(e),
26
+ )
27
+ if chat_id is not None:
28
+ name = f'{func.__name__}_{chat_id}'
29
+ if name not in self._lock:
30
+ self._lock[name] = asyncio.Lock()
31
+ async with self._lock[name]:
32
+ try:
33
+ return await func(*args, **kwargs)
34
+ finally:
35
+ self._lock.pop(name, None)
36
+
37
+ return await func(*args, **kwargs)
38
+ return async_wrapper
pytgcalls/scaffold.py CHANGED
@@ -17,6 +17,7 @@ class Scaffold:
17
17
  # noinspection PyTypeChecker
18
18
  self._binding = None
19
19
  self._need_unmute = set()
20
+ self._lock = dict()
20
21
 
21
22
  def _handle_mtproto(self):
22
23
  pass
pytgcalls/ytdlp.py CHANGED
@@ -36,6 +36,7 @@ class YtDlp:
36
36
  '-f',
37
37
  f'best[width<=?{video_parameters.width}]'
38
38
  f'[height<=?{video_parameters.height}]',
39
+ '--no-warnings',
39
40
  ]
40
41
 
41
42
  if add_commands: