py-tgcalls 2.1.2b3__py3-none-any.whl → 2.2.0rc1__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.1.2b3
3
+ Version: 2.2.0rc1
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<1.4.0,>=1.3.5b5
23
+ Requires-Dist: ntgcalls<3.0.0,>=2.0.0rc1
24
24
  Requires-Dist: deprecation
25
25
  Provides-Extra: pyrogram
26
26
  Requires-Dist: pyrogram>=1.2.20; extra == "pyrogram"
@@ -1,12 +1,13 @@
1
- py_tgcalls-2.1.2b3.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
1
+ py_tgcalls-2.2.0rc1.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
2
2
  pytgcalls/__init__.py,sha256=qbfwN7rYwIdCegMOzdcbvwazeNjDzgmowgcqLFNqKIM,308
3
- pytgcalls/__version__.py,sha256=jIltsC16890jgPh8YRlK5nMNGzaAe5P19p3v0qdpUyM,24
3
+ pytgcalls/__version__.py,sha256=jo4muqb6qG7eUqrTQ9ReKjcC5myNMlrB6VPZVMqXPWE,25
4
4
  pytgcalls/environment.py,sha256=ctCHACvG6l8SdpPewSBhOvc70kbwpv18maC0TwLvZ08,1924
5
- pytgcalls/exceptions.py,sha256=yezms8JiO7aGEkUrvTkR9QHhXtVOIXmm1Q4nQbx9tm0,3958
6
- pytgcalls/ffmpeg.py,sha256=tm6DBxyNfPh3h3an-b2s9x1UyX-cvkCdov9prlXxVZY,8649
5
+ pytgcalls/exceptions.py,sha256=Rijc-8T93WEWJxNW9jncU8_M6mYZZZcs8F2bqitEIeI,3787
6
+ pytgcalls/ffmpeg.py,sha256=CZvSyuztc-TGKbKI9_2G7CLITe1ITf315YPyprWu_Pg,8645
7
7
  pytgcalls/filters.py,sha256=qTFDlt-23xnMh_Ug2WmmOUf13JPX6_yacrv7c3F9Pp0,6125
8
+ pytgcalls/list_to_cmd.py,sha256=rGJLsejbAQdDb8pctMbLnwea5NkitlfVKc3IpoGi4V4,240
8
9
  pytgcalls/mtproto_required.py,sha256=6B-31p5qH_6oekUgypV4nK3hqPS6Nr-pA8S81wjnbaY,630
9
- pytgcalls/mutex.py,sha256=6hOwGnUTNUJliJ1GGhk47D0A3KEn8eVd-kjZq_1DdZY,670
10
+ pytgcalls/mutex.py,sha256=vWqji9IAHtAc61FUTVXncx5rZ3rVf5qG_7PI4LmuYmU,733
10
11
  pytgcalls/pytgcalls.py,sha256=DxCE0--mb53vyDXLLBAwy1cPrJgLsyC9rba_h2OzR2o,1608
11
12
  pytgcalls/pytgcalls_session.py,sha256=_BGJWvf7t3mki2DhlEPjh9cypvYuSFkMSxzTsfepwUk,2719
12
13
  pytgcalls/scaffold.py,sha256=Gahln5l70FJZwo1KGqv1A7K9Vn_ozAATpADGFJuPhKA,3162
@@ -14,7 +15,7 @@ pytgcalls/statictypes.py,sha256=CdlqgQNhTZ_uTE8-B8m01fJ7TlD2B42EI2QBPxDdAtA,3842
14
15
  pytgcalls/sync.py,sha256=IsOH3TD7cxUg_-zdGt12HoS8sBlXvcGayPZAoxxKM48,3396
15
16
  pytgcalls/version_manager.py,sha256=egeGgvb66zWlLTMuw2U-b0x8MfnRzMm1xAEVN87HF5c,296
16
17
  pytgcalls/wait_counter_lock.py,sha256=J-KCWUBCt7ktKQKyIseNG0RfXDVRh-h0wKhaZlf4aFs,437
17
- pytgcalls/ytdlp.py,sha256=jRA-mKQEXleWvaoGv9wtMa77aRjxsyQxn6_0tXI3-sA,2435
18
+ pytgcalls/ytdlp.py,sha256=MEPkVlFdbexbgqVRMt7C1YadPIER2R-4oN03osl5vq8,2473
18
19
  pytgcalls/custom_api/__init__.py,sha256=ZT8d0lc2YrDuw_YSFAXXHHMewoXGFZ-ANOBIAr0vGFQ,60
