py-tgcalls 2.2.8__py3-none-any.whl → 2.2.10__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.8
3
+ Version: 2.2.10
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/
@@ -11,16 +11,16 @@ Keywords: audio,python,library,video,telegram,stream,ffmpeg,cpp,webrtc,voice-cha
11
11
  Classifier: Operating System :: OS Independent
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3 :: Only
14
- Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
19
  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.6
23
+ Requires-Dist: ntgcalls<3.0.0,>=2.0.7
24
24
  Requires-Dist: deprecation
25
25
  Provides-Extra: pyrogram
26
26
  Requires-Dist: pyrogram>=1.2.20; extra == "pyrogram"
@@ -1,10 +1,10 @@
1
- py_tgcalls-2.2.8.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
1
+ py_tgcalls-2.2.10.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
2
2
  pytgcalls/__init__.py,sha256=qbfwN7rYwIdCegMOzdcbvwazeNjDzgmowgcqLFNqKIM,308
3
- pytgcalls/__version__.py,sha256=IqD9h-jsDDriviuNsOqmA0rXPSWRSWW_V-IX7uKeRnk,22
3
+ pytgcalls/__version__.py,sha256=lfEF2tRAjIf7jwdP4hzCfb5zYNcswMyGc2yOh47sA9k,23
4
4
  pytgcalls/chat_lock.py,sha256=u3t0G3EQ20zn89Sn5s-GWFFX9Xmu4gYWkAgzHJOk0Mc,762
5
5
  pytgcalls/environment.py,sha256=ctCHACvG6l8SdpPewSBhOvc70kbwpv18maC0TwLvZ08,1924
6
6
  pytgcalls/exceptions.py,sha256=Rijc-8T93WEWJxNW9jncU8_M6mYZZZcs8F2bqitEIeI,3787
7
- pytgcalls/ffmpeg.py,sha256=DkP-Xj9O1sohGR8TjIcCbv-oYJjnkGKYxhu7Sg6V0KY,8645
7
+ pytgcalls/ffmpeg.py,sha256=0X_hoKzLEkcIF4_sPmK2C1w8O7i14a8J3hQACASnNVE,8751
8
8
  pytgcalls/filters.py,sha256=8Fq_gvHHdqhIk_XwMJ9wneeZOwrvBkSOKaMJ60r3bZU,6157
9
9
  pytgcalls/list_to_cmd.py,sha256=rGJLsejbAQdDb8pctMbLnwea5NkitlfVKc3IpoGi4V4,240
10
10
  pytgcalls/mtproto_required.py,sha256=6B-31p5qH_6oekUgypV4nK3hqPS6Nr-pA8S81wjnbaY,630
@@ -24,13 +24,13 @@ pytgcalls/handlers/handlers_holder.py,sha256=Rxy6MNdiGOOO5thxlQQyvuXmcbdCTe0N_Q4
24
24
  pytgcalls/media_devices/__init__.py,sha256=QC7OccjY-YkcJ1xF9d1VRfM9hdgExWbInMYW92YBJ_s,309
25
25
  pytgcalls/media_devices/device_info.py,sha256=AleyVRXvZ0ylr03JQq8gPm5L-f5ySDwokDtW_Czcg50,266
26
26
  pytgcalls/media_devices/input_device.py,sha256=-Z5hjhdc1Y68mZQpVW-QgMePKGe_c5zJcYJHIzYElOY,225
27
- pytgcalls/media_devices/media_devices.py,sha256=ZgRF8j4jCJNWrW1HCUUWZMcZ9V7LOcvm_jJmy8g7ieQ,1333
27
+ pytgcalls/media_devices/media_devices.py,sha256=9MN-G2PLrYdqIXBNBpHyJz54vyhuQ1JrwKoUYiAZoXw,1388
28
28
  pytgcalls/media_devices/screen_device.py,sha256=B1MCpcqW-QXKcVafNdPQfd2Es6-ejkX2NdwbfuYmhv4,201
29
29
  pytgcalls/media_devices/speaker_device.py,sha256=39aAE2oEvlhRiUwHlIJCrSUPWIy-8J9_oq1TmCq5IjA,200
30
30
  pytgcalls/methods/__init__.py,sha256=KKnG3uI_3oKKBByQ96kHJiabjxk2J6YLs4HDfOKvQ0A,262
