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/media.py ADDED
@@ -0,0 +1,507 @@
1
+ """The media domain: what a file IS, where it went, and what it cost.
2
+
3
+ `MediaSummary` (models/message.py) answers "what is attached to this message"
4
+ in the space a message listing can afford. The shapes here answer the
5
+ questions the `media` group is actually asked — which sizes exist, what the
6
+ document id and access hash are, how far a transfer got, what the account's
7
+ own upload limits are — and they are deliberately separate models rather than
8
+ a wider `MediaSummary`, because a chat listing must not carry an access hash
9
+ and a file reference for every row.
10
+
11
+ Two conventions run through the file:
12
+
13
+ * **a byte string never crosses the wire raw.** `file_reference` and a
14
+ stripped thumbnail are base64, because JSON has no bytes and a caller that
15
+ round-trips one has to get the same bytes back.
16
+ * **an id is a *marked* id** (`chat_id`), and a document id is not — a
17
+ document has no peer arithmetic to disambiguate.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from typing import Any, Literal
23
+
24
+ from tlgr.models.base import Model
25
+ from tlgr.models.message import MediaKind, MessageEntity
26
+ from tlgr.models.peer import Peer
27
+
28
+ __all__ = [
29
+ "AutoDownloadPreset",
30
+ "AutoDownloadSaved",
31
+ "AutoDownloadSettings",
32
+ "AutoSaveException",
33
+ "AutoSaveRule",
34
+ "AutoSaveSaved",
35
+ "AutoSaveSettings",
36
+ "ContentSettings",
37
+ "ContentSettingsSaved",
38
+ "Downloaded",
39
+ "FileRef",
40
+ "MediaEdited",
41
+ "MediaEvent",
42
+ "MediaExportResult",
43
+ "MediaFile",
44
+ "MediaInfo",
45
+ "MediaItem",
46
+ "MediaLimits",
47
+ "MediaQuality",
48
+ "MediaRead",
49
+ "MediaSize",
50
+ "PaidItem",
51
+ "PaidPost",
52
+ "StorageCleared",
53
+ "StorageUsage",
54
+ "Transfer",
55
+ "TransferRestarted",
56
+ "TransferStopped",
57
+ "Uploaded",
58
+ "Wallpaper",
59
+ "WallpaperInstalled",
60
+ "WallpaperRemoved",
61
+ "WallpaperSettings",
62
+ "WallpaperUploaded",
63
+ ]
64
+
65
+ #: How a transfer is going. `cancelled` and `failed` are distinct because only
66
+ #: one of them is worth retrying automatically.
67
+ TransferState = Literal["queued", "running", "done", "failed", "cancelled"]
68
+
69
+
70
+ class MediaFile(Model):
71
+ """The handle half of a document: enough to fetch or re-send it.
72
+
73
+ Kept apart from the descriptive fields so that a listing can embed it
74
+ without every row growing an access hash it has no use for.
75
+ """
76
+
77
+ doc_id: int
78
+ access_hash: int | None = None
79
+ file_reference_b64: str | None = None
80
+ dc_id: int | None = None
81
+ mime: str | None = None
82
+ size: int | None = None
83
+ file_id: str | None = None
84
+
85
+
86
+ class MediaSize(Model):
87
+ """One `PhotoSize`/`VideoSize`/thumbnail variant.
88
+
89
+ `bytes_b64` is filled only for the inline sizes (`photoStrippedSize`,
90
+ `photoPathSize`), which are already in the message and cost no request:
91
+ that is the whole point of reporting them.
92
+ """
93
+
94
+ type: str
95
+ width: int | None = None
96
+ height: int | None = None
97
+ size: int | None = None
98
+ video: bool = False
99
+ bytes_b64: str | None = None
100
+
101
+
102
+ class MediaQuality(Model):
103
+ """One `alt_documents` transcode of a channel video."""
104
+
105
+ doc_id: int
106
+ mime: str | None = None
107
+ size: int | None = None
108
+ width: int | None = None
109
+ height: int | None = None
110
+ name: str | None = None
111
+
112
+
113
+ class MediaInfo(Model):
114
+ """Everything a message's media declares, without downloading a byte.
115
+
116
+ A strict superset of v1's `media_details()`: the kind is still decided
117
+ after collecting every `DocumentAttribute*` (a GIF carries Video *and*
118
+ Animated, so first-attribute-wins gets it wrong), and the ids, sizes,
119
+ album membership and protection state that a caller needs in order to do
120
+ anything with the file are added beside it.
121
+ """
122
+
123
+ chat_id: int
124
+ msg_id: int
125
+ kind: MediaKind
126
+ tl_type: str = ""
127
+ grouped_id: int | None = None
128
+ mime: str | None = None
129
+ size: int | None = None
130
+ file_name: str | None = None
131
+ width: int | None = None
132
+ height: int | None = None
133
+ duration: int | None = None
134
+ supports_streaming: bool = False
135
+ nosound: bool = False
136
+ round: bool = False
137
+ voice: bool = False
138
+ waveform: bool = False
139
+ title: str | None = None
140
+ performer: str | None = None
141
+ sticker: str | None = None
142
+ custom_emoji: str | None = None
143
+ spoiler: bool = False
144
+ ttl_seconds: int | None = None
145
+ video_cover: int | None = None
146
+ video_timestamp: int | None = None
147
+ has_stickers: bool = False
148
+ protected: bool = False
149
+ paid: int | None = None
150
+ dc_id: int | None = None
151
+ doc_id: int | None = None
152
+ access_hash: int | None = None
153
+ file_reference_b64: str | None = None
154
+ file_id: str | None = None
155
+ thumbs: list[MediaSize] = []
156
+ qualities: list[MediaQuality] = []
157
+ date: str = ""
158
+ date_unix: int = 0
159
+ caption: str = ""
160
+ entities: list[MessageEntity] = []
161
+ #: `--stickers`: sets baked into the photo/video.
162
+ attached_sets: list[str] = []
163
+ #: `--ads`: sponsored inserts, listed and never viewed or clicked.
164
+ ads: list[dict[str, Any]] = []
165
+ #: `--album`: the sibling messages sharing `grouped_id`.
166
+ album: list[MediaInfo] = []
167
+
168
+
169
+ class MediaItem(Model):
170
+ """One row of a shared-media listing.
171
+
172
+ The same model carries the `--counts` and `--calendar` projections, with
173
+ `count`/`period` filled instead of `msg_id`: they are three views of one
174
+ query and splitting them into three response types would make
175
+ `--select` mean something different per flag.
176
+ """
177
+
178
+ msg_id: int = 0
179
+ chat_id: int = 0
180
+ date: str = ""
181
+ date_unix: int = 0
182
+ kind: MediaKind | None = None
183
+ name: str | None = None
184
+ size: int | None = None
185
+ duration: int | None = None
186
+ mime: str | None = None
187
+ from_id: int | None = None
188
+ grouped_id: int | None = None
189
+ file_id: str | None = None
190
+ chat: Peer | None = None
191
+ #: `--counts` / `--calendar`: the media tab and how many it holds.
192
+ type: str | None = None
193
+ count: int | None = None
194
+ period: str | None = None
195
+
196
+
197
+ class Downloaded(Model):
198
+ """One file that landed on disk (or on stdout)."""
199
+
200
+ msg_id: int = 0
201
+ chat_id: int = 0
202
+ path: str = ""
203
+ bytes: int = 0
204
+ kind: str = ""
205
+ mime: str | None = None
206
+ sha256: str | None = None
207
+ file_id: str | None = None
208
+ elapsed_s: float = 0.0
209
+ skipped: bool = False
210
+ job_id: str | None = None
211
+
212
+
213
+ class Uploaded(Model):
214
+ """What a send produced: one message, an album, or just a file id."""
215
+
216
+ chat_id: int = 0
217
+ msg_id: int = 0
218
+ msg_ids: list[int] = []
219
+ grouped_id: int | None = None
220
+ kind: str = ""
221
+ file_id: str | None = None
222
+ doc_id: int | None = None
223
+ bytes: int = 0
224
+ elapsed_s: float = 0.0
225
+ #: A big-channel video the server is still converting.
226
+ processing: bool = False
227
+ scheduled_id: int | None = None
228
+ job_id: str | None = None
229
+
230
+
231
+ class MediaEdited(Model):
232
+ chat_id: int
233
+ msg_id: int
234
+ kind: str = ""
235
+ file_id: str | None = None
236
+ edit_date: str | None = None
237
+ caption: str = ""
238
+ changed: list[str] = []
239
+
240
+
241
+ class FileRef(Model):
242
+ """A portable file id, resolved and (where needed) refreshed.
243
+
244
+ `refreshed` is the interesting field: a file id carries a
245
+ `file_reference` that expires in hours, so the honest answer to "is this
246
+ id still usable" is "it is now, and here is whether I had to go and get
247
+ a new reference for it".
248
+ """
249
+
250
+ file_id: str
251
+ doc_id: int | None = None
252
+ access_hash: int | None = None
253
+ file_reference_b64: str | None = None
254
+ dc_id: int | None = None
255
+ kind: str = ""
256
+ mime: str | None = None
257
+ size: int | None = None
258
+ source: str | None = None
259
+ refreshed: bool = False
260
+ path: str | None = None
261
+
262
+
263
+ class MediaExportResult(Model):
264
+ job_id: str | None = None
265
+ chat_id: int = 0
266
+ planned: int = 0
267
+ downloaded: int = 0
268
+ skipped: int = 0
269
+ failed: int = 0
270
+ bytes: int = 0
271
+ manifest: str | None = None
272
+
273
+
274
+ class Transfer(Model):
275
+ """One entry of the Downloads panel — client-local state, as in the GUI."""
276
+
277
+ job_id: str
278
+ direction: Literal["download", "upload"] = "download"
279
+ chat_id: int | None = None
280
+ msg_id: int | None = None
281
+ name: str = ""
282
+ bytes_done: int = 0
283
+ bytes_total: int = 0
284
+ pct: float = 0.0
285
+ bps: int = 0
286
+ eta_s: int | None = None
287
+ state: TransferState = "queued"
288
+ path: str | None = None
289
+ error: str | None = None
290
+ started: str | None = None
291
+
292
+
293
+ class TransferStopped(Model):
294
+ job_ids: list[str] = []
295
+ cancelled: int = 0
296
+ kept_partial: bool = True
297
+ already: bool = False
298
+
299
+
300
+ class TransferRestarted(Model):
301
+ job_ids: list[str] = []
302
+ restarted: int = 0
303
+ resumed_from: int = 0
304
+
305
+
306
+ class MediaRead(Model):
307
+ chat_id: int
308
+ msg_ids: list[int] = []
309
+ marked: int = 0
310
+ already: bool = False
311
+
312
+
313
+ class MediaLimits(Model):
314
+ """The server's own limits, never hardcoded.
315
+
316
+ Read before an upload rather than after it: `upload_max_fileparts` is the
317
+ difference between a named refusal and a `FILE_PARTS_INVALID` twenty
318
+ minutes into a 2 GB transfer.
319
+ """
320
+
321
+ premium: bool = False
322
+ upload_max_fileparts: int = 0
323
+ upload_max_bytes: int = 0
324
+ part_size: int = 0
325
+ caption_length_limit: int = 0
326
+ message_length_limit: int = 0
327
+ album_size_max: int = 0
328
+ stickers_installed_limit: int = 0
329
+ stickers_faved_limit: int = 0
330
+ stickers_recent_limit: int = 0
331
+ saved_gifs_limit: int = 0
332
+ ringtone_size_max: int = 0
333
+ ringtone_duration_max: int = 0
334
+ stars_paid_post_amount_max: int = 0
335
+ premium_speedup_upload: int = 0
336
+ premium_speedup_download: int = 0
337
+
338
+
339
+ class AutoDownloadPreset(Model):
340
+ preset: str
341
+ disabled: bool = False
342
+ photo_size_max: int = 0
343
+ video_size_max: int = 0
344
+ file_size_max: int = 0
345
+ video_upload_maxbitrate: int = 0
346
+ video_preload_large: bool = False
347
+ audio_preload_next: bool = False
348
+ phonecalls_less_data: bool = False
349
+ stories_preload: bool = False
350
+
351
+
352
+ class AutoDownloadSettings(Model):
353
+ presets: list[AutoDownloadPreset] = []
354
+
355
+
356
+ class AutoDownloadSaved(Model):
357
+ preset: str
358
+ ok: bool = True
359
+ settings: AutoDownloadPreset | None = None
360
+
361
+
362
+ class AutoSaveRule(Model):
363
+ photos: bool = False
364
+ videos: bool = False
365
+ video_max_size: int | None = None
366
+
367
+
368
+ class AutoSaveException(Model):
369
+ chat_id: int
370
+ chat: Peer | None = None
371
+ rule: AutoSaveRule | None = None
372
+
373
+
374
+ class AutoSaveSettings(Model):
375
+ users: AutoSaveRule | None = None
376
+ chats: AutoSaveRule | None = None
377
+ broadcasts: AutoSaveRule | None = None
378
+ exceptions: list[AutoSaveException] = []
379
+
380
+
381
+ class AutoSaveSaved(Model):
382
+ scope: str
383
+ ok: bool = True
384
+ settings: AutoSaveRule | None = None
385
+ cleared_exceptions: bool = False
386
+
387
+
388
+ class ContentSettings(Model):
389
+ # Neither field carries a default: both states of a two-state setting
390
+ # matter, and `omit_defaults` would drop whichever one happened to equal
391
+ # the default — leaving a caller unable to tell "off" from "not reported".
392
+ sensitive_enabled: bool
393
+ sensitive_can_change: bool
394
+ age_verification_required: bool = False
395
+ age_verification_bot: str | None = None
396
+ reason: str | None = None
397
+
398
+
399
+ class ContentSettingsSaved(Model):
400
+ sensitive_enabled: bool
401
+ ok: bool = True
402
+ already: bool = False
403
+
404
+
405
+ class StorageUsage(Model):
406
+ root: str
407
+ bytes: int = 0
408
+ files: int = 0
409
+ partials: int = 0
410
+ oldest: str | None = None
411
+ by_chat: dict[str, int] = {}
412
+ by_type: dict[str, int] = {}
413
+ keep_days: int | None = None
414
+
415
+
416
+ class StorageCleared(Model):
417
+ deleted_files: int = 0
418
+ freed_bytes: int = 0
419
+ kept_files: int = 0
420
+ keep_days: int | None = None
421
+ dry_run: bool = False
422
+
423
+
424
+ class PaidItem(Model):
425
+ kind: str = "preview"
426
+ width: int | None = None
427
+ height: int | None = None
428
+ duration: int | None = None
429
+ doc_id: int | None = None
430
+ unlocked: bool = False
431
+
432
+
433
+ class PaidPost(Model):
434
+ chat_id: int
435
+ msg_id: int
436
+ stars_amount: int = 0
437
+ item_count: int = 0
438
+ unlocked: bool = False
439
+ items: list[PaidItem] = []
440
+ date: str = ""
441
+ date_unix: int = 0
442
+ caption: str = ""
443
+
444
+
445
+ class WallpaperSettings(Model):
446
+ blur: bool = False
447
+ motion: bool = False
448
+ intensity: int | None = None
449
+ rotation: int | None = None
450
+ colors: list[str] = []
451
+
452
+
453
+ class Wallpaper(Model):
454
+ id: int
455
+ access_hash: int | None = None
456
+ slug: str | None = None
457
+ kind: Literal["image", "pattern", "fill"] = "image"
458
+ pattern: bool = False
459
+ dark: bool = False
460
+ creator: bool = False
461
+ default: bool = False
462
+ colors: list[str] = []
463
+ blur: bool = False
464
+ motion: bool = False
465
+ intensity: int | None = None
466
+ rotation: int | None = None
467
+ document: MediaFile | None = None
468
+ link: str | None = None
469
+
470
+
471
+ class WallpaperInstalled(Model):
472
+ slug: str | None = None
473
+ installed: bool = False
474
+ saved: bool = False
475
+ reset: bool = False
476
+ settings: WallpaperSettings | None = None
477
+ already: bool = False
478
+
479
+
480
+ class WallpaperRemoved(Model):
481
+ slugs: list[str] = []
482
+ removed: int = 0
483
+ already: bool = False
484
+
485
+
486
+ class WallpaperUploaded(Model):
487
+ id: int
488
+ access_hash: int | None = None
489
+ slug: str | None = None
490
+ link: str | None = None
491
+ settings: WallpaperSettings | None = None
492
+
493
+
494
+ class MediaEvent(Model):
495
+ """One frame of `media watch`."""
496
+
497
+ event: str = "media"
498
+ chat_id: int = 0
499
+ msg_id: int = 0
500
+ kind: str = ""
501
+ mime: str | None = None
502
+ size: int | None = None
503
+ duration: int | None = None
504
+ from_id: int | None = None
505
+ file_id: str | None = None
506
+ path: str | None = None
507
+ date: str = ""