@pachca/cli 2026.6.0 → 2026.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.6.1 (16 июня 2026)
4
+
5
+ - **Изменено** (bots create): Добавлен параметр `scopes` — выбор скоупов токена бота
6
+ - **Изменено** (bots update): Добавлен параметр `scopes` — изменение скоупов токена бота
7
+ - **Добавлено** (bots update-webhook): Новая команда — саморегистрация исходящего вебхука бота его собственным токеном
8
+
3
9
  ## 2026.6.0 (15 июня 2026)
4
10
 
5
11
  - **Добавлено** (bots create): Новая команда — создание бота и получение его `access_token`
package/README.md CHANGED
@@ -78,8 +78,9 @@ pachca guide # список всех сценариев
78
78
 
79
79
  | Команда | Описание |
80
80
  |---------|---------|
81
- | `pachca bots create` | Создание бота |
82
- | `pachca bots get` | Получение бота |
81
+ | `pachca bots update-webhook` | Саморегистрация вебхука бота |
82
+ | `pachca bots create` | Новый бот |
83
+ | `pachca bots get` | Информация о боте |
83
84
  | `pachca bots update` | Редактирование бота |
84
85
  | `pachca bots list-events` | История событий |
85
86
  | `pachca bots remove-event` | Удаление события |
@@ -91,7 +92,7 @@ pachca guide # список всех сценариев
91
92
  | `pachca chats create` | Новый чат |
92
93
  | `pachca chats list` | Список чатов |
93
94
  | `pachca chats get` | Информация о чате |
94
- | `pachca chats update` | Обновление чата |
95
+ | `pachca chats update` | Редактирование чата |
95
96
  | `pachca chats archive` | Архивация чата |
96
97
  | `pachca chats unarchive` | Разархивация чата |
97
98
 
@@ -173,12 +174,12 @@ pachca guide # список всех сценариев
173
174
  | Команда | Описание |
174
175
  |---------|---------|
175
176
  | `pachca profile get-info` | Информация о токене |
176
- | `pachca profile get` | Информация о профиле |
177
- | `pachca profile update-avatar` | Загрузка аватара |
178
- | `pachca profile delete-avatar` | Удаление аватара |
179
- | `pachca profile get-status` | Текущий статус |
180
- | `pachca profile update-status` | Новый статус |
181
- | `pachca profile delete-status` | Удаление статуса |
177
+ | `pachca profile get` | Свой профиль |
178
+ | `pachca profile update-avatar` | Загрузка своего аватара |
179
+ | `pachca profile delete-avatar` | Удаление своего аватара |
180
+ | `pachca profile get-status` | Свой статус |
181
+ | `pachca profile update-status` | Новый свой статус |
182
+ | `pachca profile delete-status` | Удаление своего статуса |
182
183
 
183
184
  ### search
184
185
 
@@ -202,7 +203,7 @@ pachca guide # список всех сценариев
202
203
 
203
204
  | Команда | Описание |
204
205
  |---------|---------|
205
- | `pachca users create` | Создать сотрудника |
206
+ | `pachca users create` | Новый сотрудник |
206
207
  | `pachca users list` | Список сотрудников |
207
208
  | `pachca users get` | Информация о сотруднике |
208
209
  | `pachca users update` | Редактирование сотрудника |
