py-tgcalls 2.0.5__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.
Files changed (65) hide show
  1. {py_tgcalls-2.0.5.dist-info → py_tgcalls-2.1.0.dist-info}/METADATA +11 -16
  2. py_tgcalls-2.1.0.dist-info/RECORD +106 -0
  3. {py_tgcalls-2.0.5.dist-info → py_tgcalls-2.1.0.dist-info}/WHEEL +1 -1
  4. pytgcalls/__init__.py +2 -0
  5. pytgcalls/__version__.py +1 -1
  6. pytgcalls/exceptions.py +7 -24
  7. pytgcalls/ffmpeg.py +2 -2
  8. pytgcalls/filters.py +52 -7
  9. pytgcalls/handlers/handlers_holder.py +1 -1
  10. pytgcalls/media_devices/__init__.py +6 -2
  11. pytgcalls/media_devices/device_info.py +8 -15
  12. pytgcalls/media_devices/input_device.py +11 -0
  13. pytgcalls/media_devices/media_devices.py +41 -92
  14. pytgcalls/media_devices/screen_device.py +10 -0
  15. pytgcalls/media_devices/speaker_device.py +10 -0
  16. pytgcalls/methods/calls/change_volume_call.py +3 -0
  17. pytgcalls/methods/calls/get_participants.py +5 -1
  18. pytgcalls/methods/calls/leave_call.py +3 -1
  19. pytgcalls/methods/stream/__init__.py +14 -10
  20. pytgcalls/methods/stream/{mute_stream.py → mute.py} +2 -2
  21. pytgcalls/methods/stream/{pause_stream.py → pause.py} +2 -2
  22. pytgcalls/methods/stream/play.py +27 -21
  23. pytgcalls/methods/stream/record.py +49 -0
  24. pytgcalls/methods/stream/{resume_stream.py → resume.py} +2 -2
  25. pytgcalls/methods/stream/send_frame.py +38 -0
  26. pytgcalls/methods/stream/{played_time.py → time.py} +5 -3
  27. pytgcalls/methods/stream/{unmute_stream.py → unmute.py} +2 -2
  28. pytgcalls/methods/utilities/__init__.py +6 -0
  29. pytgcalls/methods/utilities/call_holder.py +5 -2
  30. pytgcalls/methods/utilities/join_presentation.py +50 -0
  31. pytgcalls/methods/utilities/log_retries.py +14 -0
  32. pytgcalls/methods/utilities/start.py +136 -16
  33. pytgcalls/methods/utilities/stream_params.py +69 -22
  34. pytgcalls/methods/utilities/update_sources.py +42 -0
  35. pytgcalls/mtproto/bridged_client.py +36 -2
  36. pytgcalls/mtproto/client_cache.py +46 -16
  37. pytgcalls/mtproto/hydrogram_client.py +72 -23
  38. pytgcalls/mtproto/mtproto_client.py +32 -4
  39. pytgcalls/mtproto/pyrogram_client.py +72 -23
  40. pytgcalls/mtproto/telethon_client.py +97 -33
  41. pytgcalls/scaffold.py +15 -0
  42. pytgcalls/types/__init__.py +14 -4
  43. pytgcalls/types/calls/__init__.py +2 -0
  44. pytgcalls/types/calls/call.py +5 -3
  45. pytgcalls/types/calls/call_sources.py +4 -0
  46. pytgcalls/types/chats/group_call_participant.py +23 -0
  47. pytgcalls/types/py_object.py +9 -10
  48. pytgcalls/types/raw/audio_stream.py +3 -3
  49. pytgcalls/types/raw/stream.py +8 -4
  50. pytgcalls/types/raw/video_stream.py +5 -4
  51. pytgcalls/types/stream/__init__.py +14 -4
  52. pytgcalls/types/stream/device.py +36 -0
  53. pytgcalls/types/stream/direction.py +25 -0
  54. pytgcalls/types/stream/external_media.py +8 -0
  55. pytgcalls/types/stream/frame.py +26 -0
  56. pytgcalls/types/stream/media_stream.py +178 -107
  57. pytgcalls/types/stream/record_stream.py +99 -0
  58. pytgcalls/types/stream/stream_ended.py +32 -0
  59. pytgcalls/types/stream/stream_frames.py +20 -0
  60. py_tgcalls-2.0.5.dist-info/RECORD +0 -93
  61. pytgcalls/media_devices/screen_info.py +0 -45
  62. pytgcalls/types/stream/stream_audio_ended.py +0 -9
  63. pytgcalls/types/stream/stream_video_ended.py +0 -9
  64. {py_tgcalls-2.0.5.dist-info → py_tgcalls-2.1.0.dist-info}/LICENSE +0 -0
  65. {py_tgcalls-2.0.5.dist-info → py_tgcalls-2.1.0.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,9 @@ from pyrogram.raw.functions.phone import EditGroupCallParticipant
21
21
  from pyrogram.raw.functions.phone import GetGroupCall
22
22
  from pyrogram.raw.functions.phone import GetGroupParticipants
23
23
  from pyrogram.raw.functions.phone import JoinGroupCall
24
+ from pyrogram.raw.functions.phone import JoinGroupCallPresentation
24
25
  from pyrogram.raw.functions.phone import LeaveGroupCall
26
+ from pyrogram.raw.functions.phone import LeaveGroupCallPresentation
25
27
  from pyrogram.raw.functions.phone import RequestCall
26
28
  from pyrogram.raw.functions.phone import SendSignalingData
27
29
  from pyrogram.raw.types import Channel
@@ -43,6 +45,7 @@ from pyrogram.raw.types import PhoneCall
43
45
  from pyrogram.raw.types import PhoneCallAccepted
44
46
  from pyrogram.raw.types import PhoneCallDiscarded
45
47
  from pyrogram.raw.types import PhoneCallDiscardReasonHangup
48
+ from pyrogram.raw.types import PhoneCallDiscardReasonMissed
46
49
  from pyrogram.raw.types import PhoneCallProtocol
47
50
  from pyrogram.raw.types import PhoneCallRequested
48
51
  from pyrogram.raw.types import PhoneCallWaiting
@@ -94,7 +97,7 @@ class PyrogramClient(BridgedClient):
94
97
  ):
