py-tgcalls 2.1.2b2__py3-none-any.whl → 2.2.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.
Files changed (32) hide show
  1. {py_tgcalls-2.1.2b2.dist-info → py_tgcalls-2.2.0.dist-info}/METADATA +2 -2
  2. {py_tgcalls-2.1.2b2.dist-info → py_tgcalls-2.2.0.dist-info}/RECORD +32 -31
  3. {py_tgcalls-2.1.2b2.dist-info → py_tgcalls-2.2.0.dist-info}/WHEEL +1 -1
  4. pytgcalls/__version__.py +1 -1
  5. pytgcalls/ffmpeg.py +2 -2
  6. pytgcalls/filters.py +6 -2
  7. pytgcalls/list_to_cmd.py +11 -0
  8. pytgcalls/methods/calls/leave_call.py +4 -0
  9. pytgcalls/methods/internal/connect_call.py +10 -1
  10. pytgcalls/methods/internal/handle_mtproto_updates.py +8 -15
  11. pytgcalls/methods/stream/play.py +2 -1
  12. pytgcalls/mtproto/bridged_client.py +64 -2
  13. pytgcalls/mtproto/client_cache.py +65 -72
  14. pytgcalls/mtproto/hydrogram_client.py +132 -35
  15. pytgcalls/mtproto/mtproto_client.py +11 -0
  16. pytgcalls/mtproto/pyrogram_client.py +135 -43
  17. pytgcalls/mtproto/telethon_client.py +95 -35
  18. pytgcalls/mutex.py +3 -1
  19. pytgcalls/types/cache.py +10 -5
  20. pytgcalls/types/chats/group_call_participant.py +1 -8
  21. pytgcalls/types/chats/updated_group_call_participant.py +2 -0
  22. pytgcalls/types/dict.py +1 -1
  23. pytgcalls/types/flag.py +4 -3
  24. pytgcalls/types/list.py +1 -1
  25. pytgcalls/types/participant_list.py +3 -3
  26. pytgcalls/types/py_object.py +4 -2
  27. pytgcalls/types/stream/media_stream.py +5 -4
  28. pytgcalls/types/stream/record_stream.py +3 -1
  29. pytgcalls/types/stream/video_quality.py +3 -1
  30. pytgcalls/ytdlp.py +3 -2
  31. {py_tgcalls-2.1.2b2.dist-info → py_tgcalls-2.2.0.dist-info}/licenses/LICENSE +0 -0
  32. {py_tgcalls-2.1.2b2.dist-info → py_tgcalls-2.2.0.dist-info}/top_level.txt +0 -0
@@ -6,9 +6,14 @@ from typing import Union
6
6
 
7
7
  from hydrogram import Client
8
8
  from hydrogram import ContinuePropagation
9
+ from hydrogram.errors import AuthBytesInvalid
10
+ from hydrogram.errors import BadRequest
11
+ from hydrogram.errors import FileMigrate
9
12
  from hydrogram.errors import FloodWait
10
13
  from hydrogram.raw.base import InputPeer
11
14
  from hydrogram.raw.base import InputUser
15
+ from hydrogram.raw.functions.auth import ExportAuthorization
16
+ from hydrogram.raw.functions.auth import ImportAuthorization
12
17
  from hydrogram.raw.functions.channels import GetFullChannel
13
18
  from hydrogram.raw.functions.messages import GetDhConfig
14
19
  from hydrogram.raw.functions.messages import GetFullChat
@@ -16,6 +21,7 @@ from hydrogram.raw.functions.phone import AcceptCall
16
21
  from hydrogram.raw.functions.phone import ConfirmCall
17
22
  from hydrogram.raw.functions.phone import CreateGroupCall
18
23
  from hydrogram.raw.functions.phone import DiscardCall
24
+ from hydrogram.raw.functions.phone import DiscardGroupCall
19
25
  from hydrogram.raw.functions.phone import EditGroupCallParticipant
20
26
  from hydrogram.raw.functions.phone import GetGroupCall
21
27
  from hydrogram.raw.functions.phone import GetGroupCallStreamChannels
@@ -62,6 +68,8 @@ from hydrogram.raw.types import UpdatePhoneCall
62
68
  from hydrogram.raw.types import UpdatePhoneCallSignalingData
63
69
  from hydrogram.raw.types import Updates
64
70
  from hydrogram.raw.types.messages import DhConfig
71
+ from hydrogram.session import Auth
72
+ from hydrogram.session import Session
65
73
  from ntgcalls import MediaSegmentQuality