19
20
  pytgcalls/custom_api/custom_api.py,sha256=Ko3aS6psrwPmOhRPxvG0fepXt4STrA0StvINSxz4Cj8,1890
20
21
  pytgcalls/handlers/__init__.py,sha256=pubbxI4pLqQpAKf8-toD6ija4cpSvbCJOQFjTiDjX1E,75
@@ -35,7 +36,7 @@ pytgcalls/methods/decorators/on_update.py,sha256=ZTL4YcQk0N4Ru56a5WItUvkSN5SAqr6
35
36
  pytgcalls/methods/internal/__init__.py,sha256=fcgIxUJKT6QJD30ltnOfzKsLhzTTTklD2qxKlwCvyv0,1057
36
37
  pytgcalls/methods/internal/clear_cache.py,sha256=qgG-oubmdtnefnXSiHSPHyBTyXypiLDC7G8l3FzjNw8,236
37
38
  pytgcalls/methods/internal/clear_call.py,sha256=yElvn3i6_j14Q7n9kcLSl-muYAGcaIZaEFHdp6MrN0g,549
38
- pytgcalls/methods/internal/connect_call.py,sha256=s4R-74sLippqPy1hpQasUaxwiJnZ9GVx6lgcaPqex8M,5900
39
+ pytgcalls/methods/internal/connect_call.py,sha256=Py-sB_ImH839tK9GxNUCJDJUNizsZtlm5m6kuiUX3lE,5739
39
40
  pytgcalls/methods/internal/emit_sig_data.py,sha256=ucIsknhJHB-0x7lcymXvwQ647AJQ852zH2W6MdlC3ws,216
40
41
  pytgcalls/methods/internal/handle_connection_changed.py,sha256=_1u3J6_Pjl1Gs1u_WkhG2FAUl_hxlHUiflaMkKkJDsc,866
41
42
  pytgcalls/methods/internal/handle_mtproto_updates.py,sha256=Ev2Jake6Z_SrBodnjO5N16YiYaEY3Ti4tkU1pKOsJVM,7747
@@ -110,12 +111,12 @@ pytgcalls/types/stream/device.py,sha256=EdoDg6lPE7fgoZI04Nr0E9zbIk-iRIBgYYAzVqoC
110
111
  pytgcalls/types/stream/direction.py,sha256=VepLMe-dXg4M5eVdVyIb2uxYvnpB9OJL5fEgPYUFtTI,592
111
112
  pytgcalls/types/stream/external_media.py,sha256=RiuSX5tZGdNsQZ8LIRk5Lp4Ksv9oTvaccmInJRZYo4M,114
112
113
  pytgcalls/types/stream/frame.py,sha256=TXo5HZVHbbaVNBqulMhTqGODXH3bpBVlN_of1rosNUQ,586
113
- pytgcalls/types/stream/media_stream.py,sha256=_NJFTAIUdYyTh-gjiqs6aCpAIfSVjE16mBYUapMnDfg,11917
114
- pytgcalls/types/stream/record_stream.py,sha256=RWeD9U-sqUmb_PuZQxYnExZyoibepU_8oI2yrH2Y18c,3135
114
+ pytgcalls/types/stream/media_stream.py,sha256=zcRVpNXfL8mhg-SEfAi-f0lDUZMyNYLetophvcAN_gQ,11968
115
+ pytgcalls/types/stream/record_stream.py,sha256=f4VQ6MY8HtOxt7vz0hWBFmbbAIvTRHpAIU2nmj0TF6Y,3197
115
116
  pytgcalls/types/stream/stream_ended.py,sha256=xR_kZwFf03hA6rw_nvI7Be7GwoCKzQf_1MKaGpPDXqY,716
116
117
  pytgcalls/types/stream/stream_frames.py,sha256=028ZhNV-mN3BGqMlmxusAV1xDQpXRYCeM0WXBZhRUhA,446
117
118
  pytgcalls/types/stream/video_quality.py,sha256=HBfWq005kh-D19MaVE9VzVdnODzrXf4IJUimCfslfiU,231