95
98
  user_id = self._cache.get_user_id(update.phone_call_id)
96
99
  if user_id is not None:
97
- await self.propagate(
100
+ await self._propagate(
98
101
  RawCallUpdate(
99
102
  user_id,
100
103
  RawCallUpdate.Type.SIGNALING_DATA,
@@ -118,7 +121,7 @@ class PyrogramClient(BridgedClient):
118
121
  ),
119
122
  )
120
123
  if isinstance(update.phone_call, PhoneCallAccepted):
121
- await self.propagate(
124
+ await self._propagate(
122
125
  RawCallUpdate(
123
126
  self.user_from_call(update.phone_call),
124
127
  RawCallUpdate.Type.ACCEPTED,
@@ -134,14 +137,14 @@ class PyrogramClient(BridgedClient):
134
137
  self._cache.drop_phone_call(
135
138
  user_id,
136
139
  )
137
- await self.propagate(
140
+ await self._propagate(
138
141
  ChatUpdate(
139
142
  user_id,
140
143
  ChatUpdate.Status.DISCARDED_CALL,
141
144
  ),
142
145
  )
143
146
  if isinstance(update.phone_call, PhoneCallRequested):
144
- await self.propagate(
147
+ await self._propagate(
145
148
  RawCallUpdate(
146
149
  self.user_from_call(update.phone_call),
147
150
  RawCallUpdate.Type.REQUESTED,
@@ -152,7 +155,7 @@ class PyrogramClient(BridgedClient):
152
155
  ),
153
156
  )
154
157
  if isinstance(update.phone_call, PhoneCall):
155
- await self.propagate(
158
+ await self._propagate(
156
159
  RawCallUpdate(
157
160
  self.user_from_call(update.phone_call),
158
161
  RawCallUpdate.Type.CONFIRMED,
@@ -174,12 +177,12 @@ class PyrogramClient(BridgedClient):
174
177
  ):
175
178
  participants = update.participants
176
179
  for participant in participants:
177
- result = self._cache.set_participants_cache(
180
+ result = self._cache.set_participants_cache_call(
178
181
  update.call.id,
179
182
  self.parse_participant(participant),
180
183
  )
181
184
  if result is not None:
182
- await self.propagate(
185
+ await self._propagate(
183
186
  UpdatedGroupCallParticipant(
184
187
  self._cache.get_chat_id(update.call.id),
185
188
  result,
@@ -207,7 +210,7 @@ class PyrogramClient(BridgedClient):
207
210
  GroupCallDiscarded,
208
211
  ):
209
212
  self._cache.drop_cache(chat_id)
210
- await self.propagate(
213
+ await self._propagate(
211
214
  ChatUpdate(
212
215
  chat_id,
213
216
  ChatUpdate.Status.CLOSED_VOICE_CHAT,
@@ -224,7 +227,7 @@ class PyrogramClient(BridgedClient):
224
227
  ChannelForbidden,
225
228
  ):
226
229
  self._cache.drop_cache(chat_id)
227
- await self.propagate(
230
+ await self._propagate(
228
231
  ChatUpdate(
229
232
  chat_id,
230
233
  ChatUpdate.Status.KICKED,
@@ -247,7 +250,7 @@ class PyrogramClient(BridgedClient):
247
250
  update.message.peer_id,
248
251
  PeerChat,
249
252
  ):
250
- await self.propagate(
253
+ await self._propagate(
251
254
  ChatUpdate(
252
255
  chat_id,
253
256
  ChatUpdate.Status.INVITED_VOICE_CHAT,
@@ -267,7 +270,7 @@ class PyrogramClient(BridgedClient):
267
270
  ChatForbidden,
268
271
  ):
269
272
  self._cache.drop_cache(chat_id)
270
- await self.propagate(
273
+ await self._propagate(
271
274
  ChatUpdate(
272
275
  chat_id,
273
276
  ChatUpdate.Status.KICKED,
@@ -295,7 +298,7 @@ class PyrogramClient(BridgedClient):
295
298
  self._cache.drop_cache(
296
299
  chat_id,
297
300
  )
298
- await self.propagate(
301
+ await self._propagate(
299
302
  ChatUpdate(
300
303
  chat_id,
301
304
  ChatUpdate.Status.LEFT_GROUP,
@@ -327,15 +330,22 @@ class PyrogramClient(BridgedClient):
327
330
  ).full_chat.call
328
331
 
329
332
  if input_call is not None:
330
- call: GroupCall = (
333
+ raw_call = (
331
334
  await self._app.send(
332
335
  GetGroupCall(
333
336
  call=input_call,
334
337
  limit=-1,
335
338
  ),
336
339
  )
337
- ).call
338
-
340
+ )
341
+ call: GroupCall = raw_call.call
342
+ participants: List[GroupCallParticipant] = raw_call.participants
343
+ for participant in participants:
344
+ self._cache.set_participants_cache_chat(
345
+ chat_id,
346
+ call.id,
347
+ self.parse_participant(participant),
348
+ )
339
349
  if call.schedule_date is not None:
340
350
  return None
341
351
 
@@ -403,12 +413,12 @@ class PyrogramClient(BridgedClient):
403
413
  )
404
414
  for update in result.updates:
405
415
  if isinstance(
406
- update,
407
- UpdateGroupCallParticipants,
416
+ update,
417
+ UpdateGroupCallParticipants,
408
418
  ):
409
419
  participants = update.participants
410
420
  for participant in participants:
411
- self._cache.set_participants_cache(
421
+ self._cache.set_participants_cache_call(
412
422
  update.call.id,
413
423
  self.parse_participant(participant),
414
424
  )
@@ -417,6 +427,37 @@ class PyrogramClient(BridgedClient):
417
427
 
418
428
  return json.dumps({'transport': None})
419
429
 
430
+ async def join_presentation(
431
+ self,
432
+ chat_id: int,
433
+ json_join: str,
434
+ ):
435
+ chat_call = await self._cache.get_full_chat(chat_id)
436
+ if chat_call is not None:
437
+ result: Updates = await self._app.send(
438
+ JoinGroupCallPresentation(
439
+ call=chat_call,
440
+ params=DataJSON(data=json_join),
441
+ ),
442
+ )
443
+ for update in result.updates:
444
+ if isinstance(update, UpdateGroupCallConnection):
445
+ return update.params.data
446
+
447
+ return json.dumps({'transport': None})
448
+
449
+ async def leave_presentation(
450
+ self,
451
+ chat_id: int,
452
+ ):
453
+ chat_call = await self._cache.get_full_chat(chat_id)
454
+ if chat_call is not None:
455
+ await self._app.send(
456
+ LeaveGroupCallPresentation(
457
+ call=chat_call,
458
+ ),
459
+ )
460
+
420
461
  async def request_call(
421
462
  self,
422
463
  user_id: int,
@@ -526,15 +567,21 @@ class PyrogramClient(BridgedClient):
526
567
  async def discard_call(
527
568
  self,
528
569
  chat_id: int,
570
+ is_missed: bool,
529
571
  ):
530
572
  peer = self._cache.get_phone_call(chat_id)
531
573
  if peer is None:
532
574
  return
575
+ reason = (
576
+ PhoneCallDiscardReasonMissed()
577
+ if is_missed
578
+ else PhoneCallDiscardReasonHangup()
579
+ )
533
580
  await self._app.invoke(
534
581
  DiscardCall(
535
582
  peer=peer,
536
583
  duration=0,
537
- reason=PhoneCallDiscardReasonHangup(),
584
+ reason=reason,
538
585
  connection_id=0,
539
586
  video=False,
540
587
  ),
@@ -562,8 +609,9 @@ class PyrogramClient(BridgedClient):
562
609
  self,
563
610
  chat_id: int,
564
611
  muted_status: Optional[bool],
565
- paused_status: Optional[bool],
566
- stopped_status: Optional[bool],
612
+ video_paused: Optional[bool],
613
+ video_stopped: Optional[bool],
614
+ presentation_paused: Optional[bool],
567
615
  participant: InputPeer,
568
616
  ):
569
617
  chat_call = await self._cache.get_full_chat(chat_id)
@@ -573,8 +621,9 @@ class PyrogramClient(BridgedClient):
573
621
  call=chat_call,
574
622
  participant=participant,
575
623
  muted=muted_status,
576
- video_stopped=stopped_status,
577
- video_paused=paused_status,
624
+ video_paused=video_paused,
625
+ video_stopped=video_stopped,
626
+ presentation_paused=presentation_paused,
578
627
  ),
579
628
  )
580
629
 
@@ -17,7 +17,9 @@ from telethon.tl.functions.phone import DiscardCallRequest
17
17
  from telethon.tl.functions.phone import EditGroupCallParticipantRequest
18
18
  from telethon.tl.functions.phone import GetGroupCallRequest
19
19
  from telethon.tl.functions.phone import GetGroupParticipantsRequest
20
+ from telethon.tl.functions.phone import JoinGroupCallPresentationRequest
20
21
  from telethon.tl.functions.phone import JoinGroupCallRequest
22
+ from telethon.tl.functions.phone import LeaveGroupCallPresentationRequest
21
23
  from telethon.tl.functions.phone import LeaveGroupCallRequest
22
24
  from telethon.tl.functions.phone import RequestCallRequest
23
25
  from telethon.tl.functions.phone import SendSignalingDataRequest
@@ -32,11 +34,13 @@ from telethon.tl.types import InputPhoneCall
32
34
  from telethon.tl.types import MessageActionChatDeleteUser
33
35
  from telethon.tl.types import MessageActionInviteToGroupCall
34
36
  from telethon.tl.types import MessageService
37
+ from telethon.tl.types import PeerChannel
35
38
  from telethon.tl.types import PeerChat
36
39
  from telethon.tl.types import PhoneCall
37
40
  from telethon.tl.types import PhoneCallAccepted
38
41
  from telethon.tl.types import PhoneCallDiscarded
39
42
  from telethon.tl.types import PhoneCallDiscardReasonHangup
43
+ from telethon.tl.types import PhoneCallDiscardReasonMissed
40
44
  from telethon.tl.types import PhoneCallProtocol
41
45
  from telethon.tl.types import PhoneCallRequested
42
46
  from telethon.tl.types import PhoneCallWaiting
@@ -84,7 +88,7 @@ class TelethonClient(BridgedClient):
84
88
  ):
85
89
  user_id = self._cache.get_user_id(update.phone_call_id)
86
90
  if user_id is not None:
87
- await self.propagate(
91
+ await self._propagate(
88
92
  RawCallUpdate(
89
93
  user_id,
90
94
  RawCallUpdate.Type.SIGNALING_DATA,
@@ -108,7 +112,7 @@ class TelethonClient(BridgedClient):
108
112
  ),
109
113
  )
110
114
  if isinstance(update.phone_call, PhoneCallAccepted):
111
- await self.propagate(
115
+ await self._propagate(
112
116
  RawCallUpdate(
113
117
  self.user_from_call(update.phone_call),
114
118
  RawCallUpdate.Type.ACCEPTED,
@@ -124,14 +128,14 @@ class TelethonClient(BridgedClient):
124
128
  self._cache.drop_phone_call(
125
129
  user_id,
126
130
  )
127
- await self.propagate(
131
+ await self._propagate(
128
132
  ChatUpdate(
129
133
  user_id,
130
134
  ChatUpdate.Status.DISCARDED_CALL,
131
135
  ),
132
136
  )
133
137
  if isinstance(update.phone_call, PhoneCallRequested):
134
- await self.propagate(
138
+ await self._propagate(
135
139
  RawCallUpdate(
136
140
  self.user_from_call(update.phone_call),
137
141
  RawCallUpdate.Type.REQUESTED,
@@ -142,7 +146,7 @@ class TelethonClient(BridgedClient):
142
146
  ),
143
147
  )
144
148
  if isinstance(update.phone_call, PhoneCall):
145
- await self.propagate(
149
+ await self._propagate(
146
150
  RawCallUpdate(
147
151
  self.user_from_call(update.phone_call),
148
152
  RawCallUpdate.Type.CONFIRMED,
@@ -164,12 +168,12 @@ class TelethonClient(BridgedClient):
164
168
  ):
165
169
  participants = update.participants
166
170
  for participant in participants:
167
- result = self._cache.set_participants_cache(
171
+ result = self._cache.set_participants_cache_call(
168
172
  update.call.id,
169
173
  self.parse_participant(participant),
170
174
  )
171
175
  if result is not None:
172
- await self.propagate(
176
+ await self._propagate(
173
177
  UpdatedGroupCallParticipant(
174
178
  self._cache.get_chat_id(update.call.id),
175
179
  result,
@@ -180,7 +184,9 @@ class TelethonClient(BridgedClient):
180
184
  UpdateGroupCall,
181
185
  ):
182
186
  chat_id = self.chat_id(
183
- await self._app.get_entity(update.chat_id),
187
+ await self._get_entity_group(
188
+ update.chat_id,
189
+ ),
184
190
  )
185
191
  if isinstance(
186
192
  update.call,
@@ -201,7 +207,7 @@ class TelethonClient(BridgedClient):
201
207
  self._cache.drop_cache(
202
208
  chat_id,
203
209
  )
204
- await self.propagate(
210
+ await self._propagate(
205
211
  ChatUpdate(
206
212
  chat_id,
207
213
  ChatUpdate.Status.CLOSED_VOICE_CHAT,
@@ -213,10 +219,12 @@ class TelethonClient(BridgedClient):
213
219
  ):
214
220
  chat_id = self.chat_id(update)
215
221
  try:
216
- await self._app.get_entity(chat_id)
222
+ await self._app.get_entity(
223
+ PeerChannel(chat_id),
224
+ )
217
225
  except ChannelPrivateError:
218
226
  self._cache.drop_cache(chat_id)
219
- await self.propagate(
227
+ await self._propagate(
220
228
  ChatUpdate(
221
229
  chat_id,
222
230
  ChatUpdate.Status.KICKED,
@@ -236,7 +244,7 @@ class TelethonClient(BridgedClient):
236
244
  update.message.action,
237
245
  MessageActionInviteToGroupCall,
238
246
  ):
239
- await self.propagate(
247
+ await self._propagate(
240
248
  ChatUpdate(
241
249
  chat_id,
242
250
  ChatUpdate.Status.INVITED_VOICE_CHAT,
@@ -246,7 +254,7 @@ class TelethonClient(BridgedClient):
246
254
  if isinstance(update.message.out, bool):
247
255
  if update.message.out:
248
256
  self._cache.drop_cache(chat_id)
249
- await self.propagate(
257
+ await self._propagate(
250
258
  ChatUpdate(
251
259
  chat_id,
252
260
  ChatUpdate.Status.LEFT_GROUP,
@@ -265,13 +273,23 @@ class TelethonClient(BridgedClient):
265
273
  ChatForbidden,
266
274
  ):
267
275
  self._cache.drop_cache(chat_id)
268
- await self.propagate(
276
+ await self._propagate(
269
277
  ChatUpdate(
270
278
  chat_id,
271
279
  ChatUpdate.Status.KICKED,
272
280
  ),
273
281
  )
274
282
 
283
+ async def _get_entity_group(self, chat_id):
284
+ try:
285
+ return await self._app.get_entity(
286
+ PeerChannel(chat_id),
287
+ )
288
+ except ValueError:
289
+ return await self._app.get_entity(
290
+ PeerChat(chat_id),
291
+ )
292
+
275
293
  async def get_call(
276
294
  self,
277
295
  chat_id: int,
@@ -294,20 +312,27 @@ class TelethonClient(BridgedClient):
294
312
  GetFullChatRequest(chat_id),
295
313
  )
296
314
  ).full_chat.call
315
+
297
316
  if input_call is not None:
298
- try:
299
- call: GroupCall = (
300
- await self._app(
301
- GetGroupCallRequest(
302
- call=input_call,
303
- limit=-1,
304
- ),
305
- )
306
- ).call
307
- if call.schedule_date is not None:
308
- return None
309
- except Exception as e:
310
- print(e)
317
+ raw_call = (
318
+ await self._app(
319
+ GetGroupCallRequest(
320
+ call=input_call,
321
+ limit=-1,
322
+ ),
323
+ )
324
+ )
325
+ call: GroupCall = raw_call.call
326
+ participants: List[GroupCallParticipant] = raw_call.participants
327
+ for participant in participants:
328
+ self._cache.set_participants_cache_chat(
329
+ chat_id,
330
+ call.id,
331
+ self.parse_participant(participant),
332
+ )
333
+ if call.schedule_date is not None:
334
+ return None
335
+
311
336
  return input_call
312
337
 
313
338
  async def get_dhc(self) -> DhConfig:
@@ -377,7 +402,7 @@ class TelethonClient(BridgedClient):
377
402
  ):
378
403
  participants = update.participants
379
404
  for participant in participants:
380
- self._cache.set_participants_cache(
405
+ self._cache.set_participants_cache_call(
381
406
  update.call.id,
382
407
  self.parse_participant(participant),
383
408
  )
@@ -386,6 +411,37 @@ class TelethonClient(BridgedClient):
386
411
 
387
412
  return json.dumps({'transport': None})
388
413
 
414
+ async def join_presentation(
415
+ self,
416
+ chat_id: int,
417
+ json_join: str,
418
+ ):
419
+ chat_call = await self._cache.get_full_chat(chat_id)
420
+ if chat_call is not None:
421
+ result: Updates = await self._app(
422
+ JoinGroupCallPresentationRequest(
423
+ call=chat_call,
424
+ params=DataJSON(data=json_join),
425
+ ),
426
+ )
427
+ for update in result.updates:
428
+ if isinstance(update, UpdateGroupCallConnection):
429
+ return update.params.data
430
+
431
+ return json.dumps({'transport': None})
432
+
433
+ async def leave_presentation(
434
+ self,
435
+ chat_id: int,
436
+ ):
437
+ chat_call = await self._cache.get_full_chat(chat_id)
438
+ if chat_call is not None:
439
+ await self._app(
440
+ LeaveGroupCallPresentationRequest(
441
+ call=chat_call,
442
+ ),
443
+ )
444
+
389
445
  async def request_call(
390
446
  self,
391
447
  user_id: int,
@@ -495,15 +551,21 @@ class TelethonClient(BridgedClient):
495
551
  async def discard_call(
496
552
  self,
497
553
  chat_id: int,
554
+ is_missed: bool,
498
555
  ):
499
556
  peer = self._cache.get_phone_call(chat_id)
500
557
  if peer is None:
501
558
  return
559
+ reason = (
560
+ PhoneCallDiscardReasonMissed()
561
+ if is_missed
562
+ else PhoneCallDiscardReasonHangup()
563
+ )
502
564
  await self._app(
503
565
  DiscardCallRequest(
504
566
  peer=peer,
505
567
  duration=0,
506
- reason=PhoneCallDiscardReasonHangup(),
568
+ reason=reason,
507
569
  connection_id=0,
508
570
  video=False,
509
571
  ),
@@ -531,8 +593,9 @@ class TelethonClient(BridgedClient):
531
593
  self,
532
594
  chat_id: int,
533
595
  muted_status: Optional[bool],
534
- paused_status: Optional[bool],
535
- stopped_status: Optional[bool],
596
+ video_paused: Optional[bool],
597
+ video_stopped: Optional[bool],
598
+ presentation_paused: Optional[bool],
536
599
  participant: TypeInputPeer,
537
600
  ):
538
601
  chat_call = await self._cache.get_full_chat(chat_id)
@@ -542,8 +605,9 @@ class TelethonClient(BridgedClient):
542
605
  call=chat_call,
543
606
  participant=participant,
544
607
  muted=muted_status,
545
- video_stopped=stopped_status,
546
- video_paused=paused_status,
608
+ video_paused=video_paused,
609
+ video_stopped=video_stopped,
610
+ presentation_paused=presentation_paused,
547
611
  ),
548
612
  )
549
613
 
pytgcalls/scaffold.py CHANGED
@@ -22,7 +22,9 @@ class Scaffold(HandlersHolder):
22
22
  self.loop = None
23
23
  self._need_unmute = set()
24
24
  self._p2p_configs = dict()
25
+ self._call_sources = dict()
25
26
  self._wait_connect = dict()
27
+ self._presentations = set()
26
28
 
27
29
  def _handle_mtproto(self):
28
30
  pass
@@ -36,5 +38,18 @@ class Scaffold(HandlersHolder):
36
38
  async def start(self):
37
39
  pass
38
40
 
41
+ async def play(self, chat_id: Union[int, str], stream=None, config=None):
42
+ pass
43
+
44
+ async def _update_sources(self, chat_id: Union[int, str]):
45
+ pass
46
+
47
+ async def _join_presentation(self, chat_id: Union[int, str], join: bool):
48
+ pass
49
+
50
+ @staticmethod
51
+ def _log_retries(r: int):
52
+ pass
53
+
39
54
  def on_update(self, filters=None):
40
55
  pass
@@ -10,14 +10,23 @@ from .chats import ChatUpdate
10
10
  from .chats import GroupCallParticipant
11
11
  from .chats import UpdatedGroupCallParticipant
12
12
  from .stream import AudioQuality
13
+ from .stream import Device
14
+ from .stream import Direction
15
+ from .stream import ExternalMedia
16
+ from .stream import Frame
13
17
  from .stream import MediaStream
14
- from .stream import StreamAudioEnded
15
- from .stream import StreamVideoEnded
18
+ from .stream import RecordStream
19
+ from .stream import StreamEnded
20
+ from .stream import StreamFrames
16
21
  from .stream import VideoQuality
17
22
  from .update import Update
18
23
 
19
24
  __all__ = (
20
25
  'AudioQuality',
26
+ 'Device',
27
+ 'Direction',
28
+ 'ExternalMedia',
29
+ 'Frame',
21
30
  'Browsers',
22
31
  'Cache',
23
32
  'ChatUpdate',
@@ -28,9 +37,10 @@ __all__ = (
28
37
  'RawCallUpdate',
29
38
  'GroupCallConfig',
30
39
  'GroupCallParticipant',
40
+ 'RecordStream',
31
41
  'MediaStream',
32
- 'StreamAudioEnded',
33
- 'StreamVideoEnded',
42
+ 'StreamEnded',
43
+ 'StreamFrames',
34
44
  'Update',
35
45
  'UpdatedGroupCallParticipant',
36
46
  'VideoQuality',
@@ -2,6 +2,7 @@ from .call import Call
2
2
  from .call_config import CallConfig
3
3
  from .call_data import CallData
4
4
  from .call_protocol import CallProtocol
5
+ from .call_sources import CallSources
5
6
  from .group_call_config import GroupCallConfig
6
7
  from .raw_call_update import RawCallUpdate
7
8
 
@@ -10,6 +11,7 @@ __all__ = (
10
11
  'CallData',
11
12
  'CallConfig',
12
13
  'CallProtocol',
14
+ 'CallSources',
13
15
  'GroupCallConfig',
14
16
  'RawCallUpdate',
15
17
  )
@@ -6,7 +6,7 @@ from ..flag import Flag
6
6
 
7
7
  class Call(PyObject):
8
8
  class Status(Flag):
9
- PLAYING = auto()
9
+ ACTIVE = auto()
10
10
  PAUSED = auto()
11
11
  IDLE = auto()
12
12
 
@@ -17,8 +17,10 @@ class Call(PyObject):
17
17
  def __init__(
18
18
  self,
19
19
  chat_id: int,
20
- status: Status,
20
+ playback: Status,
21
+ capture: Status,
21
22
  ):
22
23
  self.call_type = Call.Type.GROUP \
23
24
  if chat_id < 0 else Call.Type.PRIVATE
24
- self.status = status
25
+ self.playback = playback
26
+ self.capture = capture
@@ -0,0 +1,4 @@
1
+ class CallSources:
2
+ def __init__(self):
3
+ self.camera = dict()
4
+ self.presentation = dict()