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.
Files changed (192) hide show
  1. tlgr/__init__.py +3 -0
  2. tlgr/__main__.py +6 -0
  3. tlgr/actions/__init__.py +45 -0
  4. tlgr/actions/forward.py +74 -0
  5. tlgr/actions/reply.py +32 -0
  6. tlgr/cli/__init__.py +259 -0
  7. tlgr/cli/confirm.py +55 -0
  8. tlgr/cli/errors.py +84 -0
  9. tlgr/cli/gen.py +690 -0
  10. tlgr/cli/globals.py +273 -0
  11. tlgr/cli/introspect.py +170 -0
  12. tlgr/cli/params.py +189 -0
  13. tlgr/cli/render.py +418 -0
  14. tlgr/core/__init__.py +0 -0
  15. tlgr/core/accounts.py +384 -0
  16. tlgr/core/config.py +358 -0
  17. tlgr/core/custom_tl.py +170 -0
  18. tlgr/core/errors.py +687 -0
  19. tlgr/core/eventtypes.py +1170 -0
  20. tlgr/core/identity.py +127 -0
  21. tlgr/core/launchd.py +122 -0
  22. tlgr/core/logging.py +194 -0
  23. tlgr/core/media.py +134 -0
  24. tlgr/core/output.py +251 -0
  25. tlgr/core/pagination.py +227 -0
  26. tlgr/core/paths.py +360 -0
  27. tlgr/core/peers.py +427 -0
  28. tlgr/core/process.py +138 -0
  29. tlgr/core/signing.py +38 -0
  30. tlgr/core/systemd.py +96 -0
  31. tlgr/core/telethon_compat.py +295 -0
  32. tlgr/core/text.py +211 -0
  33. tlgr/core/timefmt.py +199 -0
  34. tlgr/core/tl.py +98 -0
  35. tlgr/daemon/__init__.py +0 -0
  36. tlgr/daemon/app.py +869 -0
  37. tlgr/daemon/dispatch.py +446 -0
  38. tlgr/daemon/events.py +723 -0
  39. tlgr/daemon/files.py +431 -0
  40. tlgr/daemon/idle.py +119 -0
  41. tlgr/daemon/jobs.py +68 -0
  42. tlgr/daemon/main.py +161 -0
  43. tlgr/daemon/peercred.py +75 -0
  44. tlgr/daemon/policy.py +113 -0
  45. tlgr/daemon/preauth.py +366 -0
  46. tlgr/daemon/ratelimit.py +391 -0
  47. tlgr/daemon/server.py +24 -0
  48. tlgr/daemon/session.py +648 -0
  49. tlgr/daemon/sessions.py +274 -0
  50. tlgr/daemon/singleton.py +114 -0
  51. tlgr/daemon/stream.py +193 -0
  52. tlgr/daemon/transfers.py +219 -0
  53. tlgr/daemon/webhook.py +390 -0
  54. tlgr/data/catalog_index.json +1 -0
  55. tlgr/data/parity_waivers.toml +90 -0
  56. tlgr/filters/__init__.py +42 -0
  57. tlgr/filters/compose.py +121 -0
  58. tlgr/filters/content.py +85 -0
  59. tlgr/filters/context.py +114 -0
  60. tlgr/filters/message.py +161 -0
  61. tlgr/filters/temporal.py +87 -0
  62. tlgr/filters/user.py +36 -0
  63. tlgr/gateway/__init__.py +1 -0
  64. tlgr/gateway/config.py +161 -0
  65. tlgr/gateway/engine.py +215 -0
  66. tlgr/gateway/event.py +22 -0
  67. tlgr/jobs/__init__.py +0 -0
  68. tlgr/jobs/base.py +81 -0
  69. tlgr/jobs/client.py +37 -0
  70. tlgr/models/__init__.py +1220 -0
  71. tlgr/models/admin.py +744 -0
  72. tlgr/models/auth.py +510 -0
  73. tlgr/models/base.py +81 -0
  74. tlgr/models/bot.py +576 -0
  75. tlgr/models/business.py +265 -0
  76. tlgr/models/call.py +586 -0
  77. tlgr/models/config.py +101 -0
  78. tlgr/models/contact.py +481 -0
  79. tlgr/models/daemon.py +336 -0
  80. tlgr/models/dialog.py +626 -0
  81. tlgr/models/envelope.py +68 -0
  82. tlgr/models/error.py +30 -0
  83. tlgr/models/event.py +79 -0
  84. tlgr/models/export.py +66 -0
  85. tlgr/models/gift.py +275 -0
  86. tlgr/models/inline.py +84 -0
  87. tlgr/models/location.py +115 -0
  88. tlgr/models/media.py +507 -0
  89. tlgr/models/message.py +584 -0
  90. tlgr/models/net.py +232 -0
  91. tlgr/models/notify.py +105 -0
  92. tlgr/models/page.py +32 -0
  93. tlgr/models/payment.py +172 -0
  94. tlgr/models/peer.py +400 -0
  95. tlgr/models/poll.py +119 -0
  96. tlgr/models/premium.py +161 -0
  97. tlgr/models/privacy.py +93 -0
  98. tlgr/models/profile.py +217 -0
  99. tlgr/models/reaction.py +160 -0
  100. tlgr/models/resolve.py +175 -0
  101. tlgr/models/settings.py +103 -0
  102. tlgr/models/stars.py +101 -0
  103. tlgr/models/sticker.py +243 -0
  104. tlgr/models/story.py +467 -0
  105. tlgr/models/sync.py +105 -0
  106. tlgr/models/todo.py +36 -0
  107. tlgr/models/webapp.py +89 -0
  108. tlgr/ops/__init__.py +63 -0
  109. tlgr/ops/_admin.py +313 -0
  110. tlgr/ops/_auth.py +599 -0
  111. tlgr/ops/_bots.py +586 -0
  112. tlgr/ops/_calls.py +535 -0
  113. tlgr/ops/_common.py +160 -0
  114. tlgr/ops/_layer.py +46 -0
  115. tlgr/ops/_media.py +592 -0
  116. tlgr/ops/_params.py +212 -0
  117. tlgr/ops/_rights.py +402 -0
  118. tlgr/ops/_send.py +593 -0
  119. tlgr/ops/_serialize.py +667 -0
  120. tlgr/ops/_settings.py +306 -0
  121. tlgr/ops/_spec.py +167 -0
  122. tlgr/ops/_story.py +743 -0
  123. tlgr/ops/account.py +2604 -0
  124. tlgr/ops/agent.py +937 -0
  125. tlgr/ops/auth.py +1282 -0
  126. tlgr/ops/bot.py +4880 -0
  127. tlgr/ops/business.py +1520 -0
  128. tlgr/ops/call.py +1610 -0
  129. tlgr/ops/chat.py +4025 -0
  130. tlgr/ops/chat_admin.py +929 -0
  131. tlgr/ops/chat_extra.py +1061 -0
  132. tlgr/ops/chat_invite.py +716 -0
  133. tlgr/ops/chat_manage.py +1691 -0
  134. tlgr/ops/chat_member.py +1357 -0
  135. tlgr/ops/chat_stats.py +902 -0
  136. tlgr/ops/chat_topic.py +905 -0
  137. tlgr/ops/conference.py +791 -0
  138. tlgr/ops/config.py +1698 -0
  139. tlgr/ops/contact.py +2330 -0
  140. tlgr/ops/daemon.py +1397 -0
  141. tlgr/ops/draft.py +299 -0
  142. tlgr/ops/emoji.py +343 -0
  143. tlgr/ops/events.py +1327 -0
  144. tlgr/ops/export.py +596 -0
  145. tlgr/ops/folder.py +1322 -0
  146. tlgr/ops/gif.py +522 -0
  147. tlgr/ops/gift.py +1546 -0
  148. tlgr/ops/giveaway.py +541 -0
  149. tlgr/ops/inline.py +773 -0
  150. tlgr/ops/job.py +799 -0
  151. tlgr/ops/location.py +917 -0
  152. tlgr/ops/media.py +4495 -0
  153. tlgr/ops/message.py +3769 -0
  154. tlgr/ops/net.py +536 -0
  155. tlgr/ops/notify.py +840 -0
  156. tlgr/ops/passport.py +464 -0
  157. tlgr/ops/payment.py +907 -0
  158. tlgr/ops/poll.py +1078 -0
  159. tlgr/ops/premium.py +488 -0
  160. tlgr/ops/privacy.py +794 -0
  161. tlgr/ops/profile.py +1481 -0
  162. tlgr/ops/proxy.py +750 -0
  163. tlgr/ops/reaction.py +1475 -0
  164. tlgr/ops/resolve.py +1140 -0
  165. tlgr/ops/search.py +521 -0
  166. tlgr/ops/settings.py +1066 -0
  167. tlgr/ops/stars.py +594 -0
  168. tlgr/ops/sticker.py +1602 -0
  169. tlgr/ops/story.py +3216 -0
  170. tlgr/ops/sync.py +788 -0
  171. tlgr/ops/todo.py +514 -0
  172. tlgr/ops/user.py +1406 -0
  173. tlgr/ops/vc.py +2351 -0
  174. tlgr/ops/webapp.py +717 -0
  175. tlgr/ops/webhook.py +418 -0
  176. tlgr/parity.py +386 -0
  177. tlgr/processors/__init__.py +125 -0
  178. tlgr/processors/regex.py +26 -0
  179. tlgr/processors/text.py +56 -0
  180. tlgr/registry.py +519 -0
  181. tlgr/schema.py +173 -0
  182. tlgr/transport/__init__.py +30 -0
  183. tlgr/transport/autostart.py +293 -0
  184. tlgr/transport/client.py +805 -0
  185. tlgr/transport/ndjson.py +44 -0
  186. tlgr/version.py +31 -0
  187. tlgr_cli-2.0.1.dist-info/METADATA +957 -0
  188. tlgr_cli-2.0.1.dist-info/RECORD +192 -0
  189. tlgr_cli-2.0.1.dist-info/WHEEL +5 -0
  190. tlgr_cli-2.0.1.dist-info/entry_points.txt +2 -0
  191. tlgr_cli-2.0.1.dist-info/licenses/LICENSE +21 -0
  192. 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] = []