118
- py_tgcalls-2.1.2b3.dist-info/METADATA,sha256=wzJ9y03r_nlZyBHgX4lM7sPk03_7diECvlHeM_gpp6E,5284
119
- py_tgcalls-2.1.2b3.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
120
- py_tgcalls-2.1.2b3.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
121
- py_tgcalls-2.1.2b3.dist-info/RECORD,,
119
+ py_tgcalls-2.2.0rc1.dist-info/METADATA,sha256=GjtrQPZp1x1J9YvVAqpqZ_vJVn8428ncuuyi4FVBW0c,5286
120
+ py_tgcalls-2.2.0rc1.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
121
+ py_tgcalls-2.2.0rc1.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
122
+ py_tgcalls-2.2.0rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.0)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
pytgcalls/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '2.1.2b3'
1
+ __version__ = '2.2.0rc1'
pytgcalls/exceptions.py CHANGED
@@ -169,10 +169,3 @@ class UnsupportedMethod(Exception):
169
169
  super().__init__(
170
170
  'Unsupported method for this kind of call',
171
171
  )
172
-
173
-
174
- class RTMPStreamingUnsupported(Exception):
175
- def __init__(self):
176
- super().__init__(
177
- 'Streaming into an RTMP connection is not supported',
178
- )
pytgcalls/ffmpeg.py CHANGED
@@ -207,12 +207,12 @@ def build_command(
207
207
  if headers is not None:
208
208
  for i in headers:
209
209
  ffmpeg_command.append('-headers')
210
- ffmpeg_command.append(f'"{i}: {headers[i]}"')
210
+ ffmpeg_command.append(f'{i}: {headers[i]}')
211
211
 
212
212
  ffmpeg_command += [
213
213
  '-nostdin',
214
214
  '-i',
215
- f'"{path}"' if name == 'ffmpeg' else path,
215
+ f'{path}' if name == 'ffmpeg' else path,
216
216
  ]
217
217
  ffmpeg_command += command['mid']
218
218
 
@@ -0,0 +1,11 @@
1
+ import platform
2
+ import shlex
3
+ import subprocess
4
+ from typing import List
5
+
6
+
7
+ def list_to_cmd(args: List[str]) -> str:
8
+ if platform.system() == 'Windows':
9
+ return subprocess.list2cmdline(args)
10
+ else:
11
+ return shlex.join(args)
@@ -1,14 +1,13 @@
1
1
  import asyncio
2
- import json
3
2
  from typing import Optional
4
3
  from typing import Union
5
4
 
6
5
  from ntgcalls import ConnectionMode
7
6
  from ntgcalls import ConnectionNotFound
8
7
  from ntgcalls import MediaDescription
8
+ from ntgcalls import StreamMode
9
9
  from ntgcalls import TelegramServerError
10
10
 
11
- from ...exceptions import RTMPStreamingUnsupported
12
11
  from ...exceptions import TimedOutAnswer
13
12
  from ...scaffold import Scaffold
14
13
  from ...types import CallConfig
@@ -33,8 +32,12 @@ class ConnectCall(Scaffold):
33
32
  if not payload:
34
33
  payload = await self._binding.create_call(
35
34
  chat_id,
36
- media_description,
37
35
  )
36
+ await self._binding.set_stream_sources(
37
+ chat_id,
38
+ StreamMode.CAPTURE,
39
+ media_description,
40
+ )
38
41
  result_params = await self._app.join_group_call(
39
42
  chat_id,
40
43
  payload,
@@ -43,15 +46,6 @@ class ConnectCall(Scaffold):
43
46
  media_description.screen is None,
44
47
  self._cache_user_peer.get(chat_id),
45
48
  )
46
- is_rtmp = json.loads(result_params).get('rtmp')
47
- if (
48
- media_description.camera is not None or
49
- media_description.microphone is not None or
50
- media_description.screen is not None or
51
- media_description.speaker is not None
52
- ) and is_rtmp:
53
- raise RTMPStreamingUnsupported()
54
-
55
49
  await self._binding.connect(
56
50
  chat_id,
57
51
  result_params,
@@ -74,6 +68,10 @@ class ConnectCall(Scaffold):
74
68
  )
75
69
  await self._binding.create_p2p_call(
76
70
  chat_id,
71
+ )
72
+ await self._binding.set_stream_sources(
73
+ chat_id,
74
+ StreamMode.CAPTURE,
77
75
  media_description,
78
76
  )
79
77
  data.g_a_or_b = await self._binding.init_exchange(
pytgcalls/mutex.py CHANGED
@@ -7,7 +7,9 @@ def mutex(func):
7
7
  @wraps(func)
8
8
  async def async_wrapper(*args, **kwargs):
9
9
  self = args[0]
10
- chat_id = await self.resolve_chat_id(args[1])
10
+ chat_id = await self.resolve_chat_id(
11
+ args[1] if len(args) > 1 else kwargs['chat_id'],
12
+ )
11
13
  async with self._lock:
12
14
  self._calls_lock[chat_id] = self._calls_lock.get(
13
15
  chat_id,
@@ -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 ...list_to_cmd import list_to_cmd
16
17
  from ...media_devices.input_device import InputDevice
17
18
  from ...media_devices.screen_device import ScreenDevice
18
19
  from ...statictypes import statictypes
@@ -145,7 +146,7 @@ class MediaStream(Stream):
145
146
  if self._is_audio_external else
146
147
  AudioStream(
147
148
  MediaSource.SHELL,
148
- ' '.join(
149
+ list_to_cmd(
149
150
  build_command(
150
151
  'ffmpeg',
151
152
  self._ffmpeg_parameters,
@@ -178,7 +179,7 @@ class MediaStream(Stream):
178
179
  if self._is_video_external else
179
180
  VideoStream(
180
181
  MediaSource.SHELL,
181
- ' '.join(
182
+ list_to_cmd(
182
183
  build_command(
183
184
  'ffmpeg',
184
185
  self._ffmpeg_parameters,
@@ -229,7 +230,7 @@ class MediaStream(Stream):
229
230
  ]
230
231
  except LiveStreamFound:
231
232
  live_stream = True
232
- self.camera.path = ' '.join(
233
+ self.camera.path = list_to_cmd(
233
234
  build_command(
234
235
  'ffmpeg',
235
236
  self._ffmpeg_parameters,
@@ -278,7 +279,7 @@ class MediaStream(Stream):
278
279
  )
279
280
  except LiveStreamFound:
280
281
  live_stream = True
281
- self.microphone.path = ' '.join(
282
+ self.microphone.path = list_to_cmd(
282
283
  build_command(
283
284
  'ffmpeg',
284
285
  self._ffmpeg_parameters,
@@ -3,6 +3,7 @@ from typing import Union
3
3
 
4
4
  from ntgcalls import MediaSource
5
5
 
6
+ from ...list_to_cmd import list_to_cmd
6
7
  from ...media_devices.speaker_device import SpeakerDevice
7
8
  from ...statictypes import statictypes
8
9
  from ..raw.audio_parameters import AudioParameters
@@ -72,7 +73,7 @@ class RecordStream(Stream):
72
73
  ]
73
74
  return AudioStream(
74
75
  media_source=MediaSource.SHELL,
75
- path=' '.join(commands),
76
+ path=list_to_cmd(commands),
76
77
  parameters=raw_audio_parameters,
77
78
  )
78
79
  if isinstance(audio, SpeakerDevice):
@@ -81,6 +82,7 @@ class RecordStream(Stream):
81
82
  path=audio.metadata,
82
83
  parameters=raw_audio_parameters,
83
84
  )
85
+ return None
84
86
 
85
87
  @staticmethod
86
88
  def _get_video_stream(enable):
pytgcalls/ytdlp.py CHANGED
@@ -7,6 +7,7 @@ from typing import Tuple
7
7
 
8
8
  from .exceptions import YtDlpError
9
9
  from .ffmpeg import cleanup_commands
10
+ from .list_to_cmd import list_to_cmd
10
11
  from .types.raw import VideoParameters
11
12
 
12
13
  py_logger = logging.getLogger('pytgcalls')
@@ -37,7 +38,7 @@ class YtDlp:
37
38
  'yt-dlp',
38
39
  '-g',
39
40
  '-f',
40
- 'bestvideo[vcodec~=\'(vp09|avc1)\']+m4a/best',
41
+ 'bestvideo[vcodec~="(vp09|avc1)"]+m4a/best',
41
42
  '-S',
42
43
  'res:'
43
44
  f'{min(video_parameters.width, video_parameters.height)}',
@@ -59,7 +60,7 @@ class YtDlp:
59
60
 
60
61
  py_logger.log(
61
62
  logging.DEBUG,
62
- f'Running with "{" ".join(commands)}" command',
63
+ f'Running with "{list_to_cmd(commands)}" command',
63
64
  )
64
65
  try:
65
66
  proc = await asyncio.create_subprocess_exec(