31
31
  pytgcalls/methods/calls/__init__.py,sha256=xg4DZZClEnxwaj-DAq3e8gSR-g-MiYBdUEBth64lSXA,214
32
32
  pytgcalls/methods/calls/change_volume_call.py,sha256=xMUszg44Gs1RgTXGCwcWEESnwu3XVkW8Kx9HGLDGSEo,842
33
- pytgcalls/methods/calls/get_participants.py,sha256=HDEMwZwNZM7KSb76P5XVH46qNONvBEVg4x_e-rgJscI,716
33
+ pytgcalls/methods/calls/get_participants.py,sha256=sbHHIS4TcYPwLE1qM6ltiC4XY5iIGXZFOU7ejutaewY,723
34
34
  pytgcalls/methods/calls/leave_call.py,sha256=KRwT1XGFvBeBZWzvfnEUWLXExKYGWIwOGDCa-qgH7go,1518
35
35
  pytgcalls/methods/decorators/__init__.py,sha256=TCGaEVZnHjtOwv-3PNfaCVm0kyFhJApUPUNntt6MwyM,78
36
36
  pytgcalls/methods/decorators/on_update.py,sha256=ZTL4YcQk0N4Ru56a5WItUvkSN5SAqr6_RDZvXmZMIHs,316
@@ -40,7 +40,7 @@ pytgcalls/methods/internal/clear_call.py,sha256=r9v2oPGrDfplxqlfKxT95JjOijm6daIp
40
40
  pytgcalls/methods/internal/connect_call.py,sha256=wgRtcY-YxGDFCJcLkSIqgc81DdoA9osQ_iEErqbBH7E,5770
41
41
  pytgcalls/methods/internal/emit_sig_data.py,sha256=ucIsknhJHB-0x7lcymXvwQ647AJQ852zH2W6MdlC3ws,216
42
42
  pytgcalls/methods/internal/handle_connection_changed.py,sha256=_1u3J6_Pjl1Gs1u_WkhG2FAUl_hxlHUiflaMkKkJDsc,866
43
- pytgcalls/methods/internal/handle_mtproto_updates.py,sha256=I8l9n4t2haN3wR3cCWqynIBsilN1XazuLC9l8aS7Rhw,7812
43
+ pytgcalls/methods/internal/handle_mtproto_updates.py,sha256=UVJstb-s03kzusXyEbdMml3OKLmxc5tkrI2H3SdD3M4,7888
44
44
  pytgcalls/methods/internal/handle_stream_ended.py,sha256=DllD1ZfGQbwVh-S0neocwnN-8lQtwwyrzWl9teSrZbY,561
45
45
  pytgcalls/methods/internal/handle_stream_frame.py,sha256=_FA782qlOT3tUqnySm7RBpjbgfEEzt1oEBDm-iADsbQ,1145
46
46
  pytgcalls/methods/internal/join_presentation.py,sha256=sXhmzbLWwVFi3gFl1rv0OgJsRJBrvjzRcl60N6ydNW8,2184
@@ -51,17 +51,17 @@ pytgcalls/methods/internal/switch_connection.py,sha256=Yyh7vJLgoR_jZNpUbOKTiXSt2
51
51
  pytgcalls/methods/internal/update_sources.py,sha256=ISF6u3rk4IcVrPOEOB-uZUDfnwUp2_y1_2g9GboXpWM,1562
52
52
  pytgcalls/methods/internal/update_status.py,sha256=6zH7oMM_qPE-88mdC5CBhT07gPvayBrmMAvDWwCDFtc,608
53
53
  pytgcalls/methods/stream/__init__.py,sha256=mAcOih0-NT6T_Gspej6mySpJNPuEe46sUwgKV3vSvYM,336
54
- pytgcalls/methods/stream/mute.py,sha256=ZrZS_EeNUeUxb6UgbdhwXUdRX826u-qSjH5a6sg7LsE,557
55
- pytgcalls/methods/stream/pause.py,sha256=-kNvWQuv5VlssNcL-M6rkT5TKFmXlbOzJrDny95qsUc,560
54
+ pytgcalls/methods/stream/mute.py,sha256=ygFVe7nfwN2GQyI1CjjysG4sO2PLn8CyoYkJmI9eA0w,565
55
+ pytgcalls/methods/stream/pause.py,sha256=_M5bNvzGm-UDUNoC-hwTB7JmhZlzbDnuGIDgrKF7zQ8,568
56
56
  pytgcalls/methods/stream/play.py,sha256=zJhWNCq2BKni1cCmPz6JVCTK2y-Pceh9ik4TYytR87I,3196
