py-tgcalls 2.0.2__py3-none-any.whl → 2.0.3__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: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: Async client API for the Telegram Calls.
5
5
  Author-email: Laky-64 <iraci.matteo@gmail.com>
6
6
  License: GNU LESSER GENERAL PUBLIC LICENSE
@@ -186,17 +186,17 @@ Classifier: Programming Language :: Python :: 3.12
186
186
  Requires-Python: >=3.8
187
187
  Description-Content-Type: text/markdown
188
188
  License-File: LICENSE
189
- Requires-Dist: aiohttp >=3.9.3
190
- Requires-Dist: ntgcalls >=1.2.0
189
+ Requires-Dist: aiohttp>=3.9.3
190
+ Requires-Dist: ntgcalls>=1.2.2
191
191
  Requires-Dist: psutil
192
192
  Requires-Dist: screeninfo
193
193
  Requires-Dist: deprecation
194
194
  Provides-Extra: hydrogram
195
- Requires-Dist: hydrogram >=0.1.4 ; extra == 'hydrogram'
195
+ Requires-Dist: hydrogram>=0.1.4; extra == "hydrogram"
196
196
  Provides-Extra: pyrogram
197
- Requires-Dist: pyrogram >=1.2.20 ; extra == 'pyrogram'
197
+ Requires-Dist: pyrogram>=1.2.20; extra == "pyrogram"
198
198
  Provides-Extra: telethon
199
- Requires-Dist: telethon >=1.24.0 ; extra == 'telethon'
199
+ Requires-Dist: telethon>=1.24.0; extra == "telethon"
200
200
 
201
201
  <img src="https://raw.githubusercontent.com/pytgcalls/pytgcalls/master/.github/images/banner.png" alt="pytgcalls logo" />
202
202
  <p align="center">
@@ -1,8 +1,8 @@
1
1
  pytgcalls/__init__.py,sha256=TfZGf1enqqs50mBB406vygB6zYgn3vAjBYFUDO4Pviw,248
2
- pytgcalls/__version__.py,sha256=kumiGImhzOTlTrRM-6jDo2mNnVHGO_2vxtrhB0nzAiw,22
2
+ pytgcalls/__version__.py,sha256=fcRMgwI40iVFwre_3iKQA-N6sHUo3pAErXcKJS63DRg,22
3
3
  pytgcalls/environment.py,sha256=ctCHACvG6l8SdpPewSBhOvc70kbwpv18maC0TwLvZ08,1924
4
4
  pytgcalls/exceptions.py,sha256=0MmAktc53ajYAc7ThjD2tJ9PDyibUi0iHZMfUy2IoKs,4109
5
- pytgcalls/ffmpeg.py,sha256=sut7ssGcvprC3NWFpCfyguyNKAXaeM0mv3lXSvDPRpM,8518
5
+ pytgcalls/ffmpeg.py,sha256=uAqFDPwWoABW_WfubxeulpIh5vWpylxFARgYokn3ff8,8640
6
6
  pytgcalls/filters.py,sha256=HFMBBbo_NCw6wqTtseHoDRsspJHQ49BUHBA1cxm7u4g,4852
7
7
  pytgcalls/mtproto_required.py,sha256=6B-31p5qH_6oekUgypV4nK3hqPS6Nr-pA8S81wjnbaY,630
8
8
  pytgcalls/mutex.py,sha256=Frjji5Ctzlk4AXEBuBLnDK-7HbtreoV6zuyKpFpMNI4,236
@@ -12,11 +12,11 @@ pytgcalls/scaffold.py,sha256=LihXRBl1kSqJSQvEoH5rAXJXrbnnIqSMBYrhXpW5hHs,958
12
12
  pytgcalls/statictypes.py,sha256=CdlqgQNhTZ_uTE8-B8m01fJ7TlD2B42EI2QBPxDdAtA,3842
13
13
  pytgcalls/sync.py,sha256=IsOH3TD7cxUg_-zdGt12HoS8sBlXvcGayPZAoxxKM48,3396
14
14
  pytgcalls/version_manager.py,sha256=egeGgvb66zWlLTMuw2U-b0x8MfnRzMm1xAEVN87HF5c,296
