@pachca/cli 2026.7.1 → 2026.8.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 +18 -0
- package/README.md +1 -1
- package/README.template.md +1 -1
- package/dist/base-command.js +2 -0
- package/dist/client.js +51 -17
- package/dist/commands/bots/create.js +4 -4
- package/dist/commands/bots/delete.js +1 -1
- package/dist/commands/bots/get.js +1 -1
- package/dist/commands/bots/list-events.js +2 -2
- package/dist/commands/bots/list.js +2 -2
- package/dist/commands/bots/recreate-token-self.js +2 -2
- package/dist/commands/bots/recreate-token.js +2 -2
- package/dist/commands/bots/remove-event.js +1 -1
- package/dist/commands/bots/update-webhook.js +2 -2
- package/dist/commands/bots/update.js +3 -3
- package/dist/commands/chats/archive.js +3 -3
- package/dist/commands/chats/create.js +3 -3
- package/dist/commands/chats/download-export.js +2 -2
- package/dist/commands/chats/get.js +1 -1
- package/dist/commands/chats/list.js +4 -4
- package/dist/commands/chats/request-export.js +2 -2
- package/dist/commands/chats/unarchive.js +2 -2
- package/dist/commands/chats/update.js +2 -2
- package/dist/commands/custom-properties/list.js +2 -2
- package/dist/commands/files/direct-url.js +12 -12
- package/dist/commands/files/uploads.js +2 -2
- package/dist/commands/group-tags/create.js +2 -2
- 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 +2 -2
- package/dist/commands/group-tags/update.js +1 -1
- package/dist/commands/members/add-group-tags.js +1 -1
- package/dist/commands/members/add.js +4 -4
- package/dist/commands/members/leave.js +1 -1
- package/dist/commands/members/list.js +3 -2
- package/dist/commands/members/remove.js +1 -1
- package/dist/commands/members/update.js +2 -2
- package/dist/commands/messages/create.js +4 -4
- package/dist/commands/messages/delete.js +1 -1
- package/dist/commands/messages/get.js +4 -4
- package/dist/commands/messages/list.js +3 -2
- package/dist/commands/messages/pin.js +2 -2
- package/dist/commands/messages/unfurl.js +4 -4
- package/dist/commands/messages/unpin.js +1 -1
- package/dist/commands/messages/update.js +4 -4
- package/dist/commands/oauth/token-info.js +2 -2
- package/dist/commands/profile/delete-avatar.js +1 -1
- package/dist/commands/profile/delete-status.js +1 -1
- package/dist/commands/profile/get-status.js +1 -1
- package/dist/commands/profile/get.js +3 -3
- package/dist/commands/profile/update-avatar.js +2 -2
- package/dist/commands/profile/update-status.js +2 -2
- package/dist/commands/reactions/add.js +2 -2
- package/dist/commands/reactions/list.js +1 -1
- package/dist/commands/reactions/remove.js +1 -1
- package/dist/commands/read-member/list-readers.js +2 -2
- package/dist/commands/search/list-chats.js +3 -3
- package/dist/commands/search/list-messages.js +2 -2
- package/dist/commands/search/list-users.js +4 -4
- package/dist/commands/security/list.js +5 -5
- package/dist/commands/tasks/create.js +5 -5
- package/dist/commands/tasks/delete.js +1 -1
- package/dist/commands/tasks/get.js +2 -2
- package/dist/commands/tasks/list.js +2 -2
- package/dist/commands/tasks/update.js +4 -4
- package/dist/commands/threads/add.js +3 -3
- package/dist/commands/threads/create.js +1 -1
- package/dist/commands/threads/get.js +1 -1
- package/dist/commands/threads/list.js +3 -2
- package/dist/commands/users/create.js +4 -4
- package/dist/commands/users/delete.js +1 -1
- package/dist/commands/users/get-status.js +2 -2
- package/dist/commands/users/get.js +2 -2
- package/dist/commands/users/list.js +4 -4
- package/dist/commands/users/remove-avatar.js +1 -1
- package/dist/commands/users/remove-status.js +1 -1
- package/dist/commands/users/update-avatar.js +2 -2
- package/dist/commands/users/update-status.js +2 -2
- package/dist/commands/users/update.js +3 -3
- package/dist/commands/views/open.js +4 -4
- package/dist/data/changelog.json +72 -0
- package/dist/data/endpoints.json +1 -1
- package/dist/data/workflows.json +6 -2
- package/dist/output.js +10 -2
- package/dist/profiles.js +7 -3
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026.8.0 (1 августа 2026)
|
|
4
|
+
|
|
5
|
+
- **Изменено** (api): `api POST /messages --spec` и `--docs`: у поля `files[].name` описано требование к расширению — оно должно совпадать с расширением файла в `key`
|
|
6
|
+
- **Изменено** (api): `api GET /audit_events --spec`: уточнён состав деталей событий видеозвонков, `user_updated`, `bot_deleted` и `bot_token_recreated`
|
|
7
|
+
- **Изменено** (messages list): В примерах появился шаг сценария «Получить список активных тредов за период» — раньше он был спрятан в тексте описания шага
|
|
8
|
+
|
|
9
|
+
## 2026.7.2 (27 июля 2026)
|
|
10
|
+
|
|
11
|
+
- **Удалено** (files direct-url): Файл теперь добавляется в форму последним — S3 игнорирует поля после файла, из-за чего загрузка отклонялась с 400
|
|
12
|
+
- **Удалено**: Явный `--profile` больше не перебивается переменной `PACHCA_TOKEN` — команда с указанным профилем не уйдёт в чужое пространство
|
|
13
|
+
- **Удалено**: Запись (`POST`/`DELETE`/`PATCH`) больше не повторяется автоматически при 503 — повтор мог создать дубль сообщения
|
|
14
|
+
- **Удалено**: `Retry-After` в формате даты больше не игнорируется, значение ограничено разумным пределом
|
|
15
|
+
- **Удалено** (chats download-export): Имя файла из `Content-Disposition` больше не может увести запись за пределы указанной папки
|
|
16
|
+
- **Удалено**: Вывод `-o csv`: ячейки, начинающиеся с `=`, `+`, `-` или `@`, экранируются; объекты и массивы выводятся как JSON, а не `[object Object]`
|
|
17
|
+
- **Удалено**: `--timeout` меньше 1 отклоняется, а не приводит к мгновенной отмене запроса
|
|
18
|
+
- **Удалено**: Примеры в `--help` подписаны шагом сценария, а не общим заголовком (`reactions remove` больше не подписан «Добавить реакцию»)
|
|
19
|
+
- **Удалено** (files direct-url): Команда больше не падает с TypeError при успешной загрузке: S3 отвечает 204 с пустым телом, а команда пыталась прочитать из него поле
|
|
20
|
+
|
|
3
21
|
## 2026.7.1 (24 июля 2026)
|
|
4
22
|
|
|
5
23
|
- **Добавлено** (threads create): Новая команда — создание самостоятельного треда без привязки к сообщению
|
package/README.md
CHANGED
|
@@ -392,7 +392,7 @@ pachca autocomplete powershell # PowerShell completion
|
|
|
392
392
|
|
|
393
393
|
| Переменная | Описание |
|
|
394
394
|
|-----------|---------|
|
|
395
|
-
| `PACHCA_TOKEN` | Bearer
|
|
395
|
+
| `PACHCA_TOKEN` | Bearer-токен, удобно для CI. Приоритетнее профиля, но флаги `--token` и `--profile` его перебивают |
|
|
396
396
|
| `PACHCA_PROFILE` | Активный профиль для команды |
|
|
397
397
|
| `PACHCA_TIMEOUT` | Таймаут запроса в секундах (по умолчанию 30) |
|
|
398
398
|
| `PACHCA_PROMPT_DISABLED` | Отключить интерактивные промпты |
|
package/README.template.md
CHANGED
|
@@ -209,7 +209,7 @@ pachca autocomplete powershell # PowerShell completion
|
|
|
209
209
|
|
|
210
210
|
| Переменная | Описание |
|
|
211
211
|
|-----------|---------|
|
|
212
|
-
| `PACHCA_TOKEN` | Bearer
|
|
212
|
+
| `PACHCA_TOKEN` | Bearer-токен, удобно для CI. Приоритетнее профиля, но флаги `--token` и `--profile` его перебивают |
|
|
213
213
|
| `PACHCA_PROFILE` | Активный профиль для команды |
|
|
214
214
|
| `PACHCA_TIMEOUT` | Таймаут запроса в секундах (по умолчанию 30) |
|
|
215
215
|
| `PACHCA_PROMPT_DISABLED` | Отключить интерактивные промпты |
|
package/dist/base-command.js
CHANGED
|
@@ -53,6 +53,8 @@ export class BaseCommand extends Command {
|
|
|
53
53
|
}),
|
|
54
54
|
timeout: Flags.integer({
|
|
55
55
|
description: 'Request timeout in seconds',
|
|
56
|
+
// 0 or negative would abort on the next tick; fail loudly instead.
|
|
57
|
+
min: 1,
|
|
56
58
|
}),
|
|
57
59
|
'no-retry': Flags.boolean({
|
|
58
60
|
description: 'Disable auto-retry on 429/503',
|
package/dist/client.js
CHANGED
|
@@ -74,12 +74,35 @@ export function formatDryRun(opts, isJson) {
|
|
|
74
74
|
}
|
|
75
75
|
return lines.join('\n');
|
|
76
76
|
}
|
|
77
|
+
/** Longest we honour a server-supplied `Retry-After` before falling back. */
|
|
78
|
+
const MAX_RETRY_AFTER_MS = 60_000;
|
|
79
|
+
/**
|
|
80
|
+
* `Retry-After` in milliseconds. RFC 9110 allows both delta-seconds and an
|
|
81
|
+
* HTTP-date; parsing only the former turned a date into NaN and silently
|
|
82
|
+
* discarded the server's backoff. Negative and absurd values are clamped so a
|
|
83
|
+
* hostile or buggy header can neither hot-loop nor park the CLI for a day.
|
|
84
|
+
*/
|
|
85
|
+
function parseRetryAfter(header) {
|
|
86
|
+
if (!header)
|
|
87
|
+
return 1000;
|
|
88
|
+
const seconds = Number.parseInt(header, 10);
|
|
89
|
+
const ms = Number.isNaN(seconds) ? Date.parse(header) - Date.now() : seconds * 1000;
|
|
90
|
+
if (Number.isNaN(ms))
|
|
91
|
+
return 1000;
|
|
92
|
+
return Math.min(Math.max(ms, 0), MAX_RETRY_AFTER_MS);
|
|
93
|
+
}
|
|
77
94
|
export async function request(opts, clientFlags) {
|
|
78
95
|
const url = buildUrl(opts.path, opts.query);
|
|
79
96
|
const rawEnvTimeout = process.env.PACHCA_TIMEOUT ? Number(process.env.PACHCA_TIMEOUT) : undefined;
|
|
80
97
|
const envTimeout = rawEnvTimeout && !Number.isNaN(rawEnvTimeout) ? rawEnvTimeout : undefined;
|
|
81
|
-
const
|
|
98
|
+
const requestedTimeout = opts.timeout ?? clientFlags?.timeout ?? envTimeout ?? DEFAULT_TIMEOUT;
|
|
99
|
+
// A non-positive timeout aborts on the next tick, which is never what anyone
|
|
100
|
+
// means by `--timeout 0`. The env var already ignored 0; make the flag agree.
|
|
101
|
+
const timeoutSeconds = requestedTimeout > 0 ? requestedTimeout : DEFAULT_TIMEOUT;
|
|
82
102
|
const noRetry = opts.noRetry ?? clientFlags?.['no-retry'] ?? false;
|
|
103
|
+
// Retrying a request the server may already have committed duplicates it.
|
|
104
|
+
// Only these methods are safe to repeat blindly.
|
|
105
|
+
const safeMethod = ['GET', 'HEAD', 'OPTIONS', 'PUT'].includes(opts.method);
|
|
83
106
|
const fetchHeaders = {
|
|
84
107
|
...(opts.noAuth ? {} : { Authorization: `Bearer ${opts.token}` }),
|
|
85
108
|
Accept: 'application/json',
|
|
@@ -106,14 +129,21 @@ export async function request(opts, clientFlags) {
|
|
|
106
129
|
try {
|
|
107
130
|
const controller = new AbortController();
|
|
108
131
|
const timer = setTimeout(() => controller.abort(), timeoutSeconds * 1000);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
let response;
|
|
133
|
+
try {
|
|
134
|
+
response = await fetch(url, {
|
|
135
|
+
method: opts.method,
|
|
136
|
+
headers: fetchHeaders,
|
|
137
|
+
body: fetchBody,
|
|
138
|
+
signal: controller.signal,
|
|
139
|
+
redirect: opts.isRedirect ? 'manual' : 'follow',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
// Must run on reject too: a leaked timer keeps the event loop alive and
|
|
144
|
+
// the CLI hangs for the full timeout after an otherwise successful retry.
|
|
145
|
+
clearTimeout(timer);
|
|
146
|
+
}
|
|
117
147
|
if (clientFlags?.verbose) {
|
|
118
148
|
process.stderr.write(`${ansis.dim(`← ${response.status} ${response.statusText}`)}\n`);
|
|
119
149
|
}
|
|
@@ -127,19 +157,20 @@ export async function request(opts, clientFlags) {
|
|
|
127
157
|
headers: response.headers,
|
|
128
158
|
};
|
|
129
159
|
}
|
|
130
|
-
// Handle rate limiting (429)
|
|
160
|
+
// Handle rate limiting (429). Safe for any method: a throttled request
|
|
161
|
+
// was rejected before it was processed, so it cannot have been committed.
|
|
131
162
|
if (response.status === 429 && !noRetry && attempt < MAX_RETRIES) {
|
|
132
|
-
const
|
|
133
|
-
const parsed = retryAfter ? Number.parseInt(retryAfter, 10) : NaN;
|
|
134
|
-
const waitMs = Number.isNaN(parsed) ? 1000 : parsed * 1000;
|
|
163
|
+
const waitMs = parseRetryAfter(response.headers.get('retry-after'));
|
|
135
164
|
if (clientFlags?.verbose) {
|
|
136
165
|
process.stderr.write(`${ansis.dim(`⏳ Rate limited, retrying in ${waitMs}ms...`)}\n`);
|
|
137
166
|
}
|
|
138
167
|
await sleep(waitMs);
|
|
139
168
|
continue;
|
|
140
169
|
}
|
|
141
|
-
// Handle 503 with backoff
|
|
142
|
-
|
|
170
|
+
// Handle 503 with backoff. Unlike 429, a 503 from a proxy or a draining
|
|
171
|
+
// load balancer says nothing about whether the backend already committed
|
|
172
|
+
// the write — retrying a POST there duplicates the message.
|
|
173
|
+
if (response.status === 503 && safeMethod && !noRetry && attempt < MAX_RETRIES) {
|
|
143
174
|
const baseMs = 1000;
|
|
144
175
|
const waitMs = baseMs * Math.pow(2, attempt) + Math.random() * baseMs;
|
|
145
176
|
if (clientFlags?.verbose) {
|
|
@@ -184,7 +215,6 @@ export async function request(opts, clientFlags) {
|
|
|
184
215
|
}
|
|
185
216
|
lastError = error;
|
|
186
217
|
// Only retry network errors for idempotent methods (not POST/DELETE)
|
|
187
|
-
const safeMethod = ['GET', 'HEAD', 'OPTIONS', 'PUT'].includes(opts.method);
|
|
188
218
|
if (!safeMethod || noRetry || attempt >= MAX_RETRIES) {
|
|
189
219
|
break;
|
|
190
220
|
}
|
|
@@ -292,7 +322,11 @@ export async function downloadFile(url, savePath) {
|
|
|
292
322
|
const urlPath = new URL(url).pathname;
|
|
293
323
|
filename = path.basename(urlPath.split('?')[0]);
|
|
294
324
|
}
|
|
295
|
-
|
|
325
|
+
// Strip any directory part: the name comes from a Content-Disposition on
|
|
326
|
+
// a redirect target outside our trust boundary, and `../../..` in it would
|
|
327
|
+
// otherwise let the response choose where on disk to write.
|
|
328
|
+
filename = path.basename(filename);
|
|
329
|
+
if (!filename || filename === '.' || filename === '..')
|
|
296
330
|
filename = 'download';
|
|
297
331
|
if (!fs.existsSync(savePath)) {
|
|
298
332
|
throw new Error(`Directory does not exist: ${savePath}`);
|
|
@@ -5,8 +5,8 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class BotsCreate extends BaseCommand {
|
|
6
6
|
static description = "Новый бот";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Создать бота через API и получить
|
|
9
|
-
"Настроить бота с исходящим
|
|
8
|
+
"Создать бота через API и получить токен — Создай бота. Только пользовательским токеном (не токеном бота); `nickname` обязан заканчиваться на `_bot`. Параметры вебхука (Webhook URL, события, команды) можно задать сразу или позже. Скоупы токена бота можно ограничить флагом `--scopes` (если не указать — бот получит набор по умолчанию):\n $ pachca bots create",
|
|
9
|
+
"Настроить бота с исходящим вебхуком — Создай бота, сразу указав Webhook URL и события в одном вызове (детали создания и работы с токеном — в сценарии «Создать бота через API и получить токен»):\n $ pachca bots create"
|
|
10
10
|
];
|
|
11
11
|
static scope = "bots:write";
|
|
12
12
|
static apiMethod = "POST";
|
|
@@ -35,7 +35,7 @@ export default class BotsCreate extends BaseCommand {
|
|
|
35
35
|
description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands. Суммарная длина команд, объединённых через запятую, не должна превышать 255 символов.",
|
|
36
36
|
}),
|
|
37
37
|
'scopes': Flags.string({
|
|
38
|
-
description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию.",
|
|
38
|
+
description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию. Боту доступны не все скоупы: часть из них разрешена только пользовательским ролям, и попытка назначить такой скоуп возвращает `400`. Служебные значения `bot` и `all` назначать нельзя.",
|
|
39
39
|
}),
|
|
40
40
|
'template': Flags.string({
|
|
41
41
|
description: "Шаблон форматирования входящего вебхука",
|
|
@@ -137,7 +137,7 @@ export default class BotsCreate extends BaseCommand {
|
|
|
137
137
|
path: '/bots',
|
|
138
138
|
body,
|
|
139
139
|
});
|
|
140
|
-
const responseBody = data;
|
|
140
|
+
const responseBody = (data ?? {});
|
|
141
141
|
const result = responseBody.data ?? responseBody;
|
|
142
142
|
this.output(result);
|
|
143
143
|
}
|
|
@@ -5,7 +5,7 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class BotsDelete extends BaseCommand {
|
|
6
6
|
static description = "Удаление бота";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Найти и удалить
|
|
8
|
+
"Найти и удалить бота — Возьми `id` нужного бота из списка и удали его (скоуп `bots:write`). Доступно администратору, владельцу компании или создателю бота — владельцы чатов удалять бота не могут. Прежний токен инвалидируется сразу, бот исключается из всех чатов, его исходящий вебхук удаляется:\n $ pachca bots delete"
|
|
9
9
|
];
|
|
10
10
|
static scope = "bots:write";
|
|
11
11
|
static apiMethod = "DELETE";
|
|
@@ -4,7 +4,7 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class BotsListEvents extends BaseCommand {
|
|
5
5
|
static description = "История событий";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Обработка событий через историю (polling)
|
|
7
|
+
"Обработка событий через историю (polling) — Получи накопленные события:\n $ pachca bots list-events"
|
|
8
8
|
];
|
|
9
9
|
static scope = "webhooks:events:read";
|
|
10
10
|
static apiMethod = "GET";
|
|
@@ -85,7 +85,7 @@ export default class BotsListEvents extends BaseCommand {
|
|
|
85
85
|
cursor: flags.cursor,
|
|
86
86
|
},
|
|
87
87
|
});
|
|
88
|
-
const responseBody = data;
|
|
88
|
+
const responseBody = (data ?? {});
|
|
89
89
|
const items = responseBody.data ?? responseBody;
|
|
90
90
|
this.output(items);
|
|
91
91
|
}
|
|
@@ -4,7 +4,7 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class BotsList extends BaseCommand {
|
|
5
5
|
static description = "Список ботов";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Найти и удалить
|
|
7
|
+
"Найти и удалить бота — Пользовательским токеном (скоуп `bots:read`) получи список ботов, доступных тебе для редактирования: созданных тобой и тех, чьи настройки открывают тебе доступ. Фильтруй по имени параметром `query`, следующую страницу бери из `meta.paginate.next_page`:\n $ pachca bots list"
|
|
8
8
|
];
|
|
9
9
|
static scope = "bots:read";
|
|
10
10
|
static apiMethod = "GET";
|
|
@@ -90,7 +90,7 @@ export default class BotsList extends BaseCommand {
|
|
|
90
90
|
cursor: flags.cursor,
|
|
91
91
|
},
|
|
92
92
|
});
|
|
93
|
-
const responseBody = data;
|
|
93
|
+
const responseBody = (data ?? {});
|
|
94
94
|
const items = responseBody.data ?? responseBody;
|
|
95
95
|
this.output(items);
|
|
96
96
|
}
|
|
@@ -2,7 +2,7 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
2
2
|
export default class BotsRecreateTokenSelf extends BaseCommand {
|
|
3
3
|
static description = "Ротация собственного токена бота";
|
|
4
4
|
static examples = [
|
|
5
|
-
"Ротация токена
|
|
5
|
+
"Ротация токена бота — Или: бот перевыпускает собственный токен своим же токеном (скоуп `bot_self:write`). Токен, которым выполнен запрос, инвалидируется сразу — обязательно сохрани новый `access_token` из ответа, иначе бот потеряет доступ к API:\n $ pachca bots recreate-token-self"
|
|
6
6
|
];
|
|
7
7
|
static scope = "bot_self:write";
|
|
8
8
|
static apiMethod = "POST";
|
|
@@ -19,7 +19,7 @@ export default class BotsRecreateTokenSelf extends BaseCommand {
|
|
|
19
19
|
method: 'POST',
|
|
20
20
|
path: '/bot/recreate_token',
|
|
21
21
|
});
|
|
22
|
-
const responseBody = data;
|
|
22
|
+
const responseBody = (data ?? {});
|
|
23
23
|
const result = responseBody.data ?? responseBody;
|
|
24
24
|
this.output(result);
|
|
25
25
|
}
|
|
@@ -4,7 +4,7 @@ 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";
|
|
@@ -26,7 +26,7 @@ export default class BotsRecreateToken extends BaseCommand {
|
|
|
26
26
|
method: 'POST',
|
|
27
27
|
path: `/bots/${args.id}/recreate_token`,
|
|
28
28
|
});
|
|
29
|
-
const responseBody = data;
|
|
29
|
+
const responseBody = (data ?? {});
|
|
30
30
|
const result = responseBody.data ?? responseBody;
|
|
31
31
|
this.output(result);
|
|
32
32
|
}
|
|
@@ -5,7 +5,7 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class BotsRemoveEvent extends BaseCommand {
|
|
6
6
|
static description = "Удаление события";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Обработка событий через историю (polling)
|
|
8
|
+
"Обработка событий через историю (polling) — Удали обработанное событие:\n $ pachca bots remove-event"
|
|
9
9
|
];
|
|
10
10
|
static scope = "webhooks:events:delete";
|
|
11
11
|
static apiMethod = "DELETE";
|
|
@@ -5,7 +5,7 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class BotsUpdateWebhook extends BaseCommand {
|
|
6
6
|
static description = "Саморегистрация вебхука бота";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Обновить Webhook URL
|
|
8
|
+
"Обновить Webhook URL бота — Или: бот сам обновляет свой webhook своим же токеном — без `id` и без участия администратора (нужен скоуп `bot_self:webhook:write`):\n $ pachca bots update-webhook"
|
|
9
9
|
];
|
|
10
10
|
static scope = "bot_self:webhook:write";
|
|
11
11
|
static apiMethod = "PUT";
|
|
@@ -65,7 +65,7 @@ export default class BotsUpdateWebhook extends BaseCommand {
|
|
|
65
65
|
path: '/bot/webhook',
|
|
66
66
|
body,
|
|
67
67
|
});
|
|
68
|
-
const responseBody = data;
|
|
68
|
+
const responseBody = (data ?? {});
|
|
69
69
|
const result = responseBody.data ?? responseBody;
|
|
70
70
|
this.output(result);
|
|
71
71
|
}
|
|
@@ -4,7 +4,7 @@ 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
|
|
7
|
+
"Обновить Webhook URL бота — Пользовательским токеном (с правом редактировать бота) — обнови URL по `id` бота. Пустая строка отключает вебхук:\n $ pachca bots update"
|
|
8
8
|
];
|
|
9
9
|
static scope = "bots:write";
|
|
10
10
|
static apiMethod = "PUT";
|
|
@@ -37,7 +37,7 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
37
37
|
description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands. Суммарная длина команд, объединённых через запятую, не должна превышать 255 символов.",
|
|
38
38
|
}),
|
|
39
39
|
'scopes': Flags.string({
|
|
40
|
-
description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию.",
|
|
40
|
+
description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию. Боту доступны не все скоупы: часть из них разрешена только пользовательским ролям, и попытка назначить такой скоуп возвращает `400`. Служебные значения `bot` и `all` назначать нельзя.",
|
|
41
41
|
}),
|
|
42
42
|
'template': Flags.string({
|
|
43
43
|
description: "Шаблон форматирования входящего вебхука",
|
|
@@ -111,7 +111,7 @@ export default class BotsUpdate extends BaseCommand {
|
|
|
111
111
|
path: `/bots/${args.id}`,
|
|
112
112
|
body,
|
|
113
113
|
});
|
|
114
|
-
const responseBody = data;
|
|
114
|
+
const responseBody = (data ?? {});
|
|
115
115
|
const result = responseBody.data ?? responseBody;
|
|
116
116
|
this.output(result);
|
|
117
117
|
}
|
|
@@ -4,8 +4,8 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class ChatsArchive extends BaseCommand {
|
|
5
5
|
static description = "Архивация чата";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Архивация и управление
|
|
8
|
-
"Найти и заархивировать неактивные
|
|
7
|
+
"Архивация и управление чатом — Архивировать чат:\n $ pachca chats archive",
|
|
8
|
+
"Найти и заархивировать неактивные чаты — Для каждого чата: архивируй:\n $ pachca chats archive"
|
|
9
9
|
];
|
|
10
10
|
static scope = "chats:archive";
|
|
11
11
|
static apiMethod = "PUT";
|
|
@@ -26,7 +26,7 @@ export default class ChatsArchive extends BaseCommand {
|
|
|
26
26
|
method: 'PUT',
|
|
27
27
|
path: `/chats/${args.id}/archive`,
|
|
28
28
|
});
|
|
29
|
-
const responseBody = data;
|
|
29
|
+
const responseBody = (data ?? {});
|
|
30
30
|
const result = responseBody.data ?? responseBody;
|
|
31
31
|
this.output(result);
|
|
32
32
|
}
|
|
@@ -5,8 +5,8 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class ChatsCreate extends BaseCommand {
|
|
6
6
|
static description = "Новый чат";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Создать канал и пригласить
|
|
9
|
-
"Создать проектную беседу из
|
|
8
|
+
"Создать канал и пригласить участников — Создай канал с участниками:\n $ pachca chats create",
|
|
9
|
+
"Создать проектную беседу из шаблона — Создай беседу с участниками из тега:\n $ pachca chats create"
|
|
10
10
|
];
|
|
11
11
|
static scope = "chats:create";
|
|
12
12
|
static apiMethod = "POST";
|
|
@@ -88,7 +88,7 @@ export default class ChatsCreate extends BaseCommand {
|
|
|
88
88
|
path: '/chats',
|
|
89
89
|
body,
|
|
90
90
|
});
|
|
91
|
-
const responseBody = data;
|
|
91
|
+
const responseBody = (data ?? {});
|
|
92
92
|
const result = responseBody.data ?? responseBody;
|
|
93
93
|
this.output(result);
|
|
94
94
|
}
|
|
@@ -6,7 +6,7 @@ import { formatSize } from '../../utils.js';
|
|
|
6
6
|
export default class ChatsDownloadExport extends BaseCommand {
|
|
7
7
|
static description = "Скачать архив экспорта";
|
|
8
8
|
static examples = [
|
|
9
|
-
"Экспорт истории
|
|
9
|
+
"Экспорт истории чата — Скачай файл экспорта:\n $ pachca chats download-export"
|
|
10
10
|
];
|
|
11
11
|
static hiddenAliases = ["common:get-exports"];
|
|
12
12
|
static scope = "chat_exports:read";
|
|
@@ -39,7 +39,7 @@ export default class ChatsDownloadExport extends BaseCommand {
|
|
|
39
39
|
this.success(`Сохранено: ${flags.save} (${formatSize(result.size)})`);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
const responseBody = data;
|
|
42
|
+
const responseBody = (data ?? {});
|
|
43
43
|
const result = responseBody.data ?? responseBody;
|
|
44
44
|
this.output(result);
|
|
45
45
|
}
|
|
@@ -4,9 +4,9 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class ChatsList extends BaseCommand {
|
|
5
5
|
static description = "Список чатов";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Найти активные чаты за
|
|
8
|
-
"Найти и заархивировать неактивные
|
|
9
|
-
"Создать гостя в
|
|
7
|
+
"Найти активные чаты за период — Получи чаты с активностью после указанной даты:\n $ pachca chats list",
|
|
8
|
+
"Найти и заархивировать неактивные чаты — Получи чаты без активности с нужной даты:\n $ pachca chats list",
|
|
9
|
+
"Создать гостя в чат — Выбери активный чат, в который добавить гостя — узнай его ID:\n $ pachca chats list"
|
|
10
10
|
];
|
|
11
11
|
static scope = "chats:read";
|
|
12
12
|
static apiMethod = "GET";
|
|
@@ -124,7 +124,7 @@ export default class ChatsList extends BaseCommand {
|
|
|
124
124
|
cursor: flags.cursor,
|
|
125
125
|
},
|
|
126
126
|
});
|
|
127
|
-
const responseBody = data;
|
|
127
|
+
const responseBody = (data ?? {});
|
|
128
128
|
const items = responseBody.data ?? responseBody;
|
|
129
129
|
this.output(items);
|
|
130
130
|
}
|
|
@@ -5,7 +5,7 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class ChatsRequestExport extends BaseCommand {
|
|
6
6
|
static description = "Экспорт сообщений";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Экспорт истории
|
|
8
|
+
"Экспорт истории чата — Запроси экспорт:\n $ pachca chats request-export"
|
|
9
9
|
];
|
|
10
10
|
static hiddenAliases = ["common:request-export"];
|
|
11
11
|
static scope = "chat_exports:write";
|
|
@@ -81,7 +81,7 @@ export default class ChatsRequestExport extends BaseCommand {
|
|
|
81
81
|
path: '/chats/exports',
|
|
82
82
|
body,
|
|
83
83
|
});
|
|
84
|
-
const responseBody = data;
|
|
84
|
+
const responseBody = (data ?? {});
|
|
85
85
|
const result = responseBody.data ?? responseBody;
|
|
86
86
|
this.output(result);
|
|
87
87
|
}
|
|
@@ -4,7 +4,7 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class ChatsUnarchive extends BaseCommand {
|
|
5
5
|
static description = "Разархивация чата";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Архивация и управление
|
|
7
|
+
"Архивация и управление чатом — Разархивировать чат:\n $ pachca chats unarchive"
|
|
8
8
|
];
|
|
9
9
|
static scope = "chats:archive";
|
|
10
10
|
static apiMethod = "PUT";
|
|
@@ -25,7 +25,7 @@ export default class ChatsUnarchive extends BaseCommand {
|
|
|
25
25
|
method: 'PUT',
|
|
26
26
|
path: `/chats/${args.id}/unarchive`,
|
|
27
27
|
});
|
|
28
|
-
const responseBody = data;
|
|
28
|
+
const responseBody = (data ?? {});
|
|
29
29
|
const result = responseBody.data ?? responseBody;
|
|
30
30
|
this.output(result);
|
|
31
31
|
}
|
|
@@ -4,7 +4,7 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
export default class ChatsUpdate extends BaseCommand {
|
|
5
5
|
static description = "Редактирование чата";
|
|
6
6
|
static examples = [
|
|
7
|
-
"Переименовать или обновить чат:\n $ pachca chats update"
|
|
7
|
+
"Переименовать или обновить чат — Обнови чат:\n $ pachca chats update"
|
|
8
8
|
];
|
|
9
9
|
static scope = "chats:update";
|
|
10
10
|
static apiMethod = "PUT";
|
|
@@ -54,7 +54,7 @@ export default class ChatsUpdate extends BaseCommand {
|
|
|
54
54
|
path: `/chats/${args.id}`,
|
|
55
55
|
body,
|
|
56
56
|
});
|
|
57
|
-
const responseBody = data;
|
|
57
|
+
const responseBody = (data ?? {});
|
|
58
58
|
const result = responseBody.data ?? responseBody;
|
|
59
59
|
this.output(result);
|
|
60
60
|
}
|
|
@@ -5,7 +5,7 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class CustomPropertiesList extends BaseCommand {
|
|
6
6
|
static description = "Список дополнительных полей";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Получить кастомные поля
|
|
8
|
+
"Получить кастомные поля профиля — Получи список дополнительных полей для сотрудников:\n $ pachca custom-properties list"
|
|
9
9
|
];
|
|
10
10
|
static hiddenAliases = ["common:custom-properties"];
|
|
11
11
|
static scope = "custom_properties:read";
|
|
@@ -57,7 +57,7 @@ export default class CustomPropertiesList extends BaseCommand {
|
|
|
57
57
|
'entity_type': flags['entity-type'],
|
|
58
58
|
},
|
|
59
59
|
});
|
|
60
|
-
const responseBody = data;
|
|
60
|
+
const responseBody = (data ?? {});
|
|
61
61
|
const result = responseBody.data ?? responseBody;
|
|
62
62
|
this.output(result);
|
|
63
63
|
}
|
|
@@ -84,17 +84,6 @@ export default class FilesDirectUrl extends BaseCommand {
|
|
|
84
84
|
let formData;
|
|
85
85
|
if (flags.file) {
|
|
86
86
|
formData = new FormData();
|
|
87
|
-
if (flags.file === '-') {
|
|
88
|
-
const chunks = [];
|
|
89
|
-
for await (const chunk of process.stdin)
|
|
90
|
-
chunks.push(chunk);
|
|
91
|
-
const blob = new Blob([Buffer.concat(chunks)]);
|
|
92
|
-
formData.append('file', blob, 'stdin');
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
const blob = new Blob([fs.readFileSync(flags.file)]);
|
|
96
|
-
formData.append('file', blob, path.basename(flags.file));
|
|
97
|
-
}
|
|
98
87
|
if (flags['content-disposition'])
|
|
99
88
|
formData.append('Content-Disposition', String(flags['content-disposition']));
|
|
100
89
|
if (flags['acl'])
|
|
@@ -111,6 +100,17 @@ export default class FilesDirectUrl extends BaseCommand {
|
|
|
111
100
|
formData.append('x-amz-signature', String(flags['x-amz-signature']));
|
|
112
101
|
if (flags['key'])
|
|
113
102
|
formData.append('key', String(flags['key']));
|
|
103
|
+
if (flags.file === '-') {
|
|
104
|
+
const chunks = [];
|
|
105
|
+
for await (const chunk of process.stdin)
|
|
106
|
+
chunks.push(chunk);
|
|
107
|
+
const blob = new Blob([Buffer.concat(chunks)]);
|
|
108
|
+
formData.append('file', blob, 'stdin');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const blob = new Blob([fs.readFileSync(flags.file)]);
|
|
112
|
+
formData.append('file', blob, path.basename(flags.file));
|
|
113
|
+
}
|
|
114
114
|
}
|
|
115
115
|
const { data } = await this.apiRequest({
|
|
116
116
|
method: 'POST',
|
|
@@ -118,7 +118,7 @@ export default class FilesDirectUrl extends BaseCommand {
|
|
|
118
118
|
formData,
|
|
119
119
|
noAuth: true,
|
|
120
120
|
});
|
|
121
|
-
const responseBody = data;
|
|
121
|
+
const responseBody = (data ?? {});
|
|
122
122
|
const result = responseBody.data ?? responseBody;
|
|
123
123
|
this.output(result);
|
|
124
124
|
}
|
|
@@ -2,7 +2,7 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
2
2
|
export default class FilesUploads extends BaseCommand {
|
|
3
3
|
static description = "Получение подписи, ключа и других параметров";
|
|
4
4
|
static examples = [
|
|
5
|
-
"Изменить вложения
|
|
5
|
+
"Изменить вложения сообщения — Если нужно добавить новый файл — загрузи его:\n $ pachca files uploads"
|
|
6
6
|
];
|
|
7
7
|
static hiddenAliases = ["common:uploads"];
|
|
8
8
|
static scope = "uploads:write";
|
|
@@ -20,7 +20,7 @@ export default class FilesUploads extends BaseCommand {
|
|
|
20
20
|
method: 'POST',
|
|
21
21
|
path: '/uploads',
|
|
22
22
|
});
|
|
23
|
-
const responseBody = data;
|
|
23
|
+
const responseBody = (data ?? {});
|
|
24
24
|
const result = responseBody.data ?? responseBody;
|
|
25
25
|
this.output(result);
|
|
26
26
|
}
|
|
@@ -5,7 +5,7 @@ import * as clack from '@clack/prompts';
|
|
|
5
5
|
export default class GroupTagsCreate extends BaseCommand {
|
|
6
6
|
static description = "Новый тег";
|
|
7
7
|
static examples = [
|
|
8
|
-
"Массовое создание сотрудников с
|
|
8
|
+
"Массовое создание сотрудников с тегами — Создай тег (если нужен):\n $ pachca group-tags create"
|
|
9
9
|
];
|
|
10
10
|
static scope = "group_tags:write";
|
|
11
11
|
static apiMethod = "POST";
|
|
@@ -69,7 +69,7 @@ export default class GroupTagsCreate extends BaseCommand {
|
|
|
69
69
|
path: '/group_tags',
|
|
70
70
|
body,
|
|
71
71
|
});
|
|
72
|
-
const responseBody = data;
|
|
72
|
+
const responseBody = (data ?? {});
|
|
73
73
|
const result = responseBody.data ?? responseBody;
|
|
74
74
|
this.output(result);
|
|
75
75
|
}
|
|
@@ -23,7 +23,7 @@ export default class GroupTagsGet extends BaseCommand {
|
|
|
23
23
|
method: 'GET',
|
|
24
24
|
path: `/group_tags/${args.id}`,
|
|
25
25
|
});
|
|
26
|
-
const responseBody = data;
|
|
26
|
+
const responseBody = (data ?? {});
|
|
27
27
|
const result = responseBody.data ?? responseBody;
|
|
28
28
|
this.output(result);
|
|
29
29
|
}
|