@meet-im/lxcli 0.0.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.
Files changed (90) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +3 -0
  3. package/bin/lxcli.js +2 -0
  4. package/dist/commands/auth.d.ts +2 -0
  5. package/dist/commands/auth.js +45 -0
  6. package/dist/commands/config.d.ts +2 -0
  7. package/dist/commands/config.js +28 -0
  8. package/dist/commands/generate-skills.d.ts +2 -0
  9. package/dist/commands/generate-skills.js +283 -0
  10. package/dist/commands/index.d.ts +9 -0
  11. package/dist/commands/index.js +43 -0
  12. package/dist/commands/schema.d.ts +2 -0
  13. package/dist/commands/schema.js +37 -0
  14. package/dist/commands/services/kb/config.d.ts +2 -0
  15. package/dist/commands/services/kb/config.js +32 -0
  16. package/dist/commands/services/kb/descriptions.d.ts +4 -0
  17. package/dist/commands/services/kb/descriptions.js +24 -0
  18. package/dist/commands/services/kb/handler.d.ts +12 -0
  19. package/dist/commands/services/kb/handler.js +179 -0
  20. package/dist/commands/services/kb/index.d.ts +3 -0
  21. package/dist/commands/services/kb/index.js +119 -0
  22. package/dist/commands/services/kb/params.d.ts +8 -0
  23. package/dist/commands/services/kb/params.js +73 -0
  24. package/dist/commands/services/kb/rpc.d.ts +1 -0
  25. package/dist/commands/services/kb/rpc.js +35 -0
  26. package/dist/commands/services/kb/types.d.ts +97 -0
  27. package/dist/commands/services/kb/types.js +2 -0
  28. package/dist/commands/services/kb/utils.d.ts +1 -0
  29. package/dist/commands/services/kb/utils.js +4 -0
  30. package/dist/commands/services/meet/api.d.ts +13 -0
  31. package/dist/commands/services/meet/api.js +38 -0
  32. package/dist/commands/services/meet/config.d.ts +4 -0
  33. package/dist/commands/services/meet/config.js +16 -0
  34. package/dist/commands/services/meet/descriptions.d.ts +3 -0
  35. package/dist/commands/services/meet/descriptions.js +7 -0
  36. package/dist/commands/services/meet/handler.d.ts +25 -0
  37. package/dist/commands/services/meet/handler.js +50 -0
  38. package/dist/commands/services/meet/index.d.ts +3 -0
  39. package/dist/commands/services/meet/index.js +43 -0
  40. package/dist/commands/services/meet/types.d.ts +65 -0
  41. package/dist/commands/services/meet/types.js +2 -0
  42. package/dist/commands/services/meetbot/api.d.ts +37 -0
  43. package/dist/commands/services/meetbot/api.js +130 -0
  44. package/dist/commands/services/meetbot/config.d.ts +4 -0
  45. package/dist/commands/services/meetbot/config.js +21 -0
  46. package/dist/commands/services/meetbot/descriptions.d.ts +3 -0
  47. package/dist/commands/services/meetbot/descriptions.js +10 -0
  48. package/dist/commands/services/meetbot/handler.d.ts +42 -0
  49. package/dist/commands/services/meetbot/handler.js +83 -0
  50. package/dist/commands/services/meetbot/index.d.ts +3 -0
  51. package/dist/commands/services/meetbot/index.js +74 -0
  52. package/dist/commands/services/meetbot/types.d.ts +101 -0
  53. package/dist/commands/services/meetbot/types.js +2 -0
  54. package/dist/commands/services/meetbot/utils.d.ts +28 -0
  55. package/dist/commands/services/meetbot/utils.js +78 -0
  56. package/dist/commands/services.d.ts +2 -0
  57. package/dist/commands/services.js +50 -0
  58. package/dist/commands/tenants.d.ts +2 -0
  59. package/dist/commands/tenants.js +46 -0
  60. package/dist/commands/upgrade.d.ts +2 -0
  61. package/dist/commands/upgrade.js +38 -0
  62. package/dist/commands/users.d.ts +2 -0
  63. package/dist/commands/users.js +182 -0
  64. package/dist/core/auth.d.ts +26 -0
  65. package/dist/core/auth.js +75 -0
  66. package/dist/core/config.d.ts +76 -0
  67. package/dist/core/config.js +255 -0
  68. package/dist/core/error.d.ts +128 -0
  69. package/dist/core/error.js +85 -0
  70. package/dist/core/help.d.ts +6 -0
  71. package/dist/core/help.js +15 -0
  72. package/dist/core/http.d.ts +28 -0
  73. package/dist/core/http.js +140 -0
  74. package/dist/core/logger.d.ts +24 -0
  75. package/dist/core/logger.js +53 -0
  76. package/dist/core/reserved.d.ts +13 -0
  77. package/dist/core/reserved.js +28 -0
  78. package/dist/core/tenants.d.ts +36 -0
  79. package/dist/core/tenants.js +50 -0
  80. package/dist/index.d.ts +2 -0
  81. package/dist/index.js +152 -0
  82. package/dist/types/index.d.ts +59 -0
  83. package/dist/types/index.js +5 -0
  84. package/dist/utils/index.d.ts +20 -0
  85. package/dist/utils/index.js +133 -0
  86. package/dist/utils/loose-params.d.ts +9 -0
  87. package/dist/utils/loose-params.js +274 -0
  88. package/dist/utils/table.d.ts +4 -0
  89. package/dist/utils/table.js +25 -0
  90. package/package.json +46 -0