66
74
  from ntgcalls import Protocol
67
75
 
@@ -69,7 +77,6 @@ from ..types import CallProtocol
69
77
  from ..types import ChatUpdate
70
78
  from ..types import GroupCallParticipant
71
79
  from ..types import RawCallUpdate
72
- from ..types import UpdatedGroupCallParticipant
73
80
  from .bridged_client import BridgedClient
74
81
  from .client_cache import ClientCache
75
82
 
@@ -87,7 +94,7 @@ class HydrogramClient(BridgedClient):
87
94
  self,
88
95
  )
89
96
 
90
- @self._app.on_raw_update(group=-1)
97
+ @self._app.on_raw_update(group=-9999)
91
98
  async def on_update(_, update, __, chats):
92
99
  if isinstance(
93
100
  update,
@@ -179,19 +186,22 @@ class HydrogramClient(BridgedClient):
179
186
  update,
180
187
  UpdateGroupCallParticipants,
181
188
  ):
182
- participants = update.participants
183
- for participant in participants:
184
- result = self._cache.set_participants_cache_call(
185
- update.call.id,
186
- self.parse_participant(participant),
189
+ for participant in update.participants:
190
+ chat_id = self._cache.get_chat_id(update.call.id)
191
+ p_updates = await self.diff_participants_update(
192
+ self._cache,
193
+ chat_id,
194
+ participant,
187
195
  )
188
- if result is not None:
189
- await self._propagate(
190
- UpdatedGroupCallParticipant(
191
- self._cache.get_chat_id(update.call.id),
192
- result,
193
- ),
196
+ for p_update in p_updates:
197
+ result = self._cache.set_participants_cache(
198
+ chat_id,
199
+ update.call.id,
200
+ p_update.action,
201
+ p_update.participant,
194
202
  )
203
+ if result is not None:
204
+ await self._propagate(p_update)
195
205
  if isinstance(
196
206
  update,
197
207
  UpdateGroupCall,
@@ -317,7 +327,7 @@ class HydrogramClient(BridgedClient):
317
327
  chat = await self._app.resolve_peer(chat_id)
318
328
  if isinstance(chat, InputPeerChannel):
319
329
  input_call = (
320
- await self._app.invoke(
330
+ await self._invoke(
321
331
  GetFullChannel(
322
332
  channel=InputChannel(
323
333
  channel_id=chat.channel_id,
@@ -328,14 +338,14 @@ class HydrogramClient(BridgedClient):
328
338
  ).full_chat.call
329
339
  else:
330
340
  input_call = (
331
- await self._app.invoke(
341
+ await self._invoke(
332
342
  GetFullChat(chat_id=chat.chat_id),
333
343
  )
334
344
  ).full_chat.call
335
345
 
336
346
  if input_call is not None:
337
347
  raw_call = (
338
- await self._app.invoke(
348
+ await self._invoke(
339
349
  GetGroupCall(
340
350
  call=input_call,
341
351
  limit=-1,
@@ -345,9 +355,10 @@ class HydrogramClient(BridgedClient):
345
355
  call: GroupCall = raw_call.call
346
356
  participants: List[GroupCallParticipant] = raw_call.participants
347
357
  for participant in participants:
348
- self._cache.set_participants_cache_chat(
358
+ self._cache.set_participants_cache(
349
359
  chat_id,
350
360
  call.id,
361
+ self.parse_participant_action(participant),
351
362
  self.parse_participant(participant),
352
363
  )
353
364
  if call.schedule_date is not None:
@@ -356,7 +367,7 @@ class HydrogramClient(BridgedClient):
356
367
  return input_call
357
368
 
358
369
  async def get_dhc(self) -> DhConfig:
359
- return await self._app.invoke(
370
+ return await self._invoke(
360
371
  GetDhConfig(
361
372
  version=0,
362
373
  random_length=256,
@@ -378,7 +389,7 @@ class HydrogramClient(BridgedClient):
378
389
  participants = []
379
390
  next_offset = ''
380
391
  while True:
381
- result = await self._app.invoke(
392
+ result = await self._invoke(
382
393
  GetGroupParticipants(
383
394
  call=input_call,
384
395
  ids=[],
@@ -405,7 +416,7 @@ class HydrogramClient(BridgedClient):
405
416
  ) -> str:
406
417
  chat_call = await self._cache.get_full_chat(chat_id)
407
418
  if chat_call is not None:
408
- result: Updates = await self._app.invoke(
419
+ result: Updates = await self._invoke(
409
420
  JoinGroupCall(
410
421
  call=chat_call,
411
422
  params=DataJSON(data=json_join),
@@ -422,8 +433,10 @@ class HydrogramClient(BridgedClient):
422
433
  ):
423
434
  participants = update.participants
424
435
  for participant in participants:
425
- self._cache.set_participants_cache_call(
436
+ self._cache.set_participants_cache(
437
+ chat_id,
426
438
  update.call.id,
439
+ self.parse_participant_action(participant),
427
440
  self.parse_participant(participant),
428
441
  )
429
442
  if isinstance(update, UpdateGroupCallConnection):
@@ -438,7 +451,7 @@ class HydrogramClient(BridgedClient):
438
451
  ):
439
452
  chat_call = await self._cache.get_full_chat(chat_id)
440
453
  if chat_call is not None:
441
- result: Updates = await self._app.invoke(
454
+ result: Updates = await self._invoke(
442
455
  JoinGroupCallPresentation(
443
456
  call=chat_call,
444
457
  params=DataJSON(data=json_join),
@@ -456,7 +469,7 @@ class HydrogramClient(BridgedClient):
456
469
  ):
457
470
  chat_call = await self._cache.get_full_chat(chat_id)
458
471
  if chat_call is not None:
459
- await self._app.invoke(
472
+ await self._invoke(
460
473
  LeaveGroupCallPresentation(
461
474
  call=chat_call,
462
475
  ),
@@ -469,7 +482,7 @@ class HydrogramClient(BridgedClient):
469
482
  protocol: Protocol,
470
483
  has_video: bool,
471
484
  ):
472
- update = await self._app.invoke(
485
+ update = await self._invoke(
473
486
  RequestCall(
474
487
  user_id=await self.resolve_peer(user_id),
475
488
  random_id=self.rnd_id(),
@@ -492,7 +505,7 @@ class HydrogramClient(BridgedClient):
492
505
  g_b: bytes,
493
506
  protocol: Protocol,
494
507
  ):
495
- await self._app.invoke(
508
+ await self._invoke(
496
509
  AcceptCall(
497
510
  peer=self._cache.get_phone_call(user_id),
498
511
  g_b=g_b,
@@ -508,7 +521,7 @@ class HydrogramClient(BridgedClient):
508
521
  protocol: Protocol,
509
522
  ) -> CallProtocol:
510
523
  res = (
511
- await self._app.invoke(
524
+ await self._invoke(
512
525
  ConfirmCall(
513
526
  peer=self._cache.get_phone_call(user_id),
514
527
  g_a=g_a,
@@ -528,7 +541,7 @@ class HydrogramClient(BridgedClient):
528
541
  user_id: int,
529
542
  data: bytes,
530
543
  ):
531
- await self._app.invoke(
544
+ await self._invoke(
532
545
  SendSignalingData(
533
546
  peer=self._cache.get_phone_call(user_id),
534
547
  data=data,
@@ -539,7 +552,7 @@ class HydrogramClient(BridgedClient):
539
552
  self,
540
553
  chat_id: int,
541
554
  ):
542
- result: Updates = await self._app.invoke(
555
+ result: Updates = await self._invoke(
543
556
  CreateGroupCall(
544
557
  peer=await self.resolve_peer(chat_id),
545
558
  random_id=self.rnd_id(),
@@ -569,13 +582,26 @@ class HydrogramClient(BridgedClient):
569
582
  ):
570
583
  chat_call = await self._cache.get_full_chat(chat_id)
571
584
  if chat_call is not None:
572
- await self._app.invoke(
585
+ await self._invoke(
573
586
  LeaveGroupCall(
574
587
  call=chat_call,
575
588
  source=0,
576
589
  ),
577
590
  )
578
591
 
592
+ async def close_voice_chat(
593
+ self,
594
+ chat_id: int,
595
+ ):
596
+ chat_call = await self._cache.get_full_chat(chat_id)
597
+ if chat_call is not None:
598
+ await self._invoke(
599
+ DiscardGroupCall(
600
+ call=chat_call,
601
+ ),
602
+ )
603
+ self._cache.drop_cache(chat_id)
604
+
579
605
  async def discard_call(
580
606
  self,
581
607
  chat_id: int,
@@ -589,7 +615,7 @@ class HydrogramClient(BridgedClient):
589
615
  if is_missed
590
616
  else PhoneCallDiscardReasonHangup()
591
617
  )
592
- await self._app.invoke(
618
+ await self._invoke(
593
619
  DiscardCall(
594
620
  peer=peer,
595
621
  duration=0,
@@ -608,7 +634,7 @@ class HydrogramClient(BridgedClient):
608
634
  ):
609
635
  chat_call = await self._cache.get_full_chat(chat_id)
610
636
  if chat_call is not None:
611
- await self._app.invoke(
637
+ await self._invoke(
612
638
  EditGroupCallParticipant(
613
639
  call=chat_call,
614
640
  participant=participant,
@@ -629,7 +655,7 @@ class HydrogramClient(BridgedClient):
629
655
  if chat_call is not None:
630
656
  try:
631
657
  return (
632
- await self._app.invoke(
658
+ await self._invoke(
633
659
  GetFile(
634
660
  location=InputGroupCallStream(
635
661
  call=chat_call,
@@ -656,9 +682,8 @@ class HydrogramClient(BridgedClient):
656
682
  ):
657
683
  chat_call = await self._cache.get_full_chat(chat_id)
658
684
  if chat_call is not None:
659
- # noinspection PyBroadException
660
685
  channels = (
661
- await self._app.invoke(
686
+ await self._invoke(
662
687
  GetGroupCallStreamChannels(
663
688
  call=chat_call,
664
689
  ),
@@ -680,7 +705,7 @@ class HydrogramClient(BridgedClient):
680
705
  ):
681
706
  chat_call = await self._cache.get_full_chat(chat_id)
682
707
  if chat_call is not None:
683
- await self._app.invoke(
708
+ await self._invoke(
684
709
  EditGroupCallParticipant(
685
710
  call=chat_call,
686
711
  participant=participant,
@@ -719,5 +744,77 @@ class HydrogramClient(BridgedClient):
719
744
  def no_updates(self):
720
745
  return self._app.no_updates
721
746
 
747
+ async def _invoke(
748
+ self,
749
+ request,
750
+ dc_id: Optional[int] = None,
751
+ chat_id: Optional[int] = None,
752
+ sleep_threshold: Optional[int] = None,
753
+ ):
754
+ if chat_id is not None:
755
+ dc_id = self._cache.get_dc_call(chat_id)
756
+ if dc_id is None:
757
+ session = self._app
758
+ else:
759
+ session = self._app.media_sessions.get(dc_id)
760
+ if not session:
761
+ session = self._app.media_sessions[dc_id] = Session(
762
+ self._app,
763
+ dc_id,
764
+ await Auth(
765
+ self._app,
766
+ dc_id,
767
+ await self._app.storage.test_mode(),
768
+ ).create()
769
+ if dc_id != await self._app.storage.dc_id()
770
+ else await self._app.storage.auth_key(),
771
+ await self._app.storage.test_mode(),
772
+ is_media=True,
773
+ )
774
+ await session.start()
775
+ if dc_id != await self._app.storage.dc_id():
776
+ for _ in range(3):
777
+ exported_auth = await self._invoke(
778
+ ExportAuthorization(
779
+ dc_id=dc_id,
780
+ ),
781
+ )
782
+
783
+ try:
784
+ await session.invoke(
785
+ ImportAuthorization(
786
+ id=exported_auth.id,
787
+ bytes=exported_auth.bytes,
788
+ ),
789
+ )
790
+ except AuthBytesInvalid:
791
+ continue
792
+ else:
793
+ break
794
+ else:
795
+ raise AuthBytesInvalid
796
+ try:
797
+ return await session.invoke(
798
+ request,
799
+ sleep_threshold=sleep_threshold,
800
+ )
801
+ except (BadRequest, FileMigrate) as e:
802
+ dc_new = BridgedClient.extract_dc(
803
+ str(e),
804
+ )
805
+ if dc_new is not None:
806
+ if chat_id is not None:
807
+ self._cache.set_dc_call(
808
+ chat_id,
809
+ dc_new,
810
+ )
811
+ return await self._invoke(
812
+ request,
813
+ dc_new,
814
+ chat_id,
815
+ sleep_threshold,
816
+ )
817
+ raise
818
+
722
819
  async def start(self):
723
820
  await self._app.start()
@@ -197,6 +197,17 @@ class MtProtoClient:
197
197
  else:
198
198
  raise InvalidMTProtoClient()
199
199
 
200
+ async def close_voice_chat(
201
+ self,
202
+ chat_id: int,
203
+ ):
204
+ if self._bind_client is not None:
205
+ await self._bind_client.close_voice_chat(
206
+ chat_id,
207
+ )
208
+ else:
209
+ raise InvalidMTProtoClient()
210
+
200
211
  async def change_volume(
201
212
  self,
202
213
  chat_id: int,