@pachca/cli 2026.10.2 → 2026.10.4
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 +41 -0
- package/README.md +29 -29
- package/README.template.md +19 -28
- package/dist/base-command.js +69 -37
- package/dist/client.js +58 -33
- package/dist/commands/api.js +4 -4
- package/dist/commands/auth/login.js +12 -9
- package/dist/commands/auth/logout.js +23 -12
- package/dist/commands/bots/create-token.js +0 -3
- package/dist/commands/bots/create.js +1 -5
- package/dist/commands/bots/delete.js +0 -3
- package/dist/commands/bots/get-stream.js +23 -0
- package/dist/commands/bots/list-company.js +4 -5
- package/dist/commands/bots/list-events.js +4 -5
- package/dist/commands/bots/list-scopes.js +0 -3
- package/dist/commands/bots/list-tokens.js +4 -2
- package/dist/commands/bots/list.js +4 -5
- package/dist/commands/bots/recreate-token-self.js +0 -3
- package/dist/commands/bots/recreate-token.js +0 -3
- package/dist/commands/bots/reissue-token.js +0 -3
- package/dist/commands/bots/remove-event.js +0 -3
- package/dist/commands/bots/update-webhook.js +0 -3
- package/dist/commands/bots/update.js +4 -8
- package/dist/commands/chats/archive.js +0 -4
- package/dist/commands/chats/create.js +3 -6
- package/dist/commands/chats/download-export.js +0 -3
- package/dist/commands/chats/list-company.js +4 -5
- package/dist/commands/chats/list.js +5 -8
- package/dist/commands/chats/remove-avatar.js +0 -3
- package/dist/commands/chats/request-export.js +0 -3
- package/dist/commands/chats/unarchive.js +0 -3
- package/dist/commands/chats/update-avatar.js +0 -3
- package/dist/commands/chats/update.js +0 -3
- package/dist/commands/custom-properties/list.js +0 -3
- package/dist/commands/doctor.js +60 -35
- package/dist/commands/drafts/create.js +6 -6
- package/dist/commands/drafts/delete.js +0 -3
- package/dist/commands/drafts/list.js +4 -2
- package/dist/commands/drafts/update.js +7 -4
- package/dist/commands/files/uploads.js +0 -3
- package/dist/commands/group-tags/create.js +0 -3
- package/dist/commands/group-tags/list-users.js +4 -5
- package/dist/commands/group-tags/list.js +4 -5
- package/dist/commands/important-messages/create.js +64 -0
- package/dist/commands/important-messages/delete.js +42 -0
- package/dist/commands/important-messages/list.js +91 -0
- package/dist/commands/members/add.js +1 -6
- package/dist/commands/members/leave.js +0 -3
- package/dist/commands/members/list.js +4 -6
- package/dist/commands/members/remove.js +0 -3
- package/dist/commands/members/update.js +0 -3
- package/dist/commands/messages/create.js +6 -9
- package/dist/commands/messages/delete.js +0 -3
- package/dist/commands/messages/get.js +0 -5
- package/dist/commands/messages/list.js +5 -7
- package/dist/commands/messages/pin.js +0 -3
- package/dist/commands/messages/unfurl.js +0 -3
- package/dist/commands/messages/unpin.js +0 -3
- package/dist/commands/messages/update.js +5 -8
- package/dist/commands/oauth/token-info.js +0 -3
- package/dist/commands/profile/delete-avatar.js +0 -3
- package/dist/commands/profile/delete-status.js +0 -3
- package/dist/commands/profile/get.js +0 -4
- package/dist/commands/profile/update-avatar.js +0 -3
- package/dist/commands/profile/update-status.js +1 -4
- package/dist/commands/reactions/add.js +3 -6
- package/dist/commands/reactions/list.js +4 -2
- package/dist/commands/reactions/remove.js +3 -6
- package/dist/commands/read-member/list-readers.js +4 -5
- package/dist/commands/search/list-chats.js +4 -7
- package/dist/commands/search/list-messages.js +4 -5
- package/dist/commands/search/list-users.js +4 -7
- package/dist/commands/security/list.js +4 -7
- package/dist/commands/tasks/create.js +4 -7
- package/dist/commands/tasks/delete.js +0 -3
- package/dist/commands/tasks/get.js +0 -3
- package/dist/commands/tasks/list.js +4 -7
- package/dist/commands/tasks/update.js +5 -7
- package/dist/commands/threads/add.js +0 -4
- package/dist/commands/threads/list.js +4 -6
- package/dist/commands/upload.js +27 -8
- package/dist/commands/users/create.js +0 -5
- package/dist/commands/users/delete.js +0 -3
- package/dist/commands/users/get-status.js +0 -3
- package/dist/commands/users/get.js +0 -3
- package/dist/commands/users/list.js +4 -7
- package/dist/commands/users/remove-avatar.js +0 -3
- package/dist/commands/users/remove-status.js +0 -3
- package/dist/commands/users/update-avatar.js +0 -3
- package/dist/commands/users/update-status.js +1 -4
- package/dist/commands/users/update.js +5 -5
- package/dist/commands/views/open.js +1 -5
- package/dist/commands/views/submit-response.js +0 -3
- package/dist/data/alternatives.json +5 -9
- package/dist/data/changelog.json +177 -0
- package/dist/data/endpoints.json +1 -1
- package/dist/help.js +0 -1
- package/dist/hooks/command-not-found.js +0 -1
- package/dist/hooks/init.js +13 -5
- package/dist/lib/flags.js +25 -0
- package/dist/oauth.js +11 -5
- package/dist/profiles.js +22 -4
- package/dist/token-refresh.js +61 -14
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
- package/dist/commands/guide.js +0 -90
- package/dist/data/workflows.json +0 -1058
|
@@ -4,18 +4,13 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MembersAdd extends BaseCommand {
|
|
6
6
|
static description = "Добавление участников";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Подписаться на тред сообщения — Добавь бота в участники чата треда:\n $ pachca members add",
|
|
9
|
-
"Создать канал и пригласить участников — Или добавь участников позже:\n $ pachca members add",
|
|
10
|
-
"Онбординг нового сотрудника — Добавь в нужные каналы:\n $ pachca members add"
|
|
11
|
-
];
|
|
12
7
|
static scope = "chat_members:write";
|
|
13
8
|
static apiMethod = "POST";
|
|
14
9
|
static apiPath = "/chats/{id}/members";
|
|
15
10
|
static requiredFlags = ["member-ids"];
|
|
16
11
|
static args = {
|
|
17
12
|
id: Args.integer({
|
|
18
|
-
description: "Идентификатор чата (беседа, канал или чат треда)",
|
|
13
|
+
description: "Идентификатор чата (беседа, канал или чат треда). В тред метод добавляет всех обычными участниками и без уведомления, поэтому упомяните добавленных в сообщении треда. Сотрудников не из родительского чата он добавляет туда при любой настройке «Использовать сквозные треды».",
|
|
19
14
|
required: true,
|
|
20
15
|
}),
|
|
21
16
|
};
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MembersLeave extends BaseCommand {
|
|
6
6
|
static description = "Выход из чата";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Архивация и управление чатом — Покинуть чат:\n $ pachca members leave"
|
|
9
|
-
];
|
|
10
7
|
static scope = "chats:leave";
|
|
11
8
|
static apiMethod = "DELETE";
|
|
12
9
|
static apiPath = "/chats/{id}/leave";
|
|
@@ -3,10 +3,6 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class MembersList extends BaseCommand {
|
|
5
5
|
static description = "Список участников чата";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Упомянуть пользователя — Ищи среди участников целевого чата:\n $ pachca members list",
|
|
8
|
-
"Упомянуть пользователя — Если пишешь в тред: также проверь участников родительского чата:\n $ pachca members list"
|
|
9
|
-
];
|
|
10
6
|
static scope = "chat_members:read";
|
|
11
7
|
static apiMethod = "GET";
|
|
12
8
|
static apiPath = "/chats/{id}/members";
|
|
@@ -44,6 +40,7 @@ export default class MembersList extends BaseCommand {
|
|
|
44
40
|
let nextCursor = undefined;
|
|
45
41
|
let pages = 0;
|
|
46
42
|
const seenCursors = new Set();
|
|
43
|
+
let total;
|
|
47
44
|
while (pages < 500) {
|
|
48
45
|
const query = {
|
|
49
46
|
role: flags['role'],
|
|
@@ -59,7 +56,7 @@ export default class MembersList extends BaseCommand {
|
|
|
59
56
|
const paginate = meta?.paginate;
|
|
60
57
|
nextCursor = paginate?.next_page;
|
|
61
58
|
pages++;
|
|
62
|
-
// Условие конца:
|
|
59
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
63
60
|
const hasNext = paginate?.has_next;
|
|
64
61
|
if (typeof hasNext === 'boolean') {
|
|
65
62
|
if (!hasNext)
|
|
@@ -69,7 +66,8 @@ export default class MembersList extends BaseCommand {
|
|
|
69
66
|
break;
|
|
70
67
|
}
|
|
71
68
|
if (process.stderr.isTTY) {
|
|
72
|
-
|
|
69
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
70
|
+
total ??= meta?.total;
|
|
73
71
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
74
72
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
75
73
|
}
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MembersRemove extends BaseCommand {
|
|
6
6
|
static description = "Исключение участника";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Архивация и управление чатом — Удалить участника:\n $ pachca members remove"
|
|
9
|
-
];
|
|
10
7
|
static scope = "chat_members:write";
|
|
11
8
|
static apiMethod = "DELETE";
|
|
12
9
|
static apiPath = "/chats/{id}/members/{user_id}";
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MembersUpdate extends BaseCommand {
|
|
6
6
|
static description = "Редактирование роли участника";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Архивация и управление чатом — Изменить роль участника:\n $ pachca members update"
|
|
9
|
-
];
|
|
10
7
|
static scope = "chat_members:write";
|
|
11
8
|
static apiMethod = "PUT";
|
|
12
9
|
static apiPath = "/chats/{id}/members/{user_id}";
|
|
@@ -4,11 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MessagesCreate extends BaseCommand {
|
|
6
6
|
static description = "Новое сообщение";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Найти чат по имени и отправить сообщение — Отправь сообщение в найденный чат:\n $ pachca messages create",
|
|
9
|
-
"Отправить сообщение в канал или беседу (если chat_id известен) — Отправь сообщение в чат:\n $ pachca messages create",
|
|
10
|
-
"Отправить личное сообщение пользователю — Отправь личное сообщение:\n $ pachca messages create"
|
|
11
|
-
];
|
|
12
7
|
static scope = "messages:create";
|
|
13
8
|
static apiMethod = "POST";
|
|
14
9
|
static apiPath = "/messages";
|
|
@@ -24,13 +19,13 @@ export default class MessagesCreate extends BaseCommand {
|
|
|
24
19
|
description: "Идентификатор того, что названо в `entity_type`: беседы или канала, треда либо пользователя. У треда их два: `id` треда указывают с `entity_type: \"thread\"`, а его `chat_id` — с `discussion`, как у любого чата. (pachca chats list | pachca users list)",
|
|
25
20
|
}),
|
|
26
21
|
'content': Flags.string({
|
|
27
|
-
description: "Текст сообщения. Обязателен, если к сообщению не приложены файлы. Поддерживает упоминания: `@nickname` или `<@user_id>` (будет автоматически преобразовано в `@nickname`). `@all` упоминает всех участников чата, `@here` — тех, кто сейчас в сети, а `@` с названием тега без пробелов — сотрудников этого тега. Имя без `@` и упоминание внутри строчного кода или блока кода упоминанием не считаются. У мульти-гостя `<@user_id>` недоступного ему сотрудника остаётся в тексте как есть. До 40 000 байт в UTF-8, для кириллицы это около 20 000 символов.
|
|
22
|
+
description: "Текст сообщения. Обязателен, если к сообщению не приложены файлы. Поддерживает упоминания: `@nickname` или `<@user_id>` (будет автоматически преобразовано в `@nickname`). Ник берут из ответа метода, а `user_id` — из данных: ник, составленный из имени, никого не упоминает. `@all` упоминает всех участников чата, `@here` — тех, кто сейчас в сети, а `@` с названием тега без пробелов — сотрудников этого тега. Имя без `@` и упоминание внутри строчного кода или блока кода упоминанием не считаются. У мульти-гостя `<@user_id>` недоступного ему сотрудника остаётся в тексте как есть. До 40 000 байт в UTF-8, для кириллицы это около 20 000 символов. Сообщение уходит под именем владельца токена, у бота — с бейджем «Бот».",
|
|
28
23
|
}),
|
|
29
24
|
'files': Flags.string({
|
|
30
25
|
description: "Прикрепляемые файлы",
|
|
31
26
|
}),
|
|
32
27
|
'buttons': Flags.string({
|
|
33
|
-
description: "Массив строк, каждая из которых представлена массивом кнопок. Максимум 100 кнопок у сообщения, до 8 кнопок в строке. Кнопки показываются под
|
|
28
|
+
description: "Массив строк, каждая из которых представлена массивом кнопок. Максимум 100 кнопок у сообщения, до 8 кнопок в строке. Кнопки показываются под текстом. Кнопка с `url` ведёт по ссылке, кто бы ни отправил сообщение, и события не создаёт. Кнопка с `data` работает в сообщении бота: нажатие на неё приходит событием `button_click` тому боту, который отправил сообщение, а вместе с ним `trigger_id` — на открытие формы по нему есть 3 секунды, метод [Открытие представления](POST /views/open). Подробности — в разделе [Кнопки](https://dev.pachca.com/guides/buttons).",
|
|
34
29
|
}),
|
|
35
30
|
'parent-message-id': Flags.integer({
|
|
36
31
|
description: "Идентификатор сообщения, на которое вы отвечаете с цитатой. Ответить можно на сообщение в любом чате, в том числе в треде: ответ отправляют в тот же чат или тред, где лежит это сообщение, иначе запрос вернёт ошибку `422`. Чтобы написать в тред под сообщением, укажите `entity_type: \"thread\"` и `id` треда в `entity_id`.",
|
|
@@ -42,7 +37,7 @@ export default class MessagesCreate extends BaseCommand {
|
|
|
42
37
|
description: "Полное специальное имя отправителя для этого сообщения. Вместе с `display_avatar_url` бот подписывает сообщение чужим именем и аватаром, и только это сообщение. Бейдж «Бот» остаётся, а в профиле отправителя видно настоящего бота. Так показывают автора из другой системы, когда переносят в Пачку чужую переписку. С личным токеном поле недоступно, ответ `403`. Подробности — в разделе [Боты](https://dev.pachca.com/guides/bots/overview). (макс. 255 символов)",
|
|
43
38
|
}),
|
|
44
39
|
'skip-invite-mentions': Flags.boolean({
|
|
45
|
-
description: "Пропуск добавления упомянутых сотрудников в тред. В треде упоминание работает ещё и как приглашение: упомянутого сотрудника, которого в треде нет, Пачка туда добавляет, и он получает доступ к треду и родительскому сообщению. В беседе и канале упоминание никого не добавляет, и этот параметр там ничего не меняет.",
|
|
40
|
+
description: "Пропуск добавления упомянутых сотрудников в тред. В треде упоминание работает ещё и как приглашение: упомянутого сотрудника, которого в треде нет, Пачка туда добавляет, и он получает доступ к треду и родительскому сообщению. Если в пространстве включена настройка «Использовать сквозные треды» (так по умолчанию), упоминание добавляет и сотрудника не из родительского чата, а с `true` в этом поле упоминание никого не добавляет, и тот, кого в треде нет, не получает и уведомления. Упоминание от гостя или мульти-гостя при этом добавляет только тех, с кем у автора есть общий чат. Если настройка выключена, упоминание добавляет только участников родительского чата, и это поле ничего не меняет. В беседе и канале упоминание никого не добавляет, и этот параметр там ничего не меняет.",
|
|
46
41
|
allowNo: true,
|
|
47
42
|
}),
|
|
48
43
|
'link-preview': Flags.boolean({
|
|
@@ -59,7 +54,9 @@ export default class MessagesCreate extends BaseCommand {
|
|
|
59
54
|
for await (const chunk of process.stdin) {
|
|
60
55
|
chunks.push(chunk);
|
|
61
56
|
}
|
|
62
|
-
|
|
57
|
+
const piped = Buffer.concat(chunks).toString('utf-8').trimEnd();
|
|
58
|
+
if (piped)
|
|
59
|
+
flags['content'] = piped;
|
|
63
60
|
}
|
|
64
61
|
const missingRequired = [
|
|
65
62
|
{ flag: 'entity-id', label: "Идентификатор того, что названо в `entity_type`: беседы или канала, треда либо пользователя. У треда их два: `id` треда указывают с `entity_type: \"thread\"`, а его `chat_id` — с `discussion`, как у любого чата.", type: 'integer' },
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MessagesDelete extends BaseCommand {
|
|
6
6
|
static description = "Удаление сообщения";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Удалить сообщение — Удали сообщение:\n $ pachca messages delete"
|
|
9
|
-
];
|
|
10
7
|
static scope = "messages:delete";
|
|
11
8
|
static apiMethod = "DELETE";
|
|
12
9
|
static apiPath = "/messages/{id}";
|
|
@@ -3,11 +3,6 @@ import { Args } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class MessagesGet extends BaseCommand {
|
|
5
5
|
static description = "Информация о сообщении";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Получить вложения из сообщения — Получи сообщение — в `files[]` каждый объект содержит `url`, `name`, `file_type`, `size`:\n $ pachca messages get",
|
|
8
|
-
"Изменить вложения сообщения — Получи текущие вложения из `files[]`:\n $ pachca messages get",
|
|
9
|
-
"Обработать входящий вебхук-событие — Для полной информации запроси сообщение — особенно для вложений (`files[]`):\n $ pachca messages get"
|
|
10
|
-
];
|
|
11
6
|
static scope = "messages:read";
|
|
12
7
|
static apiMethod = "GET";
|
|
13
8
|
static apiPath = "/messages/{id}";
|
|
@@ -4,10 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MessagesList extends BaseCommand {
|
|
6
6
|
static description = "Список сообщений чата";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Получить историю сообщений чата — Получи сообщения чата с пагинацией:\n $ pachca messages list",
|
|
9
|
-
"Получить список активных тредов за период — Для каждого треда возьми `chat_id` и подтяни сообщения:\n $ pachca messages list"
|
|
10
|
-
];
|
|
11
7
|
static scope = "messages:read";
|
|
12
8
|
static apiMethod = "GET";
|
|
13
9
|
static apiPath = "/messages";
|
|
@@ -30,7 +26,7 @@ export default class MessagesList extends BaseCommand {
|
|
|
30
26
|
default: "id",
|
|
31
27
|
}),
|
|
32
28
|
'order': Flags.string({
|
|
33
|
-
description: "Направление
|
|
29
|
+
description: "Направление сортировки. Применяется вместе с `sort`: сообщения от старых к новым дают `sort=id` и `order=asc`. Без `sort` сообщения идут от новых к старым при любом `order`.",
|
|
34
30
|
options: ["asc", "desc"],
|
|
35
31
|
default: "desc",
|
|
36
32
|
}),
|
|
@@ -83,6 +79,7 @@ export default class MessagesList extends BaseCommand {
|
|
|
83
79
|
let nextCursor = undefined;
|
|
84
80
|
let pages = 0;
|
|
85
81
|
const seenCursors = new Set();
|
|
82
|
+
let total;
|
|
86
83
|
while (pages < 500) {
|
|
87
84
|
const query = {
|
|
88
85
|
'chat_id': flags['chat-id'],
|
|
@@ -100,7 +97,7 @@ export default class MessagesList extends BaseCommand {
|
|
|
100
97
|
const paginate = meta?.paginate;
|
|
101
98
|
nextCursor = paginate?.next_page;
|
|
102
99
|
pages++;
|
|
103
|
-
// Условие конца:
|
|
100
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
104
101
|
const hasNext = paginate?.has_next;
|
|
105
102
|
if (typeof hasNext === 'boolean') {
|
|
106
103
|
if (!hasNext)
|
|
@@ -110,7 +107,8 @@ export default class MessagesList extends BaseCommand {
|
|
|
110
107
|
break;
|
|
111
108
|
}
|
|
112
109
|
if (process.stderr.isTTY) {
|
|
113
|
-
|
|
110
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
111
|
+
total ??= meta?.total;
|
|
114
112
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
115
113
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
116
114
|
}
|
|
@@ -3,9 +3,6 @@ import { Args } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class MessagesPin extends BaseCommand {
|
|
5
5
|
static description = "Закрепление сообщения";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Закрепить/открепить сообщение — Закрепить сообщение:\n $ pachca messages pin"
|
|
8
|
-
];
|
|
9
6
|
static scope = "pins:write";
|
|
10
7
|
static apiMethod = "POST";
|
|
11
8
|
static apiPath = "/messages/{id}/pin";
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MessagesUnfurl extends BaseCommand {
|
|
6
6
|
static description = "Unfurl (разворачивание ссылок)";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Разворачивание ссылок (unfurling) — Отправь превью-данные:\n $ pachca messages unfurl"
|
|
9
|
-
];
|
|
10
7
|
static hiddenAliases = ["link-previews:add"];
|
|
11
8
|
static scope = "link_previews:write";
|
|
12
9
|
static apiMethod = "POST";
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class MessagesUnpin extends BaseCommand {
|
|
6
6
|
static description = "Открепление сообщения";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Закрепить/открепить сообщение — Открепить сообщение:\n $ pachca messages unpin"
|
|
9
|
-
];
|
|
10
7
|
static scope = "pins:write";
|
|
11
8
|
static apiMethod = "DELETE";
|
|
12
9
|
static apiPath = "/messages/{id}/pin";
|
|
@@ -3,11 +3,6 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class MessagesUpdate extends BaseCommand {
|
|
5
5
|
static description = "Редактирование сообщения";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Отредактировать сообщение — Обнови сообщение:\n $ pachca messages update",
|
|
8
|
-
"Изменить вложения сообщения — Обнови сообщение с новым массивом `files`:\n $ pachca messages update",
|
|
9
|
-
"Обработать нажатие кнопки (callback) — Опционально: обнови исходное сообщение:\n $ pachca messages update"
|
|
10
|
-
];
|
|
11
6
|
static scope = "messages:update";
|
|
12
7
|
static apiMethod = "PUT";
|
|
13
8
|
static apiPath = "/messages/{id}";
|
|
@@ -21,10 +16,10 @@ export default class MessagesUpdate extends BaseCommand {
|
|
|
21
16
|
static flags = {
|
|
22
17
|
...BaseCommand.baseFlags,
|
|
23
18
|
'content': Flags.string({
|
|
24
|
-
description: "Текст сообщения. Поддерживает упоминания: `@nickname` или `<@user_id>` (будет автоматически преобразовано в `@nickname`). У мульти-гостя `<@user_id>` недоступного ему сотрудника остаётся в тексте как есть. До 40 000 байт в UTF-8, для кириллицы это около 20 000 символов.
|
|
19
|
+
description: "Текст сообщения. Поддерживает упоминания: `@nickname` или `<@user_id>` (будет автоматически преобразовано в `@nickname`). Ник берут из ответа метода, а `user_id` — из данных: ник, составленный из имени, никого не упоминает. У мульти-гостя `<@user_id>` недоступного ему сотрудника остаётся в тексте как есть. До 40 000 байт в UTF-8, для кириллицы это около 20 000 символов.",
|
|
25
20
|
}),
|
|
26
21
|
'files': Flags.string({
|
|
27
|
-
description: "Прикрепляемые файлы. Переданный набор заменяет прежний: чтобы оставить уже приложенный файл, передайте его снова с тем же `key`.",
|
|
22
|
+
description: "Прикрепляемые файлы. Переданный набор заменяет прежний: чтобы оставить уже приложенный файл, передайте его снова с тем же `key`. Такой файл остаётся прежним вложением с тем же `id` и названием, а его поля из запроса не применяются. Чтобы показать файл под другим названием, загрузите его заново.",
|
|
28
23
|
}),
|
|
29
24
|
'buttons': Flags.string({
|
|
30
25
|
description: "Массив строк, каждая из которых представлена массивом кнопок. Максимум 100 кнопок у сообщения, до 8 кнопок в строке. Для удаления кнопок пришлите пустой массив.",
|
|
@@ -45,7 +40,9 @@ export default class MessagesUpdate extends BaseCommand {
|
|
|
45
40
|
for await (const chunk of process.stdin) {
|
|
46
41
|
chunks.push(chunk);
|
|
47
42
|
}
|
|
48
|
-
|
|
43
|
+
const piped = Buffer.concat(chunks).toString('utf-8').trimEnd();
|
|
44
|
+
if (piped)
|
|
45
|
+
flags['content'] = piped;
|
|
49
46
|
}
|
|
50
47
|
const body = { message: {
|
|
51
48
|
content: flags['content'],
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command.js';
|
|
2
2
|
export default class OauthTokenInfo extends BaseCommand {
|
|
3
3
|
static description = "Информация о токене";
|
|
4
|
-
static examples = [
|
|
5
|
-
"Проверить свой токен — Получи информацию о токене: скоупы, дату создания, срок жизни:\n $ pachca oauth token-info"
|
|
6
|
-
];
|
|
7
4
|
static hiddenAliases = ["profile:get-info"];
|
|
8
5
|
static apiMethod = "GET";
|
|
9
6
|
static apiPath = "/oauth/token/info";
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class ProfileDeleteAvatar extends BaseCommand {
|
|
6
6
|
static description = "Удаление своего аватара";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Удалить аватар профиля — Удали аватар:\n $ pachca profile delete-avatar"
|
|
9
|
-
];
|
|
10
7
|
static scope = "profile_avatar:write";
|
|
11
8
|
static apiMethod = "DELETE";
|
|
12
9
|
static apiPath = "/profile/avatar";
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class ProfileDeleteStatus extends BaseCommand {
|
|
6
6
|
static description = "Удаление своего статуса";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Сбросить статус — Удали статус:\n $ pachca profile delete-status"
|
|
9
|
-
];
|
|
10
7
|
static scope = "profile_status:write";
|
|
11
8
|
static apiMethod = "DELETE";
|
|
12
9
|
static apiPath = "/profile/status";
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command.js';
|
|
2
2
|
export default class ProfileGet extends BaseCommand {
|
|
3
3
|
static description = "Свой профиль";
|
|
4
|
-
static examples = [
|
|
5
|
-
"Получить свой профиль — Получи информацию о текущем пользователе:\n $ pachca profile get",
|
|
6
|
-
"Получить кастомные поля профиля — Получи профиль — в `custom_properties` содержатся значения полей:\n $ pachca profile get"
|
|
7
|
-
];
|
|
8
4
|
static scope = "profile:read";
|
|
9
5
|
static apiMethod = "GET";
|
|
10
6
|
static apiPath = "/profile";
|
|
@@ -5,9 +5,6 @@ import * as fs from 'node:fs';
|
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
export default class ProfileUpdateAvatar extends BaseCommand {
|
|
7
7
|
static description = "Загрузка своего аватара";
|
|
8
|
-
static examples = [
|
|
9
|
-
"Загрузить аватар профиля — Загрузи аватар из файла:\n $ pachca profile update-avatar"
|
|
10
|
-
];
|
|
11
8
|
static scope = "profile_avatar:write";
|
|
12
9
|
static apiMethod = "PUT";
|
|
13
10
|
static apiPath = "/profile/avatar";
|
|
@@ -3,9 +3,6 @@ import { Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class ProfileUpdateStatus extends BaseCommand {
|
|
5
5
|
static description = "Новый свой статус";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Установить статус — Установи статус:\n $ pachca profile update-status"
|
|
8
|
-
];
|
|
9
6
|
static scope = "profile_status:write";
|
|
10
7
|
static apiMethod = "PUT";
|
|
11
8
|
static apiPath = "/profile/status";
|
|
@@ -14,7 +11,7 @@ export default class ProfileUpdateStatus extends BaseCommand {
|
|
|
14
11
|
static flags = {
|
|
15
12
|
...BaseCommand.baseFlags,
|
|
16
13
|
'emoji': Flags.string({
|
|
17
|
-
description: "Emoji символ статуса. Обязателен, если статуса ещё нет.",
|
|
14
|
+
description: "Emoji символ статуса. Обязателен, если статуса ещё нет. Эмодзи в текстовой форме (без U+FE0F или с U+FE0E) сохраняется и возвращается с U+FE0F. Пустое значение отвечает `400` с кодом `blank`, несколько эмодзи — с кодом `invalid`, текст вместо эмодзи или рядом с ним — с кодом `wrong_emoji`.",
|
|
18
15
|
}),
|
|
19
16
|
'title': Flags.string({
|
|
20
17
|
description: "Текст статуса. Обязателен, если статуса ещё нет. (макс. 50 символов)",
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class ReactionsAdd extends BaseCommand {
|
|
6
6
|
static description = "Добавление реакции";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Добавить реакцию на сообщение — Добавь реакцию:\n $ pachca reactions add"
|
|
9
|
-
];
|
|
10
7
|
static scope = "reactions:write";
|
|
11
8
|
static apiMethod = "POST";
|
|
12
9
|
static apiPath = "/messages/{id}/reactions";
|
|
@@ -21,17 +18,17 @@ export default class ReactionsAdd extends BaseCommand {
|
|
|
21
18
|
static flags = {
|
|
22
19
|
...BaseCommand.baseFlags,
|
|
23
20
|
'code': Flags.string({
|
|
24
|
-
description: "Emoji символ реакции.
|
|
21
|
+
description: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи. С `name` подходит любое непустое значение: оно сохраняется как передано.",
|
|
25
22
|
}),
|
|
26
23
|
'name': Flags.string({
|
|
27
|
-
description: "
|
|
24
|
+
description: "Имя кастомного эмодзи пространства. С ним реакцией ставится этот эмодзи, а если его в пространстве нет, ответ `404`.",
|
|
28
25
|
}),
|
|
29
26
|
};
|
|
30
27
|
async run() {
|
|
31
28
|
const { args, flags } = await this.parse(ReactionsAdd);
|
|
32
29
|
this.parsedFlags = flags;
|
|
33
30
|
const missingRequired = [
|
|
34
|
-
{ flag: 'code', label: "Emoji символ реакции.
|
|
31
|
+
{ flag: 'code', label: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи. С `name` подходит любое непустое значение: оно сохраняется как передано.", type: 'string' },
|
|
35
32
|
].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
|
|
36
33
|
if (missingRequired.length > 0) {
|
|
37
34
|
if (this.isInteractive()) {
|
|
@@ -35,6 +35,7 @@ export default class ReactionsList extends BaseCommand {
|
|
|
35
35
|
let nextCursor = undefined;
|
|
36
36
|
let pages = 0;
|
|
37
37
|
const seenCursors = new Set();
|
|
38
|
+
let total;
|
|
38
39
|
while (pages < 500) {
|
|
39
40
|
const query = {
|
|
40
41
|
limit: flags.limit,
|
|
@@ -49,7 +50,7 @@ export default class ReactionsList extends BaseCommand {
|
|
|
49
50
|
const paginate = meta?.paginate;
|
|
50
51
|
nextCursor = paginate?.next_page;
|
|
51
52
|
pages++;
|
|
52
|
-
// Условие конца:
|
|
53
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
53
54
|
const hasNext = paginate?.has_next;
|
|
54
55
|
if (typeof hasNext === 'boolean') {
|
|
55
56
|
if (!hasNext)
|
|
@@ -59,7 +60,8 @@ export default class ReactionsList extends BaseCommand {
|
|
|
59
60
|
break;
|
|
60
61
|
}
|
|
61
62
|
if (process.stderr.isTTY) {
|
|
62
|
-
|
|
63
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
64
|
+
total ??= meta?.total;
|
|
63
65
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
64
66
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
65
67
|
}
|
|
@@ -4,9 +4,6 @@ import { BaseCommand } from '../../base-command.js';
|
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
5
|
export default class ReactionsRemove extends BaseCommand {
|
|
6
6
|
static description = "Удаление реакции";
|
|
7
|
-
static examples = [
|
|
8
|
-
"Добавить реакцию на сообщение — Убрать реакцию:\n $ pachca reactions remove"
|
|
9
|
-
];
|
|
10
7
|
static scope = "reactions:write";
|
|
11
8
|
static apiMethod = "DELETE";
|
|
12
9
|
static apiPath = "/messages/{id}/reactions";
|
|
@@ -20,10 +17,10 @@ export default class ReactionsRemove extends BaseCommand {
|
|
|
20
17
|
static flags = {
|
|
21
18
|
...BaseCommand.baseFlags,
|
|
22
19
|
'code': Flags.string({
|
|
23
|
-
description: "Emoji символ реакции.
|
|
20
|
+
description: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи.",
|
|
24
21
|
}),
|
|
25
22
|
'name': Flags.string({
|
|
26
|
-
description: "
|
|
23
|
+
description: "Имя реакции, как в её поле `name`. С ним реакция ищется по имени, так снимается и кастомный эмодзи пространства.",
|
|
27
24
|
}),
|
|
28
25
|
force: Flags.boolean({
|
|
29
26
|
description: 'Пропустить подтверждение',
|
|
@@ -34,7 +31,7 @@ export default class ReactionsRemove extends BaseCommand {
|
|
|
34
31
|
const { args, flags } = await this.parse(ReactionsRemove);
|
|
35
32
|
this.parsedFlags = flags;
|
|
36
33
|
const missingRequired = [
|
|
37
|
-
{ flag: 'code', label: "Emoji символ реакции.
|
|
34
|
+
{ flag: 'code', label: "Emoji символ реакции. Без `name` нужен именно символ: текстовые записи вроде `+1` или `:+1:` отклоняются как неизвестный эмодзи.", type: 'string' },
|
|
38
35
|
].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
|
|
39
36
|
if (missingRequired.length > 0) {
|
|
40
37
|
if (this.isInteractive()) {
|
|
@@ -3,9 +3,6 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class ReadMemberListReaders extends BaseCommand {
|
|
5
5
|
static description = "Список прочитавших сообщение";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Проверить, кто прочитал сообщение — Получи массив `user_id` прочитавших:\n $ pachca read-member list-readers"
|
|
8
|
-
];
|
|
9
6
|
static scope = "messages:read";
|
|
10
7
|
static apiMethod = "GET";
|
|
11
8
|
static apiPath = "/messages/{id}/read_member_ids";
|
|
@@ -37,6 +34,7 @@ export default class ReadMemberListReaders extends BaseCommand {
|
|
|
37
34
|
let nextCursor = undefined;
|
|
38
35
|
let pages = 0;
|
|
39
36
|
const seenCursors = new Set();
|
|
37
|
+
let total;
|
|
40
38
|
while (pages < 500) {
|
|
41
39
|
const query = {
|
|
42
40
|
limit: flags.limit,
|
|
@@ -51,7 +49,7 @@ export default class ReadMemberListReaders extends BaseCommand {
|
|
|
51
49
|
const paginate = meta?.paginate;
|
|
52
50
|
nextCursor = paginate?.next_page;
|
|
53
51
|
pages++;
|
|
54
|
-
// Условие конца:
|
|
52
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
55
53
|
const hasNext = paginate?.has_next;
|
|
56
54
|
if (typeof hasNext === 'boolean') {
|
|
57
55
|
if (!hasNext)
|
|
@@ -61,7 +59,8 @@ export default class ReadMemberListReaders extends BaseCommand {
|
|
|
61
59
|
break;
|
|
62
60
|
}
|
|
63
61
|
if (process.stderr.isTTY) {
|
|
64
|
-
|
|
62
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
63
|
+
total ??= meta?.total;
|
|
65
64
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
66
65
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
67
66
|
}
|
|
@@ -3,11 +3,6 @@ import { Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class SearchListChats extends BaseCommand {
|
|
5
5
|
static description = "Поиск чатов";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Найти чат по имени и отправить сообщение — Найди чат по названию через поиск:\n $ pachca search list-chats",
|
|
8
|
-
"Отправить сообщение позже или по расписанию — Найди чат, в который нужно написать:\n $ pachca search list-chats",
|
|
9
|
-
"Найти чат по названию — Полнотекстовый поиск по чатам:\n $ pachca search list-chats"
|
|
10
|
-
];
|
|
11
6
|
static scope = "search:chats";
|
|
12
7
|
static apiMethod = "GET";
|
|
13
8
|
static apiPath = "/search/chats";
|
|
@@ -60,6 +55,7 @@ export default class SearchListChats extends BaseCommand {
|
|
|
60
55
|
let nextCursor = undefined;
|
|
61
56
|
let pages = 0;
|
|
62
57
|
const seenCursors = new Set();
|
|
58
|
+
let total;
|
|
63
59
|
while (pages < 500) {
|
|
64
60
|
const query = {
|
|
65
61
|
query: flags['query'],
|
|
@@ -81,7 +77,7 @@ export default class SearchListChats extends BaseCommand {
|
|
|
81
77
|
const paginate = meta?.paginate;
|
|
82
78
|
nextCursor = paginate?.next_page;
|
|
83
79
|
pages++;
|
|
84
|
-
// Условие конца:
|
|
80
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
85
81
|
const hasNext = paginate?.has_next;
|
|
86
82
|
if (typeof hasNext === 'boolean') {
|
|
87
83
|
if (!hasNext)
|
|
@@ -91,7 +87,8 @@ export default class SearchListChats extends BaseCommand {
|
|
|
91
87
|
break;
|
|
92
88
|
}
|
|
93
89
|
if (process.stderr.isTTY) {
|
|
94
|
-
|
|
90
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
91
|
+
total ??= meta?.total;
|
|
95
92
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
96
93
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
97
94
|
}
|
|
@@ -3,9 +3,6 @@ import { Flags } from '@oclif/core';
|
|
|
3
3
|
import { BaseCommand } from '../../base-command.js';
|
|
4
4
|
export default class SearchListMessages extends BaseCommand {
|
|
5
5
|
static description = "Поиск сообщений";
|
|
6
|
-
static examples = [
|
|
7
|
-
"Найти сообщение по тексту — Полнотекстовый поиск по сообщениям:\n $ pachca search list-messages"
|
|
8
|
-
];
|
|
9
6
|
static scope = "search:messages";
|
|
10
7
|
static apiMethod = "GET";
|
|
11
8
|
static apiPath = "/search/messages";
|
|
@@ -61,6 +58,7 @@ export default class SearchListMessages extends BaseCommand {
|
|
|
61
58
|
let nextCursor = undefined;
|
|
62
59
|
let pages = 0;
|
|
63
60
|
const seenCursors = new Set();
|
|
61
|
+
let total;
|
|
64
62
|
while (pages < 500) {
|
|
65
63
|
const query = {
|
|
66
64
|
query: flags['query'],
|
|
@@ -83,7 +81,7 @@ export default class SearchListMessages extends BaseCommand {
|
|
|
83
81
|
const paginate = meta?.paginate;
|
|
84
82
|
nextCursor = paginate?.next_page;
|
|
85
83
|
pages++;
|
|
86
|
-
// Условие конца:
|
|
84
|
+
// Условие конца: has_next === false, а в ответе без has_next — пустой data
|
|
87
85
|
const hasNext = paginate?.has_next;
|
|
88
86
|
if (typeof hasNext === 'boolean') {
|
|
89
87
|
if (!hasNext)
|
|
@@ -93,7 +91,8 @@ export default class SearchListMessages extends BaseCommand {
|
|
|
93
91
|
break;
|
|
94
92
|
}
|
|
95
93
|
if (process.stderr.isTTY) {
|
|
96
|
-
|
|
94
|
+
// total лежит в meta у методов поиска. Берём его с первой страницы: при поиске сообщений по дате следующие страницы считают только остаток
|
|
95
|
+
total ??= meta?.total;
|
|
97
96
|
const progress = total ? `${allData.length} / ${total}` : String(allData.length);
|
|
98
97
|
process.stderr.write(`\r Загружено: ${progress}...`);
|
|
99
98
|
}
|