@@ -3,7 +3,7 @@ import { 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 BotsCreate extends BaseCommand {
6
- static description = "Создание бота";
6
+ static description = "Новый бот";
7
7
  static examples = [
8
8
  "Создать бота через API и получить токен:\n $ pachca bots create",
9
9
  "Настроить бота с исходящим вебхуком:\n $ pachca bots create"
@@ -12,19 +12,37 @@ export default class BotsCreate extends BaseCommand {
12
12
  static apiMethod = "POST";
13
13
  static apiPath = "/bots";
14
14
  static defaultColumns = ["id", "webhook", "access_token"];
15
- static requiredFlags = ["webhook"];
15
+ static requiredFlags = ["name"];
16
16
  static args = {};
17
17
  static flags = {
18
18
  ...BaseCommand.baseFlags,
19
- 'webhook': Flags.string({
20
- description: "Объект параметров вебхука бота",
19
+ 'name': Flags.string({
20
+ description: "Имя бота",
21
+ }),
22
+ 'nickname': Flags.string({
23
+ description: "Никнейм бота. Должен заканчиваться на `_bot`.",
24
+ }),
25
+ 'outgoing-url': Flags.string({
26
+ description: "URL исходящего вебхука",
27
+ }),
28
+ 'events': Flags.string({
29
+ description: "События, на которые подписан бот",
30
+ }),
31
+ 'trigger-on': Flags.string({
32
+ description: "Условие срабатывания исходящего вебхука",
33
+ }),
34
+ 'commands': Flags.string({
35
+ description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands",
36
+ }),
37
+ 'scopes': Flags.string({
38
+ description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию.",
21
39
  }),
22
40
  };
23
41
  async run() {
24
42
  const { args, flags } = await this.parse(BotsCreate);
25
43
  this.parsedFlags = flags;
26
44
  const missingRequired = [
27
- { flag: 'webhook', label: "Объект параметров вебхука бота", type: 'string' },
45
+ { flag: 'name', label: "Имя бота", type: 'string' },
28
46
  ].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
29
47
  if (missingRequired.length > 0) {
30
48
  if (this.isInteractive()) {
@@ -46,14 +64,20 @@ export default class BotsCreate extends BaseCommand {
46
64
  }
47
65
  }
48
66
  else {
49
- this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --webhook <string>. pachca introspect bots create" });
67
+ this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --name <string>. pachca introspect bots create" });
50
68
  }
51
69
  }
52
- const body = { bot: {
53
- webhook: flags['webhook'] ? this.parseJSON(flags['webhook'], 'webhook') : undefined,
70
+ const body = { webhook: {
71
+ name: flags['name'],
72
+ nickname: flags['nickname'],
73
+ outgoing_url: flags['outgoing-url'],
74
+ events: flags['events'] ? this.parseJSON(flags['events'], 'events') : undefined,
75
+ trigger_on: flags['trigger-on'],
76
+ commands: flags['commands'] ? this.parseJSON(flags['commands'], 'commands') : undefined,
77
+ scopes: flags['scopes'] ? this.parseJSON(flags['scopes'], 'scopes') : undefined,
54
78
  } };
55
79
  // Clean undefined fields
56
- const inner = body['bot'];
80
+ const inner = body['webhook'];
57
81
  for (const [k, v] of Object.entries(inner)) {
58
82
  if (v === undefined)
59
83
  delete inner[k];
@@ -2,7 +2,7 @@
2
2
  import { Args } from '@oclif/core';
3
3
  import { BaseCommand } from '../../base-command.js';
4
4
  export default class BotsGet extends BaseCommand {
5
- static description = "Получение бота";
5
+ static description = "Информация о боте";
6
6
  static examples = [
7
7
  "Обновить Webhook URL бота:\n $ pachca bots update"
8
8
  ];
@@ -0,0 +1,72 @@
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 BotsUpdateWebhook extends BaseCommand {
6
+ static description = "Саморегистрация вебхука бота";
7
+ static examples = [
8
+ "Обновить Webhook URL бота:\n $ pachca bots update-webhook"
9
+ ];
10
+ static scope = "bot_self:webhook:write";
11
+ static apiMethod = "PUT";
12
+ static apiPath = "/bot/webhook";
13
+ static defaultColumns = ["id", "webhook"];
14
+ static requiredFlags = ["outgoing-url"];
15
+ static args = {};
16
+ static flags = {
17
+ ...BaseCommand.baseFlags,
18
+ 'outgoing-url': Flags.string({
19
+ description: "URL исходящего вебхука. Пустая строка отключает вебхук.",
20
+ }),
21
+ };
22
+ async run() {
23
+ const { args, flags } = await this.parse(BotsUpdateWebhook);
24
+ this.parsedFlags = flags;
25
+ const missingRequired = [
26
+ { flag: 'outgoing-url', label: "URL исходящего вебхука. Пустая строка отключает вебхук.", type: 'string' },
27
+ ].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
28
+ if (missingRequired.length > 0) {
29
+ if (this.isInteractive()) {
30
+ for (const field of missingRequired) {
31
+ const value = await clack.text({ message: field.label, validate: (v) => v.length === 0 ? 'Обязательное поле' : undefined });
32
+ if (clack.isCancel(value)) {
33
+ process.stderr.write('Отменено.\n');
34
+ this.exit(0);
35
+ }
36
+ if (field.type === 'integer') {
37
+ flags[field.flag] = Number.parseInt(value, 10);
38
+ }
39
+ else if (field.type === 'boolean') {
40
+ flags[field.flag] = value === 'true';
41
+ }
42
+ else {
43
+ flags[field.flag] = value;
44
+ }
45
+ }
46
+ }
47
+ else {
48
+ this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --outgoing-url <string>. pachca introspect bots update-webhook" });
49
+ }
50
+ }
51
+ const body = { webhook: {
52
+ outgoing_url: flags['outgoing-url'],
53
+ } };
54
+ // Clean undefined fields
55
+ const inner = body['webhook'];
56
+ for (const [k, v] of Object.entries(inner)) {
57
+ if (v === undefined)
58
+ delete inner[k];
59
+ }
60
+ if (Object.keys(inner).length === 0) {
61
+ this.validationError([{ message: 'Не указаны поля для обновления' }], { type: 'PACHCA_USAGE_ERROR' });
62
+ }
63
+ const { data } = await this.apiRequest({
64
+ method: 'PUT',
65
+ path: '/bot/webhook',
66
+ body,
67
+ });
68
+ const responseBody = data;
69
+ const result = responseBody.data ?? responseBody;
70
+ this.output(result);
71
+ }
72
+ }
@@ -1,7 +1,6 @@
1
1
  // Auto-generated from openapi.yaml — DO NOT EDIT
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { BaseCommand } from '../../base-command.js';
4
- import * as clack from '@clack/prompts';
5
4
  export default class BotsUpdate extends BaseCommand {
6
5
  static description = "Редактирование бота";
7
6
  static examples = [
@@ -11,7 +10,6 @@ export default class BotsUpdate extends BaseCommand {
11
10
  static apiMethod = "PUT";
12
11
  static apiPath = "/bots/{id}";
13
12
  static defaultColumns = ["id", "webhook"];
14
- static requiredFlags = ["webhook"];
15
13
  static args = {
16
14
  id: Args.integer({
17
15
  description: "Идентификатор бота (pachca bots list)",
@@ -20,44 +18,42 @@ export default class BotsUpdate extends BaseCommand {
20
18
  };
21
19
  static flags = {
22
20
  ...BaseCommand.baseFlags,
23
- 'webhook': Flags.string({
24
- description: "Объект параметров вебхука",
21
+ 'name': Flags.string({
22
+ description: "Имя бота",
23
+ }),
24
+ 'nickname': Flags.string({
25
+ description: "Никнейм бота. Должен заканчиваться на `_bot`.",
26
+ }),
27
+ 'outgoing-url': Flags.string({
28
+ description: "URL исходящего вебхука",
29
+ }),
30
+ 'events': Flags.string({
31
+ description: "События, на которые подписан бот",
32
+ }),
33
+ 'trigger-on': Flags.string({
34
+ description: "Условие срабатывания исходящего вебхука",
35
+ }),
36
+ 'commands': Flags.string({
37
+ description: "Команды бота (триггер-слова), на которые он реагирует при trigger_on = commands",
38
+ }),
39
+ 'scopes': Flags.string({
40
+ description: "Скоупы (права доступа) токена бота. Если не указано, бот получает набор по умолчанию.",
25
41
  }),
26
42
  };
27
43
  async run() {
28
44
  const { args, flags } = await this.parse(BotsUpdate);
29
45
  this.parsedFlags = flags;
30
- const missingRequired = [
31
- { flag: 'webhook', label: "Объект параметров вебхука", type: 'string' },
32
- ].filter((f) => flags[f.flag] === undefined || flags[f.flag] === null);
33
- if (missingRequired.length > 0) {
34
- if (this.isInteractive()) {
35
- for (const field of missingRequired) {
36
- const value = await clack.text({ message: field.label, validate: (v) => v.length === 0 ? 'Обязательное поле' : undefined });
37
- if (clack.isCancel(value)) {
38
- process.stderr.write('Отменено.\n');
39
- this.exit(0);
40
- }
41
- if (field.type === 'integer') {
42
- flags[field.flag] = Number.parseInt(value, 10);
43
- }
44
- else if (field.type === 'boolean') {
45
- flags[field.flag] = value === 'true';
46
- }
47
- else {
48
- flags[field.flag] = value;
49
- }
50
- }
51
- }
52
- else {
53
- this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --webhook <string>. pachca introspect bots update" });
54
- }
55
- }
56
- const body = { bot: {
57
- webhook: flags['webhook'] ? this.parseJSON(flags['webhook'], 'webhook') : undefined,
46
+ const body = { webhook: {
47
+ name: flags['name'],
48
+ nickname: flags['nickname'],
49
+ outgoing_url: flags['outgoing-url'],
50
+ events: flags['events'] ? this.parseJSON(flags['events'], 'events') : undefined,
51
+ trigger_on: flags['trigger-on'],
52
+ commands: flags['commands'] ? this.parseJSON(flags['commands'], 'commands') : undefined,
53
+ scopes: flags['scopes'] ? this.parseJSON(flags['scopes'], 'scopes') : undefined,
58
54
  } };
59
55
  // Clean undefined fields
60
- const inner = body['bot'];
56
+ const inner = body['webhook'];
61
57
  for (const [k, v] of Object.entries(inner)) {
62
58
  if (v === undefined)
63
59
  delete inner[k];
@@ -2,7 +2,7 @@
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { BaseCommand } from '../../base-command.js';
4
4
  export default class ChatsUpdate extends BaseCommand {
5
- static description = "Обновление чата";
5
+ static description = "Редактирование чата";
6
6
  static examples = [
7
7
  "Переименовать или обновить чат:\n $ pachca chats update"
8
8
  ];
@@ -3,7 +3,7 @@ import { 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 ProfileDeleteAvatar extends BaseCommand {
6
- static description = "Удаление аватара";
6
+ static description = "Удаление своего аватара";
7
7
  static examples = [
8
8
  "Загрузить аватар профиля:\n $ pachca profile update-avatar",
9
9
  "Удалить аватар профиля:\n $ pachca profile delete-avatar"
@@ -3,7 +3,7 @@ import { 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 ProfileDeleteStatus extends BaseCommand {
6
- static description = "Удаление статуса";
6
+ static description = "Удаление своего статуса";
7
7
  static examples = [
8
8
  "Установить статус:\n $ pachca profile update-status",
9
9
  "Сбросить статус:\n $ pachca profile delete-status"
@@ -1,6 +1,6 @@
1
1
  import { BaseCommand } from '../../base-command.js';
2
2
  export default class ProfileGetStatus extends BaseCommand {
3
- static description = "Текущий статус";
3
+ static description = "Свой статус";
4
4
  static examples = [
5
5
  "Установить статус:\n $ pachca profile update-status",
6
6
  "Сбросить статус:\n $ pachca profile delete-status"
@@ -1,6 +1,6 @@
1
1
  import { BaseCommand } from '../../base-command.js';
2
2
  export default class ProfileGet extends BaseCommand {
3
- static description = "Информация о профиле";
3
+ static description = "Свой профиль";
4
4
  static examples = [
5
5
  "Получить свой профиль:\n $ pachca profile get",
6
6
  "Получить кастомные поля профиля:\n $ pachca profile get"
@@ -4,7 +4,7 @@ import { BaseCommand } from '../../base-command.js';
4
4
  import * as fs from 'node:fs';
5
5
  import * as path from 'node:path';
6
6
  export default class ProfileUpdateAvatar extends BaseCommand {
7
- static description = "Загрузка аватара";
7
+ static description = "Загрузка своего аватара";
8
8
  static examples = [
9
9
  "Загрузить аватар профиля:\n $ pachca profile update-avatar",
10
10
  "Удалить аватар профиля:\n $ pachca profile delete-avatar"
@@ -3,7 +3,7 @@ import { 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 ProfileUpdateStatus extends BaseCommand {
6
- static description = "Новый статус";
6
+ static description = "Новый свой статус";
7
7
  static examples = [
8
8
  "Установить статус:\n $ pachca profile update-status",
9
9
  "Сбросить статус:\n $ pachca profile delete-status"
@@ -3,7 +3,7 @@ import { 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 UsersCreate extends BaseCommand {
6
- static description = "Создать сотрудника";
6
+ static description = "Новый сотрудник";
7
7
  static examples = [
8
8
  "Проверить, кто прочитал сообщение:\n $ pachca users list",
9
9
  "Разослать уведомление нескольким пользователям:\n $ pachca users list",
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "security:list": "Журнал аудита событий",
3
- "bots:create": "Создание бота",
4
- "bots:get": "Получение бота",
3
+ "bots:update-webhook": "Саморегистрация вебхука бота",
4
+ "bots:create": "Новый бот",
5
+ "bots:get": "Информация о боте",
5
6
  "bots:update": "Редактирование бота",
6
7
  "chats:create": "Новый чат",
7
8
  "chats:list": "Список чатов",
8
9
  "common:request-export": "Экспорт сообщений",
9
10
  "common:get-exports": "Скачать архив экспорта",
10
11
  "chats:get": "Информация о чате",
11
- "chats:update": "Обновление чата",
12
+ "chats:update": "Редактирование чата",
12
13
  "chats:archive": "Архивация чата",
13
14
  "members:add-group-tags": "Добавление тегов",
14
15
  "members:remove-group-tag": "Исключение тега",
@@ -40,12 +41,12 @@
40
41
  "read-member:list-readers": "Список прочитавших сообщение",
41
42
  "threads:add": "Новый тред",
42
43
  "profile:get-info": "Информация о токене",
43
- "profile:get": "Информация о профиле",
44
- "profile:update-avatar": "Загрузка аватара",
45
- "profile:delete-avatar": "Удаление аватара",
46
- "profile:get-status": "Текущий статус",
47
- "profile:update-status": "Новый статус",
48
- "profile:delete-status": "Удаление статуса",
44
+ "profile:get": "Свой профиль",
45
+ "profile:update-avatar": "Загрузка своего аватара",
46
+ "profile:delete-avatar": "Удаление своего аватара",
47
+ "profile:get-status": "Свой статус",
48
+ "profile:update-status": "Новый свой статус",
49
+ "profile:delete-status": "Удаление своего статуса",
49
50
  "search:list-chats": "Поиск чатов",
50
51
  "search:list-messages": "Поиск сообщений",
51
52
  "search:list-users": "Поиск сотрудников",
@@ -57,7 +58,7 @@
57
58
  "threads:list": "Список тредов",
58
59
  "threads:get": "Информация о треде",
59
60
  "common:uploads": "Получение подписи, ключа и других параметров",
60
- "users:create": "Создать сотрудника",
61
+ "users:create": "Новый сотрудник",
61
62
  "users:list": "Список сотрудников",
62
63
  "users:get": "Информация о сотруднике",
63
64
  "users:update": "Редактирование сотрудника",
@@ -1,4 +1,25 @@
1
1
  [
2
+ {
3
+ "version": "2026.6.1",
4
+ "date": "16 июня 2026",
5
+ "changes": [
6
+ {
7
+ "type": "~",
8
+ "command": "bots create",
9
+ "description": "Добавлен параметр `scopes` — выбор скоупов токена бота"
10
+ },
11
+ {
12
+ "type": "~",
13
+ "command": "bots update",
14
+ "description": "Добавлен параметр `scopes` — изменение скоупов токена бота"
15
+ },
16
+ {
17
+ "type": "+",
18
+ "command": "bots update-webhook",
19
+ "description": "Новая команда — саморегистрация исходящего вебхука бота его собственным токеном"
20
+ }
21
+ ]
22
+ },
2
23
  {
3
24
  "version": "2026.6.0",
4
25
  "date": "15 июня 2026",