57
57
  pytgcalls/methods/stream/record.py,sha256=geYSVtSbp0yRIR1Nmj-L1s-6nqQAh0x0IcA1OuFvuyA,1306
58
- pytgcalls/methods/stream/resume.py,sha256=AUHU3AtpXO2rtp2V1EKSC_KAWTk2KHMiHaqHluYy31M,563
58
+ pytgcalls/methods/stream/resume.py,sha256=FPTbHF1mizrGLa1uXkV-CbncIBy05n6AZTnCG_Ot_Jc,571
59
59
  pytgcalls/methods/stream/send_frame.py,sha256=Kj9R8OqUM-g7pt-FiWP-US7sCFkH5ciPr9S8v-WPtLg,1062
60
- pytgcalls/methods/stream/time.py,sha256=65Hc5pQaN6z6nxgwT9Zxgsnl_UosvMkcICqE2hisNWA,659
61
- pytgcalls/methods/stream/unmute.py,sha256=wgWpxakIPLzZCgojC-cIkDSnF9LtDZwdTsBOctdHibQ,563
60
+ pytgcalls/methods/stream/time.py,sha256=KG5FczRuyTIcCxwrcIm1zKmkd3oEEJpXdBLrMYHef2w,666
61
+ pytgcalls/methods/stream/unmute.py,sha256=spJpi36jCQKeuX_O4u3B_xtP8qnhOhX9Oa6DBo8q2xo,571
62
62
  pytgcalls/methods/utilities/__init__.py,sha256=JcKwqNo6fFXXfuab94fNEraKF1P9fnSSgr0WQDRjF2w,339
63
63
  pytgcalls/methods/utilities/cache_peer.py,sha256=Ylt0wCCJOoNKf1wZEXjfE8aBZKUIIgdRUFOMTGA5DfE,140
64
- pytgcalls/methods/utilities/call_holder.py,sha256=MhIbwCG6DROd9_bHGa6aqu-rB0y4sngzPBj82zLtAXU,1068
64
+ pytgcalls/methods/utilities/call_holder.py,sha256=w6cPM5-IL2iMA6rqH-q2H6cJNR2W9svTIqWa5w2NEfc,1125
65
65
  pytgcalls/methods/utilities/compose.py,sha256=Nzdv8orMmka5NIBZ1SW1nsqXRzArZl4m6FdZU7syaR4,334
66
66
  pytgcalls/methods/utilities/cpu_usage.py,sha256=Mbga4MFCIwuh7WC8sqBbv1Pa6ALcp5AIDyfYMH_Bix4,162
67
67
  pytgcalls/methods/utilities/idle.py,sha256=MDdzHTv1ws2yBhsvhBUnssGdghkZ2KwR0HUCPOwV38o,814
@@ -72,17 +72,17 @@ pytgcalls/methods/utilities/start.py,sha256=mn0kQZhTUuc-9CCJDbFIVsEtJ8kfnfZOGbVC
72
72
  pytgcalls/methods/utilities/stream_params.py,sha256=PUnctLhdCeBAg52v95vpxj-42Le5XzbnRtcfm71FDBM,3341
73
73
  pytgcalls/mtproto/__init__.py,sha256=X4zvzFG7km7qHyE0fdvA550WcOVO_xl_p__gvIfDGmw,130
74
74
  pytgcalls/mtproto/bridged_client.py,sha256=E0DLhZd-x7Uxyf6nFaTZ73COLB6BnXHzsBgqwWGHwEQ,8476
75
- pytgcalls/mtproto/client_cache.py,sha256=5unu8sjLRaIKoEgJGaIRjhA4P3U2lFpfakTKFxKLzAM,5591
76
- pytgcalls/mtproto/hydrogram_client.py,sha256=ocypZa8uH3VvSmgWE8I5rAvFs4VJ3yBphPXghB1vZyI,30019
75
+ pytgcalls/mtproto/client_cache.py,sha256=vlBXZP_cw7hdWsiS95oyePPitincu3zqaewlKjYY878,5591
76
+ pytgcalls/mtproto/hydrogram_client.py,sha256=Ihh5v0xEc9102pyhN15Se5hMytDIs5kqsoxMGJkbyZ0,30436
77
77
  pytgcalls/mtproto/mtproto_client.py,sha256=9SIG3DNeICIXvggyVE8DQWtToPtxV0t9ZKr6dEMnEMg,8783
