@will-17173/telegram-cli 0.3.0 → 0.4.1
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/README.md +73 -335
- package/README.zh-CN.md +72 -333
- package/dist/account/account-authenticator.js +95 -0
- package/dist/account/account-authenticator.js.map +1 -0
- package/dist/account/account-context.js +7 -0
- package/dist/account/account-context.js.map +1 -1
- package/dist/account/account-name.js +17 -0
- package/dist/account/account-name.js.map +1 -0
- package/dist/account/account-presets.js +20 -3
- package/dist/account/account-presets.js.map +1 -1
- package/dist/account/account-store.js +277 -37
- package/dist/account/account-store.js.map +1 -1
- package/dist/cli/app.js +12 -1
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/output.js +21 -6
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/secure-input.js +408 -0
- package/dist/cli/secure-input.js.map +1 -0
- package/dist/commands/account-options.js +37 -7
- package/dist/commands/account-options.js.map +1 -1
- package/dist/commands/account.js +144 -62
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/archive.js +151 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/config.js +119 -12
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/contact.js +58 -0
- package/dist/commands/contact.js.map +1 -0
- package/dist/commands/data.js +14 -7
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/dialog.js +156 -0
- package/dist/commands/dialog.js.map +1 -0
- package/dist/commands/folder.js +113 -0
- package/dist/commands/folder.js.map +1 -0
- package/dist/commands/group-write.js +45 -5
- package/dist/commands/group-write.js.map +1 -1
- package/dist/commands/group.js +23 -1
- package/dist/commands/group.js.map +1 -1
- package/dist/commands/notification.js +76 -0
- package/dist/commands/notification.js.map +1 -0
- package/dist/commands/query.js +22 -15
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/telegram-runner.js +40 -18
- package/dist/commands/telegram-runner.js.map +1 -1
- package/dist/commands/telegram.js +82 -38
- package/dist/commands/telegram.js.map +1 -1
- package/dist/commands/time-range.js +39 -0
- package/dist/commands/time-range.js.map +1 -0
- package/dist/commands/types.js +3 -2
- package/dist/commands/types.js.map +1 -1
- package/dist/config/credential-store.js +24 -4
- package/dist/config/credential-store.js.map +1 -1
- package/dist/config/env.js +4 -1
- package/dist/config/env.js.map +1 -1
- package/dist/group-commands/catalog.js +10 -0
- package/dist/group-commands/catalog.js.map +1 -1
- package/dist/group-commands/executor.js +13 -4
- package/dist/group-commands/executor.js.map +1 -1
- package/dist/presenters/group.js +16 -0
- package/dist/presenters/group.js.map +1 -1
- package/dist/presenters/human.js +113 -0
- package/dist/presenters/human.js.map +1 -1
- package/dist/presenters/ink/group-command-result.js +2 -0
- package/dist/presenters/ink/group-command-result.js.map +1 -1
- package/dist/presenters/ink/listen-scroll.js +4 -3
- package/dist/presenters/ink/listen-scroll.js.map +1 -1
- package/dist/presenters/ink/listen.js +245 -57
- package/dist/presenters/ink/listen.js.map +1 -1
- package/dist/presenters/ink/mouse-scroll.js +12 -0
- package/dist/presenters/ink/mouse-scroll.js.map +1 -1
- package/dist/presenters/ink/secure-input.js +68 -0
- package/dist/presenters/ink/secure-input.js.map +1 -0
- package/dist/presenters/ink/use-group-command.js +78 -17
- package/dist/presenters/ink/use-group-command.js.map +1 -1
- package/dist/presenters/markdown.js +54 -0
- package/dist/presenters/markdown.js.map +1 -0
- package/dist/presenters/structured.js +8 -3
- package/dist/presenters/structured.js.map +1 -1
- package/dist/services/account-session-service.js +241 -0
- package/dist/services/account-session-service.js.map +1 -0
- package/dist/services/archive-layout.js +61 -0
- package/dist/services/archive-layout.js.map +1 -0
- package/dist/services/archive-manifest.js +187 -0
- package/dist/services/archive-manifest.js.map +1 -0
- package/dist/services/archive-markdown.js +383 -0
- package/dist/services/archive-markdown.js.map +1 -0
- package/dist/services/archive-service.js +718 -0
- package/dist/services/archive-service.js.map +1 -0
- package/dist/services/archive-types.js +2 -0
- package/dist/services/archive-types.js.map +1 -0
- package/dist/services/attachment-download.js +7 -2
- package/dist/services/attachment-download.js.map +1 -1
- package/dist/services/auto-download-coordinator.js +2 -4
- package/dist/services/auto-download-coordinator.js.map +1 -1
- package/dist/services/contact-service.js +78 -0
- package/dist/services/contact-service.js.map +1 -0
- package/dist/services/dialog-service.js +140 -0
- package/dist/services/dialog-service.js.map +1 -0
- package/dist/services/folder-service.js +200 -0
- package/dist/services/folder-service.js.map +1 -0
- package/dist/services/group-write-service.js +78 -18
- package/dist/services/group-write-service.js.map +1 -1
- package/dist/services/message-service.js +17 -1
- package/dist/services/message-service.js.map +1 -1
- package/dist/services/notification-service.js +142 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/write-access-policy.js +19 -0
- package/dist/services/write-access-policy.js.map +1 -0
- package/dist/telegram/archive-types.js +2 -0
- package/dist/telegram/archive-types.js.map +1 -0
- package/dist/telegram/client-factory.js +51 -11
- package/dist/telegram/client-factory.js.map +1 -1
- package/dist/telegram/contact-types.js +10 -0
- package/dist/telegram/contact-types.js.map +1 -0
- package/dist/telegram/dialog-types.js +2 -0
- package/dist/telegram/dialog-types.js.map +1 -0
- package/dist/telegram/errors.js +14 -0
- package/dist/telegram/errors.js.map +1 -0
- package/dist/telegram/fake-group-management.js +5 -0
- package/dist/telegram/fake-group-management.js.map +1 -1
- package/dist/telegram/folder-types.js +13 -0
- package/dist/telegram/folder-types.js.map +1 -0
- package/dist/telegram/group-write-types.js +28 -1
- package/dist/telegram/group-write-types.js.map +1 -1
- package/dist/telegram/mtcute-archive.js +190 -0
- package/dist/telegram/mtcute-archive.js.map +1 -0
- package/dist/telegram/mtcute-client.js +72 -11
- package/dist/telegram/mtcute-client.js.map +1 -1
- package/dist/telegram/mtcute-contacts.js +90 -0
- package/dist/telegram/mtcute-contacts.js.map +1 -0
- package/dist/telegram/mtcute-dialogs.js +186 -0
- package/dist/telegram/mtcute-dialogs.js.map +1 -0
- package/dist/telegram/mtcute-folders.js +318 -0
- package/dist/telegram/mtcute-folders.js.map +1 -0
- package/dist/telegram/mtcute-group-members.js +43 -3
- package/dist/telegram/mtcute-group-members.js.map +1 -1
- package/dist/telegram/mtcute-message-normalizer.js +63 -0
- package/dist/telegram/mtcute-message-normalizer.js.map +1 -0
- package/dist/telegram/mtcute-notifications.js +101 -0
- package/dist/telegram/mtcute-notifications.js.map +1 -0
- package/dist/telegram/notification-types.js +11 -0
- package/dist/telegram/notification-types.js.map +1 -0
- package/dist/telegram/types.js +6 -1
- package/dist/telegram/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export function renderHumanMarkdown(output) {
|
|
2
|
+
switch (output.kind) {
|
|
3
|
+
case 'text':
|
|
4
|
+
return normalizeNewlines(output.text);
|
|
5
|
+
case 'detail': {
|
|
6
|
+
const rows = output.fields.map((field) => formatField(field.label, field.value));
|
|
7
|
+
return `# ${escapeMarkdownField(output.title)}\n\n${rows.join('\n')}`;
|
|
8
|
+
}
|
|
9
|
+
case 'summary': {
|
|
10
|
+
const rows = output.fields.map((field) => formatField(field.label, field.value));
|
|
11
|
+
const title = `# ${escapeMarkdownField(output.title)}\n\n${rows.join('\n')}`;
|
|
12
|
+
const table = output.table == null
|
|
13
|
+
? ''
|
|
14
|
+
: `\n\n${renderTable(output.table.columns, output.table.rows)}`;
|
|
15
|
+
return `${title}${table}`;
|
|
16
|
+
}
|
|
17
|
+
case 'table':
|
|
18
|
+
return `# ${escapeMarkdownField(output.title)}\n\n${renderTable(output.columns, output.rows)}`;
|
|
19
|
+
case 'timeline':
|
|
20
|
+
return `# ${escapeMarkdownField(output.title)}\n\n${renderTable(['PERIOD', 'COUNT'], output.rows.map((row) => [escapeMarkdownCell(row.period), escapeMarkdownCell(String(row.count))]))}`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function renderMarkdownError(code, message) {
|
|
24
|
+
return `# Error\n\n- **Code:** \`${escapeMarkdownField(code)}\`\n- **Message:** ${escapeMarkdownField(message)}`;
|
|
25
|
+
}
|
|
26
|
+
function formatField(label, value) {
|
|
27
|
+
return `- **${escapeMarkdownField(label)}:** ${escapeMarkdownField(value)}`;
|
|
28
|
+
}
|
|
29
|
+
function renderTable(columns, rows) {
|
|
30
|
+
const header = columns.map((column) => escapeMarkdownField(column)).join(' | ');
|
|
31
|
+
const separator = columns.map(() => '---').join(' | ');
|
|
32
|
+
const body = rows.length === 0
|
|
33
|
+
? []
|
|
34
|
+
: rows.map((row) => `| ${row.map((cell) => escapeMarkdownCell(cell)).join(' | ')} |`);
|
|
35
|
+
return [`| ${header} |`, `| ${separator} |`, ...body].join('\n');
|
|
36
|
+
}
|
|
37
|
+
function escapeMarkdownField(value) {
|
|
38
|
+
return escapeMarkdown(value).replaceAll('\n', '<br>');
|
|
39
|
+
}
|
|
40
|
+
function escapeMarkdownCell(value) {
|
|
41
|
+
return escapeMarkdown(value).replaceAll('\n', '<br>');
|
|
42
|
+
}
|
|
43
|
+
function escapeMarkdown(value) {
|
|
44
|
+
return normalizeNewlines(value)
|
|
45
|
+
.replaceAll('\\', '\\\\')
|
|
46
|
+
.replaceAll('|', '\\|')
|
|
47
|
+
.replaceAll('`', '\\`');
|
|
48
|
+
}
|
|
49
|
+
function normalizeNewlines(value) {
|
|
50
|
+
return value
|
|
51
|
+
.replaceAll('\r\n', '\n')
|
|
52
|
+
.replaceAll('\r', '\n');
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/presenters/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import YAML from 'yaml';
|
|
2
2
|
const SCHEMA_VERSION = '1';
|
|
3
3
|
export function resolveOutputFormat(options) {
|
|
4
|
-
if (options.json && options.yaml) {
|
|
5
|
-
throw new Error('Use only one of --json or --
|
|
4
|
+
if (options.json && (options.yaml || options.markdown)) {
|
|
5
|
+
throw new Error('Use only one of --json, --yaml, or --markdown.');
|
|
6
|
+
}
|
|
7
|
+
if (options.yaml && options.markdown) {
|
|
8
|
+
throw new Error('Use only one of --json, --yaml, or --markdown.');
|
|
6
9
|
}
|
|
7
10
|
if (options.yaml)
|
|
8
11
|
return 'yaml';
|
|
9
12
|
if (options.json)
|
|
10
13
|
return 'json';
|
|
14
|
+
if (options.markdown)
|
|
15
|
+
return 'markdown';
|
|
11
16
|
const mode = (process.env.OUTPUT || 'auto').trim().toLowerCase();
|
|
12
|
-
if (mode === 'yaml' || mode === 'json' || mode === 'rich')
|
|
17
|
+
if (mode === 'yaml' || mode === 'json' || mode === 'rich' || mode === 'markdown')
|
|
13
18
|
return mode;
|
|
14
19
|
return options.isTty === false ? 'yaml' : 'rich';
|
|
15
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured.js","sourceRoot":"","sources":["../../src/presenters/structured.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAGvB,MAAM,cAAc,GAAG,GAAG,CAAA;
|
|
1
|
+
{"version":3,"file":"structured.js","sourceRoot":"","sources":["../../src/presenters/structured.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAGvB,MAAM,cAAc,GAAG,GAAG,CAAA;AAS1B,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;IACnE,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;IACnE,CAAC;IACD,IAAI,OAAO,CAAC,IAAI;QAAE,OAAO,MAAM,CAAA;IAC/B,IAAI,OAAO,CAAC,IAAI;QAAE,OAAO,MAAM,CAAA;IAC/B,IAAI,OAAO,CAAC,QAAQ;QAAE,OAAO,UAAU,CAAA;IAEvC,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAChE,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,IAAI,CAAA;IAC7F,OAAO,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;AAClD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,IAAI,EAAE,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAe,EAAE,OAAiB;IAC3E,MAAM,KAAK,GAA4B,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IACxD,IAAI,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAA;IAClD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,CAAA;AAC7D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,MAAuB;IACtE,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC9D,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAA;AAC3D,CAAC"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, renameSync, rmSync } from 'node:fs';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { authenticateAccountAt } from '../account/account-authenticator.js';
|
|
5
|
+
import { accountSessionPath } from '../account/account-presets.js';
|
|
6
|
+
import { createTelegramClient } from '../telegram/client-factory.js';
|
|
7
|
+
import { TelegramSessionTerminatedError } from '../telegram/types.js';
|
|
8
|
+
import { isCliInterruptedError } from '../cli/secure-input.js';
|
|
9
|
+
export class AccountSessionService {
|
|
10
|
+
options;
|
|
11
|
+
createClient;
|
|
12
|
+
authenticate;
|
|
13
|
+
createTemporaryDirectory;
|
|
14
|
+
removePath;
|
|
15
|
+
renamePath;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.createClient = options.createClient ?? createTelegramClient;
|
|
19
|
+
this.authenticate = options.authenticate ?? authenticateAccountAt;
|
|
20
|
+
this.createTemporaryDirectory = options.createTemporaryDirectory ?? mkdtempSync;
|
|
21
|
+
this.removePath = options.removePath ?? ((path) => rmSync(path, { recursive: true, force: true }));
|
|
22
|
+
this.renamePath = options.renamePath ?? renameSync;
|
|
23
|
+
}
|
|
24
|
+
async logout(input) {
|
|
25
|
+
return this.options.store.withLock(async () => {
|
|
26
|
+
const registry = this.options.store.read();
|
|
27
|
+
const account = findAccount(registry, input.name);
|
|
28
|
+
if (!account)
|
|
29
|
+
return accountNotFound(input.name);
|
|
30
|
+
if (account.auth_state === 'logged_out')
|
|
31
|
+
return success(account, false);
|
|
32
|
+
let client;
|
|
33
|
+
try {
|
|
34
|
+
client = this.createClient(accountSessionPath(this.options.dataDir, account.name));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return failure('account_logout_failed', 'Unable to initialize Telegram logout.');
|
|
38
|
+
}
|
|
39
|
+
let logoutError;
|
|
40
|
+
try {
|
|
41
|
+
await client.logOut();
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
logoutError = error;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await client.close();
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (logoutError == null)
|
|
51
|
+
logoutError = error;
|
|
52
|
+
}
|
|
53
|
+
if (logoutError != null && !isTerminalSessionError(logoutError)) {
|
|
54
|
+
return failure('account_logout_failed', 'Unable to log out the Telegram account.');
|
|
55
|
+
}
|
|
56
|
+
const updated = { ...account, auth_state: 'logged_out' };
|
|
57
|
+
try {
|
|
58
|
+
this.options.store.write(updateAccount(registry, updated));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return failure('account_store_error', 'Unable to update account authentication state.');
|
|
62
|
+
}
|
|
63
|
+
return success(updated, true);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async login(input) {
|
|
67
|
+
return this.options.store.withLock(async () => {
|
|
68
|
+
const registry = this.options.store.read();
|
|
69
|
+
const account = findAccount(registry, input.name);
|
|
70
|
+
if (!account)
|
|
71
|
+
return accountNotFound(input.name);
|
|
72
|
+
if (account.auth_state === 'authenticated')
|
|
73
|
+
return success(account, false);
|
|
74
|
+
if (input.interactive === false) {
|
|
75
|
+
return failure('interaction_required', 'Account login requires an interactive terminal.');
|
|
76
|
+
}
|
|
77
|
+
const sessionPath = accountSessionPath(this.options.dataDir, account.name);
|
|
78
|
+
let temporaryDir;
|
|
79
|
+
try {
|
|
80
|
+
mkdirSync(dirname(sessionPath), { recursive: true });
|
|
81
|
+
temporaryDir = this.createTemporaryDirectory(join(dirname(sessionPath), '.login-'));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return failure('account_session_replace_failed', 'Unable to create staged account session storage.');
|
|
85
|
+
}
|
|
86
|
+
const stagedSessionPath = join(temporaryDir, 'session');
|
|
87
|
+
const discardedSessionPath = join(temporaryDir, 'discarded-session');
|
|
88
|
+
const tombstonePath = join(dirname(sessionPath), `.session-${randomUUID()}.bak`);
|
|
89
|
+
let preserveTombstone = false;
|
|
90
|
+
let preserveTemporaryDir = false;
|
|
91
|
+
let completedAccount;
|
|
92
|
+
const cleanupRecoveryPaths = [];
|
|
93
|
+
try {
|
|
94
|
+
let authenticated;
|
|
95
|
+
try {
|
|
96
|
+
authenticated = await this.authenticate(stagedSessionPath);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (isCliInterruptedError(error))
|
|
100
|
+
throw error;
|
|
101
|
+
return failure(errorCode(error, 'account_login_failed'), 'Unable to authenticate the Telegram account.');
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
await authenticated.close();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
preserveTemporaryDir = true;
|
|
108
|
+
return failure('account_login_failed', 'Unable to confirm staged Telegram session shutdown.', { recovery_path: temporaryDir });
|
|
109
|
+
}
|
|
110
|
+
if (authenticated.user.id !== account.user_id) {
|
|
111
|
+
return failure('account_identity_mismatch', `Authenticated Telegram user ${authenticated.user.id} does not match account "${account.name}" (${account.user_id}).`);
|
|
112
|
+
}
|
|
113
|
+
if (!existsSync(stagedSessionPath)) {
|
|
114
|
+
return failure('account_session_replace_failed', 'Authentication did not create a staged session.');
|
|
115
|
+
}
|
|
116
|
+
const hadOriginalSession = existsSync(sessionPath);
|
|
117
|
+
try {
|
|
118
|
+
if (hadOriginalSession)
|
|
119
|
+
this.renamePath(sessionPath, tombstonePath);
|
|
120
|
+
this.renamePath(stagedSessionPath, sessionPath);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (hadOriginalSession && existsSync(tombstonePath)) {
|
|
124
|
+
const restoreError = restoreSession(tombstonePath, sessionPath, this.renamePath);
|
|
125
|
+
if (restoreError) {
|
|
126
|
+
preserveTombstone = true;
|
|
127
|
+
return recoveryFailure('account_session_replace_failed', tombstonePath);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return failure('account_session_replace_failed', 'Unable to replace the Telegram session safely.');
|
|
131
|
+
}
|
|
132
|
+
const updated = { ...account, auth_state: 'authenticated' };
|
|
133
|
+
try {
|
|
134
|
+
this.options.store.write(updateAccount(registry, updated));
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
const rollbackError = rollbackInstalledSession({
|
|
138
|
+
discardedSessionPath,
|
|
139
|
+
hadOriginalSession,
|
|
140
|
+
renamePath: this.renamePath,
|
|
141
|
+
sessionPath,
|
|
142
|
+
tombstonePath,
|
|
143
|
+
});
|
|
144
|
+
if (rollbackError) {
|
|
145
|
+
preserveTombstone = hadOriginalSession && existsSync(tombstonePath);
|
|
146
|
+
return preserveTombstone
|
|
147
|
+
? recoveryFailure('account_store_error', tombstonePath)
|
|
148
|
+
: failure('account_store_error', 'Unable to update account authentication state and roll back the staged session.');
|
|
149
|
+
}
|
|
150
|
+
return failure('account_store_error', 'Unable to update account authentication state.');
|
|
151
|
+
}
|
|
152
|
+
completedAccount = updated;
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
if (!preserveTemporaryDir && !safelyRemove(this.removePath, temporaryDir))
|
|
156
|
+
cleanupRecoveryPaths.push(temporaryDir);
|
|
157
|
+
if (!preserveTombstone && !safelyRemove(this.removePath, tombstonePath))
|
|
158
|
+
cleanupRecoveryPaths.push(tombstonePath);
|
|
159
|
+
}
|
|
160
|
+
if (cleanupRecoveryPaths.length > 0) {
|
|
161
|
+
const primaryRecoveryPath = cleanupRecoveryPaths[cleanupRecoveryPaths.length - 1];
|
|
162
|
+
return failure('account_session_cleanup_failed', 'Account login succeeded, but secure session cleanup did not complete.', { recovery_path: primaryRecoveryPath, recovery_paths: cleanupRecoveryPaths });
|
|
163
|
+
}
|
|
164
|
+
return success(completedAccount, true);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function safelyRemove(removePath, path) {
|
|
169
|
+
try {
|
|
170
|
+
removePath(path);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function findAccount(registry, name) {
|
|
178
|
+
return registry.accounts.find((account) => account.name === name);
|
|
179
|
+
}
|
|
180
|
+
function updateAccount(registry, updated) {
|
|
181
|
+
return {
|
|
182
|
+
...registry,
|
|
183
|
+
accounts: registry.accounts.map((account) => account.name === updated.name ? updated : account),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function success(account, changed) {
|
|
187
|
+
return { ok: true, data: { account, changed } };
|
|
188
|
+
}
|
|
189
|
+
function accountNotFound(name) {
|
|
190
|
+
return failure('account_not_found', `Account "${name}" is not registered.`);
|
|
191
|
+
}
|
|
192
|
+
function failure(code, message, details) {
|
|
193
|
+
return { ok: false, error: { code, message, ...(details === undefined ? {} : { details }) } };
|
|
194
|
+
}
|
|
195
|
+
function recoveryFailure(code, recoveryPath) {
|
|
196
|
+
return failure(code, code === 'account_store_error'
|
|
197
|
+
? 'Unable to update account authentication state; the original session requires recovery.'
|
|
198
|
+
: 'Unable to replace the Telegram session; the original session requires recovery.', { recovery_path: recoveryPath });
|
|
199
|
+
}
|
|
200
|
+
function restoreSession(tombstonePath, sessionPath, renamePath) {
|
|
201
|
+
if (existsSync(sessionPath)) {
|
|
202
|
+
return new Error(`Cannot restore original session because destination exists: ${sessionPath}`);
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
renamePath(tombstonePath, sessionPath);
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
return error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function rollbackInstalledSession(options) {
|
|
213
|
+
if (existsSync(options.sessionPath)) {
|
|
214
|
+
try {
|
|
215
|
+
options.renamePath(options.sessionPath, options.discardedSessionPath);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
try {
|
|
219
|
+
rmSync(options.sessionPath, { recursive: true, force: true });
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
return new Error('Unable to discard the staged session during rollback.');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!options.hadOriginalSession || !existsSync(options.tombstonePath))
|
|
227
|
+
return undefined;
|
|
228
|
+
return restoreSession(options.tombstonePath, options.sessionPath, options.renamePath);
|
|
229
|
+
}
|
|
230
|
+
function isTerminalSessionError(error) {
|
|
231
|
+
return error instanceof TelegramSessionTerminatedError;
|
|
232
|
+
}
|
|
233
|
+
function errorCode(error, fallback) {
|
|
234
|
+
if (error !== null && typeof error === 'object' && 'code' in error) {
|
|
235
|
+
const code = error.code;
|
|
236
|
+
if (typeof code === 'string' && code.length > 0)
|
|
237
|
+
return code;
|
|
238
|
+
}
|
|
239
|
+
return fallback;
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=account-session-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-session-service.js","sourceRoot":"","sources":["../../src/services/account-session-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEzC,OAAO,EAAE,qBAAqB,EAA6B,MAAM,qCAAqC,CAAA;AAEtG,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,8BAA8B,EAA8B,MAAM,sBAAsB,CAAA;AACjG,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAsB9D,MAAM,OAAO,qBAAqB;IAOH;IANZ,YAAY,CAAgD;IAC5D,YAAY,CAAwD;IACpE,wBAAwB,CAA4B;IACpD,UAAU,CAAwB;IAClC,UAAU,CAA+C;IAE1E,YAA6B,OAAqC;QAArC,YAAO,GAAP,OAAO,CAA8B;QAChE,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,oBAAoB,CAAA;QAChE,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,qBAAqB,CAAA;QACjE,IAAI,CAAC,wBAAwB,GAAG,OAAO,CAAC,wBAAwB,IAAI,WAAW,CAAA;QAC/E,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAClG,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,UAAU,CAAA;IACpD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAA0B;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;YAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;YACjD,IAAI,CAAC,OAAO;gBAAE,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAChD,IAAI,OAAO,CAAC,UAAU,KAAK,YAAY;gBAAE,OAAO,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;YAEvE,IAAI,MAA6B,CAAA;YACjC,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;YACpF,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,OAAO,CAAC,uBAAuB,EAAE,uCAAuC,CAAC,CAAA;YAClF,CAAC;YAED,IAAI,WAAoB,CAAA;YACxB,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAA;YACvB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,WAAW,GAAG,KAAK,CAAA;YACrB,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACtB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,WAAW,IAAI,IAAI;oBAAE,WAAW,GAAG,KAAK,CAAA;YAC9C,CAAC;YAED,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChE,OAAO,OAAO,CAAC,uBAAuB,EAAE,yCAAyC,CAAC,CAAA;YACpF,CAAC;YAED,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,YAAqB,EAAE,CAAA;YACjE,IAAI,CAAC;gBACH,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;YAC5D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,OAAO,CAAC,qBAAqB,EAAE,gDAAgD,CAAC,CAAA;YACzF,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QAC/B,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAA0B;QACpC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;YAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;YACjD,IAAI,CAAC,OAAO;gBAAE,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAChD,IAAI,OAAO,CAAC,UAAU,KAAK,eAAe;gBAAE,OAAO,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;YAC1E,IAAI,KAAK,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;gBAChC,OAAO,OAAO,CAAC,sBAAsB,EAAE,iDAAiD,CAAC,CAAA;YAC3F,CAAC;YAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;YAC1E,IAAI,YAAoB,CAAA;YACxB,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;gBACpD,YAAY,GAAG,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,CAAC,CAAA;YACrF,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,OAAO,CAAC,gCAAgC,EAAE,kDAAkD,CAAC,CAAA;YACtG,CAAC;YACD,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;YACvD,MAAM,oBAAoB,GAAG,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAA;YACpE,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,YAAY,UAAU,EAAE,MAAM,CAAC,CAAA;YAChF,IAAI,iBAAiB,GAAG,KAAK,CAAA;YAC7B,IAAI,oBAAoB,GAAG,KAAK,CAAA;YAChC,IAAI,gBAAyC,CAAA;YAC7C,MAAM,oBAAoB,GAAa,EAAE,CAAA;YAEzC,IAAI,CAAC;gBACH,IAAI,aAAmC,CAAA;gBACvC,IAAI,CAAC;oBACH,aAAa,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAA;gBAC5D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,qBAAqB,CAAC,KAAK,CAAC;wBAAE,MAAM,KAAK,CAAA;oBAC7C,OAAO,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,sBAAsB,CAAC,EAAE,8CAA8C,CAAC,CAAA;gBAC1G,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,aAAa,CAAC,KAAK,EAAE,CAAA;gBAC7B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,oBAAoB,GAAG,IAAI,CAAA;oBAC3B,OAAO,OAAO,CAAC,sBAAsB,EAAE,qDAAqD,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAA;gBAChI,CAAC;gBAED,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;oBAC9C,OAAO,OAAO,CACZ,2BAA2B,EAC3B,+BAA+B,aAAa,CAAC,IAAI,CAAC,EAAE,4BAA4B,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,OAAO,IAAI,CACtH,CAAA;gBACH,CAAC;gBAED,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;oBACnC,OAAO,OAAO,CAAC,gCAAgC,EAAE,iDAAiD,CAAC,CAAA;gBACrG,CAAC;gBAED,MAAM,kBAAkB,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;gBAClD,IAAI,CAAC;oBACH,IAAI,kBAAkB;wBAAE,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;oBACnE,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAA;gBACjD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,kBAAkB,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;wBACpD,MAAM,YAAY,GAAG,cAAc,CAAC,aAAa,EAAE,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;wBAChF,IAAI,YAAY,EAAE,CAAC;4BACjB,iBAAiB,GAAG,IAAI,CAAA;4BACxB,OAAO,eAAe,CAAC,gCAAgC,EAAE,aAAa,CAAC,CAAA;wBACzE,CAAC;oBACH,CAAC;oBACD,OAAO,OAAO,CAAC,gCAAgC,EAAE,gDAAgD,CAAC,CAAA;gBACpG,CAAC;gBAED,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,eAAwB,EAAE,CAAA;gBACpE,IAAI,CAAC;oBACH,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;gBAC5D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,aAAa,GAAG,wBAAwB,CAAC;wBAC7C,oBAAoB;wBACpB,kBAAkB;wBAClB,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,WAAW;wBACX,aAAa;qBACd,CAAC,CAAA;oBACF,IAAI,aAAa,EAAE,CAAC;wBAClB,iBAAiB,GAAG,kBAAkB,IAAI,UAAU,CAAC,aAAa,CAAC,CAAA;wBACnE,OAAO,iBAAiB;4BACtB,CAAC,CAAC,eAAe,CAAC,qBAAqB,EAAE,aAAa,CAAC;4BACvD,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,iFAAiF,CAAC,CAAA;oBACvH,CAAC;oBACD,OAAO,OAAO,CAAC,qBAAqB,EAAE,gDAAgD,CAAC,CAAA;gBACzF,CAAC;gBAED,gBAAgB,GAAG,OAAO,CAAA;YAC5B,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,oBAAoB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC;oBAAE,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;gBAClH,IAAI,CAAC,iBAAiB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC;oBAAE,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YACnH,CAAC;YAED,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,mBAAmB,GAAG,oBAAoB,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAE,CAAA;gBAClF,OAAO,OAAO,CACZ,gCAAgC,EAChC,uEAAuE,EACvE,EAAE,aAAa,EAAE,mBAAmB,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAC7E,CAAA;YACH,CAAC;YACD,OAAO,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAED,SAAS,YAAY,CAAC,UAAkC,EAAE,IAAY;IACpE,IAAI,CAAC;QACH,UAAU,CAAC,IAAI,CAAC,CAAA;QAChB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAAyB,EAAE,IAAY;IAC1D,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AACnE,CAAC;AAED,SAAS,aAAa,CAAC,QAAyB,EAAE,OAAoB;IACpE,OAAO;QACL,GAAG,QAAQ;QACX,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;KAChG,CAAA;AACH,CAAC;AAED,SAAS,OAAO,CAAC,OAAoB,EAAE,OAAgB;IACrD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAA;AACjD,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,OAAO,CAAC,mBAAmB,EAAE,YAAY,IAAI,sBAAsB,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,OAAe,EAAE,OAAiB;IAC/D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CAAA;AAC/F,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,YAAoB;IACzD,OAAO,OAAO,CACZ,IAAI,EACJ,IAAI,KAAK,qBAAqB;QAC5B,CAAC,CAAC,wFAAwF;QAC1F,CAAC,CAAC,iFAAiF,EACrF,EAAE,aAAa,EAAE,YAAY,EAAE,CAChC,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CACrB,aAAqB,EACrB,WAAmB,EACnB,UAAyD;IAEzD,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,KAAK,CAAC,+DAA+D,WAAW,EAAE,CAAC,CAAA;IAChG,CAAC;IACD,IAAI,CAAC;QACH,UAAU,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;QACtC,OAAO,SAAS,CAAA;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,OAMjC;IACC,IAAI,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAA;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;YAC3E,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,kBAAkB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,aAAa,CAAC;QAAE,OAAO,SAAS,CAAA;IACvF,OAAO,cAAc,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;AACvF,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,OAAO,KAAK,YAAY,8BAA8B,CAAA;AACxD,CAAC;AAED,SAAS,SAAS,CAAC,KAAc,EAAE,QAAgB;IACjD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAA;QAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAA;IAC9D,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { posix } from 'node:path';
|
|
2
|
+
const MAX_CHAT_SLUG_BYTES = 80;
|
|
3
|
+
const MAX_FILENAME_BYTES = 255;
|
|
4
|
+
const MAX_EXTENSION_BYTES = 32;
|
|
5
|
+
const WINDOWS_RESERVED_NAME = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu;
|
|
6
|
+
const graphemeSegmenter = new Intl.Segmenter('und', { granularity: 'grapheme' });
|
|
7
|
+
function sanitizePart(value) {
|
|
8
|
+
return value
|
|
9
|
+
.normalize('NFKC')
|
|
10
|
+
.toLocaleLowerCase('und')
|
|
11
|
+
.replace(/[\p{C}\\/:*?"<>|_\s.]+/gu, '-')
|
|
12
|
+
.replace(/[^\p{L}\p{N}\p{M}-]+/gu, '-')
|
|
13
|
+
.replace(/-+/gu, '-')
|
|
14
|
+
.replace(/^-|-$/gu, '');
|
|
15
|
+
}
|
|
16
|
+
function safeInteger(value, label) {
|
|
17
|
+
if (!Number.isSafeInteger(value)) {
|
|
18
|
+
throw new Error(`archive_invalid_${label}`);
|
|
19
|
+
}
|
|
20
|
+
return String(value);
|
|
21
|
+
}
|
|
22
|
+
function truncateUtf8(value, maxBytes) {
|
|
23
|
+
let result = '';
|
|
24
|
+
let bytes = 0;
|
|
25
|
+
for (const { segment } of graphemeSegmenter.segment(value)) {
|
|
26
|
+
const segmentBytes = Buffer.byteLength(segment);
|
|
27
|
+
if (bytes + segmentBytes > maxBytes)
|
|
28
|
+
break;
|
|
29
|
+
result += segment;
|
|
30
|
+
bytes += segmentBytes;
|
|
31
|
+
}
|
|
32
|
+
return result.replace(/-$/u, '');
|
|
33
|
+
}
|
|
34
|
+
export function archiveChatFile(chatId, title) {
|
|
35
|
+
const id = safeInteger(chatId, 'chat_id');
|
|
36
|
+
const slug = truncateUtf8(sanitizePart(title), MAX_CHAT_SLUG_BYTES) || 'chat';
|
|
37
|
+
return `${id}-${slug}.md`;
|
|
38
|
+
}
|
|
39
|
+
function mediaBasename(filename, messagePrefix) {
|
|
40
|
+
const basename = filename.replace(/\\/gu, '/').split('/').at(-1) ?? '';
|
|
41
|
+
const extensionIndex = basename.lastIndexOf('.');
|
|
42
|
+
const hasExtension = extensionIndex > 0 && extensionIndex < basename.length - 1;
|
|
43
|
+
const rawStem = hasExtension ? basename.slice(0, extensionIndex) : basename;
|
|
44
|
+
const rawExtension = hasExtension ? basename.slice(extensionIndex + 1) : '';
|
|
45
|
+
let stem = sanitizePart(rawStem) || 'file';
|
|
46
|
+
const extension = truncateUtf8(sanitizePart(rawExtension), MAX_EXTENSION_BYTES);
|
|
47
|
+
if (WINDOWS_RESERVED_NAME.test(stem)) {
|
|
48
|
+
stem = `file-${stem}`;
|
|
49
|
+
}
|
|
50
|
+
const reservedBytes = Buffer.byteLength(messagePrefix)
|
|
51
|
+
+ (extension ? Buffer.byteLength(extension) + 1 : 0);
|
|
52
|
+
stem = truncateUtf8(stem, MAX_FILENAME_BYTES - reservedBytes) || 'file';
|
|
53
|
+
return extension ? `${stem}.${extension}` : stem;
|
|
54
|
+
}
|
|
55
|
+
export function archiveMediaFile(chatId, messageId, filename) {
|
|
56
|
+
const chat = safeInteger(chatId, 'chat_id');
|
|
57
|
+
const message = safeInteger(messageId, 'message_id');
|
|
58
|
+
const messagePrefix = `${message}-`;
|
|
59
|
+
return posix.join('media', chat, `${messagePrefix}${mediaBasename(filename, messagePrefix)}`);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=archive-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-layout.js","sourceRoot":"","sources":["../../src/services/archive-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { closeSync, constants, existsSync, fsyncSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join } from 'node:path';
|
|
3
|
+
import { randomBytes } from 'node:crypto';
|
|
4
|
+
const WINDOWS_RESERVED_NAME = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu;
|
|
5
|
+
const ARCHIVE_CHAT_SLUG = /^[\p{L}\p{N}\p{M}]+(?:-[\p{L}\p{N}\p{M}]+)*$/u;
|
|
6
|
+
const MAX_CHAT_SLUG_BYTES = 80;
|
|
7
|
+
const ISO_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/u;
|
|
8
|
+
const UNSUPPORTED_DIRECTORY_SYNC_CODES = new Set([
|
|
9
|
+
'EACCES',
|
|
10
|
+
'EINVAL',
|
|
11
|
+
'EISDIR',
|
|
12
|
+
'ENOSYS',
|
|
13
|
+
'ENOTSUP',
|
|
14
|
+
'EPERM',
|
|
15
|
+
]);
|
|
16
|
+
function isRecord(value) {
|
|
17
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
18
|
+
}
|
|
19
|
+
function isString(value) {
|
|
20
|
+
return typeof value === 'string';
|
|
21
|
+
}
|
|
22
|
+
function isIsoTimestamp(value) {
|
|
23
|
+
if (!isString(value))
|
|
24
|
+
return false;
|
|
25
|
+
const match = ISO_TIMESTAMP.exec(value);
|
|
26
|
+
if (!match || !Number.isFinite(Date.parse(value)))
|
|
27
|
+
return false;
|
|
28
|
+
const [, year, month, day, hour, minute, second] = match;
|
|
29
|
+
const numericYear = Number(year);
|
|
30
|
+
const numericMonth = Number(month);
|
|
31
|
+
const daysInMonth = new Date(Date.UTC(numericYear, numericMonth, 0)).getUTCDate();
|
|
32
|
+
return numericMonth >= 1
|
|
33
|
+
&& numericMonth <= 12
|
|
34
|
+
&& Number(day) >= 1
|
|
35
|
+
&& Number(day) <= daysInMonth
|
|
36
|
+
&& Number(hour) <= 23
|
|
37
|
+
&& Number(minute) <= 59
|
|
38
|
+
&& Number(second) <= 59;
|
|
39
|
+
}
|
|
40
|
+
function isNullableTimestamp(value) {
|
|
41
|
+
return value === null || isIsoTimestamp(value);
|
|
42
|
+
}
|
|
43
|
+
function isPositiveSafeInteger(value) {
|
|
44
|
+
return Number.isSafeInteger(value) && Number(value) > 0;
|
|
45
|
+
}
|
|
46
|
+
function isNullableMessageId(value) {
|
|
47
|
+
return value === null || isPositiveSafeInteger(value);
|
|
48
|
+
}
|
|
49
|
+
function isSafeRelativeFile(value) {
|
|
50
|
+
return isString(value)
|
|
51
|
+
&& value.length > 0
|
|
52
|
+
&& !value.includes('/')
|
|
53
|
+
&& !value.includes('\\')
|
|
54
|
+
&& value !== '.'
|
|
55
|
+
&& value !== '..'
|
|
56
|
+
&& !/[\p{C}]/u.test(value)
|
|
57
|
+
&& !/[<>:"|?*]/u.test(value)
|
|
58
|
+
&& !/[. ]$/u.test(value)
|
|
59
|
+
&& !WINDOWS_RESERVED_NAME.test(value)
|
|
60
|
+
&& Buffer.byteLength(value) <= 255;
|
|
61
|
+
}
|
|
62
|
+
function isChatId(value) {
|
|
63
|
+
if (!/^-?[1-9]\d*$/u.test(value))
|
|
64
|
+
return false;
|
|
65
|
+
return Number.isSafeInteger(Number(value));
|
|
66
|
+
}
|
|
67
|
+
function isArchiveChatState(value, chatId) {
|
|
68
|
+
if (!isRecord(value))
|
|
69
|
+
return false;
|
|
70
|
+
return isString(value.title)
|
|
71
|
+
&& value.title.trim().length > 0
|
|
72
|
+
&& isArchiveChatFile(value.file, chatId)
|
|
73
|
+
&& isNullableTimestamp(value.initial_since)
|
|
74
|
+
&& isNullableTimestamp(value.initial_until)
|
|
75
|
+
&& typeof value.full_history === 'boolean'
|
|
76
|
+
&& isNullableMessageId(value.last_message_id)
|
|
77
|
+
&& isNullableTimestamp(value.last_message_date)
|
|
78
|
+
&& isIsoTimestamp(value.last_run);
|
|
79
|
+
}
|
|
80
|
+
function isArchiveChatFile(value, chatId) {
|
|
81
|
+
if (!isSafeRelativeFile(value))
|
|
82
|
+
return false;
|
|
83
|
+
const prefix = `${chatId}-`;
|
|
84
|
+
if (!value.startsWith(prefix) || !value.endsWith('.md'))
|
|
85
|
+
return false;
|
|
86
|
+
const slug = value.slice(prefix.length, -3);
|
|
87
|
+
return slug.length > 0
|
|
88
|
+
&& Buffer.byteLength(slug) <= MAX_CHAT_SLUG_BYTES
|
|
89
|
+
&& slug === slug.normalize('NFKC')
|
|
90
|
+
&& slug === slug.toLocaleLowerCase('und')
|
|
91
|
+
&& ARCHIVE_CHAT_SLUG.test(slug);
|
|
92
|
+
}
|
|
93
|
+
function portableFileIdentity(value) {
|
|
94
|
+
return value.normalize('NFKC').toLocaleLowerCase('und');
|
|
95
|
+
}
|
|
96
|
+
function parseArchiveManifest(value) {
|
|
97
|
+
if (!isRecord(value))
|
|
98
|
+
throw new Error('archive_manifest_invalid');
|
|
99
|
+
if (value.schema_version !== 1) {
|
|
100
|
+
if (Number.isInteger(value.schema_version)) {
|
|
101
|
+
throw new Error('archive_schema_unsupported');
|
|
102
|
+
}
|
|
103
|
+
throw new Error('archive_manifest_invalid');
|
|
104
|
+
}
|
|
105
|
+
if (!isString(value.account_name) || value.account_name.trim().length === 0
|
|
106
|
+
|| !isPositiveSafeInteger(value.account_user_id)
|
|
107
|
+
|| !isIsoTimestamp(value.created_at)
|
|
108
|
+
|| !isIsoTimestamp(value.updated_at)
|
|
109
|
+
|| !isRecord(value.chats)) {
|
|
110
|
+
throw new Error('archive_manifest_invalid');
|
|
111
|
+
}
|
|
112
|
+
const files = new Set();
|
|
113
|
+
for (const [chatId, chat] of Object.entries(value.chats)) {
|
|
114
|
+
if (!isChatId(chatId))
|
|
115
|
+
throw new Error('archive_manifest_invalid');
|
|
116
|
+
if (!isArchiveChatState(chat, chatId))
|
|
117
|
+
throw new Error('archive_manifest_invalid');
|
|
118
|
+
const fileIdentity = portableFileIdentity(chat.file);
|
|
119
|
+
if (files.has(fileIdentity))
|
|
120
|
+
throw new Error('archive_manifest_invalid');
|
|
121
|
+
files.add(fileIdentity);
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
export function readArchiveManifest(path) {
|
|
126
|
+
if (!existsSync(path))
|
|
127
|
+
return null;
|
|
128
|
+
try {
|
|
129
|
+
return parseArchiveManifest(JSON.parse(readFileSync(path, 'utf8')));
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error instanceof Error
|
|
133
|
+
&& (error.message === 'archive_manifest_invalid'
|
|
134
|
+
|| error.message === 'archive_schema_unsupported')) {
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
throw new Error('archive_manifest_invalid');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export function validateArchiveAccount(manifest, account) {
|
|
141
|
+
if (manifest.account_user_id !== account.userId) {
|
|
142
|
+
throw new Error('archive_account_mismatch');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function syncDirectory(path) {
|
|
146
|
+
let fileDescriptor = null;
|
|
147
|
+
try {
|
|
148
|
+
fileDescriptor = openSync(path, constants.O_RDONLY);
|
|
149
|
+
fsyncSync(fileDescriptor);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
const code = error.code;
|
|
153
|
+
if (!code || !UNSUPPORTED_DIRECTORY_SYNC_CODES.has(code))
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
if (fileDescriptor !== null)
|
|
158
|
+
closeSync(fileDescriptor);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export function writeArchiveManifest(path, manifest) {
|
|
162
|
+
parseArchiveManifest(manifest);
|
|
163
|
+
const temporaryPath = join(dirname(path), `.${basename(path)}.${process.pid}.${randomBytes(8).toString('hex')}.tmp`);
|
|
164
|
+
let fileDescriptor = null;
|
|
165
|
+
try {
|
|
166
|
+
fileDescriptor = openSync(temporaryPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
|
|
167
|
+
writeFileSync(fileDescriptor, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
|
|
168
|
+
fsyncSync(fileDescriptor);
|
|
169
|
+
const descriptor = fileDescriptor;
|
|
170
|
+
fileDescriptor = null;
|
|
171
|
+
closeSync(descriptor);
|
|
172
|
+
renameSync(temporaryPath, path);
|
|
173
|
+
syncDirectory(dirname(path));
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
if (fileDescriptor !== null)
|
|
177
|
+
closeSync(fileDescriptor);
|
|
178
|
+
try {
|
|
179
|
+
unlinkSync(temporaryPath);
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (!isRecord(error) || error.code !== 'ENOENT')
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=archive-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-manifest.js","sourceRoot":"","sources":["../../src/services/archive-manifest.ts"],"names":[],"mappings":"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"}
|