@pachca/cli 2026.9.1 → 2026.10.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/CHANGELOG.md +33 -0
- package/README.md +17 -5
- package/dist/base-command.js +47 -0
- package/dist/client.js +2 -1
- package/dist/commands/auth/login.js +4 -4
- package/dist/commands/bots/create-token.js +84 -0
- package/dist/commands/bots/create.js +33 -6
- package/dist/commands/bots/delete-token.js +46 -0
- package/dist/commands/bots/delete.js +1 -1
- package/dist/commands/bots/get.js +1 -1
- package/dist/commands/bots/list-company.js +1 -1
- package/dist/commands/bots/list-events.js +1 -1
- package/dist/commands/bots/list-scopes.js +32 -0
- package/dist/commands/bots/list-tokens.js +94 -0
- package/dist/commands/bots/list.js +3 -3
- package/dist/commands/bots/recreate-token-self.js +1 -1
- package/dist/commands/bots/recreate-token.js +2 -2
- package/dist/commands/bots/reissue-token.js +37 -0
- package/dist/commands/bots/remove-avatar.js +42 -0
- package/dist/commands/bots/remove-event.js +1 -1
- package/dist/commands/bots/rotate-client-secret.js +30 -0
- package/dist/commands/bots/update-avatar.js +51 -0
- package/dist/commands/bots/update-token.js +60 -0
- package/dist/commands/bots/update.js +37 -8
- package/dist/commands/chats/create.js +1 -0
- package/dist/commands/chats/download-export.js +1 -1
- package/dist/commands/chats/get.js +1 -1
- package/dist/commands/chats/list-company.js +1 -1
- package/dist/commands/chats/list.js +1 -1
- package/dist/commands/chats/mark-unread.js +44 -0
- package/dist/commands/chats/remove-avatar.js +45 -0
- package/dist/commands/chats/request-export.js +4 -2
- package/dist/commands/chats/update-avatar.js +54 -0
- package/dist/commands/drafts/create.js +1 -1
- package/dist/commands/drafts/list.js +1 -1
- package/dist/commands/drafts/update.js +1 -1
- package/dist/commands/files/direct-url.js +8 -4
- package/dist/commands/group-tags/get.js +1 -1
- package/dist/commands/group-tags/list-users.js +2 -2
- package/dist/commands/group-tags/list.js +3 -3
- package/dist/commands/members/add.js +2 -2
- package/dist/commands/members/list.js +2 -2
- package/dist/commands/members/remove-group-tag.js +1 -1
- package/dist/commands/members/remove.js +1 -1
- package/dist/commands/members/update.js +1 -1
- package/dist/commands/messages/create.js +9 -10
- package/dist/commands/messages/get.js +1 -1
- package/dist/commands/messages/list.js +1 -1
- package/dist/commands/messages/update.js +2 -2
- package/dist/commands/profile/update-status.js +3 -32
- package/dist/commands/reactions/list.js +1 -1
- package/dist/commands/read-member/list-readers.js +1 -1
- package/dist/commands/search/list-chats.js +2 -2
- package/dist/commands/search/list-messages.js +6 -6
- package/dist/commands/search/list-users.js +4 -4
- package/dist/commands/security/list.js +2 -2
- package/dist/commands/tasks/create.js +1 -1
- package/dist/commands/tasks/get.js +1 -1
- package/dist/commands/tasks/list.js +6 -6
- package/dist/commands/tasks/update.js +1 -1
- package/dist/commands/threads/get.js +1 -1
- package/dist/commands/threads/list.js +2 -2
- package/dist/commands/upload.js +5 -2
- package/dist/commands/users/create.js +1 -1
- package/dist/commands/users/get.js +1 -1
- package/dist/commands/users/list.js +1 -1
- package/dist/commands/users/update-status.js +3 -32
- package/dist/commands/users/update.js +2 -2
- package/dist/commands/views/open.js +2 -2
- package/dist/data/alternatives.json +17 -5
- package/dist/data/changelog.json +146 -0
- package/dist/data/endpoints.json +1 -1
- package/dist/data/workflows.json +60 -9
- package/dist/oauth.js +28 -3
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -4,12 +4,12 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class BotsRecreateToken extends BaseCommand {
|
|
5
5
|
static description = "Ротация токена бота";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Ротация токена бота — Пользовательским токеном (администратор,
|
|
7
|
+
"Ротация токена бота — Пользовательским токеном (создатель бота или администратор, если бот открыт администраторам) — перевыпусти основной токен по `id` бота: тот, что без имени, а если такого нет, самый старый. Прежнее значение инвалидируется сразу:\n $ pachca bots recreate-token"
|
|
8
8
|
];
|
|
9
9
|
static scope = "bots:write";
|
|
10
10
|
static apiMethod = "POST";
|
|
11
11
|
static apiPath = "/bots/{id}/recreate_token";
|
|
12
|
-
static defaultColumns = ["id", "
|
|
12
|
+
static defaultColumns = ["id", "name", "created_at", "nickname", "avatar_url"];
|
|
13
13
|
static args = {
|
|
14
14
|
id: Args.integer({
|
|
15
15
|
description: "Идентификатор бота (pachca bots list)",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
export default class BotsReissueToken extends BaseCommand {
|
|
5
|
+
static description = "Перевыпуск токена бота";
|
|
6
|
+
static examples = [
|
|
7
|
+
"Ротация токена бота — Отдельный токен бота перевыпускай по его `id` из `pachca bots list-tokens`: значение меняется, имя и права остаются:\n $ pachca bots reissue-token"
|
|
8
|
+
];
|
|
9
|
+
static scope = "bots:write";
|
|
10
|
+
static apiMethod = "POST";
|
|
11
|
+
static apiPath = "/bots/{id}/tokens/{token_id}/reissue";
|
|
12
|
+
static defaultColumns = ["id", "name", "created_at", "token", "user_id"];
|
|
13
|
+
static args = {
|
|
14
|
+
id: Args.integer({
|
|
15
|
+
description: "Идентификатор бота (pachca bots list)",
|
|
16
|
+
required: true,
|
|
17
|
+
}),
|
|
18
|
+
token_id: Args.integer({
|
|
19
|
+
description: "Идентификатор токена",
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
static flags = {
|
|
24
|
+
...BaseCommand.baseFlags,
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { args, flags } = await this.parse(BotsReissueToken);
|
|
28
|
+
this.parsedFlags = flags;
|
|
29
|
+
const { data } = await this.apiRequest({
|
|
30
|
+
method: 'POST',
|
|
31
|
+
path: `/bots/${args.id}/tokens/${args.token_id}/reissue`,
|
|
32
|
+
});
|
|
33
|
+
const responseBody = (data ?? {});
|
|
34
|
+
const result = responseBody.data ?? responseBody;
|
|
35
|
+
this.output(result);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import * as clack from '@clack/prompts';
|
|
5
|
+
export default class BotsRemoveAvatar extends BaseCommand {
|
|
6
|
+
static description = "Удаление аватара бота";
|
|
7
|
+
static scope = "bots:write";
|
|
8
|
+
static apiMethod = "DELETE";
|
|
9
|
+
static apiPath = "/bots/{id}/avatar";
|
|
10
|
+
static args = {
|
|
11
|
+
id: Args.integer({
|
|
12
|
+
description: "Идентификатор бота (pachca bots list)",
|
|
13
|
+
required: true,
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
...BaseCommand.baseFlags,
|
|
18
|
+
force: Flags.boolean({
|
|
19
|
+
description: 'Пропустить подтверждение',
|
|
20
|
+
default: false,
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const { args, flags } = await this.parse(BotsRemoveAvatar);
|
|
25
|
+
this.parsedFlags = flags;
|
|
26
|
+
if (!flags.force) {
|
|
27
|
+
if (!this.isInteractive()) {
|
|
28
|
+
this.validationError([{ message: 'Деструктивная операция требует флага --force', flag: 'force' }], { type: 'PACHCA_DESTRUCTIVE_OP_ERROR', hint: "pachca bots remove-avatar <id> --force" });
|
|
29
|
+
}
|
|
30
|
+
const confirm = await clack.confirm({ message: 'Вы уверены?' });
|
|
31
|
+
if (clack.isCancel(confirm) || !confirm) {
|
|
32
|
+
process.stderr.write('Отменено.\n');
|
|
33
|
+
this.exit(0);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const { data } = await this.apiRequest({
|
|
37
|
+
method: 'DELETE',
|
|
38
|
+
path: `/bots/${args.id}/avatar`,
|
|
39
|
+
});
|
|
40
|
+
this.success('Удалено');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -3,7 +3,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class BotsRemoveEvent extends BaseCommand {
|
|
6
|
-
static description = "Удаление события";
|
|
6
|
+
static description = "Удаление события истории";
|
|
7
7
|
static examples = [
|
|
8
8
|
"Обработка событий через историю (polling) — Удали обработанное событие:\n $ pachca bots remove-event"
|
|
9
9
|
];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
export default class BotsRotateClientSecret extends BaseCommand {
|
|
5
|
+
static description = "Ротация секрета клиента";
|
|
6
|
+
static scope = "bots:write";
|
|
7
|
+
static apiMethod = "POST";
|
|
8
|
+
static apiPath = "/bots/{id}/rotate_client_secret";
|
|
9
|
+
static defaultColumns = ["id", "name", "created_at", "nickname", "avatar_url"];
|
|
10
|
+
static args = {
|
|
11
|
+
id: Args.integer({
|
|
12
|
+
description: "Идентификатор бота (pachca bots list)",
|
|
13
|
+
required: true,
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
...BaseCommand.baseFlags,
|
|
18
|
+
};
|
|
19
|
+
async run() {
|
|
20
|
+
const { args, flags } = await this.parse(BotsRotateClientSecret);
|
|
21
|
+
this.parsedFlags = flags;
|
|
22
|
+
const { data } = await this.apiRequest({
|
|
23
|
+
method: 'POST',
|
|
24
|
+
path: `/bots/${args.id}/rotate_client_secret`,
|
|
25
|
+
});
|
|
26
|
+
const responseBody = (data ?? {});
|
|
27
|
+
const result = responseBody.data ?? responseBody;
|
|
28
|
+
this.output(result);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
export default class BotsUpdateAvatar extends BaseCommand {
|
|
7
|
+
static description = "Загрузка аватара бота";
|
|
8
|
+
static scope = "bots:write";
|
|
9
|
+
static apiMethod = "PUT";
|
|
10
|
+
static apiPath = "/bots/{id}/avatar";
|
|
11
|
+
static defaultColumns = ["image_url"];
|
|
12
|
+
static args = {
|
|
13
|
+
id: Args.integer({
|
|
14
|
+
description: "Идентификатор бота (pachca bots list)",
|
|
15
|
+
required: true,
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
static flags = {
|
|
19
|
+
...BaseCommand.baseFlags,
|
|
20
|
+
file: Flags.string({
|
|
21
|
+
description: "Файл изображения для аватара",
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(BotsUpdateAvatar);
|
|
26
|
+
this.parsedFlags = flags;
|
|
27
|
+
let formData;
|
|
28
|
+
if (flags.file) {
|
|
29
|
+
formData = new FormData();
|
|
30
|
+
if (flags.file === '-') {
|
|
31
|
+
const chunks = [];
|
|
32
|
+
for await (const chunk of process.stdin)
|
|
33
|
+
chunks.push(chunk);
|
|
34
|
+
const blob = new Blob([Buffer.concat(chunks)]);
|
|
35
|
+
formData.append('image', blob, 'stdin');
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const blob = new Blob([fs.readFileSync(flags.file)]);
|
|
39
|
+
formData.append('image', blob, path.basename(flags.file));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const { data } = await this.apiRequest({
|
|
43
|
+
method: 'PUT',
|
|
44
|
+
path: `/bots/${args.id}/avatar`,
|
|
45
|
+
formData,
|
|
46
|
+
});
|
|
47
|
+
const responseBody = (data ?? {});
|
|
48
|
+
const result = responseBody.data ?? responseBody;
|
|
49
|
+
this.output(result);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
export default class BotsUpdateToken extends BaseCommand {
|
|
5
|
+
static description = "Изменение токена бота";
|
|
6
|
+
static scope = "bots:write";
|
|
7
|
+
static apiMethod = "PUT";
|
|
8
|
+
static apiPath = "/bots/{id}/tokens/{token_id}";
|
|
9
|
+
static defaultColumns = ["id", "name", "created_at", "token", "user_id"];
|
|
10
|
+
static args = {
|
|
11
|
+
id: Args.integer({
|
|
12
|
+
description: "Идентификатор бота (pachca bots list)",
|
|
13
|
+
required: true,
|
|
14
|
+
}),
|
|
15
|
+
token_id: Args.integer({
|
|
16
|
+
description: "Идентификатор токена",
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
static flags = {
|
|
21
|
+
...BaseCommand.baseFlags,
|
|
22
|
+
'name': Flags.string({
|
|
23
|
+
description: "Новое имя токена (макс. 255 символов)",
|
|
24
|
+
}),
|
|
25
|
+
'scopes': Flags.string({
|
|
26
|
+
description: "Новые права токена. Список заменяется целиком и действует сразу, перевыпускать токен не нужно.",
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { args, flags } = await this.parse(BotsUpdateToken);
|
|
31
|
+
this.parsedFlags = flags;
|
|
32
|
+
const validationErrors = [];
|
|
33
|
+
if (flags['name'] && String(flags['name']).length > 255) {
|
|
34
|
+
validationErrors.push({ message: `--name: максимум 255 символов (передано: ${String(flags['name']).length})`, flag: 'name' });
|
|
35
|
+
}
|
|
36
|
+
if (validationErrors.length > 0) {
|
|
37
|
+
this.validationError(validationErrors);
|
|
38
|
+
}
|
|
39
|
+
const body = {
|
|
40
|
+
name: flags['name'],
|
|
41
|
+
scopes: flags['scopes'] ? this.parseJSON(flags['scopes'], 'scopes') : undefined,
|
|
42
|
+
};
|
|
43
|
+
// Clean undefined fields
|
|
44
|
+
for (const [k, v] of Object.entries(body)) {
|
|
45
|
+
if (v === undefined)
|
|
46
|
+
delete body[k];
|
|
47
|
+
}
|
|
48
|
+
if (Object.keys(body).length === 0) {
|
|
49
|
+
this.validationError([{ message: 'Не указаны поля для обновления' }], { type: 'PACHCA_USAGE_ERROR' });
|
|
50
|
+
}
|
|
51
|
+
const { data } = await this.apiRequest({
|
|
52
|
+
method: 'PUT',
|
|
53
|
+
path: `/bots/${args.id}/tokens/${args.token_id}`,
|
|
54
|
+
body,
|
|
55
|
+
});
|
|
56
|
+
const responseBody = (data ?? {});
|
|
57
|
+
const result = responseBody.data ?? responseBody;
|
|
58
|
+
this.output(result);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -4,12 +4,14 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class BotsUpdate extends BaseCommand {
|
|
5
5
|
static description = "Редактирование бота";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Обновить Webhook URL бота — Пользовательским токеном (с правом редактировать бота) — обнови URL по `id` бота. Пустая строка отключает вебхук:\n $ pachca bots update"
|
|
7
|
+
"Обновить Webhook URL бота — Пользовательским токеном (с правом редактировать бота) — обнови URL по `id` бота. Пустая строка отключает вебхук:\n $ pachca bots update",
|
|
8
|
+
"Включить боту авторизацию от имени сотрудника — Пользовательским токеном (создатель бота или администратор, если бот открыт администраторам) включи авторизацию: где хранится секрет, адреса возврата и права, которые бот попросит у сотрудника. Права бери из `pachca bots list-scopes`:\n $ pachca bots update",
|
|
9
|
+
"Включить боту авторизацию от имени сотрудника — Чтобы бот появился в витрине, добавь описание и опубликуй страницу:\n $ pachca bots update"
|
|
8
10
|
];
|
|
9
11
|
static scope = "bots:write";
|
|
10
12
|
static apiMethod = "PUT";
|
|
11
13
|
static apiPath = "/bots/{id}";
|
|
12
|
-
static defaultColumns = ["id", "
|
|
14
|
+
static defaultColumns = ["id", "name", "created_at", "nickname", "avatar_url"];
|
|
13
15
|
static args = {
|
|
14
16
|
id: Args.integer({
|
|
15
17
|
description: "Идентификатор бота (pachca bots list)",
|
|
@@ -28,7 +30,7 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
28
30
|
description: "URL исходящего вебхука",
|
|
29
31
|
}),
|
|
30
32
|
'events': Flags.string({
|
|
31
|
-
description: "События, на которые подписан
|
|
33
|
+
description: "События, на которые подписан бот. Список заменяется целиком.",
|
|
32
34
|
}),
|
|
33
35
|
'trigger-on': Flags.string({
|
|
34
36
|
description: "Условие срабатывания исходящего вебхука",
|
|
@@ -53,7 +55,7 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
53
55
|
allowNo: true,
|
|
54
56
|
}),
|
|
55
57
|
'ignore-self-messages': Flags.boolean({
|
|
56
|
-
description: "
|
|
58
|
+
description: "Не присылать боту события о его собственных сообщениях и реакциях",
|
|
57
59
|
allowNo: true,
|
|
58
60
|
}),
|
|
59
61
|
'events-history-enabled': Flags.boolean({
|
|
@@ -64,7 +66,23 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
64
66
|
description: "Кто может добавлять бота в чаты",
|
|
65
67
|
}),
|
|
66
68
|
'can-edit': Flags.string({
|
|
67
|
-
description: "Роли, которым, помимо создателя, разрешено редактировать настройки бота. Создатель может редактировать всегда. Пустой массив — редактировать может только создатель.",
|
|
69
|
+
description: "Роли, которым, помимо создателя, разрешено редактировать настройки бота. Создатель может редактировать всегда. Пустой массив — редактировать может только создатель. Список заменяется целиком.",
|
|
70
|
+
}),
|
|
71
|
+
'single-chat': Flags.boolean({
|
|
72
|
+
description: "Ограничивает бота одной беседой или каналом: `true` — бота можно добавить только в один такой чат, `false` — в несколько. Личные чаты и треды в ограничение не входят.",
|
|
73
|
+
allowNo: true,
|
|
74
|
+
}),
|
|
75
|
+
'kind': Flags.string({
|
|
76
|
+
description: "Источник входящего вебхука. Если у бота входящего вебхука не было, он включается.",
|
|
77
|
+
}),
|
|
78
|
+
'unfurl-domains': Flags.string({
|
|
79
|
+
description: "Домены, ссылки на которые бот разворачивает, не больше 5. Работают вместе с событием `message_link_shared`. Список заменяется целиком.",
|
|
80
|
+
}),
|
|
81
|
+
'oauth-client': Flags.string({
|
|
82
|
+
description: "Настройки авторизации от имени сотрудника. Если авторизация выключена, объект её включает, а `null` выключает: выданные сотрудниками авторизации отзываются, страница в витрине удаляется, собственные токены бота продолжают работать.",
|
|
83
|
+
}),
|
|
84
|
+
'promo': Flags.string({
|
|
85
|
+
description: "Страница бота в витрине. Доступна, только когда у бота включена авторизация.",
|
|
68
86
|
}),
|
|
69
87
|
};
|
|
70
88
|
async run() {
|
|
@@ -80,7 +98,8 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
80
98
|
if (validationErrors.length > 0) {
|
|
81
99
|
this.validationError(validationErrors);
|
|
82
100
|
}
|
|
83
|
-
const body = {
|
|
101
|
+
const body = {
|
|
102
|
+
webhook: {
|
|
84
103
|
name: flags['name'],
|
|
85
104
|
nickname: flags['nickname'],
|
|
86
105
|
outgoing_url: flags['outgoing-url'],
|
|
@@ -96,14 +115,24 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
96
115
|
events_history_enabled: flags['events-history-enabled'],
|
|
97
116
|
who_can_add: flags['who-can-add'],
|
|
98
117
|
can_edit: flags['can-edit'] ? this.parseJSON(flags['can-edit'], 'can-edit') : undefined,
|
|
99
|
-
|
|
118
|
+
single_chat: flags['single-chat'],
|
|
119
|
+
kind: flags['kind'],
|
|
120
|
+
unfurl_domains: flags['unfurl-domains'] ? this.parseJSON(flags['unfurl-domains'], 'unfurl-domains') : undefined,
|
|
121
|
+
},
|
|
122
|
+
oauth_client: flags['oauth-client'] ? this.parseJSON(flags['oauth-client'], 'oauth-client') : undefined,
|
|
123
|
+
promo: flags['promo'] ? this.parseJSON(flags['promo'], 'promo') : undefined,
|
|
124
|
+
};
|
|
100
125
|
// Clean undefined fields
|
|
101
126
|
const inner = body['webhook'];
|
|
102
127
|
for (const [k, v] of Object.entries(inner)) {
|
|
103
128
|
if (v === undefined)
|
|
104
129
|
delete inner[k];
|
|
105
130
|
}
|
|
106
|
-
|
|
131
|
+
for (const [k, v] of Object.entries(body)) {
|
|
132
|
+
if (k !== 'webhook' && v === undefined)
|
|
133
|
+
delete body[k];
|
|
134
|
+
}
|
|
135
|
+
if (Object.keys(inner).length === 0 && Object.keys(body).length === 1) {
|
|
107
136
|
this.validationError([{ message: 'Не указаны поля для обновления' }], { type: 'PACHCA_USAGE_ERROR' });
|
|
108
137
|
}
|
|
109
138
|
const { data } = await this.apiRequest({
|
|
@@ -91,5 +91,6 @@ export default class ChatsCreate extends BaseCommand {
|
|
|
91
91
|
const responseBody = (data ?? {});
|
|
92
92
|
const result = responseBody.data ?? responseBody;
|
|
93
93
|
this.output(result);
|
|
94
|
+
this.warnMetaList(responseBody.meta, "not_found_member_ids", "Не удалось добавить в чат", "Таких сотрудников нет в пространстве, либо они приостановлены или удалены.");
|
|
94
95
|
}
|
|
95
96
|
}
|
|
@@ -15,7 +15,7 @@ export default class ChatsDownloadExport extends BaseCommand {
|
|
|
15
15
|
static apiPath = "/chats/exports/{id}";
|
|
16
16
|
static args = {
|
|
17
17
|
id: Args.integer({
|
|
18
|
-
description: "Идентификатор
|
|
18
|
+
description: "Идентификатор экспорта: `export_id` из вебхука о готовом архиве или число из ссылки вида `/full_exports/{id}` в уведомлении в Пачке (pachca chats list)",
|
|
19
19
|
required: true,
|
|
20
20
|
}),
|
|
21
21
|
};
|
|
@@ -9,7 +9,7 @@ export default class ChatsGet extends BaseCommand {
|
|
|
9
9
|
static defaultColumns = ["id", "name", "created_at", "owner_id", "channel"];
|
|
10
10
|
static args = {
|
|
11
11
|
id: Args.integer({
|
|
12
|
-
description: "Идентификатор
|
|
12
|
+
description: "Идентификатор чата: в ссылке веб-приложения это число из пути `/chats/{id}` (pachca chats list)",
|
|
13
13
|
required: true,
|
|
14
14
|
}),
|
|
15
15
|
};
|
|
@@ -53,7 +53,7 @@ export default class ChatsListCompany extends BaseCommand {
|
|
|
53
53
|
const paginate = meta?.paginate;
|
|
54
54
|
nextCursor = paginate?.next_page;
|
|
55
55
|
pages++;
|
|
56
|
-
// Условие конца: списочные методы — has_next === false; методы поиска
|
|
56
|
+
// Условие конца: списочные методы и /users?query= — has_next === false; методы поиска (без has_next) — пустой data
|
|
57
57
|
const hasNext = paginate?.has_next;
|
|
58
58
|
if (typeof hasNext === 'boolean') {
|
|
59
59
|
if (!hasNext)
|
|
@@ -86,7 +86,7 @@ export default class ChatsList extends BaseCommand {
|
|
|
86
86
|
const paginate = meta?.paginate;
|
|
87
87
|
nextCursor = paginate?.next_page;
|
|
88
88
|
pages++;
|
|
89
|
-
// Условие конца: списочные методы — has_next === false; методы поиска
|
|
89
|
+
// Условие конца: списочные методы и /users?query= — has_next === false; методы поиска (без has_next) — пустой data
|
|
90
90
|
const hasNext = paginate?.has_next;
|
|
91
91
|
if (typeof hasNext === 'boolean') {
|
|
92
92
|
if (!hasNext)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
export default class ChatsMarkUnread extends BaseCommand {
|
|
5
|
+
static description = "Отметка чата непрочитанным";
|
|
6
|
+
static scope = "chats:mark_unread";
|
|
7
|
+
static apiMethod = "PUT";
|
|
8
|
+
static apiPath = "/chats/{id}/unread";
|
|
9
|
+
static args = {
|
|
10
|
+
id: Args.integer({
|
|
11
|
+
description: "Идентификатор чата (беседы, канала, личного чата или чата треда) (pachca chats list)",
|
|
12
|
+
required: true,
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
15
|
+
static flags = {
|
|
16
|
+
...BaseCommand.baseFlags,
|
|
17
|
+
'message-id': Flags.integer({
|
|
18
|
+
description: "Идентификатор сообщения, с которого чат становится непрочитанным: оно и все сообщения после него. Если не передать, непрочитанным становится последнее сообщение. (pachca messages list)",
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(ChatsMarkUnread);
|
|
23
|
+
this.parsedFlags = flags;
|
|
24
|
+
const body = {
|
|
25
|
+
message_id: flags['message-id'],
|
|
26
|
+
};
|
|
27
|
+
// Clean undefined fields
|
|
28
|
+
for (const [k, v] of Object.entries(body)) {
|
|
29
|
+
if (v === undefined)
|
|
30
|
+
delete body[k];
|
|
31
|
+
}
|
|
32
|
+
if (Object.keys(body).length === 0) {
|
|
33
|
+
this.validationError([{ message: 'Не указаны поля для обновления' }], { type: 'PACHCA_USAGE_ERROR' });
|
|
34
|
+
}
|
|
35
|
+
const { data } = await this.apiRequest({
|
|
36
|
+
method: 'PUT',
|
|
37
|
+
path: `/chats/${args.id}/unread`,
|
|
38
|
+
body,
|
|
39
|
+
});
|
|
40
|
+
const responseBody = (data ?? {});
|
|
41
|
+
const result = responseBody.data ?? responseBody;
|
|
42
|
+
this.output(result);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import * as clack from '@clack/prompts';
|
|
5
|
+
export default class ChatsRemoveAvatar extends BaseCommand {
|
|
6
|
+
static description = "Удаление аватара чата";
|
|
7
|
+
static examples = [
|
|
8
|
+
"Поставить или убрать аватар чата — Чтобы убрать аватар, удали его:\n $ pachca chats remove-avatar"
|
|
9
|
+
];
|
|
10
|
+
static scope = "chats:update";
|
|
11
|
+
static apiMethod = "DELETE";
|
|
12
|
+
static apiPath = "/chats/{id}/avatar";
|
|
13
|
+
static args = {
|
|
14
|
+
id: Args.integer({
|
|
15
|
+
description: "Идентификатор чата (pachca chats list)",
|
|
16
|
+
required: true,
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
static flags = {
|
|
20
|
+
...BaseCommand.baseFlags,
|
|
21
|
+
force: Flags.boolean({
|
|
22
|
+
description: 'Пропустить подтверждение',
|
|
23
|
+
default: false,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { args, flags } = await this.parse(ChatsRemoveAvatar);
|
|
28
|
+
this.parsedFlags = flags;
|
|
29
|
+
if (!flags.force) {
|
|
30
|
+
if (!this.isInteractive()) {
|
|
31
|
+
this.validationError([{ message: 'Деструктивная операция требует флага --force', flag: 'force' }], { type: 'PACHCA_DESTRUCTIVE_OP_ERROR', hint: "pachca chats remove-avatar <id> --force" });
|
|
32
|
+
}
|
|
33
|
+
const confirm = await clack.confirm({ message: 'Вы уверены?' });
|
|
34
|
+
if (clack.isCancel(confirm) || !confirm) {
|
|
35
|
+
process.stderr.write('Отменено.\n');
|
|
36
|
+
this.exit(0);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const { data } = await this.apiRequest({
|
|
40
|
+
method: 'DELETE',
|
|
41
|
+
path: `/chats/${args.id}/avatar`,
|
|
42
|
+
});
|
|
43
|
+
this.success('Удалено');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -5,13 +5,14 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class ChatsRequestExport extends BaseCommand {
|
|
6
6
|
static description = "Экспорт сообщений";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Экспорт истории чата — Запроси
|
|
8
|
+
"Экспорт истории чата — Запроси экспорт и возьми номер выгрузки из `data.id`:\n $ pachca chats request-export"
|
|
9
9
|
];
|
|
10
10
|
static hiddenAliases = ["common:request-export"];
|
|
11
11
|
static scope = "chat_exports:write";
|
|
12
12
|
static plan = "corporation";
|
|
13
13
|
static apiMethod = "POST";
|
|
14
14
|
static apiPath = "/chats/exports";
|
|
15
|
+
static defaultColumns = ["id"];
|
|
15
16
|
static requiredFlags = ["start-at", "end-at"];
|
|
16
17
|
static args = {};
|
|
17
18
|
static flags = {
|
|
@@ -23,7 +24,7 @@ export default class ChatsRequestExport extends BaseCommand {
|
|
|
23
24
|
description: "Дата окончания для экспорта в формате YYYY-MM-DD, включительно. Если прислать дату со временем, время молча отбрасывается.",
|
|
24
25
|
}),
|
|
25
26
|
'webhook-url': Flags.string({
|
|
26
|
-
description: "Адрес, на который придёт вебхук с номером готовой
|
|
27
|
+
description: "Адрес, на который придёт вебхук с номером готовой выгрузки, когда архив будет собран. Номер приходит в поле `export_id`, а всё тело вебхука описано в разделе [Экспорт](https://dev.pachca.com/guides/export).",
|
|
27
28
|
}),
|
|
28
29
|
'chat-ids': Flags.string({
|
|
29
30
|
description: "Массив идентификаторов чатов. Указывается, если нужно получить сообщения только некоторых чатов.",
|
|
@@ -79,6 +80,7 @@ export default class ChatsRequestExport extends BaseCommand {
|
|
|
79
80
|
method: 'POST',
|
|
80
81
|
path: '/chats/exports',
|
|
81
82
|
body,
|
|
83
|
+
headers: { "Prefer": "return=representation" },
|
|
82
84
|
});
|
|
83
85
|
const responseBody = (data ?? {});
|
|
84
86
|
const result = responseBody.data ?? responseBody;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
export default class ChatsUpdateAvatar extends BaseCommand {
|
|
7
|
+
static description = "Загрузка аватара чата";
|
|
8
|
+
static examples = [
|
|
9
|
+
"Поставить или убрать аватар чата — Загрузи аватар беседы или канала:\n $ pachca chats update-avatar"
|
|
10
|
+
];
|
|
11
|
+
static scope = "chats:update";
|
|
12
|
+
static apiMethod = "PUT";
|
|
13
|
+
static apiPath = "/chats/{id}/avatar";
|
|
14
|
+
static defaultColumns = ["image_url"];
|
|
15
|
+
static args = {
|
|
16
|
+
id: Args.integer({
|
|
17
|
+
description: "Идентификатор чата (pachca chats list)",
|
|
18
|
+
required: true,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static flags = {
|
|
22
|
+
...BaseCommand.baseFlags,
|
|
23
|
+
file: Flags.string({
|
|
24
|
+
description: "Файл изображения для аватара",
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { args, flags } = await this.parse(ChatsUpdateAvatar);
|
|
29
|
+
this.parsedFlags = flags;
|
|
30
|
+
let formData;
|
|
31
|
+
if (flags.file) {
|
|
32
|
+
formData = new FormData();
|
|
33
|
+
if (flags.file === '-') {
|
|
34
|
+
const chunks = [];
|
|
35
|
+
for await (const chunk of process.stdin)
|
|
36
|
+
chunks.push(chunk);
|
|
37
|
+
const blob = new Blob([Buffer.concat(chunks)]);
|
|
38
|
+
formData.append('image', blob, 'stdin');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const blob = new Blob([fs.readFileSync(flags.file)]);
|
|
42
|
+
formData.append('image', blob, path.basename(flags.file));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const { data } = await this.apiRequest({
|
|
46
|
+
method: 'PUT',
|
|
47
|
+
path: `/chats/${args.id}/avatar`,
|
|
48
|
+
formData,
|
|
49
|
+
});
|
|
50
|
+
const responseBody = (data ?? {});
|
|
51
|
+
const result = responseBody.data ?? responseBody;
|
|
52
|
+
this.output(result);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -22,7 +22,7 @@ export default class DraftsCreate extends BaseCommand {
|
|
|
22
22
|
description: "Идентификатор того, что названо в `entity_type`: беседы или канала, треда либо сотрудника (pachca chats list | pachca users list)",
|
|
23
23
|
}),
|
|
24
24
|
'content': Flags.string({
|
|
25
|
-
description: "Текст черновика. Можно не передавать, если есть вложения, но пустым черновик быть не может.",
|
|
25
|
+
description: "Текст черновика. Можно не передавать, если есть вложения, но пустым черновик быть не может. До 40 000 байт в UTF-8, а у отложенного сообщения в пространстве с продвинутым шифрованием — до 27 000.",
|
|
26
26
|
}),
|
|
27
27
|
'parent-message-id': Flags.integer({
|
|
28
28
|
description: "Идентификатор сообщения, ответом на которое уйдёт черновик. Сообщение должно быть в том же чате.",
|
|
@@ -59,7 +59,7 @@ export default class DraftsList extends BaseCommand {
|
|
|
59
59
|
const paginate = meta?.paginate;
|
|
60
60
|
nextCursor = paginate?.next_page;
|
|
61
61
|
pages++;
|
|
62
|
-
// Условие конца: списочные методы — has_next === false; методы поиска
|
|
62
|
+
// Условие конца: списочные методы и /users?query= — has_next === false; методы поиска (без has_next) — пустой data
|
|
63
63
|
const hasNext = paginate?.has_next;
|
|
64
64
|
if (typeof hasNext === 'boolean') {
|
|
65
65
|
if (!hasNext)
|
|
@@ -16,7 +16,7 @@ export default class DraftsUpdate extends BaseCommand {
|
|
|
16
16
|
static flags = {
|
|
17
17
|
...BaseCommand.baseFlags,
|
|
18
18
|
'content': Flags.string({
|
|
19
|
-
description: "Текст
|
|
19
|
+
description: "Текст черновика. До 40 000 байт в UTF-8, а у отложенного сообщения в пространстве с продвинутым шифрованием — до 27 000.",
|
|
20
20
|
}),
|
|
21
21
|
'parent-message-id': Flags.integer({
|
|
22
22
|
description: "Идентификатор сообщения, ответом на которое уйдёт черновик. `null` снимает ответ.",
|