15
- pytgcalls/ytdlp.py,sha256=VqeWts_jgPJTmcOM5_rckuKEOA0N2FujaBWvX3CyXE0,2196
15
+ pytgcalls/ytdlp.py,sha256=jRA-mKQEXleWvaoGv9wtMa77aRjxsyQxn6_0tXI3-sA,2435
16
16
  pytgcalls/custom_api/__init__.py,sha256=ZT8d0lc2YrDuw_YSFAXXHHMewoXGFZ-ANOBIAr0vGFQ,60
17
17
  pytgcalls/custom_api/custom_api.py,sha256=Ko3aS6psrwPmOhRPxvG0fepXt4STrA0StvINSxz4Cj8,1890
18
18
  pytgcalls/handlers/__init__.py,sha256=pubbxI4pLqQpAKf8-toD6ija4cpSvbCJOQFjTiDjX1E,75
19
- pytgcalls/handlers/handlers_holder.py,sha256=eDCRF6-zPSUmBb8ZuAPiJfgDvg2Qv6efdX6GlOXHxTA,1033
19
+ pytgcalls/handlers/handlers_holder.py,sha256=ve83ydtKM5BjhsQmQ3mridD-3RnSVEi05-oDeiWv28w,1176
20
20
  pytgcalls/media_devices/__init__.py,sha256=H6uUA6akUqp8WCiT2gLrqUtFdqpd9rcfqDviP5Vhrls,183
21
21
  pytgcalls/media_devices/device_info.py,sha256=KueJCRVXXDcxQJzoGfkzcD2kL58pkMUn7Fr3aUwnNtQ,489
22
22
  pytgcalls/media_devices/media_devices.py,sha256=KG4fKfubpeMQZVm9IuQmzDaLhsvKzKRdE3zIYRAhEHM,3227
@@ -31,7 +31,7 @@ pytgcalls/methods/decorators/on_update.py,sha256=ZTL4YcQk0N4Ru56a5WItUvkSN5SAqr6
31
31
  pytgcalls/methods/stream/__init__.py,sha256=_4j-CEby4_2Kadva86tFMC4GSSzhBBjKLXfrgTk4gzo,343
32
32
  pytgcalls/methods/stream/mute_stream.py,sha256=auo2aAazfEC90Ab6MzaiPdddiJ1w4fN_9HaORkAeOBY,570
33
33
  pytgcalls/methods/stream/pause_stream.py,sha256=z_AIWABrQMHmTwvlah_PrH9EjXbro8gKxZni4Km5ICg,573
34
- pytgcalls/methods/stream/play.py,sha256=wU4WKEp4cMfJPVDW-aug69HrzXrMJHCKkqrv-pCxQkg,7307
34
+ pytgcalls/methods/stream/play.py,sha256=38eWJSXFYgq7VRm4AH6e1NJfe6nYTyJ71PbK3mFijHs,7280
35
35
  pytgcalls/methods/stream/played_time.py,sha256=IkUdyHrqpzpRl9uf0uZhg1COo4zsHnQOPu3nipjVatI,570
36
36
  pytgcalls/methods/stream/resume_stream.py,sha256=z_DgP4cDExjEqEeX_ZL--50MXQ9lrATK876SIwE71PQ,576
37
37
  pytgcalls/methods/stream/unmute_stream.py,sha256=KUMhfMbhsPmZsmpF4cGWC1FVW7YwXha2MmQnqrBhM8s,576
@@ -49,10 +49,10 @@ pytgcalls/methods/utilities/stream_params.py,sha256=hYcNxx__McmPeHgOUDEuNcN7ThgD
49
49
  pytgcalls/mtproto/__init__.py,sha256=X4zvzFG7km7qHyE0fdvA550WcOVO_xl_p__gvIfDGmw,130
50
50
  pytgcalls/mtproto/bridged_client.py,sha256=kK22n-CKjtfmtNE6bXCpuL6kWAUK2_Ul7cGgx_HNuHQ,4975
51
51
  pytgcalls/mtproto/client_cache.py,sha256=1yA5CFAmWZUsWdpqk5vlaN3j1RV1rIN-X7EcqmsnlfY,5087
52
- pytgcalls/mtproto/hydrogram_client.py,sha256=iSqwvK8yZZCYMmFQOSXpcDwZOFrBGt-3vJUMyxar-Sc,21116
52
+ pytgcalls/mtproto/hydrogram_client.py,sha256=x0s0ZmD_cVT_TtEUIT5qO0OueZg719TkfyraaUWJze0,21290
53
53
  pytgcalls/mtproto/mtproto_client.py,sha256=LO71RqgxZ3bYxSFb6l9cc4ks6_peyqHN4i_z478c7yw,6883
