@pachca/cli 2026.3.9 → 2026.4.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/CHANGELOG.md +15 -0
- package/README.md +4 -0
- package/dist/client.js +8 -1
- package/dist/commands/bots/list-events.js +2 -0
- package/dist/commands/chats/list.js +16 -8
- package/dist/commands/group-tags/list-users.js +2 -0
- package/dist/commands/group-tags/list.js +4 -2
- package/dist/commands/members/list.js +4 -0
- package/dist/commands/messages/create.js +9 -3
- package/dist/commands/messages/list.js +25 -6
- package/dist/commands/profile/delete-avatar.js +41 -0
- package/dist/commands/profile/update-avatar.js +50 -0
- package/dist/commands/reactions/list.js +2 -0
- package/dist/commands/read-member/list-readers.js +2 -0
- package/dist/commands/search/list-chats.js +2 -0
- package/dist/commands/search/list-messages.js +6 -4
- package/dist/commands/search/list-users.js +4 -2
- package/dist/commands/security/list.js +2 -29
- package/dist/commands/tasks/list.js +2 -0
- package/dist/commands/users/list.js +2 -0
- package/dist/commands/users/remove-avatar.js +46 -0
- package/dist/commands/users/update-avatar.js +55 -0
- package/dist/data/alternatives.json +4 -0
- package/dist/data/changelog.json +57 -0
- package/dist/data/workflows.json +43 -0
- package/oclif.manifest.json +1 -12576
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026.4.0 (7 апреля 2026)
|
|
4
|
+
|
|
5
|
+
- **Добавлено** (profile update-avatar): Загрузка аватара профиля
|
|
6
|
+
- **Добавлено** (profile delete-avatar): Удаление аватара профиля
|
|
7
|
+
- **Добавлено** (users update-avatar): Загрузка аватара сотрудника
|
|
8
|
+
- **Добавлено** (users remove-avatar): Удаление аватара сотрудника
|
|
9
|
+
- **Изменено** (chats list, messages list): Исправлена сортировка: --order без --sort теперь корректно работает (sort по умолчанию id, order по умолчанию desc)
|
|
10
|
+
- **Изменено** (messages list): chat_id можно передать первым аргументом: pachca messages list 12345
|
|
11
|
+
|
|
12
|
+
## 2026.3.10 (21 марта 2026)
|
|
13
|
+
|
|
14
|
+
- **Изменено** (messages create): Поле link_preview перемещено на верхний уровень тела запроса (раньше было внутри message)
|
|
15
|
+
- **Изменено** (security list): Параметры start-time и end-time стали необязательными
|
|
16
|
+
- **Изменено** (chats list, messages list): Сортировка через --sort и --order вместо --sort-id и --sort-last-message-at
|
|
17
|
+
|
|
3
18
|
## 2026.3.9 (19 марта 2026)
|
|
4
19
|
|
|
5
20
|
- **Изменено** (all): Убрана клиентская валидация скоупов — проверка разрешений теперь только на стороне API (403)
|
package/README.md
CHANGED
|
@@ -171,6 +171,8 @@ pachca guide # список всех сценариев
|
|
|
171
171
|
|---------|---------|
|
|
172
172
|
| `pachca profile get-info` | Информация о токене |
|
|
173
173
|
| `pachca profile get` | Информация о профиле |
|
|
174
|
+
| `pachca profile update-avatar` | Загрузка аватара |
|
|
175
|
+
| `pachca profile delete-avatar` | Удаление аватара |
|
|
174
176
|
| `pachca profile get-status` | Текущий статус |
|
|
175
177
|
| `pachca profile update-status` | Новый статус |
|
|
176
178
|
| `pachca profile delete-status` | Удаление статуса |
|
|
@@ -202,6 +204,8 @@ pachca guide # список всех сценариев
|
|
|
202
204
|
| `pachca users get` | Информация о сотруднике |
|
|
203
205
|
| `pachca users update` | Редактирование сотрудника |
|
|
204
206
|
| `pachca users delete` | Удаление сотрудника |
|
|
207
|
+
| `pachca users update-avatar` | Загрузка аватара сотрудника |
|
|
208
|
+
| `pachca users remove-avatar` | Удаление аватара сотрудника |
|
|
205
209
|
| `pachca users get-status` | Статус сотрудника |
|
|
206
210
|
| `pachca users update-status` | Новый статус сотрудника |
|
|
207
211
|
| `pachca users remove-status` | Удаление статуса сотрудника |
|
package/dist/client.js
CHANGED
|
@@ -32,7 +32,14 @@ function buildUrl(apiPath, query) {
|
|
|
32
32
|
if (query) {
|
|
33
33
|
for (const [key, value] of Object.entries(query)) {
|
|
34
34
|
if (value !== undefined) {
|
|
35
|
-
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
for (const v of value) {
|
|
37
|
+
url.searchParams.append(`${key}[]`, String(v));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
url.searchParams.set(key, String(value));
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
45
|
}
|
|
@@ -43,6 +43,8 @@ export default class BotsListEvents extends BaseCommand {
|
|
|
43
43
|
const items = body.data;
|
|
44
44
|
if (items)
|
|
45
45
|
allData.push(...items);
|
|
46
|
+
if (!items || items.length === 0)
|
|
47
|
+
break;
|
|
46
48
|
const meta = body.meta;
|
|
47
49
|
const paginate = meta?.paginate;
|
|
48
50
|
nextCursor = paginate?.next_page;
|
|
@@ -15,14 +15,20 @@ export default class ChatsList extends BaseCommand {
|
|
|
15
15
|
static args = {};
|
|
16
16
|
static flags = {
|
|
17
17
|
...BaseCommand.baseFlags,
|
|
18
|
-
'sort
|
|
19
|
-
description: "
|
|
18
|
+
'sort': Flags.string({
|
|
19
|
+
description: "Поле сортировки",
|
|
20
|
+
options: ["id", "last_message_at"],
|
|
21
|
+
default: "id",
|
|
20
22
|
}),
|
|
21
|
-
'
|
|
22
|
-
description: "
|
|
23
|
+
'order': Flags.string({
|
|
24
|
+
description: "Направление сортировки",
|
|
25
|
+
options: ["asc", "desc"],
|
|
26
|
+
default: "desc",
|
|
23
27
|
}),
|
|
24
28
|
'availability': Flags.string({
|
|
25
29
|
description: "Параметр, который отвечает за доступность и выборку чатов для пользователя",
|
|
30
|
+
options: ["is_member", "public"],
|
|
31
|
+
default: "is_member",
|
|
26
32
|
}),
|
|
27
33
|
'last-message-at-after': Flags.string({
|
|
28
34
|
description: "Фильтрация по времени создания последнего сообщения. Будут возвращены те чаты, время последнего созданного сообщения в которых не раньше чем указанное (в формате YYYY-MM-DDThh:mm:ss.sssZ).",
|
|
@@ -56,8 +62,8 @@ export default class ChatsList extends BaseCommand {
|
|
|
56
62
|
const seenCursors = new Set();
|
|
57
63
|
while (pages < 500) {
|
|
58
64
|
const query = {
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
sort: flags['sort'],
|
|
66
|
+
order: flags['order'],
|
|
61
67
|
availability: flags['availability'],
|
|
62
68
|
'last_message_at_after': flags['last-message-at-after'],
|
|
63
69
|
'last_message_at_before': flags['last-message-at-before'],
|
|
@@ -70,6 +76,8 @@ export default class ChatsList extends BaseCommand {
|
|
|
70
76
|
const items = body.data;
|
|
71
77
|
if (items)
|
|
72
78
|
allData.push(...items);
|
|
79
|
+
if (!items || items.length === 0)
|
|
80
|
+
break;
|
|
73
81
|
const meta = body.meta;
|
|
74
82
|
const paginate = meta?.paginate;
|
|
75
83
|
nextCursor = paginate?.next_page;
|
|
@@ -99,8 +107,8 @@ export default class ChatsList extends BaseCommand {
|
|
|
99
107
|
method: 'GET',
|
|
100
108
|
path: '/chats',
|
|
101
109
|
query: {
|
|
102
|
-
|
|
103
|
-
|
|
110
|
+
sort: flags['sort'],
|
|
111
|
+
order: flags['order'],
|
|
104
112
|
availability: flags['availability'],
|
|
105
113
|
'last_message_at_after': flags['last-message-at-after'],
|
|
106
114
|
'last_message_at_before': flags['last-message-at-before'],
|
|
@@ -48,6 +48,8 @@ export default class GroupTagsListUsers extends BaseCommand {
|
|
|
48
48
|
const items = body.data;
|
|
49
49
|
if (items)
|
|
50
50
|
allData.push(...items);
|
|
51
|
+
if (!items || items.length === 0)
|
|
52
|
+
break;
|
|
51
53
|
const meta = body.meta;
|
|
52
54
|
const paginate = meta?.paginate;
|
|
53
55
|
nextCursor = paginate?.next_page;
|
|
@@ -39,7 +39,7 @@ export default class GroupTagsList extends BaseCommand {
|
|
|
39
39
|
const seenCursors = new Set();
|
|
40
40
|
while (pages < 500) {
|
|
41
41
|
const query = {
|
|
42
|
-
names: flags['names'],
|
|
42
|
+
names: flags['names']?.split(','),
|
|
43
43
|
limit: flags.limit,
|
|
44
44
|
cursor: nextCursor,
|
|
45
45
|
};
|
|
@@ -48,6 +48,8 @@ export default class GroupTagsList extends BaseCommand {
|
|
|
48
48
|
const items = body.data;
|
|
49
49
|
if (items)
|
|
50
50
|
allData.push(...items);
|
|
51
|
+
if (!items || items.length === 0)
|
|
52
|
+
break;
|
|
51
53
|
const meta = body.meta;
|
|
52
54
|
const paginate = meta?.paginate;
|
|
53
55
|
nextCursor = paginate?.next_page;
|
|
@@ -77,7 +79,7 @@ export default class GroupTagsList extends BaseCommand {
|
|
|
77
79
|
method: 'GET',
|
|
78
80
|
path: '/group_tags',
|
|
79
81
|
query: {
|
|
80
|
-
names: flags['names'],
|
|
82
|
+
names: flags['names']?.split(','),
|
|
81
83
|
limit: flags.limit,
|
|
82
84
|
cursor: flags.cursor,
|
|
83
85
|
},
|
|
@@ -22,6 +22,8 @@ export default class MembersList extends BaseCommand {
|
|
|
22
22
|
...BaseCommand.baseFlags,
|
|
23
23
|
'role': Flags.string({
|
|
24
24
|
description: "Роль в чате",
|
|
25
|
+
options: ["all", "owner", "admin", "editor", "member"],
|
|
26
|
+
default: "all",
|
|
25
27
|
}),
|
|
26
28
|
limit: Flags.integer({
|
|
27
29
|
description: 'Количество результатов на страницу',
|
|
@@ -54,6 +56,8 @@ export default class MembersList extends BaseCommand {
|
|
|
54
56
|
const items = body.data;
|
|
55
57
|
if (items)
|
|
56
58
|
allData.push(...items);
|
|
59
|
+
if (!items || items.length === 0)
|
|
60
|
+
break;
|
|
57
61
|
const meta = body.meta;
|
|
58
62
|
const paginate = meta?.paginate;
|
|
59
63
|
nextCursor = paginate?.next_page;
|
|
@@ -98,7 +98,8 @@ export default class MessagesCreate extends BaseCommand {
|
|
|
98
98
|
if (validationErrors.length > 0) {
|
|
99
99
|
this.validationError(validationErrors);
|
|
100
100
|
}
|
|
101
|
-
const body = {
|
|
101
|
+
const body = {
|
|
102
|
+
message: {
|
|
102
103
|
entity_type: flags['entity-type'],
|
|
103
104
|
entity_id: flags['entity-id'],
|
|
104
105
|
content: flags['content'],
|
|
@@ -108,14 +109,19 @@ export default class MessagesCreate extends BaseCommand {
|
|
|
108
109
|
display_avatar_url: flags['display-avatar-url'],
|
|
109
110
|
display_name: flags['display-name'],
|
|
110
111
|
skip_invite_mentions: flags['skip-invite-mentions'],
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
},
|
|
113
|
+
link_preview: flags['link-preview'],
|
|
114
|
+
};
|
|
113
115
|
// Clean undefined fields
|
|
114
116
|
const inner = body['message'];
|
|
115
117
|
for (const [k, v] of Object.entries(inner)) {
|
|
116
118
|
if (v === undefined)
|
|
117
119
|
delete inner[k];
|
|
118
120
|
}
|
|
121
|
+
for (const [k, v] of Object.entries(body)) {
|
|
122
|
+
if (k !== 'message' && v === undefined)
|
|
123
|
+
delete body[k];
|
|
124
|
+
}
|
|
119
125
|
const { data } = await this.apiRequest({
|
|
120
126
|
method: 'POST',
|
|
121
127
|
path: '/messages',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
-
import { Flags } from '@oclif/core';
|
|
2
|
+
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 MessagesList extends BaseCommand {
|
|
@@ -14,14 +14,26 @@ export default class MessagesList extends BaseCommand {
|
|
|
14
14
|
static apiPath = "/messages";
|
|
15
15
|
static defaultColumns = ["id", "content", "created_at", "entity_type", "entity_id"];
|
|
16
16
|
static requiredFlags = ["chat-id"];
|
|
17
|
-
static args = {
|
|
17
|
+
static args = {
|
|
18
|
+
chat_id: Args.integer({
|
|
19
|
+
description: "Идентификатор чата (беседа, канал, диалог или чат треда)",
|
|
20
|
+
required: false,
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
18
23
|
static flags = {
|
|
19
24
|
...BaseCommand.baseFlags,
|
|
20
25
|
'chat-id': Flags.integer({
|
|
21
26
|
description: "Идентификатор чата (беседа, канал, диалог или чат треда)",
|
|
22
27
|
}),
|
|
23
|
-
'sort
|
|
24
|
-
description: "
|
|
28
|
+
'sort': Flags.string({
|
|
29
|
+
description: "Поле сортировки",
|
|
30
|
+
options: ["id"],
|
|
31
|
+
default: "id",
|
|
32
|
+
}),
|
|
33
|
+
'order': Flags.string({
|
|
34
|
+
description: "Направление сортировки",
|
|
35
|
+
options: ["asc", "desc"],
|
|
36
|
+
default: "desc",
|
|
25
37
|
}),
|
|
26
38
|
limit: Flags.integer({
|
|
27
39
|
description: 'Количество результатов на страницу',
|
|
@@ -37,6 +49,9 @@ export default class MessagesList extends BaseCommand {
|
|
|
37
49
|
async run() {
|
|
38
50
|
const { args, flags } = await this.parse(MessagesList);
|
|
39
51
|
this.parsedFlags = flags;
|
|
52
|
+
if (args.chat_id !== undefined && flags['chat-id'] === undefined) {
|
|
53
|
+
flags['chat-id'] = args.chat_id;
|
|
54
|
+
}
|
|
40
55
|
const missingRequired = [
|
|
41
56
|
{ flag: 'chat-id', label: "Идентификатор чата (беседа, канал, диалог или чат треда)", type: 'integer' },
|
|
42
57
|
].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
|
|
@@ -72,7 +87,8 @@ export default class MessagesList extends BaseCommand {
|
|
|
72
87
|
while (pages < 500) {
|
|
73
88
|
const query = {
|
|
74
89
|
'chat_id': flags['chat-id'],
|
|
75
|
-
|
|
90
|
+
sort: flags['sort'],
|
|
91
|
+
order: flags['order'],
|
|
76
92
|
limit: flags.limit,
|
|
77
93
|
cursor: nextCursor,
|
|
78
94
|
};
|
|
@@ -81,6 +97,8 @@ export default class MessagesList extends BaseCommand {
|
|
|
81
97
|
const items = body.data;
|
|
82
98
|
if (items)
|
|
83
99
|
allData.push(...items);
|
|
100
|
+
if (!items || items.length === 0)
|
|
101
|
+
break;
|
|
84
102
|
const meta = body.meta;
|
|
85
103
|
const paginate = meta?.paginate;
|
|
86
104
|
nextCursor = paginate?.next_page;
|
|
@@ -111,7 +129,8 @@ export default class MessagesList extends BaseCommand {
|
|
|
111
129
|
path: '/messages',
|
|
112
130
|
query: {
|
|
113
131
|
'chat_id': flags['chat-id'],
|
|
114
|
-
|
|
132
|
+
sort: flags['sort'],
|
|
133
|
+
order: flags['order'],
|
|
115
134
|
limit: flags.limit,
|
|
116
135
|
cursor: flags.cursor,
|
|
117
136
|
},
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { Flags } from '@oclif/core';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import * as clack from '@clack/prompts';
|
|
5
|
+
export default class ProfileDeleteAvatar extends BaseCommand {
|
|
6
|
+
static description = "Удаление аватара";
|
|
7
|
+
static examples = [
|
|
8
|
+
"Загрузить аватар профиля:\n $ pachca profile update-avatar",
|
|
9
|
+
"Удалить аватар профиля:\n $ pachca profile delete-avatar"
|
|
10
|
+
];
|
|
11
|
+
static scope = "profile_avatar:write";
|
|
12
|
+
static apiMethod = "DELETE";
|
|
13
|
+
static apiPath = "/profile/avatar";
|
|
14
|
+
static args = {};
|
|
15
|
+
static flags = {
|
|
16
|
+
...BaseCommand.baseFlags,
|
|
17
|
+
force: Flags.boolean({
|
|
18
|
+
description: 'Пропустить подтверждение',
|
|
19
|
+
default: false,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
async run() {
|
|
23
|
+
const { args, flags } = await this.parse(ProfileDeleteAvatar);
|
|
24
|
+
this.parsedFlags = flags;
|
|
25
|
+
if (!flags.force) {
|
|
26
|
+
if (!this.isInteractive()) {
|
|
27
|
+
this.validationError([{ message: 'Деструктивная операция требует флага --force', flag: 'force' }], { type: 'PACHCA_DESTRUCTIVE_OP_ERROR', hint: "pachca profile delete-avatar --force" });
|
|
28
|
+
}
|
|
29
|
+
const confirm = await clack.confirm({ message: 'Вы уверены?' });
|
|
30
|
+
if (clack.isCancel(confirm) || !confirm) {
|
|
31
|
+
process.stderr.write('Отменено.\n');
|
|
32
|
+
this.exit(0);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const { data } = await this.apiRequest({
|
|
36
|
+
method: 'DELETE',
|
|
37
|
+
path: '/profile/avatar',
|
|
38
|
+
});
|
|
39
|
+
this.success('Удалено');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
|
+
import { 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 ProfileUpdateAvatar extends BaseCommand {
|
|
7
|
+
static description = "Загрузка аватара";
|
|
8
|
+
static examples = [
|
|
9
|
+
"Загрузить аватар профиля:\n $ pachca profile update-avatar",
|
|
10
|
+
"Удалить аватар профиля:\n $ pachca profile delete-avatar"
|
|
11
|
+
];
|
|
12
|
+
static scope = "profile_avatar:write";
|
|
13
|
+
static apiMethod = "PUT";
|
|
14
|
+
static apiPath = "/profile/avatar";
|
|
15
|
+
static defaultColumns = ["image_url"];
|
|
16
|
+
static args = {};
|
|
17
|
+
static flags = {
|
|
18
|
+
...BaseCommand.baseFlags,
|
|
19
|
+
file: Flags.string({
|
|
20
|
+
description: "Файл изображения для аватара",
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const { args, flags } = await this.parse(ProfileUpdateAvatar);
|
|
25
|
+
this.parsedFlags = flags;
|
|
26
|
+
let formData;
|
|
27
|
+
if (flags.file) {
|
|
28
|
+
formData = new FormData();
|
|
29
|
+
if (flags.file === '-') {
|
|
30
|
+
const chunks = [];
|
|
31
|
+
for await (const chunk of process.stdin)
|
|
32
|
+
chunks.push(chunk);
|
|
33
|
+
const blob = new Blob([Buffer.concat(chunks)]);
|
|
34
|
+
formData.append('image', blob, 'stdin');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const blob = new Blob([fs.readFileSync(flags.file)]);
|
|
38
|
+
formData.append('image', blob, path.basename(flags.file));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const { data } = await this.apiRequest({
|
|
42
|
+
method: 'PUT',
|
|
43
|
+
path: '/profile/avatar',
|
|
44
|
+
formData,
|
|
45
|
+
});
|
|
46
|
+
const responseBody = data;
|
|
47
|
+
const result = responseBody.data ?? responseBody;
|
|
48
|
+
this.output(result);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -49,6 +49,8 @@ export default class ReactionsList extends BaseCommand {
|
|
|
49
49
|
const items = body.data;
|
|
50
50
|
if (items)
|
|
51
51
|
allData.push(...items);
|
|
52
|
+
if (!items || items.length === 0)
|
|
53
|
+
break;
|
|
52
54
|
const meta = body.meta;
|
|
53
55
|
const paginate = meta?.paginate;
|
|
54
56
|
nextCursor = paginate?.next_page;
|
|
@@ -47,6 +47,8 @@ export default class ReadMemberListReaders extends BaseCommand {
|
|
|
47
47
|
const items = body.data;
|
|
48
48
|
if (items)
|
|
49
49
|
allData.push(...items);
|
|
50
|
+
if (!items || items.length === 0)
|
|
51
|
+
break;
|
|
50
52
|
const meta = body.meta;
|
|
51
53
|
const paginate = meta?.paginate;
|
|
52
54
|
nextCursor = paginate?.next_page;
|
|
@@ -76,6 +76,8 @@ export default class SearchListChats extends BaseCommand {
|
|
|
76
76
|
const items = body.data;
|
|
77
77
|
if (items)
|
|
78
78
|
allData.push(...items);
|
|
79
|
+
if (!items || items.length === 0)
|
|
80
|
+
break;
|
|
79
81
|
const meta = body.meta;
|
|
80
82
|
const paginate = meta?.paginate;
|
|
81
83
|
nextCursor = paginate?.next_page;
|
|
@@ -62,8 +62,8 @@ export default class SearchListMessages extends BaseCommand {
|
|
|
62
62
|
order: flags['order'],
|
|
63
63
|
'created_from': flags['created-from'],
|
|
64
64
|
'created_to': flags['created-to'],
|
|
65
|
-
'chat_ids': flags['chat-ids'],
|
|
66
|
-
'user_ids': flags['user-ids'],
|
|
65
|
+
'chat_ids': flags['chat-ids']?.split(','),
|
|
66
|
+
'user_ids': flags['user-ids']?.split(','),
|
|
67
67
|
active: flags['active'],
|
|
68
68
|
limit: flags.limit,
|
|
69
69
|
cursor: nextCursor,
|
|
@@ -73,6 +73,8 @@ export default class SearchListMessages extends BaseCommand {
|
|
|
73
73
|
const items = body.data;
|
|
74
74
|
if (items)
|
|
75
75
|
allData.push(...items);
|
|
76
|
+
if (!items || items.length === 0)
|
|
77
|
+
break;
|
|
76
78
|
const meta = body.meta;
|
|
77
79
|
const paginate = meta?.paginate;
|
|
78
80
|
nextCursor = paginate?.next_page;
|
|
@@ -106,8 +108,8 @@ export default class SearchListMessages extends BaseCommand {
|
|
|
106
108
|
order: flags['order'],
|
|
107
109
|
'created_from': flags['created-from'],
|
|
108
110
|
'created_to': flags['created-to'],
|
|
109
|
-
'chat_ids': flags['chat-ids'],
|
|
110
|
-
'user_ids': flags['user-ids'],
|
|
111
|
+
'chat_ids': flags['chat-ids']?.split(','),
|
|
112
|
+
'user_ids': flags['user-ids']?.split(','),
|
|
111
113
|
active: flags['active'],
|
|
112
114
|
limit: flags.limit,
|
|
113
115
|
cursor: flags.cursor,
|
|
@@ -62,7 +62,7 @@ export default class SearchListUsers extends BaseCommand {
|
|
|
62
62
|
order: flags['order'],
|
|
63
63
|
'created_from': flags['created-from'],
|
|
64
64
|
'created_to': flags['created-to'],
|
|
65
|
-
'company_roles': flags['company-roles'],
|
|
65
|
+
'company_roles': flags['company-roles']?.split(','),
|
|
66
66
|
limit: flags.limit,
|
|
67
67
|
cursor: nextCursor,
|
|
68
68
|
};
|
|
@@ -71,6 +71,8 @@ export default class SearchListUsers extends BaseCommand {
|
|
|
71
71
|
const items = body.data;
|
|
72
72
|
if (items)
|
|
73
73
|
allData.push(...items);
|
|
74
|
+
if (!items || items.length === 0)
|
|
75
|
+
break;
|
|
74
76
|
const meta = body.meta;
|
|
75
77
|
const paginate = meta?.paginate;
|
|
76
78
|
nextCursor = paginate?.next_page;
|
|
@@ -105,7 +107,7 @@ export default class SearchListUsers extends BaseCommand {
|
|
|
105
107
|
order: flags['order'],
|
|
106
108
|
'created_from': flags['created-from'],
|
|
107
109
|
'created_to': flags['created-to'],
|
|
108
|
-
'company_roles': flags['company-roles'],
|
|
110
|
+
'company_roles': flags['company-roles']?.split(','),
|
|
109
111
|
limit: flags.limit,
|
|
110
112
|
cursor: flags.cursor,
|
|
111
113
|
},
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Auto-generated from openapi.yaml — DO NOT EDIT
|
|
2
2
|
import { Flags } from '@oclif/core';
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
|
-
import * as clack from '@clack/prompts';
|
|
5
4
|
export default class SecurityList extends BaseCommand {
|
|
6
5
|
static description = "Журнал аудита событий";
|
|
7
6
|
static examples = [
|
|
@@ -14,7 +13,6 @@ export default class SecurityList extends BaseCommand {
|
|
|
14
13
|
static apiMethod = "GET";
|
|
15
14
|
static apiPath = "/audit_events";
|
|
16
15
|
static defaultColumns = ["id", "created_at", "event_key", "entity_id", "entity_type"];
|
|
17
|
-
static requiredFlags = ["start-time", "end-time"];
|
|
18
16
|
static args = {};
|
|
19
17
|
static flags = {
|
|
20
18
|
...BaseCommand.baseFlags,
|
|
@@ -54,33 +52,6 @@ export default class SecurityList extends BaseCommand {
|
|
|
54
52
|
async run() {
|
|
55
53
|
const { args, flags } = await this.parse(SecurityList);
|
|
56
54
|
this.parsedFlags = flags;
|
|
57
|
-
const missingRequired = [
|
|
58
|
-
{ flag: 'start-time', label: "Начальная метка времени (включительно)", type: 'string' },
|
|
59
|
-
{ flag: 'end-time', label: "Конечная метка времени (исключительно)", type: 'string' },
|
|
60
|
-
].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
|
|
61
|
-
if (missingRequired.length > 0) {
|
|
62
|
-
if (this.isInteractive()) {
|
|
63
|
-
for (const field of missingRequired) {
|
|
64
|
-
const value = await clack.text({ message: field.label, validate: (v) => v.length === 0 ? 'Обязательное поле' : undefined });
|
|
65
|
-
if (clack.isCancel(value)) {
|
|
66
|
-
process.stderr.write('Отменено.\n');
|
|
67
|
-
this.exit(0);
|
|
68
|
-
}
|
|
69
|
-
if (field.type === 'integer') {
|
|
70
|
-
flags[field.flag] = Number.parseInt(value, 10);
|
|
71
|
-
}
|
|
72
|
-
else if (field.type === 'boolean') {
|
|
73
|
-
flags[field.flag] = value === 'true';
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
flags[field.flag] = value;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --start-time <string>, --end-time <string>. pachca introspect security list" });
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
55
|
if (flags.all) {
|
|
85
56
|
// Auto-pagination
|
|
86
57
|
const allData = [];
|
|
@@ -104,6 +75,8 @@ export default class SecurityList extends BaseCommand {
|
|
|
104
75
|
const items = body.data;
|
|
105
76
|
if (items)
|
|
106
77
|
allData.push(...items);
|
|
78
|
+
if (!items || items.length === 0)
|
|
79
|
+
break;
|
|
107
80
|
const meta = body.meta;
|
|
108
81
|
const paginate = meta?.paginate;
|
|
109
82
|
nextCursor = paginate?.next_page;
|
|
@@ -45,6 +45,8 @@ export default class TasksList extends BaseCommand {
|
|
|
45
45
|
const items = body.data;
|
|
46
46
|
if (items)
|
|
47
47
|
allData.push(...items);
|
|
48
|
+
if (!items || items.length === 0)
|
|
49
|
+
break;
|
|
48
50
|
const meta = body.meta;
|
|
49
51
|
const paginate = meta?.paginate;
|
|
50
52
|
nextCursor = paginate?.next_page;
|
|
@@ -49,6 +49,8 @@ export default class UsersList extends BaseCommand {
|
|
|
49
49
|
const items = body.data;
|
|
50
50
|
if (items)
|
|
51
51
|
allData.push(...items);
|
|
52
|
+
if (!items || items.length === 0)
|
|
53
|
+
break;
|
|
52
54
|
const meta = body.meta;
|
|
53
55
|
const paginate = meta?.paginate;
|
|
54
56
|
nextCursor = paginate?.next_page;
|
|
@@ -0,0 +1,46 @@
|
|
|
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 UsersRemoveAvatar extends BaseCommand {
|
|
6
|
+
static description = "Удаление аватара сотрудника";
|
|
7
|
+
static examples = [
|
|
8
|
+
"Загрузить аватар сотрудника:\n $ pachca users update-avatar",
|
|
9
|
+
"Удалить аватар сотрудника:\n $ pachca users remove-avatar"
|
|
10
|
+
];
|
|
11
|
+
static scope = "user_avatar:write";
|
|
12
|
+
static apiMethod = "DELETE";
|
|
13
|
+
static apiPath = "/users/{user_id}/avatar";
|
|
14
|
+
static args = {
|
|
15
|
+
user_id: Args.integer({
|
|
16
|
+
description: "Идентификатор пользователя (pachca users list)",
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
static flags = {
|
|
21
|
+
...BaseCommand.baseFlags,
|
|
22
|
+
force: Flags.boolean({
|
|
23
|
+
description: 'Пропустить подтверждение',
|
|
24
|
+
default: false,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { args, flags } = await this.parse(UsersRemoveAvatar);
|
|
29
|
+
this.parsedFlags = flags;
|
|
30
|
+
if (!flags.force) {
|
|
31
|
+
if (!this.isInteractive()) {
|
|
32
|
+
this.validationError([{ message: 'Деструктивная операция требует флага --force', flag: 'force' }], { type: 'PACHCA_DESTRUCTIVE_OP_ERROR', hint: "pachca users remove-avatar <user_id> --force" });
|
|
33
|
+
}
|
|
34
|
+
const confirm = await clack.confirm({ message: 'Вы уверены?' });
|
|
35
|
+
if (clack.isCancel(confirm) || !confirm) {
|
|
36
|
+
process.stderr.write('Отменено.\n');
|
|
37
|
+
this.exit(0);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const { data } = await this.apiRequest({
|
|
41
|
+
method: 'DELETE',
|
|
42
|
+
path: `/users/${args.user_id}/avatar`,
|
|
43
|
+
});
|
|
44
|
+
this.success('Удалено');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
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 UsersUpdateAvatar extends BaseCommand {
|
|
7
|
+
static description = "Загрузка аватара сотрудника";
|
|
8
|
+
static examples = [
|
|
9
|
+
"Загрузить аватар сотрудника:\n $ pachca users update-avatar",
|
|
10
|
+
"Удалить аватар сотрудника:\n $ pachca users remove-avatar"
|
|
11
|
+
];
|
|
12
|
+
static scope = "user_avatar:write";
|
|
13
|
+
static apiMethod = "PUT";
|
|
14
|
+
static apiPath = "/users/{user_id}/avatar";
|
|
15
|
+
static defaultColumns = ["image_url"];
|
|
16
|
+
static args = {
|
|
17
|
+
user_id: Args.integer({
|
|
18
|
+
description: "Идентификатор пользователя (pachca users list)",
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
static flags = {
|
|
23
|
+
...BaseCommand.baseFlags,
|
|
24
|
+
file: Flags.string({
|
|
25
|
+
description: "Файл изображения для аватара",
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
const { args, flags } = await this.parse(UsersUpdateAvatar);
|
|
30
|
+
this.parsedFlags = flags;
|
|
31
|
+
let formData;
|
|
32
|
+
if (flags.file) {
|
|
33
|
+
formData = new FormData();
|
|
34
|
+
if (flags.file === '-') {
|
|
35
|
+
const chunks = [];
|
|
36
|
+
for await (const chunk of process.stdin)
|
|
37
|
+
chunks.push(chunk);
|
|
38
|
+
const blob = new Blob([Buffer.concat(chunks)]);
|
|
39
|
+
formData.append('image', blob, 'stdin');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const blob = new Blob([fs.readFileSync(flags.file)]);
|
|
43
|
+
formData.append('image', blob, path.basename(flags.file));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const { data } = await this.apiRequest({
|
|
47
|
+
method: 'PUT',
|
|
48
|
+
path: `/users/${args.user_id}/avatar`,
|
|
49
|
+
formData,
|
|
50
|
+
});
|
|
51
|
+
const responseBody = data;
|
|
52
|
+
const result = responseBody.data ?? responseBody;
|
|
53
|
+
this.output(result);
|
|
54
|
+
}
|
|
55
|
+
}
|