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/event.py ADDED
@@ -0,0 +1,79 @@
1
+ """The event envelope, and the shapes that describe the event vocabulary.
2
+
3
+ The envelope is the wire shape every consumer sees. `EventType` and
4
+ `EventTypeDetail` are the *catalogue* shapes: what `tlgr events list` and
5
+ `tlgr events get` print so that an agent can discover the subscribable surface
6
+ before it opens a stream, rather than learning it from prose.
7
+
8
+ The vocabulary itself lives in `tlgr/core/eventtypes.py`; only its shape is
9
+ here, because `models/` imports nothing from tlgr (§2.2).
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import Any
15
+
16
+ from tlgr.models.base import Model
17
+
18
+ __all__ = [
19
+ "DecodedEvent",
20
+ "EventEnvelope",
21
+ "EventType",
22
+ "EventTypeDetail",
23
+ ]
24
+
25
+
26
+ class EventEnvelope(Model):
27
+ seq: int
28
+ ts: str
29
+ account: str
30
+ type: str
31
+ payload: dict[str, Any] = {}
32
+ chat_id: int | None = None
33
+ sender_id: int | None = None
34
+ # True when this event echoes an action tlgr itself performed, so a
35
+ # gateway rule cannot loop by reacting to its own output.
36
+ self_origin: bool = False
37
+ #: The raw TL update, JSON-safe, when the consumer asked for it
38
+ #: (`watch --with-raw`). Absent otherwise: it roughly doubles the frame.
39
+ raw: dict[str, Any] | None = None
40
+
41
+
42
+ class EventType(Model):
43
+ """One row of `tlgr events list`."""
44
+
45
+ type: str
46
+ group: str
47
+ summary: str
48
+ #: The `Update*` constructors that produce it.
49
+ sources: list[str] = []
50
+ telethon: str = ""
51
+ #: Which sequence box orders it: pts, qts, seq, channel_pts, version, none.
52
+ box: str = "none"
53
+ bot_only: bool = False
54
+ #: 0 when this build can parse every source; 229 when Telegram has the
55
+ #: constructor and Telethon 1.44 does not.
56
+ since_layer: int = 0
57
+ available: bool = True
58
+ derived: str = ""
59
+
60
+
61
+ class EventTypeDetail(EventType):
62
+ """`tlgr events get <type>`: the row, plus the payload and an example."""
63
+
64
+ payload: dict[str, str] = {}
65
+ json_schema: dict[str, Any] | None = None
66
+ filters: list[str] = []
67
+ example: EventEnvelope | None = None
68
+
69
+
70
+ class DecodedEvent(Model):
71
+ """`tlgr events decode`: one TL update or push payload, made a tlgr event."""
72
+
73
+ event: str
74
+ account: str = ""
75
+ chat_id: int | None = None
76
+ sender_id: int | None = None
77
+ data: dict[str, Any] = {}
78
+ raw: dict[str, Any] | None = None
79
+ push: bool = False
tlgr/models/export.py ADDED
@@ -0,0 +1,66 @@
1
+ """Takeout (data export) shapes.
2
+
3
+ A takeout session is a *mode*, not a request: once `account.initTakeoutSession`
4
+ returns an id, every subsequent call — `upload.getFile` included — has to be
5
+ wrapped in `invokeWithTakeout`, and `file_max_size` can never be changed. The
6
+ model therefore records the scope it was opened with, because a caller that
7
+ forgets it will simply get nothing back and no error.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from tlgr.models.base import Model
13
+
14
+ __all__ = [
15
+ "ExportResult",
16
+ "ExportedFile",
17
+ "MessageRange",
18
+ "TakeoutSession",
19
+ "TakeoutStatus",
20
+ ]
21
+
22
+
23
+ class TakeoutSession(Model):
24
+ takeout_id: int | None = None
25
+ scope: list[str] = []
26
+ started_at: str | None = None
27
+ expires: str | None = None
28
+ max_file_size: int = 0
29
+ #: TAKEOUT_INIT_DELAY_X: another logged-in session has to approve the
30
+ #: export first (24 h if there is none). Reported, never slept through
31
+ #: silently.
32
+ approval_required: bool = False
33
+ retry_after: int | None = None
34
+ already: bool = False
35
+
36
+
37
+ class MessageRange(Model):
38
+ min_id: int = 0
39
+ max_id: int = 0
40
+
41
+
42
+ class TakeoutStatus(Model):
43
+ #: No default: "is an export open" is the question, and a `Model` omits a
44
+ #: field equal to its default.
45
+ active: bool
46
+ takeout_id: int | None = None
47
+ started_at: str | None = None
48
+ scope: list[str] = []
49
+ max_file_size: int = 0
50
+ ranges: list[MessageRange] = []
51
+
52
+
53
+ class ExportedFile(Model):
54
+ path: str
55
+ kind: str = ""
56
+ bytes: int = 0
57
+
58
+
59
+ class ExportResult(Model):
60
+ written: int = 0
61
+ files: list[ExportedFile] = []
62
+ out: str = ""
63
+ finished: bool = False
64
+ takeout_id: int | None = None
65
+ success: bool = True
66
+ skipped: list[str] = []
tlgr/models/gift.py ADDED
@@ -0,0 +1,275 @@
1
+ """Star gifts: the catalogue, the gifts a profile holds, collectibles,
2
+ collections, the resale market and the auctions.
3
+
4
+ A gift is addressed by a **reference**, not an id, and `ref` is that string
5
+ everywhere in this module: `msg:<id>` for a gift I received in a private
6
+ chat, `<peer>:<saved_id>` for one held by a channel, or a bare collectible
7
+ slug. One spelling, so a `ref` read from a listing can be handed straight to
8
+ `gift set`, `gift convert` or `gift transfer` without a lookup table.
9
+
10
+ Every time gate the server publishes is surfaced rather than collapsed into
11
+ a boolean. "Can I transfer this?" has three different answers — yes, not yet
12
+ (and here is when), never — and a client that reports only the first two
13
+ sends its user to wait for a date that will not come.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from typing import Any
19
+
20
+ from tlgr.models.base import Model
21
+ from tlgr.models.peer import Peer
22
+
23
+ __all__ = [
24
+ "GiftAttribute",
25
+ "GiftAuction",
26
+ "GiftAuctionState",
27
+ "GiftCollection",
28
+ "GiftConverted",
29
+ "GiftCrafted",
30
+ "GiftDisplay",
31
+ "GiftListing",
32
+ "GiftOfferResolved",
33
+ "GiftTransferred",
34
+ "GiftUpgraded",
35
+ "GiftVariant",
36
+ "OwnedGift",
37
+ "ResaleGift",
38
+ "StarGift",
39
+ "UniqueGift",
40
+ ]
41
+
42
+
43
+ class GiftAttribute(Model):
44
+ """One model / pattern / backdrop of a collectible, with its rarity."""
45
+
46
+ #: model | pattern | backdrop | original-details
47
+ kind: str = ""
48
+ name: str = ""
49
+ document_id: int | None = None
50
+ rarity_permille: int | None = None
51
+ backdrop_id: int | None = None
52
+ center_color: int | None = None
53
+ edge_color: int | None = None
54
+ pattern_color: int | None = None
55
+ text_color: int | None = None
56
+ crafted: bool = False
57
+ sender_id: int | None = None
58
+ recipient_id: int | None = None
59
+ message: str | None = None
60
+ date: str | None = None
61
+
62
+
63
+ class StarGift(Model):
64
+ """A gift as the catalogue offers it."""
65
+
66
+ gift_id: int = 0
67
+ title: str = ""
68
+ stars: int = 0
69
+ convert_stars: int | None = None
70
+ upgrade_stars: int | None = None
71
+ limited: bool = False
72
+ sold_out: bool = False
73
+ birthday: bool = False
74
+ require_premium: bool = False
75
+ availability_remains: int | None = None
76
+ availability_total: int | None = None
77
+ availability_resale: int | None = None
78
+ first_sale_date: str | None = None
79
+ last_sale_date: str | None = None
80
+ document_id: int | None = None
81
+ resell_min_stars: int | None = None
82
+ #: Only filled when `--until` named a recipient.
83
+ can_send: bool | None = None
84
+ can_send_reason: str | None = None
85
+ per_user_total: int | None = None
86
+ per_user_remains: int | None = None
87
+
88
+
89
+ class UniqueGift(Model):
90
+ """A collectible: the upgraded, numbered, tradable form of a gift."""
91
+
92
+ slug: str = ""
93
+ gift_id: int = 0
94
+ id: int = 0
95
+ title: str = ""
96
+ num: int = 0
97
+ owner_id: int | None = None
98
+ owner: Peer | None = None
99
+ owner_name: str | None = None
100
+ owner_address: str | None = None
101
+ gift_address: str | None = None
102
+ availability_issued: int | None = None
103
+ availability_total: int | None = None
104
+ attributes: list[GiftAttribute] = []
105
+ resell_stars: int | None = None
106
+ resell_ton: int | None = None
107
+ resale_ton_only: bool = False
108
+ value_stars: int | None = None
109
+ value_ton: int | None = None
110
+ value_currency: str | None = None
111
+ value_usd: int | None = None
112
+ #: A TON-hosted collectible lives outside Telegram's own custody.
113
+ hosted: bool = False
114
+ burned: bool = False
115
+ crafted: bool = False
116
+ theme_available: bool = False
117
+ peer_color_available: bool = False
118
+ offer_min_stars: int | None = None
119
+ craft_chance_permille: int | None = None
120
+ link: str | None = None
121
+
122
+
123
+ class OwnedGift(Model):
124
+ """A gift a profile holds, with every gate that decides what may be done."""
125
+
126
+ ref: str = ""
127
+ #: gift | collectible
128
+ kind: str = "gift"
129
+ gift_id: int | None = None
130
+ slug: str | None = None
131
+ title: str = ""
132
+ num: int | None = None
133
+ from_id: int | None = None
134
+ from_peer: Peer | None = None
135
+ name_hidden: bool = False
136
+ message: str | None = None
137
+ date: str | None = None
138
+ date_unix: int | None = None
139
+ msg_id: int | None = None
140
+ saved_id: int | None = None
141
+ pinned: bool = False
142
+ displayed: bool = True
143
+ refunded: bool = False
144
+ can_upgrade: bool = False
145
+ convert_stars: int | None = None
146
+ upgrade_stars: int | None = None
147
+ transfer_stars: int | None = None
148
+ can_export_at: str | None = None
149
+ can_transfer_at: str | None = None
150
+ can_resell_at: str | None = None
151
+ can_craft_at: str | None = None
152
+ locked_until_date: str | None = None
153
+ resell_stars: int | None = None
154
+ resell_ton: int | None = None
155
+ collection_ids: list[int] = []
156
+ hosted: bool = False
157
+ attributes: list[GiftAttribute] = []
158
+ unique: UniqueGift | None = None
159
+
160
+
161
+ class GiftCollection(Model):
162
+ id: int
163
+ title: str = ""
164
+ count: int = 0
165
+ icon_document_id: int | None = None
166
+ order: int | None = None
167
+
168
+
169
+ class GiftDisplay(Model):
170
+ """The profile-display state of one or more gifts after `gift set`."""
171
+
172
+ ref: str = ""
173
+ refs: list[str] = []
174
+ displayed: bool | None = None
175
+ pinned: bool | None = None
176
+ worn: bool | None = None
177
+ until: str | None = None
178
+ already: bool = False
179
+
180
+
181
+ class GiftConverted(Model):
182
+ ref: str
183
+ stars_received: int
184
+ balance_after: int | None = None
185
+
186
+
187
+ class GiftUpgraded(Model):
188
+ ref: str
189
+ upgraded: bool
190
+ slug: str | None = None
191
+ num: int | None = None
192
+ attributes: list[GiftAttribute] = []
193
+ price_stars: int | None = None
194
+ refused_reason: str | None = None
195
+
196
+
197
+ class GiftTransferred(Model):
198
+ ref: str
199
+ transferred: bool
200
+ to: int | None = None
201
+ price_stars: int | None = None
202
+ can_transfer_at: str | None = None
203
+ refused_reason: str | None = None
204
+
205
+
206
+ class GiftListing(Model):
207
+ """A collectible put on (or taken off) the resale market."""
208
+
209
+ ref: str
210
+ listed: bool
211
+ price_stars: int | None = None
212
+ price_ton: int | None = None
213
+ can_resell_at: str | None = None
214
+ already: bool = False
215
+
216
+
217
+ class ResaleGift(Model):
218
+ slug: str = ""
219
+ num: int = 0
220
+ price_stars: int | None = None
221
+ price_ton: int | None = None
222
+ seller_id: int | None = None
223
+ attributes: list[GiftAttribute] = []
224
+
225
+
226
+ class GiftVariant(Model):
227
+ """One possible outcome of an upgrade, with how likely it is."""
228
+
229
+ #: model | pattern | backdrop
230
+ kind: str = ""
231
+ name: str = ""
232
+ document_id: int | None = None
233
+ rarity_permille: int | None = None
234
+ count: int | None = None
235
+ sample: bool = False
236
+
237
+
238
+ class GiftCrafted(Model):
239
+ crafted: bool
240
+ ref: str | None = None
241
+ slug: str | None = None
242
+ burned: list[str] = []
243
+ candidates: list[OwnedGift] = []
244
+
245
+
246
+ class GiftOfferResolved(Model):
247
+ msg_id: int
248
+ #: accepted | declined | refused
249
+ state: str
250
+ price_stars: int | None = None
251
+ buyer: int | None = None
252
+ reason: str | None = None
253
+
254
+
255
+ class GiftAuction(Model):
256
+ auction: str = ""
257
+ gift_id: int | None = None
258
+ slug: str | None = None
259
+ my_bid: int | None = None
260
+ min_bid: int | None = None
261
+ ends_at: str | None = None
262
+ state: str = ""
263
+
264
+
265
+ class GiftAuctionState(Model):
266
+ state: str
267
+ version: int
268
+ auction: str = ""
269
+ min_bid_amount: int | None = None
270
+ my_bid: int | None = None
271
+ position: int | None = None
272
+ ends_at: str | None = None
273
+ timeout: int | None = None
274
+ finished: bool = False
275
+ raw: dict[str, Any] | None = None
tlgr/models/inline.py ADDED
@@ -0,0 +1,84 @@
1
+ """Inline mode: what a bot answers a query with, and what sending one produces.
2
+
3
+ `InlineResult` flattens the two constructors Telegram uses — `botInlineResult`
4
+ (a URL and a `WebDocument` thumbnail the client has to fetch) and
5
+ `botInlineMediaResult` (a `Photo`/`Document` already on Telegram) — into one
6
+ row, because the difference is about where the bytes live and not about what
7
+ the caller is choosing between. `content` names which of the two it was, so a
8
+ caller that does care can still tell.
9
+
10
+ `query_id` travels on every row on purpose: it is only valid *paired* with a
11
+ result id, and only for `cache_time` seconds, so a row that carried the id
12
+ alone would be a row that cannot be sent.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import Any
18
+
19
+ from tlgr.models.base import Model
20
+
21
+ __all__ = [
22
+ "InlineEdited",
23
+ "InlineResult",
24
+ "InlineSent",
25
+ "PreparedMessage",
26
+ "PreparedSaved",
27
+ ]
28
+
29
+
30
+ class InlineResult(Model):
31
+ """One result out of `messages.getInlineBotResults`."""
32
+
33
+ #: Flat row-major index within the page — what `inline send --pick` takes.
34
+ #: -1 rather than 0 as the default, because `omit_defaults` would
35
+ #: otherwise drop the first result's index and only the first result's.
36
+ n: int = -1
37
+ id: str = ""
38
+ type: str = ""
39
+ title: str | None = None
40
+ description: str | None = None
41
+ url: str | None = None
42
+ thumb: str | None = None
43
+ #: `url` for a `botInlineResult`, `media` for a `botInlineMediaResult`.
44
+ #: Always emitted: it is the one field that says where the bytes live.
45
+ content: str = ""
46
+ #: The kind of message this result would send: text, media_auto, geo,
47
+ #: venue, contact, invoice, webpage, game or rich.
48
+ send_message: str | None = None
49
+ query_id: str = ""
50
+ doc_id: int | None = None
51
+ photo_id: int | None = None
52
+ gallery: bool = False
53
+ cache_time: int | None = None
54
+ next_offset: str | None = None
55
+ switch_pm: dict[str, Any] | None = None
56
+ switch_webview: dict[str, Any] | None = None
57
+
58
+
59
+ class InlineSent(Model):
60
+ chat_id: int = 0
61
+ msg_id: int = 0
62
+ result_id: str = ""
63
+ via_bot_id: int | None = None
64
+ quick_reply: str | None = None
65
+
66
+
67
+ class InlineEdited(Model):
68
+ inline_msg_id: str = ""
69
+ edited: bool = False
70
+
71
+
72
+ class PreparedMessage(Model):
73
+ """A message a mini app prepared for the user to share."""
74
+
75
+ query_id: str = ""
76
+ result: InlineResult | None = None
77
+ peer_types: list[str] = []
78
+ cache_time: int | None = None
79
+ expires_at: str | None = None
80
+
81
+
82
+ class PreparedSaved(Model):
83
+ id: str = ""
84
+ expires_at: str | None = None
@@ -0,0 +1,115 @@
1
+ """Locations: points, venues, live shares and who is nearby.
2
+
3
+ `GeoPoint` carries `access_hash` because the map-thumbnail endpoint needs it,
4
+ and it is exactly the kind of value `--redact` exists for: it is a capability
5
+ token for a place somebody is standing.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Literal
11
+
12
+ from tlgr.models.base import Model
13
+
14
+ __all__ = [
15
+ "GeoPoint",
16
+ "LiveLocation",
17
+ "LiveStopped",
18
+ "MapPreview",
19
+ "Nearby",
20
+ "NearbyPeer",
21
+ "SentLocation",
22
+ "Venue",
23
+ ]
24
+
25
+
26
+ class GeoPoint(Model):
27
+ lat: float = 0.0
28
+ lon: float = 0.0
29
+ accuracy: int | None = None
30
+ access_hash: int | None = None
31
+
32
+
33
+ class Venue(Model):
34
+ title: str = ""
35
+ address: str = ""
36
+ provider: str = ""
37
+ venue_id: str = ""
38
+ venue_type: str = ""
39
+ geo: GeoPoint | None = None
40
+
41
+
42
+ class SentLocation(Model):
43
+ """What a `location send` / `location venue send` produced."""
44
+
45
+ id: int = 0
46
+ chat_id: int = 0
47
+ date: str = ""
48
+ date_unix: int = 0
49
+ geo: GeoPoint | None = None
50
+ venue: Venue | None = None
51
+
52
+
53
+ class LiveLocation(Model):
54
+ """One live share — mine or somebody else's.
55
+
56
+ `expires_at` rather than `period` alone: a caller resuming after a restart
57
+ needs to know whether the share is still running, and a duration measured
58
+ from a start time it never saw does not answer that.
59
+ """
60
+
61
+ chat_id: int = 0
62
+ msg_id: int = 0
63
+ id: int = 0
64
+ peer_id: int | None = None
65
+ geo: GeoPoint | None = None
66
+ heading: int | None = None
67
+ proximity: int | None = None
68
+ period: int | None = None
69
+ expires_at: str | None = None
70
+ expires_at_unix: int | None = None
71
+ stopped: bool = False
72
+ mine: bool = False
73
+ date: str = ""
74
+ date_unix: int = 0
75
+
76
+
77
+ class LiveStopped(Model):
78
+ """`location live stop`, which may have stopped several shares at once."""
79
+
80
+ stopped: bool = False
81
+ count: int = 0
82
+ items: list[LiveLocation] = []
83
+ already: bool = False
84
+
85
+
86
+ class NearbyPeer(Model):
87
+ """A `updatePeerLocated` row: a person or a group near a point."""
88
+
89
+ peer_id: int = 0
90
+ kind: Literal["user", "group", "channel", "self"] = "user"
91
+ distance: int | None = None
92
+ expires: str | None = None
93
+ expires_unix: int | None = None
94
+
95
+
96
+ class Nearby(Model):
97
+ """The people-nearby answer, plus what I published about myself."""
98
+
99
+ items: list[NearbyPeer] = []
100
+ self_expires: int | None = None
101
+ published: bool = False
102
+
103
+
104
+ class MapPreview(Model):
105
+ """The rendered map thumbnail for a location message."""
106
+
107
+ chat_id: int = 0
108
+ msg_id: int = 0
109
+ path: str | None = None
110
+ bytes: int = 0
111
+ mime_type: str | None = None
112
+ zoom: int = 15
113
+ size: str = "512x512"
114
+ scale: int = 2
115
+ base64: str | None = None