54
- pytgcalls/mtproto/pyrogram_client.py,sha256=iyJMJo6iTULfmGh-jdfJgu8DNVFxzOn28A5_E7uH4-Q,21305
55
- pytgcalls/mtproto/telethon_client.py,sha256=8BkYncXnPUIJRgrhUBnMIlXV2_fm6vLkN8URVaSuow4,20207
54
+ pytgcalls/mtproto/pyrogram_client.py,sha256=oXKEoChpEpt3xS1NuM3rfXbmFcpWgBFyibgqm_Pp6D4,21479
55
+ pytgcalls/mtproto/telethon_client.py,sha256=j2Ybibhg67IL8M2LXBWXIJwpc6dTDMz5_9MRYsOVcuw,20373
56
56
  pytgcalls/types/__init__.py,sha256=yJVJZoH9M9u9VgpZGUX-MF4NzE-vKp4KrId21YQbcGE,910
57
57
  pytgcalls/types/browsers.py,sha256=47Kr5q96n4Q4WvVhA6IUlS2egEcA9GRLlDeFcQYyc9M,9545
58
58
  pytgcalls/types/cache.py,sha256=FfsOcmYnsBGPlJoTPIXXYcUSpGE3rhx6cjIH77hyUL0,1059
@@ -78,16 +78,16 @@ pytgcalls/types/raw/__init__.py,sha256=ROHsKFeUMUtlFbx2rhfrdB-TuVm0zBuvNo29Ccn56
78
78
  pytgcalls/types/raw/audio_parameters.py,sha256=1DsBPwdn_Ukd2Tbkb3whP_ILo9xJY_3XNNmbO4_NO9Q,449
79
79
  pytgcalls/types/raw/audio_stream.py,sha256=wEMa93hHt0VBUSuS6gPJlFIGZp5GdNU94O2C2u4AXnY,476
80
80
  pytgcalls/types/raw/stream.py,sha256=jCvFUSAdHupqMqfG1E36CgKijKoy0o2LUbgcVjj5Mz0,491
81
- pytgcalls/types/raw/video_parameters.py,sha256=LXBpdaw5vyNayVfgtmF-gRkCY_ATwAnunRDs75FQJTw,545
81
+ pytgcalls/types/raw/video_parameters.py,sha256=nUl9gkfYTVU0iLNGTtlZ5cZg8K6F7odIi9n8POJXCK4,639
82
82
  pytgcalls/types/raw/video_stream.py,sha256=2Chrk7NFWF1H9V7hH71RZ5rF3iBhT53syFkHKw4-5gc,433
83
83
  pytgcalls/types/stream/__init__.py,sha256=xfF-9ZulOLk3E6G1nw1Ky0ZRWXlFuER0Uj8HQn3650w,338
84
84
  pytgcalls/types/stream/audio_quality.py,sha256=4X94ErmTeLP4TVcE3eLtPPdtluSPxgxbgTosuNJOVhc,141
85
- pytgcalls/types/stream/media_stream.py,sha256=ZtREk2bjrBRnyKWdJWgxCa8z_NX7Oa02wUITcoI80m8,8860
85
+ pytgcalls/types/stream/media_stream.py,sha256=YoG-vISvDga1n4IHs4hdF03ldtqyojFMvwB3To_39kE,8931
86
86
  pytgcalls/types/stream/stream_audio_ended.py,sha256=2_EFa98F0vWu0d0jBmLtzp4NH_xBkDO_6yP9UtyKuCs,164
87
87
  pytgcalls/types/stream/stream_video_ended.py,sha256=9YFTTZPMDpB95eb815rGtgDrzBGfTeazJ5mZwP6Hvks,164
88
88
  pytgcalls/types/stream/video_quality.py,sha256=HBfWq005kh-D19MaVE9VzVdnODzrXf4IJUimCfslfiU,231
