py-tgcalls 2.0.6__py3-none-any.whl → 2.1.0__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.
- {py_tgcalls-2.0.6.dist-info → py_tgcalls-2.1.0.dist-info}/METADATA +11 -16
- py_tgcalls-2.1.0.dist-info/RECORD +106 -0
- {py_tgcalls-2.0.6.dist-info → py_tgcalls-2.1.0.dist-info}/WHEEL +1 -1
- pytgcalls/__init__.py +2 -0
- pytgcalls/__version__.py +1 -1
- pytgcalls/exceptions.py +7 -24
- pytgcalls/ffmpeg.py +2 -2
- pytgcalls/filters.py +49 -6
- pytgcalls/handlers/handlers_holder.py +1 -1
- pytgcalls/media_devices/__init__.py +6 -2
- pytgcalls/media_devices/device_info.py +8 -15
- pytgcalls/media_devices/input_device.py +11 -0
- pytgcalls/media_devices/media_devices.py +41 -92
- pytgcalls/media_devices/screen_device.py +10 -0
- pytgcalls/media_devices/speaker_device.py +10 -0
- pytgcalls/methods/calls/change_volume_call.py +3 -0
- pytgcalls/methods/calls/get_participants.py +5 -1
- pytgcalls/methods/calls/leave_call.py +3 -1
- pytgcalls/methods/stream/__init__.py +14 -10
- pytgcalls/methods/stream/{mute_stream.py → mute.py} +2 -2
- pytgcalls/methods/stream/{pause_stream.py → pause.py} +2 -2
- pytgcalls/methods/stream/play.py +27 -21
- pytgcalls/methods/stream/record.py +49 -0
- pytgcalls/methods/stream/{resume_stream.py → resume.py} +2 -2
- pytgcalls/methods/stream/send_frame.py +38 -0
- pytgcalls/methods/stream/{played_time.py → time.py} +5 -3
- pytgcalls/methods/stream/{unmute_stream.py → unmute.py} +2 -2
- pytgcalls/methods/utilities/__init__.py +6 -0
- pytgcalls/methods/utilities/call_holder.py +5 -2
- pytgcalls/methods/utilities/join_presentation.py +50 -0
- pytgcalls/methods/utilities/log_retries.py +14 -0
- pytgcalls/methods/utilities/start.py +136 -16
- pytgcalls/methods/utilities/stream_params.py +69 -22
- pytgcalls/methods/utilities/update_sources.py +42 -0
- pytgcalls/mtproto/bridged_client.py +36 -2
- pytgcalls/mtproto/client_cache.py +46 -16
- pytgcalls/mtproto/hydrogram_client.py +72 -23
- pytgcalls/mtproto/mtproto_client.py +32 -4
- pytgcalls/mtproto/pyrogram_client.py +72 -23
- pytgcalls/mtproto/telethon_client.py +97 -33
- pytgcalls/scaffold.py +15 -0
- pytgcalls/types/__init__.py +14 -4
- pytgcalls/types/calls/__init__.py +2 -0
- pytgcalls/types/calls/call.py +5 -3
- pytgcalls/types/calls/call_sources.py +4 -0
- pytgcalls/types/chats/group_call_participant.py +23 -0
- pytgcalls/types/py_object.py +9 -10
- pytgcalls/types/raw/audio_stream.py +3 -3
- pytgcalls/types/raw/stream.py +8 -4
- pytgcalls/types/raw/video_stream.py +5 -4
- pytgcalls/types/stream/__init__.py +14 -4
- pytgcalls/types/stream/device.py +36 -0
- pytgcalls/types/stream/direction.py +25 -0
- pytgcalls/types/stream/external_media.py +8 -0
- pytgcalls/types/stream/frame.py +26 -0
- pytgcalls/types/stream/media_stream.py +178 -107
- pytgcalls/types/stream/record_stream.py +99 -0
- pytgcalls/types/stream/stream_ended.py +32 -0
- pytgcalls/types/stream/stream_frames.py +20 -0
- py_tgcalls-2.0.6.dist-info/RECORD +0 -93
- pytgcalls/media_devices/screen_info.py +0 -45
- pytgcalls/types/stream/stream_audio_ended.py +0 -9
- pytgcalls/types/stream/stream_video_ended.py +0 -9
- {py_tgcalls-2.0.6.dist-info → py_tgcalls-2.1.0.dist-info}/LICENSE +0 -0
- {py_tgcalls-2.0.6.dist-info → py_tgcalls-2.1.0.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: py-tgcalls
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Async client API for the Telegram Calls.
|
|
5
5
|
Author-email: Laky-64 <iraci.matteo@gmail.com>
|
|
6
|
-
License:
|
|
6
|
+
License: GNU LESSER GENERAL PUBLIC LICENSE
|
|
7
7
|
Version 3, 29 June 2007
|
|
8
8
|
|
|
9
9
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
@@ -178,25 +178,23 @@ Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGP
|
|
|
178
178
|
Classifier: Operating System :: OS Independent
|
|
179
179
|
Classifier: Programming Language :: Python :: 3
|
|
180
180
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
181
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
182
181
|
Classifier: Programming Language :: Python :: 3.9
|
|
183
182
|
Classifier: Programming Language :: Python :: 3.10
|
|
184
183
|
Classifier: Programming Language :: Python :: 3.11
|
|
185
184
|
Classifier: Programming Language :: Python :: 3.12
|
|
186
|
-
|
|
185
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
186
|
+
Requires-Python: >=3.9
|
|
187
187
|
Description-Content-Type: text/markdown
|
|
188
188
|
License-File: LICENSE
|
|
189
189
|
Requires-Dist: aiohttp>=3.9.3
|
|
190
|
-
Requires-Dist: ntgcalls<1.
|
|
191
|
-
Requires-Dist: psutil
|
|
192
|
-
Requires-Dist: screeninfo
|
|
190
|
+
Requires-Dist: ntgcalls<1.4.0,>=1.3.0
|
|
193
191
|
Requires-Dist: deprecation
|
|
194
|
-
Provides-Extra: hydrogram
|
|
195
|
-
Requires-Dist: hydrogram>=0.1.4; extra == "hydrogram"
|
|
196
192
|
Provides-Extra: pyrogram
|
|
197
193
|
Requires-Dist: pyrogram>=1.2.20; extra == "pyrogram"
|
|
198
194
|
Provides-Extra: telethon
|
|
199
195
|
Requires-Dist: telethon>=1.24.0; extra == "telethon"
|
|
196
|
+
Provides-Extra: hydrogram
|
|
197
|
+
Requires-Dist: hydrogram>=0.1.4; extra == "hydrogram"
|
|
200
198
|
|
|
201
199
|
<img src="https://raw.githubusercontent.com/pytgcalls/pytgcalls/master/.github/images/banner.png" alt="pytgcalls logo" />
|
|
202
200
|
<p align="center">
|
|
@@ -223,23 +221,20 @@ Requires-Dist: telethon>=1.24.0; extra == "telethon"
|
|
|
223
221
|
</a>
|
|
224
222
|
</p>
|
|
225
223
|
|
|
226
|
-
# PyTgCalls [](https://pypi.org/project/py-tgcalls/) [](https://pypi.org/project/py-tgcalls/) [](https://pepy.tech/project/py-tgcalls)
|
|
227
225
|
This project allows making Telegram call using MtProto and WebRTC, this is possible thanks to the power of [NTgCalls] library and [@evgeny-nadymov]
|
|
228
226
|
|
|
229
227
|
#### Example Usage
|
|
230
228
|
```python
|
|
231
229
|
from pytgcalls import PyTgCalls
|
|
232
230
|
from pytgcalls import idle
|
|
233
|
-
from pytgcalls.types import MediaStream
|
|
234
231
|
...
|
|
235
232
|
chat_id = -1001185324811
|
|
236
233
|
app = PyTgCalls(client)
|
|
237
234
|
app.start()
|
|
238
235
|
app.play(
|
|
239
236
|
chat_id,
|
|
240
|
-
|
|
241
|
-
'http://docs.evostream.com/sample_content/assets/sintel1m720p.mp4',
|
|
242
|
-
)
|
|
237
|
+
'http://docs.evostream.com/sample_content/assets/sintel1m720p.mp4',
|
|
243
238
|
)
|
|
244
239
|
idle()
|
|
245
240
|
```
|
|
@@ -252,7 +247,7 @@ idle()
|
|
|
252
247
|
- Mute/unmute, pause/resume, stop/play, volume control and more...
|
|
253
248
|
|
|
254
249
|
## Requirements
|
|
255
|
-
- Python 3.
|
|
250
|
+
- Python 3.9 or higher.
|
|
256
251
|
- An MTProto Client
|
|
257
252
|
- A [Telegram API key](https://docs.pyrogram.org/intro/setup#api-keys).
|
|
258
253
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
pytgcalls/__init__.py,sha256=qbfwN7rYwIdCegMOzdcbvwazeNjDzgmowgcqLFNqKIM,308
|
|
2
|
+
pytgcalls/__version__.py,sha256=LbU43-7hsLmdXWI0wTAl3y6D3Tr7CbJiDOLXwl7clj8,22
|
|
3
|
+
pytgcalls/environment.py,sha256=ctCHACvG6l8SdpPewSBhOvc70kbwpv18maC0TwLvZ08,1924
|
|
4
|
+
pytgcalls/exceptions.py,sha256=-xy-V-qIDx4fvAoeJfSWA0rjqKSgBN6kDr2No7ZuULo,3778
|
|
5
|
+
pytgcalls/ffmpeg.py,sha256=tm6DBxyNfPh3h3an-b2s9x1UyX-cvkCdov9prlXxVZY,8649
|
|
6
|
+
pytgcalls/filters.py,sha256=qTFDlt-23xnMh_Ug2WmmOUf13JPX6_yacrv7c3F9Pp0,6125
|
|
7
|
+
pytgcalls/mtproto_required.py,sha256=6B-31p5qH_6oekUgypV4nK3hqPS6Nr-pA8S81wjnbaY,630
|
|
8
|
+
pytgcalls/mutex.py,sha256=Frjji5Ctzlk4AXEBuBLnDK-7HbtreoV6zuyKpFpMNI4,236
|
|
9
|
+
pytgcalls/pytgcalls.py,sha256=oBcWgBwusnXmjHrLEE99VVXARReVyrXdn9SyeBWHbVo,1479
|
|
10
|
+
pytgcalls/pytgcalls_session.py,sha256=_BGJWvf7t3mki2DhlEPjh9cypvYuSFkMSxzTsfepwUk,2719
|
|
11
|
+
pytgcalls/scaffold.py,sha256=SwePuT9V8LdOFy0KRlAnRSbsB2zeGQ4fs9ilrq7HZYI,1353
|
|
12
|
+
pytgcalls/statictypes.py,sha256=CdlqgQNhTZ_uTE8-B8m01fJ7TlD2B42EI2QBPxDdAtA,3842
|
|
13
|
+
pytgcalls/sync.py,sha256=IsOH3TD7cxUg_-zdGt12HoS8sBlXvcGayPZAoxxKM48,3396
|
|
14
|
+
pytgcalls/version_manager.py,sha256=egeGgvb66zWlLTMuw2U-b0x8MfnRzMm1xAEVN87HF5c,296
|
|
15
|
+
pytgcalls/ytdlp.py,sha256=jRA-mKQEXleWvaoGv9wtMa77aRjxsyQxn6_0tXI3-sA,2435
|
|
16
|
+
pytgcalls/custom_api/__init__.py,sha256=ZT8d0lc2YrDuw_YSFAXXHHMewoXGFZ-ANOBIAr0vGFQ,60
|
|
17
|
+
pytgcalls/custom_api/custom_api.py,sha256=Ko3aS6psrwPmOhRPxvG0fepXt4STrA0StvINSxz4Cj8,1890
|
|
18
|
+
pytgcalls/handlers/__init__.py,sha256=pubbxI4pLqQpAKf8-toD6ija4cpSvbCJOQFjTiDjX1E,75
|
|
19
|
+
pytgcalls/handlers/handlers_holder.py,sha256=Rxy6MNdiGOOO5thxlQQyvuXmcbdCTe0N_Q4H6YzpjHU,1177
|
|
20
|
+
pytgcalls/media_devices/__init__.py,sha256=QC7OccjY-YkcJ1xF9d1VRfM9hdgExWbInMYW92YBJ_s,309
|
|
21
|
+
pytgcalls/media_devices/device_info.py,sha256=AleyVRXvZ0ylr03JQq8gPm5L-f5ySDwokDtW_Czcg50,266
|
|
22
|
+
pytgcalls/media_devices/input_device.py,sha256=-Z5hjhdc1Y68mZQpVW-QgMePKGe_c5zJcYJHIzYElOY,225
|
|
23
|
+
pytgcalls/media_devices/media_devices.py,sha256=ZgRF8j4jCJNWrW1HCUUWZMcZ9V7LOcvm_jJmy8g7ieQ,1333
|
|
24
|
+
pytgcalls/media_devices/screen_device.py,sha256=B1MCpcqW-QXKcVafNdPQfd2Es6-ejkX2NdwbfuYmhv4,201
|
|
25
|
+
pytgcalls/media_devices/speaker_device.py,sha256=39aAE2oEvlhRiUwHlIJCrSUPWIy-8J9_oq1TmCq5IjA,200
|
|
26
|
+
pytgcalls/methods/__init__.py,sha256=hk1blAT5u_Isemdrg0nqInLsdRzTTZnak5NdAfkBPAk,217
|
|
27
|
+
pytgcalls/methods/calls/__init__.py,sha256=xg4DZZClEnxwaj-DAq3e8gSR-g-MiYBdUEBth64lSXA,214
|
|
28
|
+
pytgcalls/methods/calls/change_volume_call.py,sha256=xMUszg44Gs1RgTXGCwcWEESnwu3XVkW8Kx9HGLDGSEo,842
|
|
29
|
+
pytgcalls/methods/calls/get_participants.py,sha256=HDEMwZwNZM7KSb76P5XVH46qNONvBEVg4x_e-rgJscI,716
|
|
30
|
+
pytgcalls/methods/calls/leave_call.py,sha256=ay07za5mNKmXGzmpeU6gJJmHVrLeXRtRmFT4QP94pGA,1475
|
|
31
|
+
pytgcalls/methods/decorators/__init__.py,sha256=TCGaEVZnHjtOwv-3PNfaCVm0kyFhJApUPUNntt6MwyM,78
|
|
32
|
+
pytgcalls/methods/decorators/on_update.py,sha256=ZTL4YcQk0N4Ru56a5WItUvkSN5SAqr6_RDZvXmZMIHs,316
|
|
33
|
+
pytgcalls/methods/stream/__init__.py,sha256=mAcOih0-NT6T_Gspej6mySpJNPuEe46sUwgKV3vSvYM,336
|
|
34
|
+
pytgcalls/methods/stream/mute.py,sha256=ZrZS_EeNUeUxb6UgbdhwXUdRX826u-qSjH5a6sg7LsE,557
|
|
35
|
+
pytgcalls/methods/stream/pause.py,sha256=-kNvWQuv5VlssNcL-M6rkT5TKFmXlbOzJrDny95qsUc,560
|
|
36
|
+
pytgcalls/methods/stream/play.py,sha256=-Ld5TQWLhU_ktKrb7q1Xrym36UGrWhaenIbjj-3mM3k,7524
|
|
37
|
+
pytgcalls/methods/stream/record.py,sha256=p9td2tZ4-QMpY8I8LDc1PrFVN3g-vlDINF5I7CmLsvA,1567
|
|
38
|
+
pytgcalls/methods/stream/resume.py,sha256=AUHU3AtpXO2rtp2V1EKSC_KAWTk2KHMiHaqHluYy31M,563
|
|
39
|
+
pytgcalls/methods/stream/send_frame.py,sha256=Kj9R8OqUM-g7pt-FiWP-US7sCFkH5ciPr9S8v-WPtLg,1062
|
|
40
|
+
pytgcalls/methods/stream/time.py,sha256=65Hc5pQaN6z6nxgwT9Zxgsnl_UosvMkcICqE2hisNWA,659
|
|
41
|
+
pytgcalls/methods/stream/unmute.py,sha256=wgWpxakIPLzZCgojC-cIkDSnF9LtDZwdTsBOctdHibQ,563
|
|
42
|
+
pytgcalls/methods/utilities/__init__.py,sha256=HHAkTQEX_23uwo1fxnCIoE2rLBm7fKSQa52SwBLudTI,522
|
|
43
|
+
pytgcalls/methods/utilities/cache_peer.py,sha256=Ylt0wCCJOoNKf1wZEXjfE8aBZKUIIgdRUFOMTGA5DfE,140
|
|
44
|
+
pytgcalls/methods/utilities/call_holder.py,sha256=MhIbwCG6DROd9_bHGa6aqu-rB0y4sngzPBj82zLtAXU,1068
|
|
45
|
+
pytgcalls/methods/utilities/compose.py,sha256=Nzdv8orMmka5NIBZ1SW1nsqXRzArZl4m6FdZU7syaR4,334
|
|
46
|
+
pytgcalls/methods/utilities/cpu_usage.py,sha256=Mbga4MFCIwuh7WC8sqBbv1Pa6ALcp5AIDyfYMH_Bix4,162
|
|
47
|
+
pytgcalls/methods/utilities/idle.py,sha256=MDdzHTv1ws2yBhsvhBUnssGdghkZ2KwR0HUCPOwV38o,814
|
|
48
|
+
pytgcalls/methods/utilities/join_presentation.py,sha256=gvxmFVzf6xsQZ4bPOz5wK8oZ0up1QD0DB2HpO5JcpGw,1671
|
|
49
|
+
pytgcalls/methods/utilities/log_retries.py,sha256=6nD9J3350t82I0PKzK1pVx3ZaCBHATReiXYMs3PuVhQ,342
|
|
50
|
+
pytgcalls/methods/utilities/ping.py,sha256=hhIMSHk2BzMB-IKpwLdZFVrsEvGm2ftJwKLs1k4anh8,244
|
|
51
|
+
pytgcalls/methods/utilities/resolve_chat_id.py,sha256=92x2LHbUlnJMm-kS3fXOYmzYpY2TZbqtQD2rw3eBXDY,382
|
|
52
|
+
pytgcalls/methods/utilities/run.py,sha256=cnYQd2xB5Cr_WS0Q2cXJZPGiN6JOCULzj1r4xXVyrlg,152
|
|
53
|
+
pytgcalls/methods/utilities/start.py,sha256=Qc-uP9B6fgHtNOfjKJfgtYnWTY8JeIb6PSLmWPFXLOk,14376
|
|
54
|
+
pytgcalls/methods/utilities/stream_params.py,sha256=fOSloo1A7WTxaZEtOiPXjdexMeoJjq8CZtfHuIFX7Ns,3325
|
|
55
|
+
pytgcalls/methods/utilities/update_sources.py,sha256=ISF6u3rk4IcVrPOEOB-uZUDfnwUp2_y1_2g9GboXpWM,1562
|
|
56
|
+
pytgcalls/mtproto/__init__.py,sha256=X4zvzFG7km7qHyE0fdvA550WcOVO_xl_p__gvIfDGmw,130
|
|
57
|
+
pytgcalls/mtproto/bridged_client.py,sha256=hktnfpfBK7PEL2n7Y0kBZzI7dkLlsdrDwkYliZki8zQ,5915
|
|
58
|
+
pytgcalls/mtproto/client_cache.py,sha256=Mt0827e_T8DXJHOTkXhkIQUT9EUBWjoLcFcXP1gBnZY,5973
|
|
59
|
+
pytgcalls/mtproto/hydrogram_client.py,sha256=SbyLIffnexzI6xuSkpqzChT70xGXwti_c5sjKUZFqwQ,23031
|
|
60
|
+
pytgcalls/mtproto/mtproto_client.py,sha256=1C1Cc1GOrKom-70NqUOICKxjfjgpPZBSdKdwFUjZzBc,7616
|
|
61
|
+
pytgcalls/mtproto/pyrogram_client.py,sha256=GFt_2QoSEuRaIkUziZOnpBj8zEPiDGs55IriHU0jXwI,23213
|
|
62
|
+
pytgcalls/mtproto/telethon_client.py,sha256=L91_Zxud-pvtJy36fBi6daowNV2qPZHUEp5dcsu031I,22451
|
|
63
|
+
pytgcalls/types/__init__.py,sha256=iXAzXG5WgbICLQV1JT_F4QtOqKWC8X3334-MOv2SXW4,1127
|
|
64
|
+
pytgcalls/types/browsers.py,sha256=47Kr5q96n4Q4WvVhA6IUlS2egEcA9GRLlDeFcQYyc9M,9545
|
|
65
|
+
pytgcalls/types/cache.py,sha256=FfsOcmYnsBGPlJoTPIXXYcUSpGE3rhx6cjIH77hyUL0,1059
|
|
66
|
+
pytgcalls/types/dict.py,sha256=lAo9hu4VlVJa9S7P8Y81BYmKtvz0rH7hwpGcH3ynHUw,78
|
|
67
|
+
pytgcalls/types/flag.py,sha256=dQPcQmTgTQzcOLTvGe8t_e9mY4qsVnCZFrrTk17b2Xw,132
|
|
68
|
+
pytgcalls/types/list.py,sha256=UjP_XxxMpPkLlu6yEy29JYqOM5VITFwwJcDm0wZni1c,78
|
|
69
|
+
pytgcalls/types/participant_list.py,sha256=LmGjU63MK1v3SS2_4xNbk04OOjmukNdAXYLRn2L-730,916
|
|
70
|
+
pytgcalls/types/py_object.py,sha256=__GNXgffGK4jhdF4QPqIknd0k2myObJf_7fW3pNGpbU,836
|
|
71
|
+
pytgcalls/types/update.py,sha256=wPCzWLhrsScZ3ksRTyt8IuDaaG5YI-ItG_Yw-OqzK2Y,157
|
|
72
|
+
pytgcalls/types/user_agent.py,sha256=sSfeGqUe0v0wqBgdVszNFK0iOC_0Tdyto9CglBXlY4U,1086
|
|
73
|
+
pytgcalls/types/calls/__init__.py,sha256=f0zMKm_mwvNsDRPgs8IopuCEefU3V0-kuHAFsTMBoAc,403
|
|
74
|
+
pytgcalls/types/calls/call.py,sha256=n7LW7FRNT2qJzbYC3D312judOlVUuocQ1eW9l9scGCo,546
|
|
75
|
+
pytgcalls/types/calls/call_config.py,sha256=b6P43YTGF2t7E2CyD1mSYPJDUBvYYeHoxB3hSbTVyOY,120
|
|
76
|
+
pytgcalls/types/calls/call_data.py,sha256=-qPj2QhWv32Xs7LyFQY4hiWDqJ21B8VBvdzREK8bDvY,544
|
|
77
|
+
pytgcalls/types/calls/call_protocol.py,sha256=OVIQs1VgdY-DWbZbNr41hjLA4pGQvHx8Rgom1_NhJxQ,408
|
|
78
|
+
pytgcalls/types/calls/call_sources.py,sha256=sBhumPgEaN8uAKjBwb1Zf_Ag0qrceti2mURXqMhBusg,107
|
|
79
|
+
pytgcalls/types/calls/group_call_config.py,sha256=auKH-hZJWj8PhTkyeQ_VK2z9NpNvNC7Scl_IhEUMnQM,353
|
|
80
|
+
pytgcalls/types/calls/raw_call_update.py,sha256=hpNw6HrTW8Z36Lh2HinS-wzprryRtsIxyIFbIfjGgeI,795
|
|
81
|
+
pytgcalls/types/chats/__init__.py,sha256=v8pUp_vbr2kQpyHtAQc80N-YqzmXHe9SbllUsa6njkU,261
|
|
82
|
+
pytgcalls/types/chats/chat_update.py,sha256=wh8v2I-pZxJWGNBjIwWRbhY-ZCI4v8qGabDTpuJaHu0,619
|
|
83
|
+
pytgcalls/types/chats/group_call_participant.py,sha256=XG4dekFV9GYHASqy_bSE6YnZ1uDunFFif-xLAy_eYGY,1711
|
|
84
|
+
pytgcalls/types/chats/updated_group_call_participant.py,sha256=-KID-z-4e43fhYWQp0pNMKPfmZizbJHXyzn6yLtIGNg,291
|
|
85
|
+
pytgcalls/types/raw/__init__.py,sha256=ROHsKFeUMUtlFbx2rhfrdB-TuVm0zBuvNo29Ccn5614,308
|
|
86
|
+
pytgcalls/types/raw/audio_parameters.py,sha256=1DsBPwdn_Ukd2Tbkb3whP_ILo9xJY_3XNNmbO4_NO9Q,449
|
|
87
|
+
pytgcalls/types/raw/audio_stream.py,sha256=oN7Sx9oLbNFuNXiGYpoNabMwqWKGquLiHEywef28o7c,488
|
|
88
|
+
pytgcalls/types/raw/stream.py,sha256=xJ3w77ofKFnLIA4cAWIuw2yREpMPvTzIvtei-3xEbJQ,666
|
|
89
|
+
pytgcalls/types/raw/video_parameters.py,sha256=nUl9gkfYTVU0iLNGTtlZ5cZg8K6F7odIi9n8POJXCK4,639
|
|
90
|
+
pytgcalls/types/raw/video_stream.py,sha256=uE3jU9kJsrAoefXtDtEKNqTjcYGaQbZ1gbJ1SfiVWIc,488
|
|
91
|
+
pytgcalls/types/stream/__init__.py,sha256=4CfgKXoEZX8BvV_ImBlY108MvRELNCf_-CPAMJ9szgk,561
|
|
92
|
+
pytgcalls/types/stream/audio_quality.py,sha256=4X94ErmTeLP4TVcE3eLtPPdtluSPxgxbgTosuNJOVhc,141
|
|
93
|
+
pytgcalls/types/stream/device.py,sha256=EdoDg6lPE7fgoZI04Nr0E9zbIk-iRIBgYYAzVqoCBPM,961
|
|
94
|
+
pytgcalls/types/stream/direction.py,sha256=VepLMe-dXg4M5eVdVyIb2uxYvnpB9OJL5fEgPYUFtTI,592
|
|
95
|
+
pytgcalls/types/stream/external_media.py,sha256=RiuSX5tZGdNsQZ8LIRk5Lp4Ksv9oTvaccmInJRZYo4M,114
|
|
96
|
+
pytgcalls/types/stream/frame.py,sha256=TXo5HZVHbbaVNBqulMhTqGODXH3bpBVlN_of1rosNUQ,586
|
|
97
|
+
pytgcalls/types/stream/media_stream.py,sha256=_NJFTAIUdYyTh-gjiqs6aCpAIfSVjE16mBYUapMnDfg,11917
|
|
98
|
+
pytgcalls/types/stream/record_stream.py,sha256=RWeD9U-sqUmb_PuZQxYnExZyoibepU_8oI2yrH2Y18c,3135
|
|
99
|
+
pytgcalls/types/stream/stream_ended.py,sha256=xR_kZwFf03hA6rw_nvI7Be7GwoCKzQf_1MKaGpPDXqY,716
|
|
100
|
+
pytgcalls/types/stream/stream_frames.py,sha256=028ZhNV-mN3BGqMlmxusAV1xDQpXRYCeM0WXBZhRUhA,446
|
|
101
|
+
pytgcalls/types/stream/video_quality.py,sha256=HBfWq005kh-D19MaVE9VzVdnODzrXf4IJUimCfslfiU,231
|
|
102
|
+
py_tgcalls-2.1.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
|
|
103
|
+
py_tgcalls-2.1.0.dist-info/METADATA,sha256=WKf9Cm8Eyr7cdLT-44TOKK1ytzdlQ0E_682IQBjNGzM,14325
|
|
104
|
+
py_tgcalls-2.1.0.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
105
|
+
py_tgcalls-2.1.0.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
|
|
106
|
+
py_tgcalls-2.1.0.dist-info/RECORD,,
|
pytgcalls/__init__.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .__version__ import __version__
|
|
2
2
|
from .custom_api import CustomApi
|
|
3
|
+
from .media_devices import MediaDevices
|
|
3
4
|
from .pytgcalls import PyTgCalls
|
|
4
5
|
from .sync import compose
|
|
5
6
|
from .sync import idle
|
|
@@ -9,5 +10,6 @@ __all__ = (
|
|
|
9
10
|
'compose',
|
|
10
11
|
'CustomApi',
|
|
11
12
|
'PyTgCalls',
|
|
13
|
+
'MediaDevices',
|
|
12
14
|
'idle',
|
|
13
15
|
)
|
pytgcalls/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '2.0
|
|
1
|
+
__version__ = '2.1.0'
|
pytgcalls/exceptions.py
CHANGED
|
@@ -37,13 +37,6 @@ class TooOldHydrogramVersion(Exception):
|
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
class InvalidStreamMode(Exception):
|
|
41
|
-
def __init__(self):
|
|
42
|
-
super().__init__(
|
|
43
|
-
'Invalid stream mode',
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
40
|
class NoMTProtoClientSet(Exception):
|
|
48
41
|
def __init__(self):
|
|
49
42
|
super().__init__(
|
|
@@ -86,13 +79,6 @@ class NotInCallError(Exception):
|
|
|
86
79
|
)
|
|
87
80
|
|
|
88
81
|
|
|
89
|
-
class AlreadyJoinedError(Exception):
|
|
90
|
-
def __init__(self):
|
|
91
|
-
super().__init__(
|
|
92
|
-
'Already joined into group call',
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
|
|
96
82
|
class ClientNotStarted(Exception):
|
|
97
83
|
def __init__(self):
|
|
98
84
|
super().__init__(
|
|
@@ -115,16 +101,6 @@ class TooManyCustomApiDecorators(Exception):
|
|
|
115
101
|
)
|
|
116
102
|
|
|
117
103
|
|
|
118
|
-
class GroupCallNotFound(Exception):
|
|
119
|
-
def __init__(
|
|
120
|
-
self,
|
|
121
|
-
chat_id: int,
|
|
122
|
-
):
|
|
123
|
-
super().__init__(
|
|
124
|
-
f'Group call not found with the chat id {chat_id}',
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
|
|
128
104
|
class InvalidMTProtoClient(Exception):
|
|
129
105
|
def __init__(self):
|
|
130
106
|
super().__init__(
|
|
@@ -186,3 +162,10 @@ class MTProtoClientNotConnected(Exception):
|
|
|
186
162
|
super().__init__(
|
|
187
163
|
'MTProto client not connected',
|
|
188
164
|
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class UnsupportedMethod(Exception):
|
|
168
|
+
def __init__(self):
|
|
169
|
+
super().__init__(
|
|
170
|
+
'Unsupported method for this kind of call',
|
|
171
|
+
)
|
pytgcalls/ffmpeg.py
CHANGED
|
@@ -74,7 +74,7 @@ async def check_stream(
|
|
|
74
74
|
codec_name = stream.get('codec_name', '')
|
|
75
75
|
image_codecs = ['png', 'jpeg', 'jpg', 'mjpeg']
|
|
76
76
|
if codec_type == 'video':
|
|
77
|
-
is_image
|
|
77
|
+
is_image &= codec_name in image_codecs
|
|
78
78
|
have_video = True
|
|
79
79
|
original_width = int(stream.get('width', 0))
|
|
80
80
|
original_height = int(stream.get('height', 0))
|
|
@@ -270,7 +270,7 @@ def _extract_stream_params(command: List[str]):
|
|
|
270
270
|
def _build_ffmpeg_options(
|
|
271
271
|
stream_parameters: Union[AudioParameters, VideoParameters],
|
|
272
272
|
) -> List[str]:
|
|
273
|
-
log_level = logging.getLogger().level
|
|
273
|
+
log_level = logging.getLogger('ffmpeg').level
|
|
274
274
|
ffmpeg_level = 'info' if log_level == logging.DEBUG else 'quiet'
|
|
275
275
|
|
|
276
276
|
options = ['-v', ffmpeg_level, '-f']
|
pytgcalls/filters.py
CHANGED
|
@@ -7,9 +7,11 @@ from typing import Union
|
|
|
7
7
|
from .mtproto import BridgedClient
|
|
8
8
|
from .pytgcalls import PyTgCalls
|
|
9
9
|
from .types import ChatUpdate
|
|
10
|
+
from .types import Device
|
|
11
|
+
from .types import Direction
|
|
10
12
|
from .types import GroupCallParticipant
|
|
11
|
-
from .types import
|
|
12
|
-
from .types import
|
|
13
|
+
from .types import StreamEnded
|
|
14
|
+
from .types import StreamFrames
|
|
13
15
|
from .types import Update
|
|
14
16
|
from .types import UpdatedGroupCallParticipant
|
|
15
17
|
|
|
@@ -135,11 +137,27 @@ async def _me_filter(_, client: PyTgCalls, u: Update):
|
|
|
135
137
|
me = create(_me_filter)
|
|
136
138
|
|
|
137
139
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
# noinspection PyPep8Naming
|
|
141
|
+
class stream_end(Filter):
|
|
142
|
+
def __init__(
|
|
143
|
+
self,
|
|
144
|
+
stream_type: Optional[StreamEnded.Type] = None,
|
|
145
|
+
device: Optional[Device] = None,
|
|
146
|
+
):
|
|
147
|
+
self.stream_type = stream_type
|
|
148
|
+
self.device = device
|
|
141
149
|
|
|
142
|
-
|
|
150
|
+
async def __call__(self, client: PyTgCalls, update: Update):
|
|
151
|
+
if isinstance(update, StreamEnded):
|
|
152
|
+
return (
|
|
153
|
+
(
|
|
154
|
+
self.stream_type is None or
|
|
155
|
+
self.stream_type & update.stream_type
|
|
156
|
+
) and (
|
|
157
|
+
self.device is None or
|
|
158
|
+
self.device & update.device
|
|
159
|
+
)
|
|
160
|
+
)
|
|
143
161
|
|
|
144
162
|
|
|
145
163
|
# noinspection PyPep8Naming
|
|
@@ -170,6 +188,7 @@ class chat_update(Filter):
|
|
|
170
188
|
return False
|
|
171
189
|
|
|
172
190
|
|
|
191
|
+
# noinspection PyPep8Naming
|
|
173
192
|
class call_participant(Filter):
|
|
174
193
|
def __init__(self, flags: Optional[GroupCallParticipant.Action] = None):
|
|
175
194
|
self.flags = flags
|
|
@@ -180,3 +199,27 @@ class call_participant(Filter):
|
|
|
180
199
|
return True
|
|
181
200
|
return self.flags & update.participant.action
|
|
182
201
|
return False
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# noinspection PyPep8Naming
|
|
205
|
+
class stream_frame(Filter):
|
|
206
|
+
def __init__(
|
|
207
|
+
self,
|
|
208
|
+
directions: Optional[Direction] = None,
|
|
209
|
+
devices: Optional[Device] = None,
|
|
210
|
+
):
|
|
211
|
+
self.directions = directions
|
|
212
|
+
self.devices = devices
|
|
213
|
+
|
|
214
|
+
async def __call__(self, client: PyTgCalls, update: Update):
|
|
215
|
+
if isinstance(update, StreamFrames):
|
|
216
|
+
return (
|
|
217
|
+
(
|
|
218
|
+
self.directions is None or
|
|
219
|
+
self.directions & update.direction
|
|
220
|
+
) and (
|
|
221
|
+
self.devices is None or
|
|
222
|
+
self.devices & update.device
|
|
223
|
+
)
|
|
224
|
+
)
|
|
225
|
+
return False
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
from .device_info import DeviceInfo
|
|
2
|
+
from .input_device import InputDevice
|
|
2
3
|
from .media_devices import MediaDevices
|
|
3
|
-
from .
|
|
4
|
+
from .screen_device import ScreenDevice
|
|
5
|
+
from .speaker_device import SpeakerDevice
|
|
4
6
|
|
|
5
7
|
__all__ = (
|
|
6
8
|
'DeviceInfo',
|
|
9
|
+
'InputDevice',
|
|
7
10
|
'MediaDevices',
|
|
8
|
-
'
|
|
11
|
+
'ScreenDevice',
|
|
12
|
+
'SpeakerDevice',
|
|
9
13
|
)
|
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
from sys import platform
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
class DeviceInfo:
|
|
5
2
|
def __init__(
|
|
6
3
|
self,
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
name: str,
|
|
5
|
+
metadata: str,
|
|
6
|
+
is_video: bool,
|
|
9
7
|
):
|
|
10
|
-
self.
|
|
11
|
-
self.
|
|
12
|
-
self.
|
|
8
|
+
self.title = name
|
|
9
|
+
self.metadata = metadata
|
|
10
|
+
self.is_video = is_video
|
|
13
11
|
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
self.ffmpeg_parameters += ['dshow']
|
|
17
|
-
return f'audio={self.identifier}'
|
|
18
|
-
else:
|
|
19
|
-
self.ffmpeg_parameters += ['pulse']
|
|
20
|
-
return self.identifier
|
|
12
|
+
def __repr__(self):
|
|
13
|
+
return self.title
|
|
@@ -1,101 +1,50 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import subprocess
|
|
4
|
-
from sys import platform
|
|
5
|
-
|
|
6
|
-
from screeninfo import get_monitors
|
|
7
|
-
from screeninfo import ScreenInfoError
|
|
1
|
+
from ntgcalls import DeviceInfo as RawDeviceInfo
|
|
2
|
+
from ntgcalls import NTgCalls
|
|
8
3
|
|
|
9
4
|
from ..types.list import List
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
5
|
+
from .input_device import InputDevice
|
|
6
|
+
from .screen_device import ScreenDevice
|
|
7
|
+
from .speaker_device import SpeakerDevice
|
|
12
8
|
|
|
13
9
|
|
|
14
10
|
class MediaDevices:
|
|
15
11
|
@staticmethod
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
12
|
+
def _parse_devices(devices: list[RawDeviceInfo], is_video: bool) -> List:
|
|
13
|
+
return List(
|
|
14
|
+
InputDevice(device.name, device.metadata, is_video)
|
|
15
|
+
for device in devices
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def microphone_devices() -> List:
|
|
20
|
+
return MediaDevices._parse_devices(
|
|
21
|
+
NTgCalls.get_media_devices().microphone,
|
|
22
|
+
False,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def speaker_devices() -> List:
|
|
27
|
+
return List(
|
|
28
|
+
SpeakerDevice(
|
|
29
|
+
device.name,
|
|
30
|
+
device.metadata,
|
|
31
|
+
)
|
|
32
|
+
for device in NTgCalls.get_media_devices().speaker
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def camera_devices() -> List:
|
|
37
|
+
return MediaDevices._parse_devices(
|
|
38
|
+
NTgCalls.get_media_devices().camera,
|
|
39
|
+
True,
|
|
40
|
+
)
|
|
34
41
|
|
|
35
42
|
@staticmethod
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if platform == 'win32':
|
|
42
|
-
commands = [
|
|
43
|
-
'ffmpeg',
|
|
44
|
-
'-list_devices',
|
|
45
|
-
'true',
|
|
46
|
-
'-f',
|
|
47
|
-
'dshow',
|
|
48
|
-
'-i',
|
|
49
|
-
'dummy',
|
|
50
|
-
]
|
|
51
|
-
else:
|
|
52
|
-
commands = [
|
|
53
|
-
'pactl',
|
|
54
|
-
'list',
|
|
55
|
-
'sources',
|
|
56
|
-
]
|
|
57
|
-
ffmpeg = await asyncio.create_subprocess_exec(
|
|
58
|
-
*tuple(commands),
|
|
59
|
-
stdout=asyncio.subprocess.PIPE,
|
|
60
|
-
stderr=asyncio.subprocess.PIPE,
|
|
43
|
+
def screen_devices() -> List:
|
|
44
|
+
return List(
|
|
45
|
+
ScreenDevice(
|
|
46
|
+
device.name,
|
|
47
|
+
device.metadata,
|
|
61
48
|
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
ffmpeg.communicate(),
|
|
65
|
-
timeout=3,
|
|
66
|
-
)
|
|
67
|
-
result: str = ''
|
|
68
|
-
if platform == 'win32':
|
|
69
|
-
result = stderr.decode('utf-8')
|
|
70
|
-
elif platform != 'darwin':
|
|
71
|
-
result = stdout.decode('utf-8')
|
|
72
|
-
except subprocess.TimeoutExpired:
|
|
73
|
-
return list_devices
|
|
74
|
-
if platform == 'win32':
|
|
75
|
-
list_raw = result.split('DirectShow audio devices')
|
|
76
|
-
if len(list_raw) < 2:
|
|
77
|
-
return list_devices
|
|
78
|
-
output = re.findall(
|
|
79
|
-
'\\[.*?].*?"(.*?)".*?\n\\[.*?].*?"(.*?)"', list_raw[1],
|
|
80
|
-
)
|
|
81
|
-
for device in output:
|
|
82
|
-
list_devices.append(
|
|
83
|
-
DeviceInfo(
|
|
84
|
-
device[1],
|
|
85
|
-
device[0],
|
|
86
|
-
),
|
|
87
|
-
)
|
|
88
|
-
else:
|
|
89
|
-
output = re.findall(
|
|
90
|
-
'Name: (.*?)\n.*?Description: (.*?)\n', result,
|
|
91
|
-
)
|
|
92
|
-
for device in output:
|
|
93
|
-
list_devices.append(
|
|
94
|
-
DeviceInfo(
|
|
95
|
-
device[0],
|
|
96
|
-
device[1],
|
|
97
|
-
),
|
|
98
|
-
)
|
|
99
|
-
except FileNotFoundError:
|
|
100
|
-
pass
|
|
101
|
-
return list_devices
|
|
49
|
+
for device in NTgCalls.get_media_devices().screen
|
|
50
|
+
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Union
|
|
2
2
|
|
|
3
3
|
from ...exceptions import NoActiveGroupCall
|
|
4
|
+
from ...exceptions import UnsupportedMethod
|
|
4
5
|
from ...mtproto_required import mtproto_required
|
|
5
6
|
from ...scaffold import Scaffold
|
|
6
7
|
from ...statictypes import statictypes
|
|
@@ -15,6 +16,8 @@ class ChangeVolumeCall(Scaffold):
|
|
|
15
16
|
volume: int,
|
|
16
17
|
):
|
|
17
18
|
chat_id = await self.resolve_chat_id(chat_id)
|
|
19
|
+
if chat_id >= 0: # type: ignore
|
|
20
|
+
raise UnsupportedMethod()
|
|
18
21
|
chat_call = await self._app.get_full_chat(
|
|
19
22
|
chat_id,
|
|
20
23
|
)
|
|
@@ -2,6 +2,7 @@ from typing import List
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
from typing import Union
|
|
4
4
|
|
|
5
|
+
from ...exceptions import UnsupportedMethod
|
|
5
6
|
from ...mtproto_required import mtproto_required
|
|
6
7
|
from ...scaffold import Scaffold
|
|
7
8
|
from ...statictypes import statictypes
|
|
@@ -15,6 +16,9 @@ class GetParticipants(Scaffold):
|
|
|
15
16
|
self,
|
|
16
17
|
chat_id: Union[int, str],
|
|
17
18
|
) -> Optional[List[GroupCallParticipant]]:
|
|
19
|
+
chat_id = await self.resolve_chat_id(chat_id)
|
|
20
|
+
if chat_id >= 0: # type: ignore
|
|
21
|
+
raise UnsupportedMethod()
|
|
18
22
|
return await self._app.get_group_call_participants(
|
|
19
|
-
|
|
23
|
+
chat_id,
|
|
20
24
|
)
|
|
@@ -40,9 +40,11 @@ class LeaveCall(Scaffold):
|
|
|
40
40
|
chat_id,
|
|
41
41
|
)
|
|
42
42
|
else:
|
|
43
|
-
await self._app.discard_call(chat_id)
|
|
43
|
+
await self._app.discard_call(chat_id, False)
|
|
44
44
|
if is_p2p_waiting:
|
|
45
45
|
self._p2p_configs.pop(chat_id)
|
|
46
46
|
return
|
|
47
47
|
if chat_id < 0: # type: ignore
|
|
48
48
|
self._need_unmute.discard(chat_id)
|
|
49
|
+
self._presentations.discard(chat_id)
|
|
50
|
+
self._call_sources.pop(chat_id, None)
|