@craftsamo/telegram-tools 0.1.0 → 0.2.0
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.
- package/.antigravity-plugin/plugin.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/cli.js +439 -404
- package/dist/mcp.js +157 -135
- package/dist/opencode.js +196 -148
- package/package.json +1 -1
- package/plugin.yaml +1 -1
package/dist/cli.js
CHANGED
|
@@ -20229,6 +20229,7 @@ function acquireSyncLock(path) {
|
|
|
20229
20229
|
}
|
|
20230
20230
|
|
|
20231
20231
|
// src/core/time.ts
|
|
20232
|
+
var MS_PER_S = 1e3;
|
|
20232
20233
|
var MS_PER_MINUTE = 6e4;
|
|
20233
20234
|
var MINUTES_PER_HOUR = 60;
|
|
20234
20235
|
var localOffsetMinutes = (ms) => -new Date(ms).getTimezoneOffset();
|
|
@@ -21229,7 +21230,6 @@ async function callService(socketPath, method, params, options) {
|
|
|
21229
21230
|
// src/core/chat/live.ts
|
|
21230
21231
|
var REFRESH_TIMEOUT_MS = 12e4;
|
|
21231
21232
|
var FETCH_TIMEOUT_MS = 18e4;
|
|
21232
|
-
var MS_PER_S = 1e3;
|
|
21233
21233
|
function requestHistory(socket, params, signal) {
|
|
21234
21234
|
return callService(socket, SERVICE_REQUESTS.history, params, { effect: "read", signal });
|
|
21235
21235
|
}
|
|
@@ -21357,113 +21357,6 @@ var messageEntry = external_exports.object({
|
|
|
21357
21357
|
private_note: external_exports.string().optional()
|
|
21358
21358
|
});
|
|
21359
21359
|
|
|
21360
|
-
// src/core/chat/schema.ts
|
|
21361
|
-
var METHODS = ["list", "view", "topics", "search", "around", "fetch"];
|
|
21362
|
-
var GENERAL_TOPIC2 = 1;
|
|
21363
|
-
var LIMITS = {
|
|
21364
|
-
list: { default: 30, max: 200 },
|
|
21365
|
-
view: { default: 50, max: 300 },
|
|
21366
|
-
topics: { default: 30, max: TOPICS_LIMIT },
|
|
21367
|
-
search: { default: 30, max: 200 }
|
|
21368
|
-
};
|
|
21369
|
-
var AROUND_COUNT = { default: 5, max: AROUND_LIMIT };
|
|
21370
|
-
var FETCH_PAGES = { default: 1, max: FETCH_PAGE_LIMIT };
|
|
21371
|
-
var accountArgument = external_exports.string().optional().describe("The account label; may be left out when only one account is logged in.");
|
|
21372
|
-
var input3 = external_exports.object({
|
|
21373
|
-
method: external_exports.enum(METHODS).describe(
|
|
21374
|
-
"`list` finds chats; `view` reads the newest messages of one chat between two times, oldest first; `topics` lists the topics of a forum chat; `search` finds messages in the mirror by words; `around` reads the messages around one; `fetch` adds older history of a mirrored chat to the mirror."
|
|
21375
|
-
),
|
|
21376
|
-
account: accountArgument,
|
|
21377
|
-
query: external_exports.string().optional().describe(
|
|
21378
|
-
"list: only chats whose name or username holds this text; a leading @ is ignored. search (required): the words to look for, all of which a message must hold in its text, caption or file name, in any order. Both ignore case and letter width."
|
|
21379
|
-
),
|
|
21380
|
-
unread: external_exports.boolean().optional().describe("list: only chats with unread messages."),
|
|
21381
|
-
last: external_exports.boolean().optional().describe("list: add each chat's newest mirrored message as `last_message`."),
|
|
21382
|
-
refresh: external_exports.boolean().optional().describe(
|
|
21383
|
-
"list: first take the chat list from Telegram (needs the sync service), then read it, and report when in `refreshed_at`."
|
|
21384
|
-
),
|
|
21385
|
-
chat: external_exports.string().optional().describe(
|
|
21386
|
-
"view, topics, around, fetch (required) and search (optional, to search one chat): the chat id, from `list`, such as 123456789 or -1001234567890. A name, username or phone number is not a chat."
|
|
21387
|
-
),
|
|
21388
|
-
topic: external_exports.number().int().positive().optional().describe(
|
|
21389
|
-
`view, around: only messages of this topic of a forum chat (ids from \`topics\`); the General topic is ${GENERAL_TOPIC2}. Refused for a chat without topics.`
|
|
21390
|
-
),
|
|
21391
|
-
after: external_exports.string().optional().describe(
|
|
21392
|
-
"view, search: only messages after this time (exclusive): RFC 3339 with an offset, or a date or time without one, read as local time, such as 2026-11-07 or 2026-11-07T14:03."
|
|
21393
|
-
),
|
|
21394
|
-
before: external_exports.string().optional().describe("view, search: only messages before this time (exclusive); the same forms as `after`."),
|
|
21395
|
-
limit: external_exports.number().int().optional().describe(
|
|
21396
|
-
`How many to return. list: default ${LIMITS.list.default}, at most ${LIMITS.list.max}. view: default ${LIMITS.view.default}, at most ${LIMITS.view.max} (${HISTORY_LIMIT} for a chat read live). topics: default ${LIMITS.topics.default}, at most ${LIMITS.topics.max}. search: default ${LIMITS.search.default}, at most ${LIMITS.search.max}. A larger value is lowered to the most; a result may hold fewer to stay a size a model can read.`
|
|
21397
|
-
),
|
|
21398
|
-
cursor: external_exports.string().optional().describe("The `next` of the previous result, to continue where it stopped."),
|
|
21399
|
-
id: external_exports.number().int().positive().optional().describe("around (required): the id of the message to read around."),
|
|
21400
|
-
before_count: external_exports.number().int().optional().describe(
|
|
21401
|
-
`around: how many older messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21402
|
-
),
|
|
21403
|
-
after_count: external_exports.number().int().optional().describe(
|
|
21404
|
-
`around: how many newer messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21405
|
-
),
|
|
21406
|
-
pages: external_exports.number().int().optional().describe(
|
|
21407
|
-
`fetch: how many pages of ${FETCH_PAGE_SIZE} older messages to add, default ${FETCH_PAGES.default}, at most ${FETCH_PAGES.max}.`
|
|
21408
|
-
)
|
|
21409
|
-
});
|
|
21410
|
-
var nameCut = external_exports.literal(true).optional().describe("Set when the name was longer than the most a result carries and was cut.");
|
|
21411
|
-
var chatEntry2 = external_exports.object({
|
|
21412
|
-
id: external_exports.string().describe("The chat id: Telegram's signed id as text, such as `123456789` or `-1001234567890`."),
|
|
21413
|
-
kind: external_exports.enum(CHAT_KINDS).describe("`self` is Saved Messages."),
|
|
21414
|
-
name: external_exports.string().nullable().describe("The person's or chat's name; null when none is known."),
|
|
21415
|
-
name_cut: nameCut,
|
|
21416
|
-
username: external_exports.string().optional(),
|
|
21417
|
-
mirrored: external_exports.boolean().describe("Whether the mirror keeps this chat's messages."),
|
|
21418
|
-
unread: external_exports.number().int().describe("Incoming messages not read yet."),
|
|
21419
|
-
last_activity_at: localTimeSchema.nullable().describe("The latest message's time, in local time with offset; null when none is known."),
|
|
21420
|
-
forum: external_exports.literal(true).optional().describe("Set for a supergroup with topics."),
|
|
21421
|
-
archived: external_exports.literal(true).optional(),
|
|
21422
|
-
left: external_exports.literal(true).optional().describe("Set for a group or channel the user has left or been removed from."),
|
|
21423
|
-
can_send: external_exports.literal(false).optional().describe("Set when the user is known not to be able to write here."),
|
|
21424
|
-
auto_delete_seconds: external_exports.number().int().optional().describe("The chat's auto-delete period, when on."),
|
|
21425
|
-
last_message: messageEntry.nullable().optional().describe("With `last`: the newest mirrored message of the chat, or null when none is mirrored.")
|
|
21426
|
-
});
|
|
21427
|
-
var topicEntry = external_exports.object({
|
|
21428
|
-
id: external_exports.number().int().describe(`The topic id, to pass as \`topic\` to \`view\`; ${GENERAL_TOPIC2} is the General topic.`),
|
|
21429
|
-
title: external_exports.string().nullable().describe("The topic's title; null when none is known."),
|
|
21430
|
-
closed: external_exports.literal(true).optional().describe("Set for a topic that is closed."),
|
|
21431
|
-
pinned: external_exports.literal(true).optional().describe("Set for a topic that is pinned."),
|
|
21432
|
-
unread: external_exports.number().int().describe("Messages in it not read yet."),
|
|
21433
|
-
last_activity_at: localTimeSchema.nullable().describe("The newest message's time, in local time with offset; null when none is known.")
|
|
21434
|
-
});
|
|
21435
|
-
var output3 = external_exports.object({
|
|
21436
|
-
chats: external_exports.array(chatEntry2).optional().describe("list: the chats, newest activity first."),
|
|
21437
|
-
refreshed_at: localTimeSchema.optional().describe("list with `refresh`: when the chat list was taken from Telegram, in local time with offset."),
|
|
21438
|
-
chat: chatEntry2.optional().describe("view, topics, around, fetch: the chat read."),
|
|
21439
|
-
messages: external_exports.array(messageEntry).optional().describe("view, around: the messages, oldest first. search: the hits, newest first."),
|
|
21440
|
-
live: external_exports.literal(true).optional().describe(
|
|
21441
|
-
"view, around: set when the chat is not mirrored, so the messages were read from Telegram and stored nowhere."
|
|
21442
|
-
),
|
|
21443
|
-
topics: external_exports.array(topicEntry).optional().describe("topics: the topics, most recently active first."),
|
|
21444
|
-
anchor: external_exports.number().int().optional().describe("around: the id of the message read around, among `messages`."),
|
|
21445
|
-
trimmed_before: external_exports.number().int().optional().describe(
|
|
21446
|
-
"around: how many older messages were left out, farthest first, to keep the result a size that can be read."
|
|
21447
|
-
),
|
|
21448
|
-
trimmed_after: external_exports.number().int().optional().describe(
|
|
21449
|
-
"around: how many newer messages were left out, farthest first, to keep the result a size that can be read."
|
|
21450
|
-
),
|
|
21451
|
-
scanned_to: localTimeSchema.optional().describe(
|
|
21452
|
-
"search: set when the search stopped before the end of the history it covers: the time of the oldest message looked at, in local time with offset. `next` continues from there."
|
|
21453
|
-
),
|
|
21454
|
-
scope: external_exports.string().optional().describe("search: what the search covers and what it does not."),
|
|
21455
|
-
fetched: external_exports.object({
|
|
21456
|
-
added: external_exports.number().int().describe("How many messages the mirror gained."),
|
|
21457
|
-
pages: external_exports.number().int().describe("How many pages were read."),
|
|
21458
|
-
complete: external_exports.boolean().describe("Whether Telegram has nothing older for this chat."),
|
|
21459
|
-
oldest_at: localTimeSchema.nullable().describe(
|
|
21460
|
-
"The time of the oldest message the mirror now holds of this chat, in local time with offset; null when none."
|
|
21461
|
-
)
|
|
21462
|
-
}).optional().describe("fetch: what the history fetch stored."),
|
|
21463
|
-
next: external_exports.string().optional().describe("Pass back as `cursor` to continue; absent when there is no more."),
|
|
21464
|
-
note: external_exports.string().describe("Says that what the result carries is data written by other people.")
|
|
21465
|
-
});
|
|
21466
|
-
|
|
21467
21360
|
// src/core/chat/message-rows.ts
|
|
21468
21361
|
var MESSAGE_COLUMNS = "chat, id, topic, ts, from_me, sender, sender_name, kind, body, entities, media, action, reply, forward, grouped, reactions, edited, expires, view_once, self_destruct";
|
|
21469
21362
|
function liveMessages(now) {
|
|
@@ -21471,7 +21364,7 @@ function liveMessages(now) {
|
|
|
21471
21364
|
}
|
|
21472
21365
|
function inTopic(topic) {
|
|
21473
21366
|
return {
|
|
21474
|
-
condition: topic ===
|
|
21367
|
+
condition: topic === GENERAL_TOPIC ? "(topic IS NULL OR topic = ?)" : "topic = ?",
|
|
21475
21368
|
params: [topic]
|
|
21476
21369
|
};
|
|
21477
21370
|
}
|
|
@@ -21696,6 +21589,112 @@ var cuttableMessage = {
|
|
|
21696
21589
|
drop: dropMetadata
|
|
21697
21590
|
};
|
|
21698
21591
|
|
|
21592
|
+
// src/core/chat/schema.ts
|
|
21593
|
+
var METHODS = ["list", "view", "topics", "search", "around", "fetch"];
|
|
21594
|
+
var LIMITS = {
|
|
21595
|
+
list: { default: 30, max: 200 },
|
|
21596
|
+
view: { default: 50, max: 300 },
|
|
21597
|
+
topics: { default: 30, max: TOPICS_LIMIT },
|
|
21598
|
+
search: { default: 30, max: 200 }
|
|
21599
|
+
};
|
|
21600
|
+
var AROUND_COUNT = { default: 5, max: AROUND_LIMIT };
|
|
21601
|
+
var FETCH_PAGES = { default: 1, max: FETCH_PAGE_LIMIT };
|
|
21602
|
+
var accountArgument = external_exports.string().optional().describe("The account label; may be left out when only one account is logged in.");
|
|
21603
|
+
var input3 = external_exports.object({
|
|
21604
|
+
method: external_exports.enum(METHODS).describe(
|
|
21605
|
+
"`list` finds chats; `view` reads the newest messages of one chat between two times, oldest first; `topics` lists the topics of a forum chat; `search` finds messages in the mirror by words; `around` reads the messages around one; `fetch` adds older history of a mirrored chat to the mirror."
|
|
21606
|
+
),
|
|
21607
|
+
account: accountArgument,
|
|
21608
|
+
query: external_exports.string().optional().describe(
|
|
21609
|
+
"list: only chats whose name or username holds this text; a leading @ is ignored. search (required): the words to look for, all of which a message must hold in its text, caption or file name, in any order. Both ignore case and letter width."
|
|
21610
|
+
),
|
|
21611
|
+
unread: external_exports.boolean().optional().describe("list: only chats with unread messages."),
|
|
21612
|
+
last: external_exports.boolean().optional().describe("list: add each chat's newest mirrored message as `last_message`."),
|
|
21613
|
+
refresh: external_exports.boolean().optional().describe(
|
|
21614
|
+
"list: first take the chat list from Telegram (needs the sync service), then read it, and report when in `refreshed_at`."
|
|
21615
|
+
),
|
|
21616
|
+
chat: external_exports.string().optional().describe(
|
|
21617
|
+
"view, topics, around, fetch (required) and search (optional, to search one chat): the chat id, from `list`, such as 123456789 or -1001234567890. A name, username or phone number is not a chat."
|
|
21618
|
+
),
|
|
21619
|
+
topic: external_exports.number().int().positive().optional().describe(
|
|
21620
|
+
`view, around: only messages of this topic of a forum chat (ids from \`topics\`); the General topic is ${GENERAL_TOPIC}. Refused for a chat without topics.`
|
|
21621
|
+
),
|
|
21622
|
+
after: external_exports.string().optional().describe(
|
|
21623
|
+
"view, search: only messages after this time (exclusive): RFC 3339 with an offset, or a date or time without one, read as local time, such as 2026-11-07 or 2026-11-07T14:03."
|
|
21624
|
+
),
|
|
21625
|
+
before: external_exports.string().optional().describe("view, search: only messages before this time (exclusive); the same forms as `after`."),
|
|
21626
|
+
limit: external_exports.number().int().optional().describe(
|
|
21627
|
+
`How many to return. list: default ${LIMITS.list.default}, at most ${LIMITS.list.max}. view: default ${LIMITS.view.default}, at most ${LIMITS.view.max} (${HISTORY_LIMIT} for a chat read live). topics: default ${LIMITS.topics.default}, at most ${LIMITS.topics.max}. search: default ${LIMITS.search.default}, at most ${LIMITS.search.max}. A larger value is lowered to the most; a result may hold fewer to stay a size a model can read.`
|
|
21628
|
+
),
|
|
21629
|
+
cursor: external_exports.string().optional().describe("The `next` of the previous result, to continue where it stopped."),
|
|
21630
|
+
id: external_exports.number().int().positive().optional().describe("around (required): the id of the message to read around."),
|
|
21631
|
+
before_count: external_exports.number().int().optional().describe(
|
|
21632
|
+
`around: how many older messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21633
|
+
),
|
|
21634
|
+
after_count: external_exports.number().int().optional().describe(
|
|
21635
|
+
`around: how many newer messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21636
|
+
),
|
|
21637
|
+
pages: external_exports.number().int().optional().describe(
|
|
21638
|
+
`fetch: how many pages of ${FETCH_PAGE_SIZE} older messages to add, default ${FETCH_PAGES.default}, at most ${FETCH_PAGES.max}.`
|
|
21639
|
+
)
|
|
21640
|
+
});
|
|
21641
|
+
var nameCut = external_exports.literal(true).optional().describe("Set when the name was longer than the most a result carries and was cut.");
|
|
21642
|
+
var chatEntry2 = external_exports.object({
|
|
21643
|
+
id: external_exports.string().describe("The chat id: Telegram's signed id as text, such as `123456789` or `-1001234567890`."),
|
|
21644
|
+
kind: external_exports.enum(CHAT_KINDS).describe("`self` is Saved Messages."),
|
|
21645
|
+
name: external_exports.string().nullable().describe("The person's or chat's name; null when none is known."),
|
|
21646
|
+
name_cut: nameCut,
|
|
21647
|
+
username: external_exports.string().optional(),
|
|
21648
|
+
mirrored: external_exports.boolean().describe("Whether the mirror keeps this chat's messages."),
|
|
21649
|
+
unread: external_exports.number().int().describe("Incoming messages not read yet."),
|
|
21650
|
+
last_activity_at: localTimeSchema.nullable().describe("The latest message's time, in local time with offset; null when none is known."),
|
|
21651
|
+
forum: external_exports.literal(true).optional().describe("Set for a supergroup with topics."),
|
|
21652
|
+
archived: external_exports.literal(true).optional(),
|
|
21653
|
+
left: external_exports.literal(true).optional().describe("Set for a group or channel the user has left or been removed from."),
|
|
21654
|
+
can_send: external_exports.literal(false).optional().describe("Set when the user is known not to be able to write here."),
|
|
21655
|
+
auto_delete_seconds: external_exports.number().int().optional().describe("The chat's auto-delete period, when on."),
|
|
21656
|
+
last_message: messageEntry.nullable().optional().describe("With `last`: the newest mirrored message of the chat, or null when none is mirrored.")
|
|
21657
|
+
});
|
|
21658
|
+
var topicEntry = external_exports.object({
|
|
21659
|
+
id: external_exports.number().int().describe(`The topic id, to pass as \`topic\` to \`view\`; ${GENERAL_TOPIC} is the General topic.`),
|
|
21660
|
+
title: external_exports.string().nullable().describe("The topic's title; null when none is known."),
|
|
21661
|
+
closed: external_exports.literal(true).optional().describe("Set for a topic that is closed."),
|
|
21662
|
+
pinned: external_exports.literal(true).optional().describe("Set for a topic that is pinned."),
|
|
21663
|
+
unread: external_exports.number().int().describe("Messages in it not read yet."),
|
|
21664
|
+
last_activity_at: localTimeSchema.nullable().describe("The newest message's time, in local time with offset; null when none is known.")
|
|
21665
|
+
});
|
|
21666
|
+
var output3 = external_exports.object({
|
|
21667
|
+
chats: external_exports.array(chatEntry2).optional().describe("list: the chats, newest activity first."),
|
|
21668
|
+
refreshed_at: localTimeSchema.optional().describe("list with `refresh`: when the chat list was taken from Telegram, in local time with offset."),
|
|
21669
|
+
chat: chatEntry2.optional().describe("view, topics, around, fetch: the chat read."),
|
|
21670
|
+
messages: external_exports.array(messageEntry).optional().describe("view, around: the messages, oldest first. search: the hits, newest first."),
|
|
21671
|
+
live: external_exports.literal(true).optional().describe(
|
|
21672
|
+
"view, around: set when the chat is not mirrored, so the messages were read from Telegram and stored nowhere."
|
|
21673
|
+
),
|
|
21674
|
+
topics: external_exports.array(topicEntry).optional().describe("topics: the topics, most recently active first."),
|
|
21675
|
+
anchor: external_exports.number().int().optional().describe("around: the id of the message read around, among `messages`."),
|
|
21676
|
+
trimmed_before: external_exports.number().int().optional().describe(
|
|
21677
|
+
"around: how many older messages were left out, farthest first, to keep the result a size that can be read."
|
|
21678
|
+
),
|
|
21679
|
+
trimmed_after: external_exports.number().int().optional().describe(
|
|
21680
|
+
"around: how many newer messages were left out, farthest first, to keep the result a size that can be read."
|
|
21681
|
+
),
|
|
21682
|
+
scanned_to: localTimeSchema.optional().describe(
|
|
21683
|
+
"search: set when the search stopped before the end of the history it covers: the time of the oldest message looked at, in local time with offset. `next` continues from there."
|
|
21684
|
+
),
|
|
21685
|
+
scope: external_exports.string().optional().describe("search: what the search covers and what it does not."),
|
|
21686
|
+
fetched: external_exports.object({
|
|
21687
|
+
added: external_exports.number().int().describe("How many messages the mirror gained."),
|
|
21688
|
+
pages: external_exports.number().int().describe("How many pages were read."),
|
|
21689
|
+
complete: external_exports.boolean().describe("Whether Telegram has nothing older for this chat."),
|
|
21690
|
+
oldest_at: localTimeSchema.nullable().describe(
|
|
21691
|
+
"The time of the oldest message the mirror now holds of this chat, in local time with offset; null when none."
|
|
21692
|
+
)
|
|
21693
|
+
}).optional().describe("fetch: what the history fetch stored."),
|
|
21694
|
+
next: external_exports.string().optional().describe("Pass back as `cursor` to continue; absent when there is no more."),
|
|
21695
|
+
note: external_exports.string().describe("Says that what the result carries is data written by other people.")
|
|
21696
|
+
});
|
|
21697
|
+
|
|
21699
21698
|
// src/core/chat/around.ts
|
|
21700
21699
|
var TRIMMED_RESERVE = 100;
|
|
21701
21700
|
var NO_MESSAGE = "No message with this id in this chat.";
|
|
@@ -21898,7 +21897,7 @@ function listChats(mirror, args, now) {
|
|
|
21898
21897
|
return result;
|
|
21899
21898
|
}
|
|
21900
21899
|
|
|
21901
|
-
// src/core/
|
|
21900
|
+
// src/core/open.ts
|
|
21902
21901
|
async function pickPaths(ctx, account2) {
|
|
21903
21902
|
if (!ctx.stateDir) throw new ToolError("internal_error", "The entry point did not supply a state directory.");
|
|
21904
21903
|
return pickLabel(ctx.stateDir, account2);
|
|
@@ -22318,6 +22317,56 @@ var CHAT_FACT_TRANSLATIONS = {
|
|
|
22318
22317
|
}
|
|
22319
22318
|
};
|
|
22320
22319
|
|
|
22320
|
+
// src/core/chat/media-facts.ts
|
|
22321
|
+
var MEDIA_KIND_WORDS = {
|
|
22322
|
+
photo: "Photo",
|
|
22323
|
+
document: "Document",
|
|
22324
|
+
audio: "Audio",
|
|
22325
|
+
voice: "Voice message",
|
|
22326
|
+
video: "Video",
|
|
22327
|
+
sticker: "Sticker",
|
|
22328
|
+
dice: "Dice",
|
|
22329
|
+
contact: "Contact",
|
|
22330
|
+
venue: "Venue",
|
|
22331
|
+
geo: "Location",
|
|
22332
|
+
geo_live: "Live location",
|
|
22333
|
+
game: "Game",
|
|
22334
|
+
invoice: "Invoice",
|
|
22335
|
+
webpage: "Link preview",
|
|
22336
|
+
poll: "Poll",
|
|
22337
|
+
todo: "Checklist",
|
|
22338
|
+
story: "Story",
|
|
22339
|
+
paid: "Paid media",
|
|
22340
|
+
unsupported: "Unsupported media"
|
|
22341
|
+
};
|
|
22342
|
+
function mediaKindValue(type3) {
|
|
22343
|
+
return Object.hasOwn(MEDIA_KIND_WORDS, type3) ? { text: MEDIA_KIND_WORDS[type3] } : type3;
|
|
22344
|
+
}
|
|
22345
|
+
var MEDIA_FACT_TRANSLATIONS = {
|
|
22346
|
+
ja: {
|
|
22347
|
+
Media: "\u30E1\u30C7\u30A3\u30A2",
|
|
22348
|
+
Photo: "\u5199\u771F",
|
|
22349
|
+
Document: "\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
22350
|
+
Audio: "\u97F3\u58F0",
|
|
22351
|
+
"Voice message": "\u30DC\u30A4\u30B9\u30E1\u30C3\u30BB\u30FC\u30B8",
|
|
22352
|
+
Video: "\u52D5\u753B",
|
|
22353
|
+
Sticker: "\u30B9\u30BF\u30F3\u30D7",
|
|
22354
|
+
Dice: "\u30B5\u30A4\u30B3\u30ED",
|
|
22355
|
+
Contact: "\u9023\u7D61\u5148",
|
|
22356
|
+
Venue: "\u5834\u6240",
|
|
22357
|
+
Location: "\u4F4D\u7F6E\u60C5\u5831",
|
|
22358
|
+
"Live location": "\u30E9\u30A4\u30D6\u4F4D\u7F6E\u60C5\u5831",
|
|
22359
|
+
Game: "\u30B2\u30FC\u30E0",
|
|
22360
|
+
Invoice: "\u8ACB\u6C42\u66F8",
|
|
22361
|
+
"Link preview": "\u30EA\u30F3\u30AF\u306E\u30D7\u30EC\u30D3\u30E5\u30FC",
|
|
22362
|
+
Poll: "\u6295\u7968",
|
|
22363
|
+
Checklist: "\u30C1\u30A7\u30C3\u30AF\u30EA\u30B9\u30C8",
|
|
22364
|
+
Story: "\u30B9\u30C8\u30FC\u30EA\u30FC",
|
|
22365
|
+
"Paid media": "\u6709\u6599\u30E1\u30C7\u30A3\u30A2",
|
|
22366
|
+
"Unsupported media": "\u672A\u5BFE\u5FDC\u306E\u30E1\u30C7\u30A3\u30A2"
|
|
22367
|
+
}
|
|
22368
|
+
};
|
|
22369
|
+
|
|
22321
22370
|
// src/core/facts.ts
|
|
22322
22371
|
function sizeFact(bytes2) {
|
|
22323
22372
|
return { label: "Size", value: { text: bytes2 === 1 ? "{bytes} byte" : "{bytes} bytes", values: { bytes: bytes2 } } };
|
|
@@ -24319,14 +24368,6 @@ function namesOf(file2, id) {
|
|
|
24319
24368
|
const name = safeFileName(file2.name, { kind: file2.kind, id, type: file2.type });
|
|
24320
24369
|
return { name, shown: file2.name === null ? file2.kind : name };
|
|
24321
24370
|
}
|
|
24322
|
-
var FILE_KIND_WORDS = {
|
|
24323
|
-
photo: "Photo",
|
|
24324
|
-
document: "Document",
|
|
24325
|
-
audio: "Audio",
|
|
24326
|
-
voice: "Voice message",
|
|
24327
|
-
video: "Video",
|
|
24328
|
-
sticker: "Sticker"
|
|
24329
|
-
};
|
|
24330
24371
|
function saveHeadline(file2, chat) {
|
|
24331
24372
|
if (file2 !== void 0 && chat !== null) return { text: "About to save {file} from {chat}", values: { file: file2, chat } };
|
|
24332
24373
|
if (chat !== null) return { text: "About to save a file from {chat}", values: { chat } };
|
|
@@ -24334,9 +24375,8 @@ function saveHeadline(file2, chat) {
|
|
|
24334
24375
|
return void 0;
|
|
24335
24376
|
}
|
|
24336
24377
|
function fileFacts(media, unpack) {
|
|
24337
|
-
const kind = media && Object.hasOwn(FILE_KIND_WORDS, media.type) ? FILE_KIND_WORDS[media.type] : void 0;
|
|
24338
24378
|
return [
|
|
24339
|
-
...media ? [{ label: "File", value:
|
|
24379
|
+
...media ? [{ label: "File", value: mediaKindValue(media.type) }] : [],
|
|
24340
24380
|
...unpack ? [{ label: "Unpack", value: { text: "Yes" } }] : [],
|
|
24341
24381
|
...media?.size !== void 0 && Number.isSafeInteger(media.size) && media.size > 0 ? [sizeFact(media.size)] : []
|
|
24342
24382
|
];
|
|
@@ -24851,9 +24891,8 @@ async function checkArchive(path, format2, limits, signal) {
|
|
|
24851
24891
|
}
|
|
24852
24892
|
|
|
24853
24893
|
// src/core/outgoing/limits.ts
|
|
24854
|
-
var BYTES_PER_MB2 = 1024 * 1024;
|
|
24855
24894
|
var MAX_FILES = 10;
|
|
24856
|
-
var MAX_TOTAL_BYTES = 100 *
|
|
24895
|
+
var MAX_TOTAL_BYTES = 100 * BYTES_PER_MB;
|
|
24857
24896
|
|
|
24858
24897
|
// src/core/file/send/constants.ts
|
|
24859
24898
|
var SEND_FILES_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
@@ -25575,39 +25614,46 @@ async function wholeCallDescription(spec, args, ctx) {
|
|
|
25575
25614
|
// src/core/message/action-describe.ts
|
|
25576
25615
|
var EDIT_HEADLINES = {
|
|
25577
25616
|
named: "About to edit message {id} in {chat}",
|
|
25578
|
-
saved: "About to edit message {id} in Saved Messages"
|
|
25617
|
+
saved: "About to edit message {id} in Saved Messages",
|
|
25618
|
+
bare: "About to edit message {id}"
|
|
25579
25619
|
};
|
|
25580
25620
|
var DELETE_HEADLINES = {
|
|
25581
|
-
named: "About to delete message {id} from {chat}",
|
|
25582
|
-
saved: "About to delete message {id} from Saved Messages"
|
|
25621
|
+
named: "About to delete message {id} from {chat} for everyone",
|
|
25622
|
+
saved: "About to delete message {id} from Saved Messages",
|
|
25623
|
+
bare: "About to delete message {id} for everyone"
|
|
25583
25624
|
};
|
|
25584
25625
|
var REACT_HEADLINES = {
|
|
25585
25626
|
named: "About to react {emoji} to message {id} in {chat}",
|
|
25586
|
-
saved: "About to react {emoji} to message {id} in Saved Messages"
|
|
25627
|
+
saved: "About to react {emoji} to message {id} in Saved Messages",
|
|
25628
|
+
bare: "About to react {emoji} to message {id}"
|
|
25587
25629
|
};
|
|
25588
25630
|
var UNREACT_HEADLINES = {
|
|
25589
25631
|
named: "About to remove your reaction from message {id} in {chat}",
|
|
25590
|
-
saved: "About to remove your reaction from message {id} in Saved Messages"
|
|
25632
|
+
saved: "About to remove your reaction from message {id} in Saved Messages",
|
|
25633
|
+
bare: "About to remove your reaction from message {id}"
|
|
25591
25634
|
};
|
|
25592
25635
|
var PIN_HEADLINES = {
|
|
25593
25636
|
named: "About to pin message {id} in {chat}",
|
|
25594
|
-
saved: "About to pin message {id} in Saved Messages"
|
|
25637
|
+
saved: "About to pin message {id} in Saved Messages",
|
|
25638
|
+
bare: "About to pin message {id}"
|
|
25595
25639
|
};
|
|
25596
25640
|
var UNPIN_HEADLINES = {
|
|
25597
25641
|
named: "About to unpin message {id} in {chat}",
|
|
25598
|
-
saved: "About to unpin message {id} in Saved Messages"
|
|
25642
|
+
saved: "About to unpin message {id} in Saved Messages",
|
|
25643
|
+
bare: "About to unpin message {id}"
|
|
25599
25644
|
};
|
|
25600
25645
|
var MARK_READ_HEADLINES = {
|
|
25601
25646
|
named: "About to mark {chat} read up to message {id}",
|
|
25602
|
-
saved: "About to mark Saved Messages read up to message {id}"
|
|
25647
|
+
saved: "About to mark Saved Messages read up to message {id}",
|
|
25648
|
+
bare: "About to mark messages read up to message {id}"
|
|
25603
25649
|
};
|
|
25604
25650
|
function actionHeadline(headlines, { kind, name }, id, values) {
|
|
25605
25651
|
if (kind === "self") return { text: headlines.saved, values: { id: String(id), ...values } };
|
|
25606
|
-
return name === null ?
|
|
25652
|
+
return name === null ? { text: headlines.bare, values: { id: String(id), ...values } } : { text: headlines.named, values: { id: String(id), chat: name, ...values } };
|
|
25607
25653
|
}
|
|
25608
25654
|
function currentFacts({ body, media }) {
|
|
25609
|
-
|
|
25610
|
-
return
|
|
25655
|
+
if (body) return [{ label: "Current", value: cut2(body, MAX_VALUE_LENGTH) }];
|
|
25656
|
+
return media ? [{ label: "Media", value: mediaKindValue(media.type) }] : [];
|
|
25611
25657
|
}
|
|
25612
25658
|
function describeAction(headlines, chat, id, message2, extras = {}) {
|
|
25613
25659
|
const headline = actionHeadline(headlines, chat, id, extras.values ?? {});
|
|
@@ -25843,7 +25889,7 @@ var telegramMessageDelete = defineTool({
|
|
|
25843
25889
|
"A result means Telegram deleted the message for everyone. `already` means it was gone before this call.",
|
|
25844
25890
|
"A failure `uncertain` means the delete may have gone through: check the chat in Telegram and never ask for it again without the user checking."
|
|
25845
25891
|
].join(" "),
|
|
25846
|
-
intent: "About to delete a message",
|
|
25892
|
+
intent: "About to delete a message for everyone",
|
|
25847
25893
|
toolset: "actions",
|
|
25848
25894
|
class: "administrative",
|
|
25849
25895
|
input: deleteInput,
|
|
@@ -26449,12 +26495,6 @@ var FILE_TRANSLATIONS = {
|
|
|
26449
26495
|
"About to save a file from {chat}": "{chat} \u306E\u30D5\u30A1\u30A4\u30EB\u3092\u4FDD\u5B58\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26450
26496
|
"About to save {file}": "{file} \u3092\u4FDD\u5B58\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26451
26497
|
File: "\u30D5\u30A1\u30A4\u30EB",
|
|
26452
|
-
Photo: "\u5199\u771F",
|
|
26453
|
-
Document: "\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
26454
|
-
Audio: "\u97F3\u58F0",
|
|
26455
|
-
"Voice message": "\u30DC\u30A4\u30B9\u30E1\u30C3\u30BB\u30FC\u30B8",
|
|
26456
|
-
Video: "\u52D5\u753B",
|
|
26457
|
-
Sticker: "\u30B9\u30BF\u30F3\u30D7",
|
|
26458
26498
|
Unpack: "\u5C55\u958B",
|
|
26459
26499
|
Yes: "\u3059\u308B"
|
|
26460
26500
|
}
|
|
@@ -26469,24 +26509,31 @@ var ACTION_TRANSLATIONS = {
|
|
|
26469
26509
|
"Pin or unpin a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30D4\u30F3\u7559\u3081\u3059\u308B\u30FB\u89E3\u9664\u3059\u308B",
|
|
26470
26510
|
"Mark a chat read": "\u30C1\u30E3\u30C3\u30C8\u3092\u65E2\u8AAD\u306B\u3059\u308B",
|
|
26471
26511
|
"About to edit a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26472
|
-
"About to delete a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26512
|
+
"About to delete a message for everyone": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u5168\u54E1\u5206\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26473
26513
|
"About to change a reaction": "\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26474
26514
|
"About to pin or unpin a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u30D4\u30F3\u7559\u3081\u3092\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26475
26515
|
"About to mark messages read": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26476
26516
|
"About to edit message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26477
|
-
"About to edit message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26478
|
-
"About to
|
|
26479
|
-
"About to delete message {id} from
|
|
26517
|
+
"About to edit message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26518
|
+
"About to edit message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26519
|
+
"About to delete message {id} from {chat} for everyone": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u5168\u54E1\u5206\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26520
|
+
"About to delete message {id} from Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26521
|
+
"About to delete message {id} for everyone": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u5168\u54E1\u5206\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26480
26522
|
"About to react {emoji} to message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306B {emoji} \u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4ED8\u3051\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26481
|
-
"About to react {emoji} to message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26523
|
+
"About to react {emoji} to message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306B {emoji} \u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4ED8\u3051\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26524
|
+
"About to react {emoji} to message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306B {emoji} \u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4ED8\u3051\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26482
26525
|
"About to remove your reaction from message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u304B\u3089\u81EA\u5206\u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5916\u305D\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26483
|
-
"About to remove your reaction from message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26526
|
+
"About to remove your reaction from message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u304B\u3089\u81EA\u5206\u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5916\u305D\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26527
|
+
"About to remove your reaction from message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u304B\u3089\u81EA\u5206\u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5916\u305D\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26484
26528
|
"About to pin message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u30D4\u30F3\u7559\u3081\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26485
|
-
"About to pin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26529
|
+
"About to pin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u30D4\u30F3\u7559\u3081\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26530
|
+
"About to pin message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u30D4\u30F3\u7559\u3081\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26486
26531
|
"About to unpin message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306E\u30D4\u30F3\u7559\u3081\u3092\u89E3\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26487
|
-
"About to unpin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26532
|
+
"About to unpin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306E\u30D4\u30F3\u7559\u3081\u3092\u89E3\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26533
|
+
"About to unpin message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306E\u30D4\u30F3\u7559\u3081\u3092\u89E3\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26488
26534
|
"About to mark {chat} read up to message {id}": "{chat} \u3092\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u307E\u3067\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26489
26535
|
"About to mark Saved Messages read up to message {id}": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u307E\u3067\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26536
|
+
"About to mark messages read up to message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u307E\u3067\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26490
26537
|
Message: "\u30E1\u30C3\u30BB\u30FC\u30B8",
|
|
26491
26538
|
Current: "\u73FE\u5728\u306E\u5185\u5BB9",
|
|
26492
26539
|
Replaces: "\u7F6E\u304D\u63DB\u3048\u308B\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3",
|
|
@@ -26530,6 +26577,7 @@ var SYNC_TRANSLATIONS = {
|
|
|
26530
26577
|
var ALL_TRANSLATIONS = mergeTranslations(
|
|
26531
26578
|
FACT_TRANSLATIONS,
|
|
26532
26579
|
CHAT_FACT_TRANSLATIONS,
|
|
26580
|
+
MEDIA_FACT_TRANSLATIONS,
|
|
26533
26581
|
MESSAGE_TRANSLATIONS,
|
|
26534
26582
|
ACTION_TRANSLATIONS,
|
|
26535
26583
|
FILE_TRANSLATIONS,
|
|
@@ -94531,7 +94579,7 @@ function createTelegramClient(settings) {
|
|
|
94531
94579
|
function deviceInfo() {
|
|
94532
94580
|
return {
|
|
94533
94581
|
model: `${PROJECT.name} (unofficial)`,
|
|
94534
|
-
appVersion: true ? "0.
|
|
94582
|
+
appVersion: true ? "0.2.0" : DEV_VERSION,
|
|
94535
94583
|
systemVersion: `${type2()} ${release()}`
|
|
94536
94584
|
};
|
|
94537
94585
|
}
|
|
@@ -96219,9 +96267,8 @@ function applyRead(mirror, read) {
|
|
|
96219
96267
|
}
|
|
96220
96268
|
|
|
96221
96269
|
// src/core/telegram/ingest-messages.ts
|
|
96222
|
-
var MS_PER_S2 = 1e3;
|
|
96223
96270
|
function expiryOf(msg) {
|
|
96224
|
-
return isCount(msg.ttl) && msg.ttl > 0 ? msg.ts + msg.ttl *
|
|
96271
|
+
return isCount(msg.ttl) && msg.ttl > 0 ? msg.ts + msg.ttl * MS_PER_S : null;
|
|
96225
96272
|
}
|
|
96226
96273
|
function findVersion(mirror, chat, id) {
|
|
96227
96274
|
const row = mirror.prepare("SELECT ts, body, entities, media, edited, expires FROM messages WHERE chat = ? AND id = ?").get(chat, id);
|
|
@@ -96759,7 +96806,6 @@ import { Buffer as Buffer8 } from "node:buffer";
|
|
|
96759
96806
|
import { open as open6 } from "node:fs/promises";
|
|
96760
96807
|
|
|
96761
96808
|
// src/core/telegram/sync-download-file.ts
|
|
96762
|
-
var MS_PER_S3 = 1e3;
|
|
96763
96809
|
var FILE_KINDS = ["photo", "document", "audio", "voice", "video", "sticker"];
|
|
96764
96810
|
function isFileMedia(media) {
|
|
96765
96811
|
return media !== null && FILE_KINDS.includes(media.type);
|
|
@@ -96773,7 +96819,7 @@ function messageFile(message2) {
|
|
|
96773
96819
|
}
|
|
96774
96820
|
function disappearsAtOf(message2) {
|
|
96775
96821
|
const ttl = message2.ttlPeriod;
|
|
96776
|
-
return ttl ? message2.date.getTime() + ttl *
|
|
96822
|
+
return ttl ? message2.date.getTime() + ttl * MS_PER_S : void 0;
|
|
96777
96823
|
}
|
|
96778
96824
|
|
|
96779
96825
|
// src/core/telegram/sync-download-refusal.ts
|
|
@@ -96801,11 +96847,10 @@ function tooLargeReason(size, maxBytes) {
|
|
|
96801
96847
|
// src/core/telegram/sync-download-stream.ts
|
|
96802
96848
|
import { open as open4 } from "node:fs/promises";
|
|
96803
96849
|
var FILE_MODE3 = 384;
|
|
96804
|
-
var MS_PER_S4 = 1e3;
|
|
96805
96850
|
function stalled(stallMs) {
|
|
96806
96851
|
return new ToolError(
|
|
96807
96852
|
"upstream_error",
|
|
96808
|
-
`The download received nothing for ${stallMs /
|
|
96853
|
+
`The download received nothing for ${stallMs / MS_PER_S} seconds; try again later.`
|
|
96809
96854
|
);
|
|
96810
96855
|
}
|
|
96811
96856
|
async function writeAll2(handle, chunk) {
|
|
@@ -96814,7 +96859,7 @@ async function writeAll2(handle, chunk) {
|
|
|
96814
96859
|
}
|
|
96815
96860
|
async function writeDownload(ctx, signal, media, file2, max3) {
|
|
96816
96861
|
const env = { endSession: ctx.endSession, log: ctx.settings.log };
|
|
96817
|
-
const stallMs = ctx.settings.
|
|
96862
|
+
const stallMs = ctx.settings.transferStallMs;
|
|
96818
96863
|
const failure2 = (error62) => {
|
|
96819
96864
|
if (signal.aborted) return cancelled();
|
|
96820
96865
|
if (error62 instanceof MtTimeoutError && error62.timeout === stallMs) return stalled(stallMs);
|
|
@@ -97144,6 +97189,202 @@ var FileKeeper = class {
|
|
|
97144
97189
|
}
|
|
97145
97190
|
};
|
|
97146
97191
|
|
|
97192
|
+
// src/core/telegram/sync-options.ts
|
|
97193
|
+
var SECOND_MS2 = 1e3;
|
|
97194
|
+
var MINUTE_MS = 60 * SECOND_MS2;
|
|
97195
|
+
var HOUR_MS = 60 * MINUTE_MS;
|
|
97196
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
97197
|
+
var TRANSFER_STALL_MS = 6e4;
|
|
97198
|
+
var DEFAULT_HEARTBEAT_EVERY_MS = 5 * SECOND_MS2;
|
|
97199
|
+
var DEFAULT_GAP_AFTER_MS = 30 * SECOND_MS2;
|
|
97200
|
+
var DEFAULT_OFFLINE_LIMIT_MS = 10 * MINUTE_MS;
|
|
97201
|
+
var DEFAULT_PURGE_EVERY_MS = HOUR_MS;
|
|
97202
|
+
var DEFAULT_REFRESH_EVERY_MS = 30 * MINUTE_MS;
|
|
97203
|
+
var DEFAULT_REFRESH_RETRY_MS = MINUTE_MS;
|
|
97204
|
+
var DEFAULT_ROUND_EVERY_MS = 5 * SECOND_MS2;
|
|
97205
|
+
var DEFAULT_STOP_WAIT_MS = 10 * SECOND_MS2;
|
|
97206
|
+
var DEFAULT_SEED_WITHIN_MS = 30 * DAY_MS;
|
|
97207
|
+
var DEFAULT_SEED_COUNT = 50;
|
|
97208
|
+
var DEFAULT_SEED_CHATS_PER_ROUND = 20;
|
|
97209
|
+
var DEFAULT_SEED_ATTEMPTS = 3;
|
|
97210
|
+
var DEFAULT_FILL_LIMIT = 200;
|
|
97211
|
+
var DEFAULT_PACE_MS = [500, 1500];
|
|
97212
|
+
function resolveOptions(options) {
|
|
97213
|
+
return {
|
|
97214
|
+
...options,
|
|
97215
|
+
now: options.now ?? Date.now,
|
|
97216
|
+
pause: options.pause ?? realPause,
|
|
97217
|
+
heartbeatEveryMs: options.heartbeatEveryMs ?? DEFAULT_HEARTBEAT_EVERY_MS,
|
|
97218
|
+
gapAfterMs: options.gapAfterMs ?? DEFAULT_GAP_AFTER_MS,
|
|
97219
|
+
offlineLimitMs: options.offlineLimitMs ?? DEFAULT_OFFLINE_LIMIT_MS,
|
|
97220
|
+
purgeEveryMs: options.purgeEveryMs ?? DEFAULT_PURGE_EVERY_MS,
|
|
97221
|
+
refreshEveryMs: options.refreshEveryMs ?? DEFAULT_REFRESH_EVERY_MS,
|
|
97222
|
+
refreshRetryMs: options.refreshRetryMs ?? DEFAULT_REFRESH_RETRY_MS,
|
|
97223
|
+
roundEveryMs: options.roundEveryMs ?? DEFAULT_ROUND_EVERY_MS,
|
|
97224
|
+
stopWaitMs: options.stopWaitMs ?? DEFAULT_STOP_WAIT_MS,
|
|
97225
|
+
seedWithinMs: options.seedWithinMs ?? DEFAULT_SEED_WITHIN_MS,
|
|
97226
|
+
seedCount: options.seedCount ?? DEFAULT_SEED_COUNT,
|
|
97227
|
+
seedChatsPerRound: options.seedChatsPerRound ?? DEFAULT_SEED_CHATS_PER_ROUND,
|
|
97228
|
+
seedAttempts: options.seedAttempts ?? DEFAULT_SEED_ATTEMPTS,
|
|
97229
|
+
fillLimit: options.fillLimit ?? DEFAULT_FILL_LIMIT,
|
|
97230
|
+
paceMs: options.paceMs ?? DEFAULT_PACE_MS,
|
|
97231
|
+
transferStallMs: options.transferStallMs ?? TRANSFER_STALL_MS
|
|
97232
|
+
};
|
|
97233
|
+
}
|
|
97234
|
+
|
|
97235
|
+
// src/core/telegram/sync-message.ts
|
|
97236
|
+
function readMessage(message2, channels) {
|
|
97237
|
+
const input8 = messageInputOf(message2);
|
|
97238
|
+
if (!input8) return null;
|
|
97239
|
+
const peer = readOrNull(() => message2.chat);
|
|
97240
|
+
const chat = peer ? chatInputOf(peer) : null;
|
|
97241
|
+
if (chat && !keepsKind(chat.kind, channels)) return null;
|
|
97242
|
+
return { chat, message: input8, topic: topicInputOfAction(message2) };
|
|
97243
|
+
}
|
|
97244
|
+
function writeMessage(mirror, ctx, read, channels) {
|
|
97245
|
+
if (read.chat) rememberChats(mirror, [read.chat], ctx.now, channels);
|
|
97246
|
+
if (read.topic) upsertTopics(mirror, [read.topic], ctx.now);
|
|
97247
|
+
return storeMessage(mirror, ctx, read.message);
|
|
97248
|
+
}
|
|
97249
|
+
|
|
97250
|
+
// src/core/telegram/sync-receive.ts
|
|
97251
|
+
var SKIPPED = "skipped";
|
|
97252
|
+
function countsOf(outcomes) {
|
|
97253
|
+
const counts = /* @__PURE__ */ new Map();
|
|
97254
|
+
for (const outcome of outcomes) counts.set(outcome, (counts.get(outcome) ?? 0) + 1);
|
|
97255
|
+
return [...counts].map(([outcome, count]) => `${outcome}=${count}`).join(" ") || "none";
|
|
97256
|
+
}
|
|
97257
|
+
var Receiver = class {
|
|
97258
|
+
deps;
|
|
97259
|
+
keeper;
|
|
97260
|
+
halted = false;
|
|
97261
|
+
constructor(deps) {
|
|
97262
|
+
this.deps = deps;
|
|
97263
|
+
}
|
|
97264
|
+
/**
|
|
97265
|
+
* Registers the handlers on the client's emitters; call it before the client
|
|
97266
|
+
* connects. `keeper` keeps the files of the disappearing messages that
|
|
97267
|
+
* arrive, when `keepDisappearing` is on.
|
|
97268
|
+
*/
|
|
97269
|
+
attach(client, keeper) {
|
|
97270
|
+
this.keeper = keeper;
|
|
97271
|
+
client.onNewMessage.add((message2) => this.onMessage("message", message2));
|
|
97272
|
+
client.onEditMessage.add((message2) => this.onMessage("edit", message2));
|
|
97273
|
+
client.onDeleteMessage.add((update) => this.onDelete(update));
|
|
97274
|
+
client.onHistoryRead.add((update) => this.onRead(update));
|
|
97275
|
+
}
|
|
97276
|
+
/** Stops storing: whatever arrives from here on is ignored. */
|
|
97277
|
+
halt() {
|
|
97278
|
+
this.halted = true;
|
|
97279
|
+
}
|
|
97280
|
+
onMessage(label, message2) {
|
|
97281
|
+
const { channels, keepDisappearing } = this.deps;
|
|
97282
|
+
const done = this.process(
|
|
97283
|
+
label,
|
|
97284
|
+
() => readMessage(message2, channels),
|
|
97285
|
+
(read, ctx) => writeMessage(this.deps.mirror, ctx, read, channels)
|
|
97286
|
+
);
|
|
97287
|
+
if (keepDisappearing && label === "message" && done?.outcome === "stored") {
|
|
97288
|
+
this.keeper?.keep(message2, done.prepared.message);
|
|
97289
|
+
}
|
|
97290
|
+
}
|
|
97291
|
+
onDelete(update) {
|
|
97292
|
+
const { mirror, coverage, keepDisappearing } = this.deps;
|
|
97293
|
+
const done = this.process(
|
|
97294
|
+
"delete",
|
|
97295
|
+
() => deleteInputOf(update),
|
|
97296
|
+
(input8, ctx) => {
|
|
97297
|
+
if (input8.chat !== null && !findChat(mirror, input8.chat)?.followed) return SKIPPED;
|
|
97298
|
+
coverage.note(ctx.now);
|
|
97299
|
+
return countsOf(deleteMessages2(mirror, ctx, input8));
|
|
97300
|
+
}
|
|
97301
|
+
);
|
|
97302
|
+
if (keepDisappearing && done && done.outcome !== SKIPPED) {
|
|
97303
|
+
this.keeper?.forgetMessages(done.prepared.chat, done.prepared.ids);
|
|
97304
|
+
}
|
|
97305
|
+
}
|
|
97306
|
+
onRead(update) {
|
|
97307
|
+
this.process(
|
|
97308
|
+
"read",
|
|
97309
|
+
() => readInputOf(update),
|
|
97310
|
+
(input8) => {
|
|
97311
|
+
applyRead(this.deps.mirror, input8);
|
|
97312
|
+
return "applied";
|
|
97313
|
+
}
|
|
97314
|
+
);
|
|
97315
|
+
}
|
|
97316
|
+
/**
|
|
97317
|
+
* Turns the update into `prepared` outside the transaction, so that what
|
|
97318
|
+
* fails there is only mtcute's data, then writes it. `store` names the
|
|
97319
|
+
* outcome for the log. Resolves with `prepared` and the outcome once it is
|
|
97320
|
+
* written, and with null when the update was not (unreadable, not for the
|
|
97321
|
+
* mirror, or a storage failure).
|
|
97322
|
+
*/
|
|
97323
|
+
process(label, prepare2, store) {
|
|
97324
|
+
if (this.halted) return null;
|
|
97325
|
+
const { mirror, now, keepDisappearing, log } = this.deps;
|
|
97326
|
+
let prepared;
|
|
97327
|
+
try {
|
|
97328
|
+
prepared = prepare2();
|
|
97329
|
+
} catch (error62) {
|
|
97330
|
+
log(`event: ${label} unreadable (${errorLabel(error62)})`);
|
|
97331
|
+
return null;
|
|
97332
|
+
}
|
|
97333
|
+
if (prepared === null) {
|
|
97334
|
+
log(`event: ${label} ${SKIPPED}`);
|
|
97335
|
+
return null;
|
|
97336
|
+
}
|
|
97337
|
+
let outcome;
|
|
97338
|
+
try {
|
|
97339
|
+
const received = now();
|
|
97340
|
+
outcome = inTransaction(mirror, () => {
|
|
97341
|
+
const result = store(prepared, { now: received, keepDisappearing });
|
|
97342
|
+
if (result !== SKIPPED) setMeta(mirror, { [META.lastReceivedAt]: received });
|
|
97343
|
+
return result;
|
|
97344
|
+
});
|
|
97345
|
+
} catch {
|
|
97346
|
+
this.failStorage();
|
|
97347
|
+
return null;
|
|
97348
|
+
}
|
|
97349
|
+
log(`event: ${label} ${outcome}`);
|
|
97350
|
+
return { prepared, outcome };
|
|
97351
|
+
}
|
|
97352
|
+
failStorage() {
|
|
97353
|
+
if (this.halted) return;
|
|
97354
|
+
this.halted = true;
|
|
97355
|
+
this.deps.onStorageFailure();
|
|
97356
|
+
this.deps.log(STORAGE_FAILURE_REASON);
|
|
97357
|
+
}
|
|
97358
|
+
};
|
|
97359
|
+
|
|
97360
|
+
// src/core/telegram/sync-request-queue.ts
|
|
97361
|
+
var RequestQueue = class {
|
|
97362
|
+
/** Settles when the last job in line is done. It never rejects. */
|
|
97363
|
+
tail = Promise.resolve();
|
|
97364
|
+
/**
|
|
97365
|
+
* Runs `work` once the jobs ahead are done. Rejects as `cancelled()`, without
|
|
97366
|
+
* running `work`, when `signal` aborts first; the jobs behind it then wait
|
|
97367
|
+
* for the ones ahead of it, as they would have.
|
|
97368
|
+
*/
|
|
97369
|
+
async run(signal, work) {
|
|
97370
|
+
const ahead = this.tail;
|
|
97371
|
+
let done = () => {
|
|
97372
|
+
};
|
|
97373
|
+
this.tail = new Promise((resolve8) => done = resolve8);
|
|
97374
|
+
try {
|
|
97375
|
+
await abortable(ahead, signal);
|
|
97376
|
+
} catch (error62) {
|
|
97377
|
+
void ahead.then(done);
|
|
97378
|
+
throw error62;
|
|
97379
|
+
}
|
|
97380
|
+
try {
|
|
97381
|
+
return await work();
|
|
97382
|
+
} finally {
|
|
97383
|
+
done();
|
|
97384
|
+
}
|
|
97385
|
+
}
|
|
97386
|
+
};
|
|
97387
|
+
|
|
97147
97388
|
// src/core/telegram/sync-request-calls.ts
|
|
97148
97389
|
async function viaTelegram(ctx, call, what, work) {
|
|
97149
97390
|
const signal = AbortSignal.any([call.signal, ctx.signal]);
|
|
@@ -97404,7 +97645,6 @@ function expectNoParams(params, what) {
|
|
|
97404
97645
|
}
|
|
97405
97646
|
|
|
97406
97647
|
// src/core/telegram/sync-download.ts
|
|
97407
|
-
var DOWNLOAD_STALL_MS = 6e4;
|
|
97408
97648
|
function fileOf(message2, id) {
|
|
97409
97649
|
const file2 = messageFile(message2);
|
|
97410
97650
|
if (!file2) {
|
|
@@ -97478,201 +97718,6 @@ function downloadRequest(ctx, queue, raw, call) {
|
|
|
97478
97718
|
return keptCopy(ctx, params).then((kept) => kept ?? queue.run(signal, () => downloadFile(ctx, call, signal, params)));
|
|
97479
97719
|
}
|
|
97480
97720
|
|
|
97481
|
-
// src/core/telegram/sync-options.ts
|
|
97482
|
-
var SECOND_MS2 = 1e3;
|
|
97483
|
-
var MINUTE_MS = 60 * SECOND_MS2;
|
|
97484
|
-
var HOUR_MS = 60 * MINUTE_MS;
|
|
97485
|
-
var DAY_MS = 24 * HOUR_MS;
|
|
97486
|
-
var DEFAULT_HEARTBEAT_EVERY_MS = 5 * SECOND_MS2;
|
|
97487
|
-
var DEFAULT_GAP_AFTER_MS = 30 * SECOND_MS2;
|
|
97488
|
-
var DEFAULT_OFFLINE_LIMIT_MS = 10 * MINUTE_MS;
|
|
97489
|
-
var DEFAULT_PURGE_EVERY_MS = HOUR_MS;
|
|
97490
|
-
var DEFAULT_REFRESH_EVERY_MS = 30 * MINUTE_MS;
|
|
97491
|
-
var DEFAULT_REFRESH_RETRY_MS = MINUTE_MS;
|
|
97492
|
-
var DEFAULT_ROUND_EVERY_MS = 5 * SECOND_MS2;
|
|
97493
|
-
var DEFAULT_STOP_WAIT_MS = 10 * SECOND_MS2;
|
|
97494
|
-
var DEFAULT_SEED_WITHIN_MS = 30 * DAY_MS;
|
|
97495
|
-
var DEFAULT_SEED_COUNT = 50;
|
|
97496
|
-
var DEFAULT_SEED_CHATS_PER_ROUND = 20;
|
|
97497
|
-
var DEFAULT_SEED_ATTEMPTS = 3;
|
|
97498
|
-
var DEFAULT_FILL_LIMIT = 200;
|
|
97499
|
-
var DEFAULT_PACE_MS = [500, 1500];
|
|
97500
|
-
function resolveOptions(options) {
|
|
97501
|
-
return {
|
|
97502
|
-
...options,
|
|
97503
|
-
now: options.now ?? Date.now,
|
|
97504
|
-
pause: options.pause ?? realPause,
|
|
97505
|
-
heartbeatEveryMs: options.heartbeatEveryMs ?? DEFAULT_HEARTBEAT_EVERY_MS,
|
|
97506
|
-
gapAfterMs: options.gapAfterMs ?? DEFAULT_GAP_AFTER_MS,
|
|
97507
|
-
offlineLimitMs: options.offlineLimitMs ?? DEFAULT_OFFLINE_LIMIT_MS,
|
|
97508
|
-
purgeEveryMs: options.purgeEveryMs ?? DEFAULT_PURGE_EVERY_MS,
|
|
97509
|
-
refreshEveryMs: options.refreshEveryMs ?? DEFAULT_REFRESH_EVERY_MS,
|
|
97510
|
-
refreshRetryMs: options.refreshRetryMs ?? DEFAULT_REFRESH_RETRY_MS,
|
|
97511
|
-
roundEveryMs: options.roundEveryMs ?? DEFAULT_ROUND_EVERY_MS,
|
|
97512
|
-
stopWaitMs: options.stopWaitMs ?? DEFAULT_STOP_WAIT_MS,
|
|
97513
|
-
seedWithinMs: options.seedWithinMs ?? DEFAULT_SEED_WITHIN_MS,
|
|
97514
|
-
seedCount: options.seedCount ?? DEFAULT_SEED_COUNT,
|
|
97515
|
-
seedChatsPerRound: options.seedChatsPerRound ?? DEFAULT_SEED_CHATS_PER_ROUND,
|
|
97516
|
-
seedAttempts: options.seedAttempts ?? DEFAULT_SEED_ATTEMPTS,
|
|
97517
|
-
fillLimit: options.fillLimit ?? DEFAULT_FILL_LIMIT,
|
|
97518
|
-
paceMs: options.paceMs ?? DEFAULT_PACE_MS,
|
|
97519
|
-
downloadStallMs: options.downloadStallMs ?? DOWNLOAD_STALL_MS
|
|
97520
|
-
};
|
|
97521
|
-
}
|
|
97522
|
-
|
|
97523
|
-
// src/core/telegram/sync-message.ts
|
|
97524
|
-
function readMessage(message2, channels) {
|
|
97525
|
-
const input8 = messageInputOf(message2);
|
|
97526
|
-
if (!input8) return null;
|
|
97527
|
-
const peer = readOrNull(() => message2.chat);
|
|
97528
|
-
const chat = peer ? chatInputOf(peer) : null;
|
|
97529
|
-
if (chat && !keepsKind(chat.kind, channels)) return null;
|
|
97530
|
-
return { chat, message: input8, topic: topicInputOfAction(message2) };
|
|
97531
|
-
}
|
|
97532
|
-
function writeMessage(mirror, ctx, read, channels) {
|
|
97533
|
-
if (read.chat) rememberChats(mirror, [read.chat], ctx.now, channels);
|
|
97534
|
-
if (read.topic) upsertTopics(mirror, [read.topic], ctx.now);
|
|
97535
|
-
return storeMessage(mirror, ctx, read.message);
|
|
97536
|
-
}
|
|
97537
|
-
|
|
97538
|
-
// src/core/telegram/sync-receive.ts
|
|
97539
|
-
var SKIPPED = "skipped";
|
|
97540
|
-
function countsOf(outcomes) {
|
|
97541
|
-
const counts = /* @__PURE__ */ new Map();
|
|
97542
|
-
for (const outcome of outcomes) counts.set(outcome, (counts.get(outcome) ?? 0) + 1);
|
|
97543
|
-
return [...counts].map(([outcome, count]) => `${outcome}=${count}`).join(" ") || "none";
|
|
97544
|
-
}
|
|
97545
|
-
var Receiver = class {
|
|
97546
|
-
deps;
|
|
97547
|
-
keeper;
|
|
97548
|
-
halted = false;
|
|
97549
|
-
constructor(deps) {
|
|
97550
|
-
this.deps = deps;
|
|
97551
|
-
}
|
|
97552
|
-
/**
|
|
97553
|
-
* Registers the handlers on the client's emitters; call it before the client
|
|
97554
|
-
* connects. `keeper` keeps the files of the disappearing messages that
|
|
97555
|
-
* arrive, when `keepDisappearing` is on.
|
|
97556
|
-
*/
|
|
97557
|
-
attach(client, keeper) {
|
|
97558
|
-
this.keeper = keeper;
|
|
97559
|
-
client.onNewMessage.add((message2) => this.onMessage("message", message2));
|
|
97560
|
-
client.onEditMessage.add((message2) => this.onMessage("edit", message2));
|
|
97561
|
-
client.onDeleteMessage.add((update) => this.onDelete(update));
|
|
97562
|
-
client.onHistoryRead.add((update) => this.onRead(update));
|
|
97563
|
-
}
|
|
97564
|
-
/** Stops storing: whatever arrives from here on is ignored. */
|
|
97565
|
-
halt() {
|
|
97566
|
-
this.halted = true;
|
|
97567
|
-
}
|
|
97568
|
-
onMessage(label, message2) {
|
|
97569
|
-
const { channels, keepDisappearing } = this.deps;
|
|
97570
|
-
const done = this.process(
|
|
97571
|
-
label,
|
|
97572
|
-
() => readMessage(message2, channels),
|
|
97573
|
-
(read, ctx) => writeMessage(this.deps.mirror, ctx, read, channels)
|
|
97574
|
-
);
|
|
97575
|
-
if (keepDisappearing && label === "message" && done?.outcome === "stored") {
|
|
97576
|
-
this.keeper?.keep(message2, done.prepared.message);
|
|
97577
|
-
}
|
|
97578
|
-
}
|
|
97579
|
-
onDelete(update) {
|
|
97580
|
-
const { mirror, coverage, keepDisappearing } = this.deps;
|
|
97581
|
-
const done = this.process(
|
|
97582
|
-
"delete",
|
|
97583
|
-
() => deleteInputOf(update),
|
|
97584
|
-
(input8, ctx) => {
|
|
97585
|
-
if (input8.chat !== null && !findChat(mirror, input8.chat)?.followed) return SKIPPED;
|
|
97586
|
-
coverage.note(ctx.now);
|
|
97587
|
-
return countsOf(deleteMessages2(mirror, ctx, input8));
|
|
97588
|
-
}
|
|
97589
|
-
);
|
|
97590
|
-
if (keepDisappearing && done && done.outcome !== SKIPPED) {
|
|
97591
|
-
this.keeper?.forgetMessages(done.prepared.chat, done.prepared.ids);
|
|
97592
|
-
}
|
|
97593
|
-
}
|
|
97594
|
-
onRead(update) {
|
|
97595
|
-
this.process(
|
|
97596
|
-
"read",
|
|
97597
|
-
() => readInputOf(update),
|
|
97598
|
-
(input8) => {
|
|
97599
|
-
applyRead(this.deps.mirror, input8);
|
|
97600
|
-
return "applied";
|
|
97601
|
-
}
|
|
97602
|
-
);
|
|
97603
|
-
}
|
|
97604
|
-
/**
|
|
97605
|
-
* Turns the update into `prepared` outside the transaction, so that what
|
|
97606
|
-
* fails there is only mtcute's data, then writes it. `store` names the
|
|
97607
|
-
* outcome for the log. Resolves with `prepared` and the outcome once it is
|
|
97608
|
-
* written, and with null when the update was not (unreadable, not for the
|
|
97609
|
-
* mirror, or a storage failure).
|
|
97610
|
-
*/
|
|
97611
|
-
process(label, prepare2, store) {
|
|
97612
|
-
if (this.halted) return null;
|
|
97613
|
-
const { mirror, now, keepDisappearing, log } = this.deps;
|
|
97614
|
-
let prepared;
|
|
97615
|
-
try {
|
|
97616
|
-
prepared = prepare2();
|
|
97617
|
-
} catch (error62) {
|
|
97618
|
-
log(`event: ${label} unreadable (${errorLabel(error62)})`);
|
|
97619
|
-
return null;
|
|
97620
|
-
}
|
|
97621
|
-
if (prepared === null) {
|
|
97622
|
-
log(`event: ${label} ${SKIPPED}`);
|
|
97623
|
-
return null;
|
|
97624
|
-
}
|
|
97625
|
-
let outcome;
|
|
97626
|
-
try {
|
|
97627
|
-
const received = now();
|
|
97628
|
-
outcome = inTransaction(mirror, () => {
|
|
97629
|
-
const result = store(prepared, { now: received, keepDisappearing });
|
|
97630
|
-
if (result !== SKIPPED) setMeta(mirror, { [META.lastReceivedAt]: received });
|
|
97631
|
-
return result;
|
|
97632
|
-
});
|
|
97633
|
-
} catch {
|
|
97634
|
-
this.failStorage();
|
|
97635
|
-
return null;
|
|
97636
|
-
}
|
|
97637
|
-
log(`event: ${label} ${outcome}`);
|
|
97638
|
-
return { prepared, outcome };
|
|
97639
|
-
}
|
|
97640
|
-
failStorage() {
|
|
97641
|
-
if (this.halted) return;
|
|
97642
|
-
this.halted = true;
|
|
97643
|
-
this.deps.onStorageFailure();
|
|
97644
|
-
this.deps.log(STORAGE_FAILURE_REASON);
|
|
97645
|
-
}
|
|
97646
|
-
};
|
|
97647
|
-
|
|
97648
|
-
// src/core/telegram/sync-request-queue.ts
|
|
97649
|
-
var RequestQueue = class {
|
|
97650
|
-
/** Settles when the last job in line is done. It never rejects. */
|
|
97651
|
-
tail = Promise.resolve();
|
|
97652
|
-
/**
|
|
97653
|
-
* Runs `work` once the jobs ahead are done. Rejects as `cancelled()`, without
|
|
97654
|
-
* running `work`, when `signal` aborts first; the jobs behind it then wait
|
|
97655
|
-
* for the ones ahead of it, as they would have.
|
|
97656
|
-
*/
|
|
97657
|
-
async run(signal, work) {
|
|
97658
|
-
const ahead = this.tail;
|
|
97659
|
-
let done = () => {
|
|
97660
|
-
};
|
|
97661
|
-
this.tail = new Promise((resolve8) => done = resolve8);
|
|
97662
|
-
try {
|
|
97663
|
-
await abortable(ahead, signal);
|
|
97664
|
-
} catch (error62) {
|
|
97665
|
-
void ahead.then(done);
|
|
97666
|
-
throw error62;
|
|
97667
|
-
}
|
|
97668
|
-
try {
|
|
97669
|
-
return await work();
|
|
97670
|
-
} finally {
|
|
97671
|
-
done();
|
|
97672
|
-
}
|
|
97673
|
-
}
|
|
97674
|
-
};
|
|
97675
|
-
|
|
97676
97721
|
// src/core/telegram/sync-list-requests.ts
|
|
97677
97722
|
function expectListable({ mirror, settings }, chats) {
|
|
97678
97723
|
for (const id of chats) {
|
|
@@ -97724,7 +97769,6 @@ async function syncRemove(ctx, raw) {
|
|
|
97724
97769
|
}
|
|
97725
97770
|
|
|
97726
97771
|
// src/core/telegram/sync-send-outcome.ts
|
|
97727
|
-
var MS_PER_S5 = 1e3;
|
|
97728
97772
|
var RANDOM_ID_DUPLICATE = "RANDOM_ID_DUPLICATE";
|
|
97729
97773
|
var CALL_TIMEOUT = "TIMEOUT";
|
|
97730
97774
|
var REFUSAL_CODES = [400, 403, 406];
|
|
@@ -97807,7 +97851,7 @@ function sentMessageOf(response, randomId) {
|
|
|
97807
97851
|
return {
|
|
97808
97852
|
form: "short",
|
|
97809
97853
|
id: response.id,
|
|
97810
|
-
date: response.date *
|
|
97854
|
+
date: response.date * MS_PER_S,
|
|
97811
97855
|
ttl: response.ttlPeriod ?? null,
|
|
97812
97856
|
entities: response.entities ?? []
|
|
97813
97857
|
};
|
|
@@ -98075,12 +98119,27 @@ function sendRequest(ctx, queue, raw, call) {
|
|
|
98075
98119
|
}
|
|
98076
98120
|
|
|
98077
98121
|
// src/core/telegram/sync-action.ts
|
|
98078
|
-
function
|
|
98122
|
+
function runAction(ctx, queue, raw, call, parse6, act) {
|
|
98123
|
+
const params = parse6(raw);
|
|
98124
|
+
const signal = AbortSignal.any([call.signal, ctx.signal]);
|
|
98125
|
+
return queue.run(signal, () => act(params, signal));
|
|
98126
|
+
}
|
|
98127
|
+
async function resolveChatPeer(ctx, call, signal, what, chat) {
|
|
98128
|
+
const peer = await viaTelegram(ctx, call, what, () => ctx.client.resolvePeer(Number(chat)));
|
|
98129
|
+
if (signal.aborted) throw cancelled();
|
|
98130
|
+
return peer;
|
|
98131
|
+
}
|
|
98132
|
+
function inputChannelOf(peer) {
|
|
98133
|
+
if (peer._ !== "inputPeerChannel") return void 0;
|
|
98134
|
+
const { channelId, accessHash } = peer;
|
|
98135
|
+
return { _: "inputChannel", channelId, accessHash };
|
|
98136
|
+
}
|
|
98137
|
+
function performAction(ctx, signal, refusals, request) {
|
|
98079
98138
|
return callOnce(
|
|
98080
98139
|
ctx,
|
|
98081
98140
|
signal,
|
|
98082
98141
|
refusals.words.name,
|
|
98083
|
-
call,
|
|
98142
|
+
(options) => ctx.client.call(request, options),
|
|
98084
98143
|
(error62, trouble) => actionFailureOf(error62, trouble, refusals)
|
|
98085
98144
|
);
|
|
98086
98145
|
}
|
|
@@ -98161,10 +98220,9 @@ var DELETE_REFUSALS = {
|
|
|
98161
98220
|
}
|
|
98162
98221
|
]
|
|
98163
98222
|
};
|
|
98164
|
-
function requestOf(
|
|
98165
|
-
if (
|
|
98166
|
-
|
|
98167
|
-
return { _: "channels.deleteMessages", channel: { _: "inputChannel", channelId, accessHash }, id: [id] };
|
|
98223
|
+
function requestOf(channel, id) {
|
|
98224
|
+
if (!channel) return { _: "messages.deleteMessages", revoke: true, id: [id] };
|
|
98225
|
+
return { _: "channels.deleteMessages", channel, id: [id] };
|
|
98168
98226
|
}
|
|
98169
98227
|
function recordDelete(ctx, { id: chat, kind }, id) {
|
|
98170
98228
|
recordAction(ctx, "delete", () => {
|
|
@@ -98180,22 +98238,17 @@ function recordDelete(ctx, { id: chat, kind }, id) {
|
|
|
98180
98238
|
async function deleteOwn(ctx, call, signal, params) {
|
|
98181
98239
|
const { chat, message: message2 } = targetOf(ctx.mirror, params.chat, params.id, DELETE_WORDS);
|
|
98182
98240
|
if (!message2) return { id: params.id, deleted: true, already: true };
|
|
98183
|
-
const
|
|
98184
|
-
|
|
98185
|
-
|
|
98186
|
-
const affected = await performAction(ctx, signal, DELETE_REFUSALS, (options) => ctx.client.call(request, options));
|
|
98187
|
-
if (affected) handOverAffected(ctx, "delete", affected, peer._ === "inputPeerChannel" ? peer.channelId : void 0);
|
|
98241
|
+
const channel = inputChannelOf(await resolveChatPeer(ctx, call, signal, "delete", params.chat));
|
|
98242
|
+
const affected = await performAction(ctx, signal, DELETE_REFUSALS, requestOf(channel, params.id));
|
|
98243
|
+
if (affected) handOverAffected(ctx, "delete", affected, channel?.channelId);
|
|
98188
98244
|
recordDelete(ctx, chat, params.id);
|
|
98189
98245
|
return { id: params.id, deleted: true, ...!affected || affected.ptsCount === 0 ? { already: true } : {} };
|
|
98190
98246
|
}
|
|
98191
98247
|
function deleteRequest(ctx, queue, raw, call) {
|
|
98192
|
-
|
|
98193
|
-
const signal = AbortSignal.any([call.signal, ctx.signal]);
|
|
98194
|
-
return queue.run(signal, () => deleteOwn(ctx, call, signal, params));
|
|
98248
|
+
return runAction(ctx, queue, raw, call, parseDeleteParams, (params, signal) => deleteOwn(ctx, call, signal, params));
|
|
98195
98249
|
}
|
|
98196
98250
|
|
|
98197
98251
|
// src/core/telegram/sync-edit.ts
|
|
98198
|
-
var MS_PER_S6 = 1e3;
|
|
98199
98252
|
var EDIT_WORDS = {
|
|
98200
98253
|
name: "edit",
|
|
98201
98254
|
gerund: "editing",
|
|
@@ -98255,25 +98308,22 @@ function acceptedResult2(ctx, params, response) {
|
|
|
98255
98308
|
throw uncertainAction(EDIT_WORDS, "Telegram's answer did not name the edited message");
|
|
98256
98309
|
}
|
|
98257
98310
|
recordEdit(ctx, params, raw, group);
|
|
98258
|
-
return { id: params.id, edited: raw.editDate *
|
|
98311
|
+
return { id: params.id, edited: raw.editDate * MS_PER_S };
|
|
98259
98312
|
}
|
|
98260
98313
|
async function editText(ctx, call, signal, params) {
|
|
98261
98314
|
refuseUneditable(targetOf(ctx.mirror, params.chat, params.id, EDIT_WORDS), params.text);
|
|
98262
|
-
const peer = await
|
|
98263
|
-
if (signal.aborted) throw cancelled();
|
|
98315
|
+
const peer = await resolveChatPeer(ctx, call, signal, "edit", params.chat);
|
|
98264
98316
|
const request = {
|
|
98265
98317
|
_: "messages.editMessage",
|
|
98266
98318
|
peer,
|
|
98267
98319
|
id: params.id,
|
|
98268
98320
|
message: params.text
|
|
98269
98321
|
};
|
|
98270
|
-
const response = await performAction(ctx, signal, EDIT_REFUSALS,
|
|
98322
|
+
const response = await performAction(ctx, signal, EDIT_REFUSALS, request);
|
|
98271
98323
|
return response === void 0 ? alreadyResult(ctx, params) : acceptedResult2(ctx, params, response);
|
|
98272
98324
|
}
|
|
98273
98325
|
function editRequest(ctx, queue, raw, call) {
|
|
98274
|
-
|
|
98275
|
-
const signal = AbortSignal.any([call.signal, ctx.signal]);
|
|
98276
|
-
return queue.run(signal, () => editText(ctx, call, signal, params));
|
|
98326
|
+
return runAction(ctx, queue, raw, call, parseEditParams, (params, signal) => editText(ctx, call, signal, params));
|
|
98277
98327
|
}
|
|
98278
98328
|
|
|
98279
98329
|
// src/core/telegram/sync-mark-read.ts
|
|
@@ -98290,9 +98340,9 @@ var MARK_READ_REFUSALS = {
|
|
|
98290
98340
|
};
|
|
98291
98341
|
function requestOf2(peer, { up_to, topic }) {
|
|
98292
98342
|
if (topic !== void 0) return { _: "messages.readDiscussion", peer, msgId: topic, readMaxId: up_to };
|
|
98293
|
-
|
|
98294
|
-
|
|
98295
|
-
return { _: "channels.readHistory", channel
|
|
98343
|
+
const channel = inputChannelOf(peer);
|
|
98344
|
+
if (!channel) return { _: "messages.readHistory", peer, maxId: up_to };
|
|
98345
|
+
return { _: "channels.readHistory", channel, maxId: up_to };
|
|
98296
98346
|
}
|
|
98297
98347
|
function unreadPast(mirror, chat, readMax) {
|
|
98298
98348
|
const row = mirror.prepare("SELECT COUNT(*) AS unread FROM messages WHERE chat = ? AND from_me = 0 AND id > ?").get(chat, readMax);
|
|
@@ -98318,23 +98368,19 @@ async function markRead(ctx, call, signal, params) {
|
|
|
98318
98368
|
checkInTopic(message2.topic, topic, MARK_READ_WORDS.past);
|
|
98319
98369
|
const done = { chat, up_to, ...topic === void 0 ? {} : { topic } };
|
|
98320
98370
|
if (topic === void 0 && row.read_max !== null && row.read_max >= up_to) return { ...done, already: true };
|
|
98321
|
-
const peer = await
|
|
98322
|
-
if (signal.aborted) throw cancelled();
|
|
98323
|
-
const request = requestOf2(peer, params);
|
|
98371
|
+
const peer = await resolveChatPeer(ctx, call, signal, "mark read", chat);
|
|
98324
98372
|
const answer = await performAction(
|
|
98325
98373
|
ctx,
|
|
98326
98374
|
signal,
|
|
98327
98375
|
MARK_READ_REFUSALS,
|
|
98328
|
-
(
|
|
98376
|
+
requestOf2(peer, params)
|
|
98329
98377
|
);
|
|
98330
98378
|
if (typeof answer === "object") handOverAffected(ctx, "mark read", answer);
|
|
98331
98379
|
if (topic === void 0) recordRead(ctx, params);
|
|
98332
98380
|
return done;
|
|
98333
98381
|
}
|
|
98334
98382
|
function markReadRequest(ctx, queue, raw, call) {
|
|
98335
|
-
|
|
98336
|
-
const signal = AbortSignal.any([call.signal, ctx.signal]);
|
|
98337
|
-
return queue.run(signal, () => markRead(ctx, call, signal, params));
|
|
98383
|
+
return runAction(ctx, queue, raw, call, parseMarkReadParams, (params, signal) => markRead(ctx, call, signal, params));
|
|
98338
98384
|
}
|
|
98339
98385
|
|
|
98340
98386
|
// src/core/telegram/sync-pin.ts
|
|
@@ -98384,8 +98430,7 @@ async function pinMessage2(ctx, call, signal, params) {
|
|
|
98384
98430
|
const unpin = params.unpin === true;
|
|
98385
98431
|
const { chat } = anyMessageOf(ctx.mirror, params.chat, params.id, unpin ? UNPIN_WORDS : PIN_WORDS);
|
|
98386
98432
|
checkBothSides(chat.kind, params.both_sides);
|
|
98387
|
-
const peer = await
|
|
98388
|
-
if (signal.aborted) throw cancelled();
|
|
98433
|
+
const peer = await resolveChatPeer(ctx, call, signal, "pin", params.chat);
|
|
98389
98434
|
const request = {
|
|
98390
98435
|
_: "messages.updatePinnedMessage",
|
|
98391
98436
|
peer,
|
|
@@ -98394,21 +98439,14 @@ async function pinMessage2(ctx, call, signal, params) {
|
|
|
98394
98439
|
...unpin ? { unpin } : {},
|
|
98395
98440
|
...isPrivateChat(chat.kind) && !params.both_sides ? { pmOneside: true } : {}
|
|
98396
98441
|
};
|
|
98397
|
-
const response = await performAction(
|
|
98398
|
-
ctx,
|
|
98399
|
-
signal,
|
|
98400
|
-
unpin ? UNPIN_REFUSALS : PIN_REFUSALS,
|
|
98401
|
-
(options) => ctx.client.call(request, options)
|
|
98402
|
-
);
|
|
98442
|
+
const response = await performAction(ctx, signal, unpin ? UNPIN_REFUSALS : PIN_REFUSALS, request);
|
|
98403
98443
|
if (response === void 0) return { id: params.id, pinned: !unpin, already: true };
|
|
98404
98444
|
handOver(ctx, response, "pin");
|
|
98405
98445
|
recordServiceMessages(ctx, params.chat, response);
|
|
98406
98446
|
return { id: params.id, pinned: !unpin };
|
|
98407
98447
|
}
|
|
98408
98448
|
function pinRequest(ctx, queue, raw, call) {
|
|
98409
|
-
|
|
98410
|
-
const signal = AbortSignal.any([call.signal, ctx.signal]);
|
|
98411
|
-
return queue.run(signal, () => pinMessage2(ctx, call, signal, params));
|
|
98449
|
+
return runAction(ctx, queue, raw, call, parsePinParams, (params, signal) => pinMessage2(ctx, call, signal, params));
|
|
98412
98450
|
}
|
|
98413
98451
|
|
|
98414
98452
|
// src/core/telegram/sync-react.ts
|
|
@@ -98474,24 +98512,21 @@ async function reactTo(ctx, call, signal, params) {
|
|
|
98474
98512
|
if (params.emoji !== void 0 && ownReaction(storedReactions(message2.reactions)) === params.emoji) {
|
|
98475
98513
|
return { ...doneOf(params), already: true };
|
|
98476
98514
|
}
|
|
98477
|
-
const peer = await
|
|
98478
|
-
if (signal.aborted) throw cancelled();
|
|
98515
|
+
const peer = await resolveChatPeer(ctx, call, signal, "react", params.chat);
|
|
98479
98516
|
const request = {
|
|
98480
98517
|
_: "messages.sendReaction",
|
|
98481
98518
|
peer,
|
|
98482
98519
|
msgId: params.id,
|
|
98483
98520
|
reaction: params.emoji === void 0 ? [] : [{ _: "reactionEmoji", emoticon: params.emoji }]
|
|
98484
98521
|
};
|
|
98485
|
-
const response = await performAction(ctx, signal, REACT_REFUSALS,
|
|
98522
|
+
const response = await performAction(ctx, signal, REACT_REFUSALS, request);
|
|
98486
98523
|
if (response === void 0) return { ...doneOf(params), already: true };
|
|
98487
98524
|
handOver(ctx, response, "react");
|
|
98488
98525
|
recordReaction(ctx, params, response);
|
|
98489
98526
|
return doneOf(params);
|
|
98490
98527
|
}
|
|
98491
98528
|
function reactRequest(ctx, queue, raw, call) {
|
|
98492
|
-
|
|
98493
|
-
const signal = AbortSignal.any([call.signal, ctx.signal]);
|
|
98494
|
-
return queue.run(signal, () => reactTo(ctx, call, signal, params));
|
|
98529
|
+
return runAction(ctx, queue, raw, call, parseReactParams, (params, signal) => reactTo(ctx, call, signal, params));
|
|
98495
98530
|
}
|
|
98496
98531
|
|
|
98497
98532
|
// src/core/telegram/sync-send-outbox.ts
|
|
@@ -98567,7 +98602,7 @@ function uploadFailure(ctx, signal, error62, name) {
|
|
|
98567
98602
|
return refusal ?? new ToolError("upstream_error", `The upload of ${name} failed (${errorLabel(error62)}); nothing was sent.`);
|
|
98568
98603
|
}
|
|
98569
98604
|
async function uploadOne(ctx, signal, file2) {
|
|
98570
|
-
const stallMs = ctx.settings.
|
|
98605
|
+
const stallMs = ctx.settings.transferStallMs;
|
|
98571
98606
|
const stall = new AbortController();
|
|
98572
98607
|
const uploadSignal = AbortSignal.any([signal, stall.signal]);
|
|
98573
98608
|
let stalled2 = false;
|