tlgr-cli 2.0.1__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.
- tlgr/__init__.py +3 -0
- tlgr/__main__.py +6 -0
- tlgr/actions/__init__.py +45 -0
- tlgr/actions/forward.py +74 -0
- tlgr/actions/reply.py +32 -0
- tlgr/cli/__init__.py +259 -0
- tlgr/cli/confirm.py +55 -0
- tlgr/cli/errors.py +84 -0
- tlgr/cli/gen.py +690 -0
- tlgr/cli/globals.py +273 -0
- tlgr/cli/introspect.py +170 -0
- tlgr/cli/params.py +189 -0
- tlgr/cli/render.py +418 -0
- tlgr/core/__init__.py +0 -0
- tlgr/core/accounts.py +384 -0
- tlgr/core/config.py +358 -0
- tlgr/core/custom_tl.py +170 -0
- tlgr/core/errors.py +687 -0
- tlgr/core/eventtypes.py +1170 -0
- tlgr/core/identity.py +127 -0
- tlgr/core/launchd.py +122 -0
- tlgr/core/logging.py +194 -0
- tlgr/core/media.py +134 -0
- tlgr/core/output.py +251 -0
- tlgr/core/pagination.py +227 -0
- tlgr/core/paths.py +360 -0
- tlgr/core/peers.py +427 -0
- tlgr/core/process.py +138 -0
- tlgr/core/signing.py +38 -0
- tlgr/core/systemd.py +96 -0
- tlgr/core/telethon_compat.py +295 -0
- tlgr/core/text.py +211 -0
- tlgr/core/timefmt.py +199 -0
- tlgr/core/tl.py +98 -0
- tlgr/daemon/__init__.py +0 -0
- tlgr/daemon/app.py +869 -0
- tlgr/daemon/dispatch.py +446 -0
- tlgr/daemon/events.py +723 -0
- tlgr/daemon/files.py +431 -0
- tlgr/daemon/idle.py +119 -0
- tlgr/daemon/jobs.py +68 -0
- tlgr/daemon/main.py +161 -0
- tlgr/daemon/peercred.py +75 -0
- tlgr/daemon/policy.py +113 -0
- tlgr/daemon/preauth.py +366 -0
- tlgr/daemon/ratelimit.py +391 -0
- tlgr/daemon/server.py +24 -0
- tlgr/daemon/session.py +648 -0
- tlgr/daemon/sessions.py +274 -0
- tlgr/daemon/singleton.py +114 -0
- tlgr/daemon/stream.py +193 -0
- tlgr/daemon/transfers.py +219 -0
- tlgr/daemon/webhook.py +390 -0
- tlgr/data/catalog_index.json +1 -0
- tlgr/data/parity_waivers.toml +90 -0
- tlgr/filters/__init__.py +42 -0
- tlgr/filters/compose.py +121 -0
- tlgr/filters/content.py +85 -0
- tlgr/filters/context.py +114 -0
- tlgr/filters/message.py +161 -0
- tlgr/filters/temporal.py +87 -0
- tlgr/filters/user.py +36 -0
- tlgr/gateway/__init__.py +1 -0
- tlgr/gateway/config.py +161 -0
- tlgr/gateway/engine.py +215 -0
- tlgr/gateway/event.py +22 -0
- tlgr/jobs/__init__.py +0 -0
- tlgr/jobs/base.py +81 -0
- tlgr/jobs/client.py +37 -0
- tlgr/models/__init__.py +1220 -0
- tlgr/models/admin.py +744 -0
- tlgr/models/auth.py +510 -0
- tlgr/models/base.py +81 -0
- tlgr/models/bot.py +576 -0
- tlgr/models/business.py +265 -0
- tlgr/models/call.py +586 -0
- tlgr/models/config.py +101 -0
- tlgr/models/contact.py +481 -0
- tlgr/models/daemon.py +336 -0
- tlgr/models/dialog.py +626 -0
- tlgr/models/envelope.py +68 -0
- tlgr/models/error.py +30 -0
- tlgr/models/event.py +79 -0
- tlgr/models/export.py +66 -0
- tlgr/models/gift.py +275 -0
- tlgr/models/inline.py +84 -0
- tlgr/models/location.py +115 -0
- tlgr/models/media.py +507 -0
- tlgr/models/message.py +584 -0
- tlgr/models/net.py +232 -0
- tlgr/models/notify.py +105 -0
- tlgr/models/page.py +32 -0
- tlgr/models/payment.py +172 -0
- tlgr/models/peer.py +400 -0
- tlgr/models/poll.py +119 -0
- tlgr/models/premium.py +161 -0
- tlgr/models/privacy.py +93 -0
- tlgr/models/profile.py +217 -0
- tlgr/models/reaction.py +160 -0
- tlgr/models/resolve.py +175 -0
- tlgr/models/settings.py +103 -0
- tlgr/models/stars.py +101 -0
- tlgr/models/sticker.py +243 -0
- tlgr/models/story.py +467 -0
- tlgr/models/sync.py +105 -0
- tlgr/models/todo.py +36 -0
- tlgr/models/webapp.py +89 -0
- tlgr/ops/__init__.py +63 -0
- tlgr/ops/_admin.py +313 -0
- tlgr/ops/_auth.py +599 -0
- tlgr/ops/_bots.py +586 -0
- tlgr/ops/_calls.py +535 -0
- tlgr/ops/_common.py +160 -0
- tlgr/ops/_layer.py +46 -0
- tlgr/ops/_media.py +592 -0
- tlgr/ops/_params.py +212 -0
- tlgr/ops/_rights.py +402 -0
- tlgr/ops/_send.py +593 -0
- tlgr/ops/_serialize.py +667 -0
- tlgr/ops/_settings.py +306 -0
- tlgr/ops/_spec.py +167 -0
- tlgr/ops/_story.py +743 -0
- tlgr/ops/account.py +2604 -0
- tlgr/ops/agent.py +937 -0
- tlgr/ops/auth.py +1282 -0
- tlgr/ops/bot.py +4880 -0
- tlgr/ops/business.py +1520 -0
- tlgr/ops/call.py +1610 -0
- tlgr/ops/chat.py +4025 -0
- tlgr/ops/chat_admin.py +929 -0
- tlgr/ops/chat_extra.py +1061 -0
- tlgr/ops/chat_invite.py +716 -0
- tlgr/ops/chat_manage.py +1691 -0
- tlgr/ops/chat_member.py +1357 -0
- tlgr/ops/chat_stats.py +902 -0
- tlgr/ops/chat_topic.py +905 -0
- tlgr/ops/conference.py +791 -0
- tlgr/ops/config.py +1698 -0
- tlgr/ops/contact.py +2330 -0
- tlgr/ops/daemon.py +1397 -0
- tlgr/ops/draft.py +299 -0
- tlgr/ops/emoji.py +343 -0
- tlgr/ops/events.py +1327 -0
- tlgr/ops/export.py +596 -0
- tlgr/ops/folder.py +1322 -0
- tlgr/ops/gif.py +522 -0
- tlgr/ops/gift.py +1546 -0
- tlgr/ops/giveaway.py +541 -0
- tlgr/ops/inline.py +773 -0
- tlgr/ops/job.py +799 -0
- tlgr/ops/location.py +917 -0
- tlgr/ops/media.py +4495 -0
- tlgr/ops/message.py +3769 -0
- tlgr/ops/net.py +536 -0
- tlgr/ops/notify.py +840 -0
- tlgr/ops/passport.py +464 -0
- tlgr/ops/payment.py +907 -0
- tlgr/ops/poll.py +1078 -0
- tlgr/ops/premium.py +488 -0
- tlgr/ops/privacy.py +794 -0
- tlgr/ops/profile.py +1481 -0
- tlgr/ops/proxy.py +750 -0
- tlgr/ops/reaction.py +1475 -0
- tlgr/ops/resolve.py +1140 -0
- tlgr/ops/search.py +521 -0
- tlgr/ops/settings.py +1066 -0
- tlgr/ops/stars.py +594 -0
- tlgr/ops/sticker.py +1602 -0
- tlgr/ops/story.py +3216 -0
- tlgr/ops/sync.py +788 -0
- tlgr/ops/todo.py +514 -0
- tlgr/ops/user.py +1406 -0
- tlgr/ops/vc.py +2351 -0
- tlgr/ops/webapp.py +717 -0
- tlgr/ops/webhook.py +418 -0
- tlgr/parity.py +386 -0
- tlgr/processors/__init__.py +125 -0
- tlgr/processors/regex.py +26 -0
- tlgr/processors/text.py +56 -0
- tlgr/registry.py +519 -0
- tlgr/schema.py +173 -0
- tlgr/transport/__init__.py +30 -0
- tlgr/transport/autostart.py +293 -0
- tlgr/transport/client.py +805 -0
- tlgr/transport/ndjson.py +44 -0
- tlgr/version.py +31 -0
- tlgr_cli-2.0.1.dist-info/METADATA +957 -0
- tlgr_cli-2.0.1.dist-info/RECORD +192 -0
- tlgr_cli-2.0.1.dist-info/WHEEL +5 -0
- tlgr_cli-2.0.1.dist-info/entry_points.txt +2 -0
- tlgr_cli-2.0.1.dist-info/licenses/LICENSE +21 -0
- tlgr_cli-2.0.1.dist-info/top_level.txt +1 -0
tlgr/models/call.py
ADDED
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
"""Call shapes: 1:1 calls, video chats, livestreams and conferences.
|
|
2
|
+
|
|
3
|
+
One thing is true of every model in here and is stated on the wire rather than
|
|
4
|
+
in a footnote: **tlgr is a control plane**. It rings, answers, mutes, invites,
|
|
5
|
+
records and reads state; it never carries audio or video, because there is no
|
|
6
|
+
tgcalls binding behind it. Every shape that describes something a media engine
|
|
7
|
+
would otherwise be doing therefore carries a `media` field, and its value is
|
|
8
|
+
always `"none"` — a caller that asks tlgr to "join a call" learns from the
|
|
9
|
+
answer, not from the manual, that nobody can hear it.
|
|
10
|
+
|
|
11
|
+
The second recurring shape is `CallRef`. Telegram addresses a group call by
|
|
12
|
+
`(id, access_hash)`, a conference additionally by an invite `slug`, and an
|
|
13
|
+
invitation by the service message that carries it; a caller that has any one
|
|
14
|
+
of those must be able to feed it back to the next command, so every group-call
|
|
15
|
+
response echoes the whole reference rather than a bare id.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
from tlgr.models.base import Model
|
|
23
|
+
from tlgr.models.peer import Peer
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"MEDIA_NONE",
|
|
27
|
+
"ActiveCall",
|
|
28
|
+
"Call",
|
|
29
|
+
"CallConfig",
|
|
30
|
+
"CallDebugUpload",
|
|
31
|
+
"CallDeclined",
|
|
32
|
+
"CallEnded",
|
|
33
|
+
"CallEvent",
|
|
34
|
+
"CallIdentity",
|
|
35
|
+
"CallLogDeleted",
|
|
36
|
+
"CallLogEntry",
|
|
37
|
+
"CallRating",
|
|
38
|
+
"CallRef",
|
|
39
|
+
"CallSignal",
|
|
40
|
+
"CallUpgrade",
|
|
41
|
+
"ChainBlock",
|
|
42
|
+
"ConferenceCreated",
|
|
43
|
+
"ConferenceDeclined",
|
|
44
|
+
"ConferenceInfo",
|
|
45
|
+
"ConferenceInvited",
|
|
46
|
+
"ConferenceRelayed",
|
|
47
|
+
"ConferenceRemoved",
|
|
48
|
+
"ConferenceRevoked",
|
|
49
|
+
"GroupCall",
|
|
50
|
+
"GroupCallCreated",
|
|
51
|
+
"GroupCallEnded",
|
|
52
|
+
"GroupCallEvent",
|
|
53
|
+
"GroupCallInvited",
|
|
54
|
+
"GroupCallJoined",
|
|
55
|
+
"GroupCallLeft",
|
|
56
|
+
"GroupCallLink",
|
|
57
|
+
"GroupCallParticipant",
|
|
58
|
+
"GroupCallSettings",
|
|
59
|
+
"GroupCallStarted",
|
|
60
|
+
"InCallMessage",
|
|
61
|
+
"InCallMessagesDeleted",
|
|
62
|
+
"MuteState",
|
|
63
|
+
"ParticipantRemoved",
|
|
64
|
+
"RaisedHand",
|
|
65
|
+
"RtmpInfo",
|
|
66
|
+
"StreamChannel",
|
|
67
|
+
"StreamDownload",
|
|
68
|
+
"VideoState",
|
|
69
|
+
"VolumeState",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
MEDIA_NONE = "none"
|
|
73
|
+
"""The only value `media` ever takes.
|
|
74
|
+
|
|
75
|
+
Declared **without a default** on every model that carries it, because
|
|
76
|
+
`Model` omits defaults from the JSON and a promise that disappears from the
|
|
77
|
+
wire is not a promise. Every construction site therefore repeats
|
|
78
|
+
`media=MEDIA_NONE` by hand, and mypy notices when a new one forgets.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class CallRef(Model):
|
|
83
|
+
"""How a group call, conference or live story is addressed and echoed.
|
|
84
|
+
|
|
85
|
+
`slug` is the shareable half of a conference link and `msg_id` the
|
|
86
|
+
invitation service message; both are alternative ways of naming the same
|
|
87
|
+
call, and a response carries whichever the server told us about.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
id: int = 0
|
|
91
|
+
access_hash: int | None = None
|
|
92
|
+
slug: str | None = None
|
|
93
|
+
msg_id: int | None = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# ---------------------------------------------------------------------------
|
|
97
|
+
# 1:1 calls
|
|
98
|
+
# ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class Call(Model):
|
|
102
|
+
"""A 1:1 voice or video call, as far as signalling can see it.
|
|
103
|
+
|
|
104
|
+
`state` is the `phoneCall*` constructor reduced to a word — `waiting`,
|
|
105
|
+
`requested`, `accepted`, `active`, `discarded`, `empty` — because the
|
|
106
|
+
constructor name is the only place the ringing state machine is written
|
|
107
|
+
down, and a caller scripting "wait until it is answered" needs it.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
call_id: int
|
|
111
|
+
state: str
|
|
112
|
+
media: str
|
|
113
|
+
video: bool = False
|
|
114
|
+
peer: Peer | None = None
|
|
115
|
+
access_hash: int | None = None
|
|
116
|
+
admin_id: int | None = None
|
|
117
|
+
participant_id: int | None = None
|
|
118
|
+
out: bool = False
|
|
119
|
+
date: str | None = None
|
|
120
|
+
date_unix: int | None = None
|
|
121
|
+
conference_supported: bool | None = None
|
|
122
|
+
#: The four-emoji key verification, when *this* session ran the DH
|
|
123
|
+
#: exchange. Null otherwise: it cannot be derived from the server's view.
|
|
124
|
+
fingerprint: list[str] | None = None
|
|
125
|
+
connections: int = 0
|
|
126
|
+
protocol: dict[str, Any] | None = None
|
|
127
|
+
need_rating: bool | None = None
|
|
128
|
+
need_debug: bool | None = None
|
|
129
|
+
reason: str | None = None
|
|
130
|
+
duration: int | None = None
|
|
131
|
+
can_call: bool | None = None
|
|
132
|
+
can_video_call: bool | None = None
|
|
133
|
+
private: bool | None = None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class CallEnded(Model):
|
|
137
|
+
call_id: int
|
|
138
|
+
reason: str
|
|
139
|
+
duration: int = 0
|
|
140
|
+
need_rating: bool = False
|
|
141
|
+
need_debug: bool = False
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class CallDeclined(Model):
|
|
145
|
+
call_id: int
|
|
146
|
+
reason: str
|
|
147
|
+
reply_message_id: int | None = None
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class CallRating(Model):
|
|
151
|
+
call_id: int
|
|
152
|
+
rating: int
|
|
153
|
+
comment: str = ""
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class CallDebugUpload(Model):
|
|
157
|
+
call_id: int
|
|
158
|
+
uploaded: list[str] = []
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class CallConfig(Model):
|
|
162
|
+
"""Everything a client needs before it can ring.
|
|
163
|
+
|
|
164
|
+
`dh` is reported only with the validation verdict beside it: the prime
|
|
165
|
+
comes from the server and a client that trusts it blind has no key
|
|
166
|
+
exchange, it has a key the server chose.
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
tgcalls_config: dict[str, Any] | None = None
|
|
170
|
+
timeouts: dict[str, int] = {}
|
|
171
|
+
dh: dict[str, Any] | None = None
|
|
172
|
+
call_requests_disabled: bool | None = None
|
|
173
|
+
conference_call_size_limit: int | None = None
|
|
174
|
+
limits: dict[str, int] = {}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class CallLogEntry(Model):
|
|
178
|
+
"""One row of the Calls tab, decoded from its service message."""
|
|
179
|
+
|
|
180
|
+
msg_id: int
|
|
181
|
+
chat_id: int
|
|
182
|
+
date: str
|
|
183
|
+
date_unix: int
|
|
184
|
+
kind: str
|
|
185
|
+
direction: str
|
|
186
|
+
peer: Peer | None = None
|
|
187
|
+
call_id: int | None = None
|
|
188
|
+
video: bool = False
|
|
189
|
+
reason: str | None = None
|
|
190
|
+
duration: int = 0
|
|
191
|
+
missed: bool = False
|
|
192
|
+
active: bool | None = None
|
|
193
|
+
other_participants: list[Peer] = []
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class CallLogDeleted(Model):
|
|
197
|
+
deleted: int = 0
|
|
198
|
+
revoked: bool = False
|
|
199
|
+
offset: int = 0
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class CallSignal(Model):
|
|
203
|
+
"""One tgcalls signalling packet, in either direction, base64-encoded."""
|
|
204
|
+
|
|
205
|
+
direction: str
|
|
206
|
+
call_id: int
|
|
207
|
+
data: str
|
|
208
|
+
at: str
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class CallEvent(Model):
|
|
212
|
+
"""A line of `call watch`.
|
|
213
|
+
|
|
214
|
+
`should_ring` is the CLI's verdict, not a server field: a conference
|
|
215
|
+
invitation rings only when the app-config allows call requests and the
|
|
216
|
+
action is neither missed nor already active, and resolving that once here
|
|
217
|
+
is what keeps every notifier script from getting it wrong.
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
kind: str
|
|
221
|
+
at: str
|
|
222
|
+
call_id: int | None = None
|
|
223
|
+
peer: Peer | None = None
|
|
224
|
+
video: bool = False
|
|
225
|
+
state: str | None = None
|
|
226
|
+
msg_id: int | None = None
|
|
227
|
+
other_participants: list[Peer] = []
|
|
228
|
+
should_ring: bool | None = None
|
|
229
|
+
data: str | None = None
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class CallUpgrade(Model):
|
|
233
|
+
"""`call invite`: the 1:1 call became a conference."""
|
|
234
|
+
|
|
235
|
+
call_id: int
|
|
236
|
+
conference: CallRef | None = None
|
|
237
|
+
slug: str | None = None
|
|
238
|
+
invite_link: str | None = None
|
|
239
|
+
invited: list[Peer] = []
|
|
240
|
+
migrated: bool = False
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
# ---------------------------------------------------------------------------
|
|
244
|
+
# Group calls: video chats, livestreams, live stories, conferences
|
|
245
|
+
# ---------------------------------------------------------------------------
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class StreamChannel(Model):
|
|
249
|
+
channel: int
|
|
250
|
+
scale: int = 0
|
|
251
|
+
last_timestamp_ms: int = 0
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class GroupCall(Model):
|
|
255
|
+
"""A video chat, livestream, live story or conference.
|
|
256
|
+
|
|
257
|
+
`kind` is derived, not sent: the server has one `groupCall` constructor
|
|
258
|
+
for all four products and the difference is in the flags (`conference`,
|
|
259
|
+
`rtmp_stream`) and in the peer it hangs off.
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
call: CallRef
|
|
263
|
+
media: str
|
|
264
|
+
kind: str = "video-chat"
|
|
265
|
+
title: str | None = None
|
|
266
|
+
participants_count: int = 0
|
|
267
|
+
join_muted: bool = False
|
|
268
|
+
can_change_join_muted: bool = False
|
|
269
|
+
messages_enabled: bool = False
|
|
270
|
+
can_change_messages_enabled: bool = False
|
|
271
|
+
record_start_date: str | None = None
|
|
272
|
+
record_video_active: bool = False
|
|
273
|
+
rtmp_stream: bool = False
|
|
274
|
+
#: In a big livestream the participant list carries publishers only. A
|
|
275
|
+
#: caller must not read that as an empty audience — `participants_count`
|
|
276
|
+
#: is the real number.
|
|
277
|
+
listeners_hidden: bool = False
|
|
278
|
+
conference: bool = False
|
|
279
|
+
creator: bool = False
|
|
280
|
+
schedule_date: str | None = None
|
|
281
|
+
schedule_start_subscribed: bool = False
|
|
282
|
+
stream_dc_id: int | None = None
|
|
283
|
+
invite_link: str | None = None
|
|
284
|
+
send_paid_messages_stars: int | None = None
|
|
285
|
+
default_send_as: Peer | None = None
|
|
286
|
+
unmuted_video_count: int = 0
|
|
287
|
+
unmuted_video_limit: int = 0
|
|
288
|
+
version: int = 0
|
|
289
|
+
discarded: bool = False
|
|
290
|
+
duration: int | None = None
|
|
291
|
+
chat: Peer | None = None
|
|
292
|
+
limits: dict[str, int] | None = None
|
|
293
|
+
stream_channels: list[StreamChannel] | None = None
|
|
294
|
+
live_edge_ms: int | None = None
|
|
295
|
+
sources_joined: list[int] | None = None
|
|
296
|
+
sources_missing: list[int] | None = None
|
|
297
|
+
donors: dict[str, Any] | None = None
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class GroupCallParticipant(Model):
|
|
301
|
+
peer: Peer | None = None
|
|
302
|
+
source: int = 0
|
|
303
|
+
muted: bool = False
|
|
304
|
+
can_self_unmute: bool = False
|
|
305
|
+
muted_by_you: bool = False
|
|
306
|
+
volume: int | None = None
|
|
307
|
+
volume_by_admin: bool = False
|
|
308
|
+
raise_hand: bool = False
|
|
309
|
+
raise_hand_rating: int | None = None
|
|
310
|
+
video: bool = False
|
|
311
|
+
presentation: bool = False
|
|
312
|
+
video_joined: bool = False
|
|
313
|
+
is_self: bool = False
|
|
314
|
+
left: bool = False
|
|
315
|
+
about: str | None = None
|
|
316
|
+
joined_at: str | None = None
|
|
317
|
+
last_active: str | None = None
|
|
318
|
+
paid_stars_total: int | None = None
|
|
319
|
+
#: `joined`, `invited` or `calling` for a conference; null when only the
|
|
320
|
+
#: E2E chain would know, which needs a block parser tlgr does not have.
|
|
321
|
+
state: str | None = None
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class GroupCallCreated(Model):
|
|
325
|
+
call: CallRef
|
|
326
|
+
chat_id: int
|
|
327
|
+
kind: str = "video-chat"
|
|
328
|
+
title: str | None = None
|
|
329
|
+
schedule_date: str | None = None
|
|
330
|
+
rtmp_stream: bool = False
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class GroupCallStarted(Model):
|
|
334
|
+
call: CallRef
|
|
335
|
+
chat_id: int
|
|
336
|
+
started: bool
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
class GroupCallEnded(Model):
|
|
340
|
+
call: CallRef
|
|
341
|
+
ended: bool
|
|
342
|
+
duration: int | None = None
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class GroupCallSettings(Model):
|
|
346
|
+
"""What `vc set` changed, read back rather than echoed."""
|
|
347
|
+
|
|
348
|
+
call: CallRef
|
|
349
|
+
title: str | None = None
|
|
350
|
+
join_muted: bool | None = None
|
|
351
|
+
messages_enabled: bool | None = None
|
|
352
|
+
send_paid_messages_stars: int | None = None
|
|
353
|
+
schedule_start_subscribed: bool | None = None
|
|
354
|
+
record_start_date: str | None = None
|
|
355
|
+
record_video_active: bool | None = None
|
|
356
|
+
changed: list[str] = []
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class GroupCallJoined(Model):
|
|
360
|
+
call: CallRef
|
|
361
|
+
media: str
|
|
362
|
+
joined: bool
|
|
363
|
+
source: int = 0
|
|
364
|
+
mode: str = "webrtc"
|
|
365
|
+
join_as: Peer | None = None
|
|
366
|
+
can_self_unmute: bool = False
|
|
367
|
+
params: dict[str, Any] | None = None
|
|
368
|
+
experimental: bool = False
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class GroupCallLeft(Model):
|
|
372
|
+
call: CallRef
|
|
373
|
+
left: bool
|
|
374
|
+
source: int = 0
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
class GroupCallInvited(Model):
|
|
378
|
+
invited: list[Peer] = []
|
|
379
|
+
added: list[Peer] = []
|
|
380
|
+
failed: list[dict[str, Any]] = []
|
|
381
|
+
link_sent: list[Peer] = []
|
|
382
|
+
link: str | None = None
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
class GroupCallLink(Model):
|
|
386
|
+
kind: str
|
|
387
|
+
link: str | None = None
|
|
388
|
+
invite_hash: str | None = None
|
|
389
|
+
fallback: bool = False
|
|
390
|
+
revoked: bool = False
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class ActiveCall(Model):
|
|
394
|
+
"""One row of "chats with a call running right now"."""
|
|
395
|
+
|
|
396
|
+
chat: Peer | None = None
|
|
397
|
+
call: CallRef | None = None
|
|
398
|
+
chat_id: int = 0
|
|
399
|
+
title: str | None = None
|
|
400
|
+
participants_count: int = 0
|
|
401
|
+
active: bool = True
|
|
402
|
+
not_empty: bool = False
|
|
403
|
+
schedule_date: str | None = None
|
|
404
|
+
rtmp_stream: bool = False
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class CallIdentity(Model):
|
|
408
|
+
"""A peer you may appear as: "Display as" / "Comment as"."""
|
|
409
|
+
|
|
410
|
+
peer: Peer | None = None
|
|
411
|
+
kind: str = "join-as"
|
|
412
|
+
default: bool = False
|
|
413
|
+
is_self: bool = False
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
class RtmpInfo(Model):
|
|
417
|
+
"""RTMP ingest credentials. The key is a publishing credential.
|
|
418
|
+
|
|
419
|
+
It is masked unless the caller asked for it in so many words, because the
|
|
420
|
+
obvious thing to do with a CLI's output is paste it into a bug report.
|
|
421
|
+
"""
|
|
422
|
+
|
|
423
|
+
url: str = ""
|
|
424
|
+
key: str = ""
|
|
425
|
+
key_shown: bool = False
|
|
426
|
+
key_file: str | None = None
|
|
427
|
+
peer: Peer | None = None
|
|
428
|
+
live_story: bool = False
|
|
429
|
+
revoked: bool = False
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
class MuteState(Model):
|
|
433
|
+
call: CallRef
|
|
434
|
+
media: str
|
|
435
|
+
muted: bool
|
|
436
|
+
peer: Peer | None = None
|
|
437
|
+
can_self_unmute: bool | None = None
|
|
438
|
+
muted_by_you: bool = False
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
class RaisedHand(Model):
|
|
442
|
+
call: CallRef
|
|
443
|
+
raise_hand: bool
|
|
444
|
+
peer: Peer | None = None
|
|
445
|
+
raise_hand_rating: int | None = None
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
class VolumeState(Model):
|
|
449
|
+
call: CallRef
|
|
450
|
+
peer: Peer | None = None
|
|
451
|
+
volume: int = 100
|
|
452
|
+
volume_by_admin: bool = False
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
class VideoState(Model):
|
|
456
|
+
call: CallRef
|
|
457
|
+
media: str
|
|
458
|
+
video_stopped: bool | None = None
|
|
459
|
+
video_paused: bool | None = None
|
|
460
|
+
presentation: bool | None = None
|
|
461
|
+
presentation_paused: bool | None = None
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
class ParticipantRemoved(Model):
|
|
465
|
+
chat_id: int
|
|
466
|
+
removed: bool
|
|
467
|
+
peer: Peer | None = None
|
|
468
|
+
banned: bool = False
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class InCallMessage(Model):
|
|
472
|
+
"""A message on the in-call overlay. It has no history: read it live."""
|
|
473
|
+
|
|
474
|
+
call: CallRef
|
|
475
|
+
msg_id: int = 0
|
|
476
|
+
from_id: Peer | None = None
|
|
477
|
+
date: str | None = None
|
|
478
|
+
date_unix: int | None = None
|
|
479
|
+
text: str = ""
|
|
480
|
+
paid_message_stars: int | None = None
|
|
481
|
+
ttl: int | None = None
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
class InCallMessagesDeleted(Model):
|
|
485
|
+
call: CallRef
|
|
486
|
+
deleted: list[int] = []
|
|
487
|
+
participant: Peer | None = None
|
|
488
|
+
reported: bool = False
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
class GroupCallEvent(Model):
|
|
492
|
+
"""A line of `vc watch`."""
|
|
493
|
+
|
|
494
|
+
kind: str
|
|
495
|
+
at: str
|
|
496
|
+
call: CallRef | None = None
|
|
497
|
+
version: int | None = None
|
|
498
|
+
participant: GroupCallParticipant | None = None
|
|
499
|
+
participants: list[GroupCallParticipant] = []
|
|
500
|
+
message: InCallMessage | None = None
|
|
501
|
+
connection: dict[str, Any] | None = None
|
|
502
|
+
blocks: list[str] = []
|
|
503
|
+
encrypted: str | None = None
|
|
504
|
+
resync: bool = False
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
class StreamDownload(Model):
|
|
508
|
+
"""What `vc download` wrote to disk."""
|
|
509
|
+
|
|
510
|
+
call: CallRef
|
|
511
|
+
media: str
|
|
512
|
+
out: str = "-"
|
|
513
|
+
bytes: int = 0
|
|
514
|
+
chunks: int = 0
|
|
515
|
+
mode: str = "stream"
|
|
516
|
+
stream_dc_id: int | None = None
|
|
517
|
+
first_time_ms: int | None = None
|
|
518
|
+
last_time_ms: int | None = None
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
# ---------------------------------------------------------------------------
|
|
522
|
+
# Conferences
|
|
523
|
+
# ---------------------------------------------------------------------------
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class ConferenceCreated(Model):
|
|
527
|
+
call: CallRef
|
|
528
|
+
media: str
|
|
529
|
+
joined: bool
|
|
530
|
+
slug: str | None = None
|
|
531
|
+
invite_link: str | None = None
|
|
532
|
+
creator: bool = True
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
class ConferenceInfo(Model):
|
|
536
|
+
call: CallRef
|
|
537
|
+
conference: bool
|
|
538
|
+
slug: str | None = None
|
|
539
|
+
invite_link: str | None = None
|
|
540
|
+
participants_count: int = 0
|
|
541
|
+
creator: bool = False
|
|
542
|
+
messages_enabled: bool = False
|
|
543
|
+
title: str | None = None
|
|
544
|
+
limits: dict[str, int] | None = None
|
|
545
|
+
qr: str | None = None
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
class ConferenceInvited(Model):
|
|
549
|
+
invited: list[Peer] = []
|
|
550
|
+
failed: list[dict[str, Any]] = []
|
|
551
|
+
link_sent: list[Peer] = []
|
|
552
|
+
link: str | None = None
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
class ConferenceDeclined(Model):
|
|
556
|
+
msg_id: int
|
|
557
|
+
declined: bool
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
class ConferenceRemoved(Model):
|
|
561
|
+
call: CallRef
|
|
562
|
+
removed: list[Peer] = []
|
|
563
|
+
only_left: bool = False
|
|
564
|
+
kicked: bool = False
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
class ConferenceRevoked(Model):
|
|
568
|
+
call: CallRef
|
|
569
|
+
revoked: bool
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
class ConferenceRelayed(Model):
|
|
573
|
+
"""`conference send`: tlgr carried opaque bytes it cannot read."""
|
|
574
|
+
|
|
575
|
+
call: CallRef
|
|
576
|
+
kind: str
|
|
577
|
+
sent: bool
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
class ChainBlock(Model):
|
|
581
|
+
"""One block of the conference's E2E chain, base64, unvalidated."""
|
|
582
|
+
|
|
583
|
+
sub_chain_id: int
|
|
584
|
+
height: int
|
|
585
|
+
block: str
|
|
586
|
+
next_offset: int | None = None
|
tlgr/models/config.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Local configuration shapes: keys, effective values, paths, validation.
|
|
2
|
+
|
|
3
|
+
`config get`/`set` are about **this installation** — identity, transport,
|
|
4
|
+
proxy, flood budget, presence policy, event buffer. The server's own
|
|
5
|
+
configuration is a different noun (`config server`, `config app`,
|
|
6
|
+
`config info`) and a different model file (`models/net.py`), because reading
|
|
7
|
+
`message_length_max` off Telegram and setting `daemon.idle_timeout` on this
|
|
8
|
+
machine have nothing in common but the word "config".
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from tlgr.models.base import Model
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"ConfigEntry",
|
|
19
|
+
"ConfigKey",
|
|
20
|
+
"ConfigPaths",
|
|
21
|
+
"ConfigValue",
|
|
22
|
+
"InitResult",
|
|
23
|
+
"ValidationIssue",
|
|
24
|
+
"ValidationReport",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ConfigKey(Model):
|
|
29
|
+
"""One documented knob, machine-readable so an agent need not read docs."""
|
|
30
|
+
|
|
31
|
+
key: str
|
|
32
|
+
type: str = "string"
|
|
33
|
+
default: Any = None
|
|
34
|
+
scope: str = "global"
|
|
35
|
+
section: str = ""
|
|
36
|
+
requires_restart: bool = False
|
|
37
|
+
secret: bool = False
|
|
38
|
+
help: str = ""
|
|
39
|
+
choices: list[str] = []
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ConfigEntry(Model):
|
|
43
|
+
"""One key's effective value, and where it came from."""
|
|
44
|
+
|
|
45
|
+
key: str
|
|
46
|
+
value: Any = None
|
|
47
|
+
default: Any = None
|
|
48
|
+
source: str = "default"
|
|
49
|
+
scope: str = "global"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ConfigValue(Model):
|
|
53
|
+
"""The result of a `config get` / `set` / `unset`."""
|
|
54
|
+
|
|
55
|
+
key: str
|
|
56
|
+
value: Any = None
|
|
57
|
+
previous: Any = None
|
|
58
|
+
default: Any = None
|
|
59
|
+
source: str = ""
|
|
60
|
+
help: str = ""
|
|
61
|
+
updated: bool = False
|
|
62
|
+
removed: bool = False
|
|
63
|
+
already: bool = False
|
|
64
|
+
requires_restart: bool = False
|
|
65
|
+
applied: bool = False
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ConfigPaths(Model):
|
|
69
|
+
"""Where everything lives. Session and secrets files are credentials."""
|
|
70
|
+
|
|
71
|
+
config_dir: str = ""
|
|
72
|
+
config: str = ""
|
|
73
|
+
jobs: str = ""
|
|
74
|
+
webhook: str = ""
|
|
75
|
+
secrets: str = ""
|
|
76
|
+
sessions: str = ""
|
|
77
|
+
logs: str = ""
|
|
78
|
+
socket: str = ""
|
|
79
|
+
pid: str = ""
|
|
80
|
+
dead_letter: str = ""
|
|
81
|
+
path: str | None = None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class InitResult(Model):
|
|
85
|
+
created: list[str] = []
|
|
86
|
+
skipped: list[str] = []
|
|
87
|
+
path: str = ""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class ValidationIssue(Model):
|
|
91
|
+
file: str
|
|
92
|
+
message: str
|
|
93
|
+
key: str | None = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class ValidationReport(Model):
|
|
97
|
+
ok: bool = True
|
|
98
|
+
valid: bool = True
|
|
99
|
+
files: list[str] = []
|
|
100
|
+
errors: list[ValidationIssue] = []
|
|
101
|
+
warnings: list[ValidationIssue] = []
|