89
- py_tgcalls-2.0.2.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
90
- py_tgcalls-2.0.2.dist-info/METADATA,sha256=0Fmju1o3_K53gft3sMZpLHnaPKlK6c4ioF660I5SYkM,14357
91
- py_tgcalls-2.0.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
92
- py_tgcalls-2.0.2.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
93
- py_tgcalls-2.0.2.dist-info/RECORD,,
89
+ py_tgcalls-2.0.3.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
90
+ py_tgcalls-2.0.3.dist-info/METADATA,sha256=0uu5GSvIXH0bc_1fZt1N8WWlN8Hx_Kmn-v3z2V0hd3w,14349
91
+ py_tgcalls-2.0.3.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
92
+ py_tgcalls-2.0.3.dist-info/top_level.txt,sha256=IUDUwn0KkcbUYZbCe9R5AUb2Ob-lmllNUGQqyeXXd8A,10
93
+ py_tgcalls-2.0.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (74.1.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
pytgcalls/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '2.0.2'
1
+ __version__ = '2.0.3'
pytgcalls/ffmpeg.py CHANGED
@@ -95,7 +95,10 @@ async def check_stream(
95
95
  new_w = min(original_width, stream_parameters.width)
96
96
  new_h = int(new_w / ratio)
97
97
 
98
- if new_h > stream_parameters.height:
98
+ if (
99
+ new_h > stream_parameters.height and
100
+ stream_parameters.adjust_by_height
101
+ ):
99
102
  new_h = stream_parameters.height
100
103
  new_w = int(new_h * ratio)
101
104
 
@@ -282,6 +285,8 @@ def _build_ffmpeg_options(
282
285
  options.extend([
283
286
  'rawvideo',
284
287
  '-r', str(stream_parameters.frame_rate),
288
+ '-pix_fmt',
289
+ 'yuv420p',
285
290
  '-vf',
286
291
  f'scale={stream_parameters.width}:{stream_parameters.height}',
287
292
  ])
@@ -41,3 +41,9 @@ class HandlersHolder:
41
41
  ) -> Callable:
42
42
  self._callbacks.append(Callback(func, filters))
43
43
  return func
44
+
45
+ def remove_handler(
46
+ self,
47
+ func: Callable,
48
+ ):
49
+ self._callbacks = [x for x in self._callbacks if x.func != func]
@@ -52,7 +52,7 @@ class Play(Scaffold):
52
52
  try:
53
53
  return await self._binding.change_stream(
54
54
  chat_id,
55
- await StreamParams.get_stream_params(stream),
55
+ media_description,
56
56
  )
57
57
  except FileError as e:
58
58
  raise FileNotFoundError(e)
@@ -78,7 +78,7 @@ class HydrogramClient(BridgedClient):
78
78
  self,
79
79
  )
80
80
 
81
- @self._app.on_raw_update()
81
+ @self._app.on_raw_update(group=-1)
82
82
  async def on_update(_, update, __, chats):
83
83
  if isinstance(
84
84
  update,
@@ -353,19 +353,24 @@ class HydrogramClient(BridgedClient):
353
353
  self,
354
354
  input_call: InputGroupCall,
355
355
  ) -> List[GroupCallParticipant]:
356
+ participants = []
357
+ next_offset = ''
358
+ while True:
359
+ result = await self._app.invoke(
360
+ GetGroupParticipants(
361
+ call=input_call,
362
+ ids=[],
363
+ sources=[],
364
+ offset=next_offset,
365
+ limit=0,
366
+ ),
367
+ )
368
+ participants.extend(result.participants)
369
+ if not (next_offset := result.next_offset):
370
+ break
356
371
  return [
357
372
  self.parse_participant(participant)
358
- for participant in (
359
- await self._app.invoke(
360
- GetGroupParticipants(
361
- call=input_call,
362
- ids=[],
363
- sources=[],
364
- offset='',
365
- limit=500,
366
- ),
367
- )
368
- ).participants
373
+ for participant in participants
369
374
  ]
370
375
 
371
376
  async def join_group_call(
@@ -86,7 +86,7 @@ class PyrogramClient(BridgedClient):
86
86
  self,
87
87
  )
88
88
 
89
- @self._app.on_raw_update()
89
+ @self._app.on_raw_update(group=-1)
90
90
  async def on_update(_, update, __, chats):
91
91
  if isinstance(
92
92
  update,
@@ -361,19 +361,24 @@ class PyrogramClient(BridgedClient):
361
361
  self,
362
362
  input_call: InputGroupCall,
363
363
  ) -> List[GroupCallParticipant]:
364
+ participants = []
365
+ next_offset = ''
366
+ while True:
367
+ result = await self._app.send(
368
+ GetGroupParticipants(
369
+ call=input_call,
370
+ ids=[],
371
+ sources=[],
372
+ offset=next_offset,
373
+ limit=0,
374
+ ),
375
+ )
376
+ participants.extend(result.participants)
377
+ if not (next_offset := result.next_offset):
378
+ break
364
379
  return [
365
380
  self.parse_participant(participant)
366
- for participant in (
367
- await self._app.send(
368
- GetGroupParticipants(
369
- call=input_call,
370
- ids=[],
371
- sources=[],
372
- offset='',
373
- limit=500,
374
- ),
375
- )
376
- ).participants
381
+ for participant in participants
377
382
  ]
378
383
 
379
384
  async def join_group_call(
@@ -330,19 +330,24 @@ class TelethonClient(BridgedClient):
330
330
  self,
331
331
  input_call: InputGroupCall,
332
332
  ) -> List[GroupCallParticipant]:
333
+ participants = []
334
+ next_offset = ''
335
+ while True:
336
+ result = await self._app(
337
+ GetGroupParticipantsRequest(
338
+ call=input_call,
339
+ ids=[],
340
+ sources=[],
341
+ offset=next_offset,
342
+ limit=0,
343
+ ),
344
+ )
345
+ participants.extend(result.participants)
346
+ if not (next_offset := result.next_offset):
347
+ break
333
348
  return [
334
349
  self.parse_participant(participant)
335
- for participant in (
336
- await self._app(
337
- GetGroupParticipantsRequest(
338
- call=input_call,
339
- ids=[],
340
- sources=[],
341
- offset='',
342
- limit=500,
343
- ),
344
- )
345
- ).participants
350
+ for participant in participants
346
351
  ]
347
352
 
348
353
  async def join_group_call(
@@ -10,6 +10,7 @@ class VideoParameters(PyObject):
10
10
  width: int = 640,
11
11
  height: int = 360,
12
12
  frame_rate: int = 20,
13
+ adjust_by_height: bool = True,
13
14
  ):
14
15
  max_w, max_h, max_fps = max(
15
16
  VideoQuality, key=lambda x: x.value[0],
@@ -17,3 +18,4 @@ class VideoParameters(PyObject):
17
18
  self.width: int = min(width, max_w)
18
19
  self.height: int = min(height, max_h)
19
20
  self.frame_rate: int = min(frame_rate, max_fps)
21
+ self.adjust_by_height: bool = adjust_by_height
@@ -62,7 +62,10 @@ class MediaStream(Stream):
62
62
  if isinstance(video_parameters, VideoParameters):
63
63
  self._video_parameters = video_parameters
64
64
  elif isinstance(video_parameters, VideoQuality):
65
- self._video_parameters = VideoParameters(*video_parameters.value)
65
+ self._video_parameters = VideoParameters(
66
+ *video_parameters.value,
67
+ adjust_by_height=False,
68
+ )
66
69
 
67
70
  self._media_path: Optional[str] = None
68
71
  self._audio_path: Optional[str] = None
pytgcalls/ytdlp.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import logging
2
3
  import re
3
4
  import shlex
4
5
  from typing import Optional
@@ -8,6 +9,8 @@ from .exceptions import YtDlpError
8
9
  from .ffmpeg import cleanup_commands
9
10
  from .types.raw import VideoParameters
10
11
 
12
+ py_logger = logging.getLogger('pytgcalls')
13
+
11
14
 
12
15
  class YtDlp:
13
16
  YOUTUBE_REGX = re.compile(
@@ -34,8 +37,10 @@ class YtDlp:
34
37
  'yt-dlp',
35
38
  '-g',
36
39
  '-f',
37
- f'best[width<=?{video_parameters.width}]'
38
- f'[height<=?{video_parameters.height}]',
40
+ 'bestvideo[vcodec~=\'(vp09|avc1)\']+m4a/best',
41
+ '-S',
42
+ 'res:'
43
+ f'{min(video_parameters.width, video_parameters.height)}',
39
44
  '--no-warnings',
40
45
  ]
41
46
 
@@ -52,6 +57,10 @@ class YtDlp:
52
57
 
53
58
  commands.append(link)
54
59
 
60
+ py_logger.log(
61
+ logging.DEBUG,
62
+ f'Running with "{" ".join(commands)}" command',
63
+ )
55
64
  try:
56
65
  proc = await asyncio.create_subprocess_exec(
57
66
  *commands,