78
- pytgcalls/mtproto/pyrogram_client.py,sha256=iyygyyh7pN0xCqLF50fA48lgLsucw7awogWCd5tOmLc,30005
79
- pytgcalls/mtproto/telethon_client.py,sha256=DHtGbSqqjMMqrIyDKWdrK3NUoWX3i_tYQm9oYJQ1-vA,28172
78
+ pytgcalls/mtproto/pyrogram_client.py,sha256=KZr5ySyi57czQfNb94J1HQPckZv97ejb2DorILczVZs,30582
79
+ pytgcalls/mtproto/telethon_client.py,sha256=oWzZqrxjPGmY6RyEUTOKzzjwpkPOfvPmMON8OZtQFEg,28726
80
80
  pytgcalls/types/__init__.py,sha256=GlgBBXAwbNopXSeTTmiXktrEJhhN_rMBtuAllTBbN3k,1189
81
81
  pytgcalls/types/browsers.py,sha256=47Kr5q96n4Q4WvVhA6IUlS2egEcA9GRLlDeFcQYyc9M,9545
82
82
  pytgcalls/types/cache.py,sha256=nJh6B7xnvAiLh0mDJYS9sYhnRvj0BqxrQBLXs4WEUMs,1235
83
- pytgcalls/types/dict.py,sha256=-R1v5-v5WzhquPN25Bfw9Ow6q2lRRgpsq_FlsOawCUw,78
83
+ pytgcalls/types/dict.py,sha256=wvQRUcCxvxxHjss9zPe9D1cIq5Yf2N1uDIJFgR0x9_Q,147
84
84
  pytgcalls/types/flag.py,sha256=MeWDKkUAZa97fUPg5Ni5Rf4pDgiZ_OSRZPseEY7d3rw,104
85
- pytgcalls/types/list.py,sha256=rGzD9LWAI2hUX71OL_pqZn08YHEbZ-AZ6RTjXPc9wJA,78
85
+ pytgcalls/types/list.py,sha256=WfS3b86ulCUCHGknHAnhqqI83_xCJnjonXwqeZvmqYk,128
86
86
  pytgcalls/types/participant_list.py,sha256=wG7a8dvcmcUkagmSo-g4thGMBrqMdEU0fA_zD4tCk2w,931
87
87
  pytgcalls/types/py_object.py,sha256=jisGKqJINuzAjkIkLIps61uYM0eFSmC9TtgxGRDAMZI,934
88
88
  pytgcalls/types/update.py,sha256=wPCzWLhrsScZ3ksRTyt8IuDaaG5YI-ItG_Yw-OqzK2Y,157
@@ -112,12 +112,12 @@ pytgcalls/types/stream/device.py,sha256=EdoDg6lPE7fgoZI04Nr0E9zbIk-iRIBgYYAzVqoC
112
112
  pytgcalls/types/stream/direction.py,sha256=VepLMe-dXg4M5eVdVyIb2uxYvnpB9OJL5fEgPYUFtTI,592
113
113
  pytgcalls/types/stream/external_media.py,sha256=RiuSX5tZGdNsQZ8LIRk5Lp4Ksv9oTvaccmInJRZYo4M,114
114
114
  pytgcalls/types/stream/frame.py,sha256=TXo5HZVHbbaVNBqulMhTqGODXH3bpBVlN_of1rosNUQ,586
115
- pytgcalls/types/stream/media_stream.py,sha256=zcRVpNXfL8mhg-SEfAi-f0lDUZMyNYLetophvcAN_gQ,11968
115
+ pytgcalls/types/stream/media_stream.py,sha256=bt6EKKkbNjS8JSIQFoxc_QM_FS1t6n-CA8hlykpTxa4,12229
116
116
  pytgcalls/types/stream/record_stream.py,sha256=f4VQ6MY8HtOxt7vz0hWBFmbbAIvTRHpAIU2nmj0TF6Y,3197
117
117
  pytgcalls/types/stream/stream_ended.py,sha256=xR_kZwFf03hA6rw_nvI7Be7GwoCKzQf_1MKaGpPDXqY,716
118
118
  pytgcalls/types/stream/stream_frames.py,sha256=028ZhNV-mN3BGqMlmxusAV1xDQpXRYCeM0WXBZhRUhA,446