@@ -0,0 +1,50 @@
1
+ // src/commands/services/meet/handler.ts
2
+ import { getCurrentUser, getGatewayForUser } from '../../../core/auth.js';
3
+ import { outputCliError } from '../../../core/error.js';
4
+ import { outputJson, parseCliParams } from '../../../utils/index.js';
5
+ import { syncMsg, getConvInfo2, getMyInfo } from './api.js';
6
+ /**
7
+ * 获取 meet 认证信息
8
+ */
9
+ export function getMeetAuth(userName) {
10
+ const user = getCurrentUser(userName);
11
+ if (!user) {
12
+ outputCliError('USER_NOT_FOUND', 'No user configured. Run "lxcli auth" first.');
13
+ }
14
+ return {
15
+ user: user,
16
+ token: user.token,
17
+ };
18
+ }
19
+ export async function handleSyncMsg(options) {
20
+ if (!options.params) {
21
+ outputCliError('PARAM_INVALID', 'Missing required option: --params.');
22
+ }
23
+ const { user, token } = getMeetAuth(options.user);
24
+ const gateway = options.gateway || getGatewayForUser(user, 'meet');
25
+ const params = parseCliParams(options.params);
26
+ if (!params.sessionInfo) {
27
+ outputCliError('PARAM_INVALID', 'Missing required field: sessionInfo.');
28
+ }
29
+ const result = await syncMsg(gateway, params, token);
30
+ outputJson(result);
31
+ }
32
+ export async function handleGetConvInfo2(options) {
33
+ if (!options.params) {
34
+ outputCliError('PARAM_INVALID', 'Missing required option: --params.');
35
+ }
36
+ const { user, token } = getMeetAuth(options.user);
37
+ const gateway = options.gateway || getGatewayForUser(user, 'meet');
38
+ const params = parseCliParams(options.params);
39
+ if (!params.sessionInfo) {
40
+ outputCliError('PARAM_INVALID', 'Missing required field: sessionInfo.');
41
+ }
42
+ const result = await getConvInfo2(gateway, params, token);
43
+ outputJson(result);
44
+ }
45
+ export async function handleGetMyInfo(options) {
46
+ const { user, token } = getMeetAuth(options.user);
47
+ const gateway = options.gateway || getGatewayForUser(user, 'meet');
48
+ const result = await getMyInfo(gateway, token);
49
+ outputJson(result);
50
+ }
@@ -0,0 +1,3 @@
1
+ import type { ServiceCommand } from '../../../types/index.js';
2
+ declare const meetService: ServiceCommand;
3
+ export default meetService;
@@ -0,0 +1,43 @@
1
+ // src/commands/services/meet/index.ts
2
+ import { registerService } from '../../../core/tenants.js';
3
+ import { meetConfig } from './config.js';
4
+ import { COMMAND_DESCRIPTIONS } from './descriptions.js';
5
+ import { handleSyncMsg, handleGetConvInfo2, handleGetMyInfo } from './handler.js';
6
+ const meetService = {
7
+ name: 'meet',
8
+ description: 'MeetIM Core API',
9
+ enabled: false,
10
+ register(cmd) {
11
+ registerService(meetConfig);
12
+ cmd.description(this.description).allowUnknownOption(false);
13
+ // 无子命令时显示帮助
14
+ cmd.action(() => {
15
+ console.log(cmd.helpInformation());
16
+ process.exitCode = 0;
17
+ });
18
+ // syncMsg
19
+ cmd
20
+ .command('syncMsg')
21
+ .description(COMMAND_DESCRIPTIONS.syncMsg)
22
+ .requiredOption('--params <json>', 'JSON params: {sessionInfo, beginSeqId?, endSeqId?, limit?}')
23
+ .option('--user <user>', 'Specify user')
24
+ .option('--gateway <url>', 'Override meet gateway')
25
+ .action(handleSyncMsg);
26
+ // getConvInfo2
27
+ cmd
28
+ .command('getConvInfo2')
29
+ .description(COMMAND_DESCRIPTIONS.getConvInfo2)
30
+ .requiredOption('--params <json>', 'JSON params: {sessionInfo}')
31
+ .option('--user <user>', 'Specify user')
32
+ .option('--gateway <url>', 'Override meet gateway')
33
+ .action(handleGetConvInfo2);
34
+ // getMyInfo
35
+ cmd
36
+ .command('getMyInfo')
37
+ .description(COMMAND_DESCRIPTIONS.getMyInfo)
38
+ .option('--user <user>', 'Specify user')
39
+ .option('--gateway <url>', 'Override meet gateway')
40
+ .action(handleGetMyInfo);
41
+ },
42
+ };
43
+ export default meetService;
@@ -0,0 +1,65 @@
1
+ export interface SessionInfo {
2
+ firstID: number;
3
+ secondID: number;
4
+ /** 1=私聊, 3=群聊 */
5
+ sessionType: 1 | 3;
6
+ companyID?: number;
7
+ }
8
+ export interface SyncMsgParams {
9
+ sessionInfo: SessionInfo;
10
+ beginSeqId?: number;
11
+ endSeqId?: number;
12
+ limit?: number;
13
+ isForward?: boolean;
14
+ notReaded?: boolean;
15
+ }
16
+ export interface MsgContent {
17
+ seqID: number;
18
+ content: string;
19
+ fromUID: number;
20
+ timestamp: number;
21
+ [key: string]: unknown;
22
+ }
23
+ export interface SyncMsgResult {
24
+ msgs: MsgContent[];
25
+ lastSeqId: number;
26
+ isMin: boolean;
27
+ [key: string]: unknown;
28
+ }
29
+ export interface GetConvInfo2Params {
30
+ sessionInfo: SessionInfo;
31
+ }
32
+ export interface ConvInfo {
33
+ groupID: number;
34
+ name: string;
35
+ avatar: string;
36
+ memberCount: number;
37
+ [key: string]: unknown;
38
+ }
39
+ export interface ConvMember {
40
+ userID: number;
41
+ nickName: string;
42
+ avatar: string;
43
+ [key: string]: unknown;
44
+ }
45
+ export interface GetConvInfo2Result {
46
+ convInfo: ConvInfo;
47
+ isInGroup: boolean;
48
+ isDiscarded: boolean;
49
+ members?: ConvMember[];
50
+ total?: number;
51
+ [key: string]: unknown;
52
+ }
53
+ export interface UserInfo {
54
+ userID: number;
55
+ nickName: string;
56
+ avatar: string;
57
+ mobile?: string;
58
+ email?: string;
59
+ [key: string]: unknown;
60
+ }
61
+ export interface GetMyInfoResult {
62
+ uInfo: UserInfo;
63
+ currentCompanyID: number;
64
+ [key: string]: unknown;
65
+ }
@@ -0,0 +1,2 @@
1
+ // src/commands/services/meet/types.ts
2
+ export {};
@@ -0,0 +1,37 @@
1
+ import type { SyncCompanyUserResult, SendMessageParams, SendMessageResult, GetUpdatesV2Result, UploadURLResult, UploadFileResult, SendUserTypingParams, GetAccessURLParams, AccessURLResult } from './types.js';
2
+ /**
3
+ * 同步企业用户
4
+ */
5
+ export declare function syncCompanyUser(gateway: string, headers: Record<string, string>): Promise<SyncCompanyUserResult>;
6
+ /**
7
+ * 发送消息
8
+ */
9
+ export declare function sendMessage(gateway: string, params: SendMessageParams, headers: Record<string, string>): Promise<SendMessageResult>;
10
+ /**
11
+ * 获取 Bot 更新(长轮询)
12
+ */
13
+ export declare function getUpdates(gateway: string, timeout: number, limit: number, headers: Record<string, string>): Promise<GetUpdatesV2Result>;
14
+ /**
15
+ * 获取上传 URL
16
+ */
17
+ export declare function getUploadURL(gateway: string, fileName: string, contentType: string, md5: string, size: number, headers: Record<string, string>): Promise<UploadURLResult>;
18
+ /**
19
+ * 上传到 OSS
20
+ */
21
+ export declare function uploadToOSS(signedUrl: string, buffer: Buffer, contentType: string, callback?: string): Promise<{
22
+ id: number;
23
+ path: string;
24
+ size: number;
25
+ }>;
26
+ /**
27
+ * 上传文件(完整流程)
28
+ */
29
+ export declare function uploadFile(gateway: string, filePath: string, contentType: string, md5: string, headers: Record<string, string>): Promise<UploadFileResult>;
30
+ /**
31
+ * 发送正在输入状态
32
+ */
33
+ export declare function sendUserTyping(gateway: string, params: SendUserTypingParams, headers: Record<string, string>): Promise<void>;
34
+ /**
35
+ * 获取文件访问 URL
36
+ */
37
+ export declare function getAccessURL(gateway: string, params: GetAccessURLParams, headers: Record<string, string>): Promise<AccessURLResult>;
@@ -0,0 +1,130 @@
1
+ // src/commands/services/meetbot/api.ts
2
+ import { readFileSync } from 'node:fs';
3
+ import { request } from '../../../core/http.js';
4
+ import { outputCliError } from '../../../core/error.js';
5
+ /**
6
+ * 同步企业用户
7
+ */
8
+ export async function syncCompanyUser(gateway, headers) {
9
+ return request({
10
+ gateway,
11
+ path: '/general/SyncCompanyUser',
12
+ method: 'POST',
13
+ body: { syncAt: 0 },
14
+ headers,
15
+ });
16
+ }
17
+ /**
18
+ * 发送消息
19
+ */
20
+ export async function sendMessage(gateway, params, headers) {
21
+ return request({
22
+ gateway,
23
+ path: '/im/bot/sendMessage',
24
+ method: 'POST',
25
+ body: params,
26
+ headers,
27
+ });
28
+ }
29
+ /**
30
+ * 获取 Bot 更新(长轮询)
31
+ */
32
+ export async function getUpdates(gateway, timeout, limit, headers) {
33
+ return request({
34
+ gateway,
35
+ path: '/im/bot/getUpdatesV2',
36
+ method: 'POST',
37
+ body: { timeout, limit },
38
+ headers,
39
+ });
40
+ }
41
+ /**
42
+ * 获取上传 URL
43
+ */
44
+ export async function getUploadURL(gateway, fileName, contentType, md5, size, headers) {
45
+ return request({
46
+ gateway,
47
+ path: '/getUploadURL',
48
+ method: 'POST',
49
+ body: { originFileName: fileName, contentType, md5, size },
50
+ headers,
51
+ maxRetries: 3,
52
+ });
53
+ }
54
+ /**
55
+ * 上传到 OSS
56
+ */
57
+ export async function uploadToOSS(signedUrl, buffer, contentType, callback) {
58
+ const headers = { 'Content-Type': contentType };
59
+ if (callback)
60
+ headers['X-Oss-Callback'] = callback;
61
+ const response = await fetch(signedUrl, { method: 'PUT', headers, body: new Uint8Array(buffer) });
62
+ if (!response.ok) {
63
+ const errorBody = await response.text().catch(() => '');
64
+ outputCliError('NETWORK_ERROR', `OSS upload failed: ${response.status} - ${errorBody}`);
65
+ }
66
+ const responseText = await response.text();
67
+ let result;
68
+ try {
69
+ const parsed = JSON.parse(responseText);
70
+ result = { id: parsed.id || parsed.ID || 0, path: parsed.path || '', size: parsed.size || 0 };
71
+ }
72
+ catch {
73
+ const idMatch = responseText.match(/<id>(\d+)<\/id>/i);
74
+ const pathMatch = responseText.match(/<path>([^<]*)<\/path>/i);
75
+ const sizeMatch = responseText.match(/<size>(\d+)<\/size>/i);
76
+ result = {
77
+ id: idMatch?.[1] ? parseInt(idMatch[1], 10) : 0,
78
+ path: pathMatch?.[1] || '',
79
+ size: sizeMatch?.[1] ? parseInt(sizeMatch[1], 10) : 0,
80
+ };
81
+ }
82
+ return result;
83
+ }
84
+ /**
85
+ * 上传文件(完整流程)
86
+ */
87
+ export async function uploadFile(gateway, filePath, contentType, md5, headers) {
88
+ const fileBuffer = readFileSync(filePath);
89
+ const size = fileBuffer.length;
90
+ const uploadResult = await getUploadURL(gateway, filePath.split(/[/\\]/).pop() || filePath, contentType, md5, size, headers);
91
+ // 秒传(MD5 匹配)
92
+ if (uploadResult.id > 0 && !uploadResult.signedUrl) {
93
+ return { fileID: uploadResult.id, path: uploadResult.path, size: uploadResult.size };
94
+ }
95
+ // 上传到 OSS
96
+ const ossResult = await uploadToOSS(uploadResult.signedUrl, fileBuffer, contentType, uploadResult.callback);
97
+ return { fileID: ossResult.id, path: ossResult.path, size: ossResult.size };
98
+ }
99
+ /**
100
+ * 发送正在输入状态
101
+ */
102
+ export async function sendUserTyping(gateway, params, headers) {
103
+ return request({
104
+ gateway,
105
+ path: '/im/SendUserTyping',
106
+ method: 'POST',
107
+ body: params,
108
+ headers,
109
+ });
110
+ }
111
+ /**
112
+ * 获取文件访问 URL
113
+ */
114
+ export async function getAccessURL(gateway, params, headers) {
115
+ return request({
116
+ gateway,
117
+ path: '/im/bot/getAccessURL',
118
+ method: 'GET',
119
+ query: {
120
+ firstId: params.firstId,
121
+ secondId: params.secondId,
122
+ sessionType: params.sessionType,
123
+ seqId: params.seqId,
124
+ fileId: params.fileId,
125
+ ...(params.companyId !== undefined && { companyId: params.companyId }),
126
+ ...(params['x-oss-process'] !== undefined && { 'x-oss-process': params['x-oss-process'] }),
127
+ },
128
+ headers,
129
+ });
130
+ }
@@ -0,0 +1,4 @@
1
+ import type { Env } from '../../../types/index.js';
2
+ import type { ServiceGatewayConfig } from '../../../core/tenants.js';
3
+ export declare const meetbotConfig: ServiceGatewayConfig;
4
+ export declare function getMeetbotGateway(tenant: string, env: Env): string | undefined;
@@ -0,0 +1,21 @@
1
+ // src/commands/services/meetbot/config.ts
2
+ export const meetbotConfig = {
3
+ name: 'meetbot',
4
+ gateways: {
5
+ meet: {
6
+ test: 'https://staging-meet-api.miyachat.com',
7
+ pre: 'https://pre-meet-api.miyachat.com',
8
+ staging: 'https://staging-meet-api.miyachat.com',
9
+ beta: 'https://staging-meet-api.miyachat.com',
10
+ prod: 'https://meet-api.miyachat.com',
11
+ },
12
+ // 其他企业可以在这里扩展
13
+ // co: {
14
+ // test: 'https://...',
15
+ // prod: 'https://...',
16
+ // },
17
+ },
18
+ };
19
+ export function getMeetbotGateway(tenant, env) {
20
+ return meetbotConfig.gateways[tenant]?.[env];
21
+ }
@@ -0,0 +1,3 @@
1
+ export declare const COMMANDS: readonly ["getUsers", "sendMessage", "getUpdates", "uploadFile", "sendUserTyping", "getAccessURL"];
2
+ export type CommandName = typeof COMMANDS[number];
3
+ export declare const COMMAND_DESCRIPTIONS: Record<CommandName, string>;
@@ -0,0 +1,10 @@
1
+ // src/commands/services/meetbot/descriptions.ts
2
+ export const COMMANDS = ['getUsers', 'sendMessage', 'getUpdates', 'uploadFile', 'sendUserTyping', 'getAccessURL'];
3
+ export const COMMAND_DESCRIPTIONS = {
4
+ getUsers: 'Sync meetbot users',
5
+ sendMessage: 'Send meetbot message',
6
+ getUpdates: 'Get bot updates (long polling)',
7
+ uploadFile: 'Upload file to meetbot OSS',
8
+ sendUserTyping: 'Send typing status (0=stop, 1=typing)',
9
+ getAccessURL: 'Get file access URL',
10
+ };
@@ -0,0 +1,42 @@
1
+ export interface GetUsersOptions {
2
+ user?: string;
3
+ gateway?: string;
4
+ format: string;
5
+ }
6
+ export declare function handleGetUsers(options: GetUsersOptions): Promise<void>;
7
+ export interface SendMessageOptions {
8
+ user?: string;
9
+ gateway?: string;
10
+ to?: string;
11
+ content?: string;
12
+ group?: boolean;
13
+ company?: number;
14
+ params?: string;
15
+ }
16
+ export declare function handleSendMessage(options: SendMessageOptions): Promise<void>;
17
+ export interface GetUpdatesOptions {
18
+ user?: string;
19
+ gateway?: string;
20
+ timeout: number;
21
+ limit: number;
22
+ }
23
+ export declare function handleGetUpdates(options: GetUpdatesOptions): Promise<void>;
24
+ export interface UploadFileOptions {
25
+ user?: string;
26
+ gateway?: string;
27
+ file: string;
28
+ contentType: string;
29
+ }
30
+ export declare function handleUploadFile(options: UploadFileOptions): Promise<void>;
31
+ export interface SendUserTypingOptions {
32
+ user?: string;
33
+ gateway?: string;
34
+ params?: string;
35
+ }
36
+ export declare function handleSendUserTyping(options: SendUserTypingOptions): Promise<void>;
37
+ export interface GetAccessURLOptions {
38
+ user?: string;
39
+ gateway?: string;
40
+ params?: string;
41
+ }
42
+ export declare function handleGetAccessURL(options: GetAccessURLOptions): Promise<void>;
@@ -0,0 +1,83 @@
1
+ // src/commands/services/meetbot/handler.ts
2
+ import { getGatewayForUser } from '../../../core/auth.js';
3
+ import { outputCliError } from '../../../core/error.js';
4
+ import { outputJson, parseListFormat, parseCliParams, mergeParams } from '../../../utils/index.js';
5
+ import { formatTable } from '../../../utils/table.js';
6
+ import { getBotAuthHeader, extractBotId, buildSessionInfo, normalizeUsers, computeMD5 } from './utils.js';
7
+ import { syncCompanyUser, sendMessage, getUpdates, uploadFile, sendUserTyping, getAccessURL } from './api.js';
8
+ export async function handleGetUsers(options) {
9
+ const { user, headers } = getBotAuthHeader(options.user);
10
+ const gateway = options.gateway || getGatewayForUser(user, 'meetbot');
11
+ const result = await syncCompanyUser(gateway, headers);
12
+ const users = normalizeUsers(result);
13
+ const format = parseListFormat(options.format);
14
+ if (format === 'table') {
15
+ console.log(formatTable(users.map(u => ({ ...u })), ['userID', 'nickName']));
16
+ return;
17
+ }
18
+ outputJson(users);
19
+ }
20
+ export async function handleSendMessage(options) {
21
+ if (options.params && (options.to || options.content)) {
22
+ outputCliError('PARAM_INVALID', '--params cannot be used together with --to/--group/--company/--content.');
23
+ }
24
+ if (!options.params && (!options.to || !options.content)) {
25
+ outputCliError('PARAM_INVALID', 'Missing required options: --to and --content, or provide --params.');
26
+ }
27
+ const { user, headers } = getBotAuthHeader(options.user);
28
+ const gateway = options.gateway || getGatewayForUser(user, 'meetbot');
29
+ const botId = extractBotId(user.token);
30
+ if (botId === null) {
31
+ outputCliError('PARAM_INVALID', 'Cannot extract botId from token. Token format should be "bot_id:secret".');
32
+ }
33
+ const params = mergeParams(options);
34
+ const payload = params.sessionInfo && params.msgContent
35
+ ? params
36
+ : {
37
+ sessionInfo: buildSessionInfo(Number(options.to), botId, !!options.group, options.company ?? user.companyID ?? 1),
38
+ msgContent: {
39
+ content: String(options.content || ''),
40
+ },
41
+ };
42
+ const result = await sendMessage(gateway, payload, headers);
43
+ outputJson(result);
44
+ }
45
+ export async function handleGetUpdates(options) {
46
+ const { user, headers } = getBotAuthHeader(options.user);
47
+ const gateway = options.gateway || getGatewayForUser(user, 'meetbot');
48
+ const result = await getUpdates(gateway, options.timeout, options.limit, headers);
49
+ outputJson(result);
50
+ }
51
+ export async function handleUploadFile(options) {
52
+ const { user, headers } = getBotAuthHeader(options.user);
53
+ const gateway = options.gateway || getGatewayForUser(user, 'meetbot');
54
+ const md5 = await computeMD5(options.file);
55
+ const result = await uploadFile(gateway, options.file, options.contentType, md5, headers);
56
+ outputJson(result);
57
+ }
58
+ export async function handleSendUserTyping(options) {
59
+ if (!options.params) {
60
+ outputCliError('PARAM_INVALID', 'Missing required option: --params.');
61
+ }
62
+ const { user, headers } = getBotAuthHeader(options.user);
63
+ const gateway = options.gateway || getGatewayForUser(user, 'meetbot');
64
+ const params = parseCliParams(options.params);
65
+ if (!params.sessionInfo || params.action === undefined) {
66
+ outputCliError('PARAM_INVALID', 'Missing required fields: sessionInfo and action.');
67
+ }
68
+ await sendUserTyping(gateway, params, headers);
69
+ outputJson({ success: true });
70
+ }
71
+ export async function handleGetAccessURL(options) {
72
+ if (!options.params) {
73
+ outputCliError('PARAM_INVALID', 'Missing required option: --params.');
74
+ }
75
+ const { user, headers } = getBotAuthHeader(options.user);
76
+ const gateway = options.gateway || getGatewayForUser(user, 'meetbot');
77
+ const params = parseCliParams(options.params);
78
+ if (!params.firstId || !params.secondId || !params.sessionType || !params.seqId || !params.fileId) {
79
+ outputCliError('PARAM_INVALID', 'Missing required fields: firstId, secondId, sessionType, seqId, fileId.');
80
+ }
81
+ const result = await getAccessURL(gateway, params, headers);
82
+ outputJson(result);
83
+ }
@@ -0,0 +1,3 @@
1
+ import type { ServiceCommand } from '../../../types/index.js';
2
+ declare const meetbotService: ServiceCommand;
3
+ export default meetbotService;
@@ -0,0 +1,74 @@
1
+ // src/commands/services/meetbot/index.ts
2
+ import { registerService } from '../../../core/tenants.js';
3
+ import { meetbotConfig } from './config.js';
4
+ import { COMMAND_DESCRIPTIONS } from './descriptions.js';
5
+ import { handleGetUsers, handleSendMessage, handleGetUpdates, handleUploadFile, handleSendUserTyping, handleGetAccessURL } from './handler.js';
6
+ const meetbotService = {
7
+ name: 'meetbot',
8
+ description: 'MeetIM Bot API',
9
+ enabled: false,
10
+ register(cmd) {
11
+ registerService(meetbotConfig);
12
+ cmd.description(this.description).allowUnknownOption(false);
13
+ // 无子命令时显示帮助
14
+ cmd.action(() => {
15
+ console.log(cmd.helpInformation());
16
+ process.exitCode = 0;
17
+ });
18
+ // getUsers
19
+ cmd
20
+ .command('getUsers')
21
+ .description(COMMAND_DESCRIPTIONS.getUsers)
22
+ .option('--user <user>', 'Specify user')
23
+ .option('--gateway <url>', 'Override meetbot gateway')
24
+ .option('--format <format>', 'Output format (json, table)', 'json')
25
+ .action(handleGetUsers);
26
+ // sendMessage
27
+ cmd
28
+ .command('sendMessage')
29
+ .description(COMMAND_DESCRIPTIONS.sendMessage)
30
+ .option('--content <text>', 'Message content')
31
+ .option('--user <user>', 'Specify user')
32
+ .option('--gateway <url>', 'Override meetbot gateway')
33
+ .option('--to <id>', 'Target user/group ID')
34
+ .option('--group', 'Group chat (default: private)')
35
+ .option('--company <id>', 'Company ID (default: from user config or 1)', Number)
36
+ .option('--params <json>', 'Full JSON params')
37
+ .action(handleSendMessage);
38
+ // getUpdates
39
+ cmd
40
+ .command('getUpdates')
41
+ .description(COMMAND_DESCRIPTIONS.getUpdates)
42
+ .option('--user <user>', 'Specify user')
43
+ .option('--gateway <url>', 'Override meetbot gateway')
44
+ .option('--timeout <seconds>', 'Long polling timeout in seconds (default: 30)', Number, 30)
45
+ .option('--limit <count>', 'Max messages per fetch (default: 100)', Number, 100)
46
+ .action(handleGetUpdates);
47
+ // uploadFile
48
+ cmd
49
+ .command('uploadFile')
50
+ .description(COMMAND_DESCRIPTIONS.uploadFile)
51
+ .requiredOption('--file <path>', 'File path to upload')
52
+ .option('--user <user>', 'Specify user')
53
+ .option('--gateway <url>', 'Override meetbot gateway')
54
+ .option('--content-type <mime>', 'Content type (default: auto-detect)', 'application/octet-stream')
55
+ .action(handleUploadFile);
56
+ // sendUserTyping
57
+ cmd
58
+ .command('sendUserTyping')
59
+ .description(COMMAND_DESCRIPTIONS.sendUserTyping)
60
+ .requiredOption('--params <json>', 'JSON params: {sessionInfo, action}')
61
+ .option('--user <user>', 'Specify user')
62
+ .option('--gateway <url>', 'Override meetbot gateway')
63
+ .action(handleSendUserTyping);
64
+ // getAccessURL
65
+ cmd
66
+ .command('getAccessURL')
67
+ .description(COMMAND_DESCRIPTIONS.getAccessURL)
68
+ .requiredOption('--params <json>', 'JSON params: {firstId, secondId, sessionType, seqId, fileId, ...}')
69
+ .option('--user <user>', 'Specify user')
70
+ .option('--gateway <url>', 'Override meetbot gateway')
71
+ .action(handleGetAccessURL);
72
+ },
73
+ };
74
+ export default meetbotService;