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.
- {py_tgcalls-2.0.5.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.5.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 +52 -7
- 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.5.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.5.dist-info → py_tgcalls-2.1.0.dist-info}/LICENSE +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
)
|
|
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
|
-
|
|
407
|
-
|
|
416
|
+
update,
|
|
417
|
+
UpdateGroupCallParticipants,
|
|
408
418
|
):
|
|
409
419
|
participants = update.participants
|
|
410
420
|
for participant in participants:
|
|
411
|
-
self._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=
|
|
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
|
-
|
|
566
|
-
|
|
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
|
-
|
|
577
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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.
|
|
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=
|
|
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
|
-
|
|
535
|
-
|
|
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
|
-
|
|
546
|
-
|
|
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
|
pytgcalls/types/__init__.py
CHANGED
|
@@ -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
|
|
15
|
-
from .stream import
|
|
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
|
-
'
|
|
33
|
-
'
|
|
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
|
)
|
pytgcalls/types/calls/call.py
CHANGED
|
@@ -6,7 +6,7 @@ from ..flag import Flag
|
|
|
6
6
|
|
|
7
7
|
class Call(PyObject):
|
|
8
8
|
class Status(Flag):
|
|
9
|
-
|
|
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
|
-
|
|
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.
|
|
25
|
+
self.playback = playback
|
|
26
|
+
self.capture = capture
|