119
119
  pytgcalls/types/stream/video_quality.py,sha256=eMCBFPwh5meX3UVEaozcGlwmgaujfpiTa3vBVSBBP_8,275
120
- py_tgcalls-2.2.8.dist-info/METADATA,sha256=ES6Bwhsvi1yPMrVGm9cW03FNWRCtW-fuzQApJVLBPeQ,5280
121
- py_tgcalls-2.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
122
- py_tgcalls-2.2.8.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
123
- py_tgcalls-2.2.8.dist-info/RECORD,,
120
+ py_tgcalls-2.2.10.dist-info/METADATA,sha256=2J2H8kJ43gPD3UaOTydwrotSNZ17B-E78IosYzlWqA4,5282
121
+ py_tgcalls-2.2.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
122
+ py_tgcalls-2.2.10.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
123
+ py_tgcalls-2.2.10.dist-info/RECORD,,
pytgcalls/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '2.2.8'
1
+ __version__ = '2.2.10'
pytgcalls/ffmpeg.py CHANGED
@@ -126,6 +126,7 @@ async def cleanup_commands(
126
126
  proc_res = await asyncio.create_subprocess_exec(
127
127
  commands[0] if not process_name else process_name,
128
128
  '-h',
129
+ 'full',
129
130
  stdout=asyncio.subprocess.PIPE,
130
131
  stderr=asyncio.subprocess.PIPE,
131
132
  )
@@ -138,7 +139,8 @@ async def cleanup_commands(
138
139
  except (subprocess.TimeoutExpired, JSONDecodeError):
139
140
  proc_res.terminate()
140
141
  raise
141
- supported = re.findall(r'(?m)^ *(-.*?)\s+', result)
142
+ supported = re.findall(r'(?m)^ *(-\w+).*?\s+', result)
143
+ supported += ['-i']
142
144
  new_commands = []
143
145
  ignore_next = False
144
146
 
@@ -147,8 +149,11 @@ async def cleanup_commands(
147
149
  if v[0] == '-':
148
150
  ignore_next = v not in supported or \
149
151
  blacklist is not None and v in blacklist
152
+
150
153
  if not ignore_next:
151
154
  new_commands += [v]
155
+ elif v[0] != '-':
156
+ ignore_next = False
152
157
  return new_commands
153
158
  except FileNotFoundError:
154
159
  raise FFmpegError(f'{commands[0]} not installed')
@@ -210,7 +215,6 @@ def build_command(
210
215
  ffmpeg_command.append(f'{i}: {headers[i]}')
211
216
 
212
217
  ffmpeg_command += [
213
- '-nostdin',
214
218
  '-i',
215
219
  f'{path}' if name == 'ffmpeg' else path,
216
220
  ]
@@ -16,14 +16,14 @@ class MediaDevices:
16
16
  )
17
17
 
18
18
  @staticmethod
19
- def microphone_devices() -> List:
19
+ def microphone_devices() -> List[InputDevice]:
20
20
  return MediaDevices._parse_devices(
21
21
  NTgCalls.get_media_devices().microphone,
22
22
  False,
23
23
  )
24
24
 
25
25
  @staticmethod
26
- def speaker_devices() -> List:
26
+ def speaker_devices() -> List[SpeakerDevice]:
27
27
  return List(
28
28
  SpeakerDevice(
29
29
  device.name,
@@ -33,14 +33,14 @@ class MediaDevices:
33
33
  )
34
34
 
35
35
  @staticmethod
36
- def camera_devices() -> List:
36
+ def camera_devices() -> List[InputDevice]:
37
37
  return MediaDevices._parse_devices(
38
38
  NTgCalls.get_media_devices().camera,
39
39
  True,
40
40
  )
41
41
 
42
42
  @staticmethod
43
- def screen_devices() -> List:
43
+ def screen_devices() -> List[ScreenDevice]:
44
44
  return List(
45
45
  ScreenDevice(
46
46
  device.name,
@@ -1,4 +1,3 @@
1
- from typing import List
2
1
  from typing import Optional
3
2
  from typing import Union
4
3
 
@@ -7,6 +6,7 @@ from ...mtproto_required import mtproto_required
7
6
  from ...scaffold import Scaffold
8
7
  from ...statictypes import statictypes
9
8
  from ...types.chats import GroupCallParticipant
9
+ from ...types.list import List
10
10
 
11
11
 
12
12
  class GetParticipants(Scaffold):
@@ -148,7 +148,8 @@ class HandleMTProtoUpdates(Scaffold):
148
148
  chat_peer,
149
149
  ) == participant.user_id if chat_peer else False
150
150
  if is_self:
151
- if action == GroupCallParticipant.Action.KICKED:
151
+ if action == GroupCallParticipant.Action.KICKED or \
152
+ action == GroupCallParticipant.Action.LEFT:
152
153
  await self._clear_call(chat_id)
153
154
  if (
154
155
  chat_id in self._need_unmute and
@@ -14,7 +14,7 @@ class Mute(Scaffold):
14
14
  async def mute(
15
15
  self,
16
16
  chat_id: Union[int, str],
17
- ):
17
+ ) -> bool:
18
18
  chat_id = await self.resolve_chat_id(chat_id)
19
19
  try:
20
20
  return await self._binding.mute(chat_id)
@@ -14,7 +14,7 @@ class Pause(Scaffold):
14
14
  async def pause(
15
15
  self,
16
16
  chat_id: Union[int, str],
17
- ):
17
+ ) -> bool:
18
18
  chat_id = await self.resolve_chat_id(chat_id)
19
19
  try:
20
20
  return await self._binding.pause(chat_id)
@@ -14,7 +14,7 @@ class Resume(Scaffold):
14
14
  async def resume(
15
15
  self,
16
16
  chat_id: Union[int, str],
17
- ):
17
+ ) -> bool:
18
18
  chat_id = await self.resolve_chat_id(chat_id)
19
19
  try:
20
20
  return await self._binding.resume(chat_id)
@@ -16,7 +16,7 @@ class Time(Scaffold):
16
16
  self,
17
17
  chat_id: Union[int, str],
18
18
  direction: Direction = Direction.OUTGOING,
19
- ):
19
+ ) -> int:
20
20
  chat_id = await self.resolve_chat_id(chat_id)
21
21
  try:
22
22
  return await self._binding.time(chat_id, direction.to_raw())
@@ -14,7 +14,7 @@ class UnMute(Scaffold):
14
14
  async def unmute(
15
15
  self,
16
16
  chat_id: Union[int, str],
17
- ):
17
+ ) -> bool:
18
18
  chat_id = await self.resolve_chat_id(chat_id)
19
19
  try:
20
20
  return await self._binding.unmute(chat_id)
@@ -15,7 +15,7 @@ class CallHolder(Scaffold):
15
15
  }
16
16
 
17
17
  @property
18
- async def calls(self):
18
+ async def calls(self) -> Dict[int, Call]:
19
19
  calls_list = await self._binding.calls()
20
20
  return Dict({
21
21
  x: Call(
@@ -26,14 +26,14 @@ class CallHolder(Scaffold):
26
26
  })
27
27
 
28
28
  @property
29
- async def group_calls(self):
29
+ async def group_calls(self) -> Dict[int, Call]:
30
30
  return Dict({
31
31
  chat_id: x
32
32
  for chat_id, x in (await self.calls).items() if chat_id < 0
33
33
  })
34
34
 
35
35
  @property
36
- async def private_calls(self):
36
+ async def private_calls(self) -> Dict[int, Call]:
37
37
  return Dict({
38
38
  chat_id: x
39
39
  for chat_id, x in (await self.calls).items() if chat_id > 0
@@ -18,7 +18,7 @@ class ClientCache:
18
18
  app: BridgedClient,
19
19
  ):
20
20
  self._app: BridgedClient = app
21
- cache_duration = 0 if app.no_updates() else cache_duration
21
+ cache_duration = 1 if app.no_updates() else cache_duration
22
22
  full_chat_duration = 1 if app.no_updates() else cache_duration
23
23
  self._full_chat_cache = Cache(full_chat_duration)
24
24
  self._call_participants_cache = Cache(cache_duration)
@@ -209,30 +209,38 @@ class HydrogramClient(BridgedClient):
209
209
  update,
210
210
  UpdateGroupCall,
211
211
  ):
212
- chat_id = self.chat_id(chats[update.chat_id])
213
- if isinstance(
214
- update.call,
215
- GroupCall,
216
- ):
217
- if update.call.schedule_date is None:
218
- self._cache.set_cache(
219
- chat_id,
220
- InputGroupCall(
221
- access_hash=update.call.access_hash,
222
- id=update.call.id,
212
+ chat_id: Optional[int] = None
213
+ if update.chat_id:
214
+ chat_id = self.chat_id(
215
+ chats[update.chat_id],
216
+ )
217
+ elif self._cache.get_chat_id(update.call.id) is not None:
218
+ chat_id = self._cache.get_chat_id(update.call.id)
219
+
220
+ if chat_id is not None:
221
+ if isinstance(
222
+ update.call,
223
+ GroupCall,
224
+ ):
225
+ if update.call.schedule_date is None:
226
+ self._cache.set_cache(
227
+ chat_id,
228
+ InputGroupCall(
229
+ access_hash=update.call.access_hash,
230
+ id=update.call.id,
231
+ ),
232
+ )
233
+ if isinstance(
234
+ update.call,
235
+ GroupCallDiscarded,
236
+ ):
237
+ self._cache.drop_cache(chat_id)
238
+ await self._propagate(
239
+ ChatUpdate(
240
+ chat_id,
241
+ ChatUpdate.Status.CLOSED_VOICE_CHAT,
223
242
  ),
224
243
  )
225
- if isinstance(
226
- update.call,
227
- GroupCallDiscarded,
228
- ):
229
- self._cache.drop_cache(chat_id)
230
- await self._propagate(
231
- ChatUpdate(
232
- chat_id,
233
- ChatUpdate.Status.CLOSED_VOICE_CHAT,
234
- ),
235
- )
236
244
  if isinstance(
237
245
  update,
238
246
  (
@@ -210,30 +210,41 @@ class PyrogramClient(BridgedClient):
210
210
  update,
211
211
  UpdateGroupCall,
212
212
  ):
213
- chat_id = self.chat_id(chats[update.chat_id])
214
- if isinstance(
215
- update.call,
216
- GroupCall,
217
- ):
218
- if update.call.schedule_date is None:
219
- self._cache.set_cache(
220
- chat_id,
221
- InputGroupCall(
222
- access_hash=update.call.access_hash,
223
- id=update.call.id,
213
+ if getattr(update, 'chat_id', None) is not None:
214
+ # noinspection PyUnresolvedReferences
215
+ chat_id = self.chat_id(
216
+ chats[update.chat_id],
217
+ )
218
+ elif getattr(update, 'peer', None) is not None:
219
+ # noinspection PyUnresolvedReferences
220
+ chat_id = self.chat_id(update.peer)
221
+ else:
222
+ chat_id = self._cache.get_chat_id(update.call.id)
223
+
224
+ if chat_id is not None:
225
+ if isinstance(
226
+ update.call,
227
+ GroupCall,
228
+ ):
229
+ if update.call.schedule_date is None:
230
+ self._cache.set_cache(
231
+ chat_id,
232
+ InputGroupCall(
233
+ access_hash=update.call.access_hash,
234
+ id=update.call.id,
235
+ ),
236
+ )
237
+ if isinstance(
238
+ update.call,
239
+ GroupCallDiscarded,
240
+ ):
241
+ self._cache.drop_cache(chat_id)
242
+ await self._propagate(
243
+ ChatUpdate(
244
+ chat_id,
245
+ ChatUpdate.Status.CLOSED_VOICE_CHAT,
224
246
  ),
225
247
  )
226
- if isinstance(
227
- update.call,
228
- GroupCallDiscarded,
229
- ):
230
- self._cache.drop_cache(chat_id)
231
- await self._propagate(
232
- ChatUpdate(
233
- chat_id,
234
- ChatUpdate.Status.CLOSED_VOICE_CHAT,
235
- ),
236
- )
237
248
  if isinstance(
238
249
  update,
239
250
  (
@@ -204,36 +204,45 @@ class TelethonClient(BridgedClient):
204
204
  update,
205
205
  UpdateGroupCall,
206
206
  ):
207
- chat_id = self.chat_id(
208
- await self._get_entity_group(
209
- update.chat_id,
210
- ),
211
- )
212
- if isinstance(
213
- update.call,
214
- GroupCall,
215
- ):
216
- if update.call.schedule_date is None:
217
- self._cache.set_cache(
207
+ if getattr(update, 'chat_id', None) is not None:
208
+ # noinspection PyUnresolvedReferences
209
+ chat_id = self.chat_id(
210
+ await self._get_entity_group(
211
+ update.chat_id,
212
+ ),
213
+ )
214
+ elif getattr(update, 'peer', None) is not None:
215
+ # noinspection PyUnresolvedReferences
216
+ chat_id = self.chat_id(update.peer)
217
+ else:
218
+ chat_id = self._cache.get_chat_id(update.call.id)
219
+
220
+ if chat_id is not None:
221
+ if isinstance(
222
+ update.call,
223
+ GroupCall,
224
+ ):
225
+ if update.call.schedule_date is None:
226
+ self._cache.set_cache(
227
+ chat_id,
228
+ InputGroupCall(
229
+ access_hash=update.call.access_hash,
230
+ id=update.call.id,
231
+ ),
232
+ )
233
+ if isinstance(
234
+ update.call,
235
+ GroupCallDiscarded,
236
+ ):
237
+ self._cache.drop_cache(
218
238
  chat_id,
219
- InputGroupCall(
220
- access_hash=update.call.access_hash,
221
- id=update.call.id,
239
+ )
240
+ await self._propagate(
241
+ ChatUpdate(
242
+ chat_id,
243
+ ChatUpdate.Status.CLOSED_VOICE_CHAT,
222
244
  ),
223
245
  )
224
- if isinstance(
225
- update.call,
226
- GroupCallDiscarded,
227
- ):
228
- self._cache.drop_cache(
229
- chat_id,
230
- )
231
- await self._propagate(
232
- ChatUpdate(
233
- chat_id,
234
- ChatUpdate.Status.CLOSED_VOICE_CHAT,
235
- ),
236
- )
237
246
  if isinstance(
238
247
  update,
239
248
  (
pytgcalls/types/dict.py CHANGED
@@ -1,5 +1,10 @@
1
+ from typing import TypeVar
2
+
1
3
  from ..types.py_object import PyObject
2
4
 
5
+ T = TypeVar('T')
6
+ U = TypeVar('U')
7
+
3
8
 
4
- class Dict(PyObject, dict):
9
+ class Dict(PyObject, dict[T, U]):
5
10
  pass
pytgcalls/types/list.py CHANGED
@@ -1,5 +1,10 @@
1
+ from typing import TypeVar
2
+
1
3
  from ..types.py_object import PyObject
2
4
 
3
5
 
4
- class List(PyObject, list):
6
+ T = TypeVar('T')
7
+
8
+
9
+ class List(PyObject, list[T]):
5
10
  pass
@@ -13,6 +13,7 @@ from ...exceptions import NoAudioSourceFound
13
13
  from ...exceptions import NoVideoSourceFound
14
14
  from ...ffmpeg import build_command
15
15
  from ...ffmpeg import check_stream
16
+ from ...ffmpeg import cleanup_commands
16
17
  from ...list_to_cmd import list_to_cmd
17
18
  from ...media_devices.input_device import InputDevice
18
19
  from ...media_devices.screen_device import ScreenDevice
@@ -231,14 +232,16 @@ class MediaStream(Stream):
231
232
  except LiveStreamFound:
232
233
  live_stream = True
233
234
  self.camera.path = list_to_cmd(
234
- build_command(
235
- 'ffmpeg',
236
- self._ffmpeg_parameters,
237
- self._media_path,
238
- self._video_parameters,
239
- image_commands,
240
- self._headers,
241
- live_stream,
235
+ await cleanup_commands(
236
+ build_command(
237
+ 'ffmpeg',
238
+ self._ffmpeg_parameters,
239
+ self._media_path,
240
+ self._video_parameters,
241
+ image_commands,
242
+ self._headers,
243
+ live_stream,
244
+ ),
242
245
  ),
243
246
  )
244
247
  except NoVideoSourceFound as e:
@@ -280,14 +283,16 @@ class MediaStream(Stream):
280
283
  except LiveStreamFound:
281
284
  live_stream = True
282
285
  self.microphone.path = list_to_cmd(
283
- build_command(
284
- 'ffmpeg',
285
- self._ffmpeg_parameters,
286
- self._audio_path,
287
- self._audio_parameters,
288
- [],
289
- self._headers,
290
- live_stream,
286
+ await cleanup_commands(
287
+ build_command(
288
+ 'ffmpeg',
289
+ self._ffmpeg_parameters,
290
+ self._audio_path,
291
+ self._audio_parameters,
292
+ [],
293
+ self._headers,
294
+ live_stream,
295
+ ),
291
296
  ),
292
297
  )
293
298
  except NoAudioSourceFound as e: