import { Command } from 'commander' import { handleError } from '@/shared/utils/error-handler' import { formatOutput } from '@/shared/utils/output' import { type BotOption, getClient } from './shared' async function sendAction(channelInput: string, text: string, options: BotOption & { thread?: string }): Promise { try { const client = await getClient(options) const channel = await client.resolveChannel(channelInput) const result = await client.postMessage(channel, text, { thread_ts: options.thread, }) console.log( formatOutput( { ts: result.ts, channel, text: result.text, thread_ts: result.thread_ts, }, options.pretty, ), ) } catch (error) { handleError(error as Error) } } async function listAction(channelInput: string, options: BotOption & { limit?: string }): Promise { try { const client = await getClient(options) const channel = await client.resolveChannel(channelInput) const limit = options.limit ? parseInt(options.limit, 10) : 20 const messages = await client.getConversationHistory(channel, { limit }) console.log(formatOutput(messages, options.pretty)) } catch (error) { handleError(error as Error) } } async function getAction(channelInput: string, ts: string, options: BotOption): Promise { try { const client = await getClient(options) const channel = await client.resolveChannel(channelInput) const message = await client.getMessage(channel, ts) if (!message) { console.log(formatOutput({ error: 'Message not found' }, options.pretty)) process.exit(1) } console.log(formatOutput(message, options.pretty)) } catch (error) { handleError(error as Error) } } async function editAction(channelInput: string, ts: string, text: string, options: BotOption): Promise { try { const client = await getClient(options) const channel = await client.resolveChannel(channelInput) const message = await client.updateMessage(channel, ts, text) console.log( formatOutput( { ts: message.ts, text: message.text, type: message.type, user: message.user, }, options.pretty, ), ) } catch (error) { handleError(error as Error) } } async function deleteAction(channelInput: string, ts: string, options: BotOption & { force?: boolean }): Promise { try { if (!options.force) { console.log(formatOutput({ warning: 'Use --force to confirm deletion', ts }, options.pretty)) process.exit(1) } const client = await getClient(options) const channel = await client.resolveChannel(channelInput) await client.deleteMessage(channel, ts) console.log(formatOutput({ deleted: ts }, options.pretty)) } catch (error) { handleError(error as Error) } } async function typingAction(channelInput: string, threadTs: string, status: string, options: BotOption): Promise { try { const client = await getClient(options) const channel = await client.resolveChannel(channelInput) await client.setAssistantStatus(channel, threadTs, status) console.log(formatOutput({ channel, thread_ts: threadTs, status }, options.pretty)) } catch (error) { handleError(error as Error) } } async function repliesAction( channelInput: string, threadTs: string, options: BotOption & { limit?: string }, ): Promise { try { const client = await getClient(options) const channel = await client.resolveChannel(channelInput) const limit = options.limit ? parseInt(options.limit, 10) : 100 const messages = await client.getThreadReplies(channel, threadTs, { limit }) console.log(formatOutput(messages, options.pretty)) } catch (error) { handleError(error as Error) } } export const messageCommand = new Command('message') .description('Message commands') .addCommand( new Command('send') .description('Send a message to a channel') .argument('', 'Channel ID or name') .argument('', 'Message text') .option('--thread ', 'Thread timestamp for replies') .option('--bot ', 'Use specific bot') .option('--pretty', 'Pretty print JSON output') .action(sendAction), ) .addCommand( new Command('list') .description('List messages in a channel') .argument('', 'Channel ID or name') .option('--limit ', 'Number of messages to fetch', '20') .option('--bot ', 'Use specific bot') .option('--pretty', 'Pretty print JSON output') .action(listAction), ) .addCommand( new Command('get') .description('Get a single message') .argument('', 'Channel ID or name') .argument('', 'Message timestamp') .option('--bot ', 'Use specific bot') .option('--pretty', 'Pretty print JSON output') .action(getAction), ) .addCommand( new Command('edit') .description('Edit a message') .argument('', 'Channel ID or name') .argument('', 'Message timestamp') .argument('', 'New message text') .option('--bot ', 'Use specific bot') .option('--pretty', 'Pretty print JSON output') .action(editAction), ) .addCommand( new Command('delete') .description('Delete a message') .argument('', 'Channel ID or name') .argument('', 'Message timestamp') .option('--force', 'Skip confirmation') .option('--bot ', 'Use specific bot') .option('--pretty', 'Pretty print JSON output') .action(deleteAction), ) .addCommand( new Command('typing') .description('Set typing status in an AI Assistant thread (e.g. "is typing...")') .argument('', 'Channel ID or name') .argument('', 'Thread timestamp') .argument('[status]', 'Status text (pass empty string to clear)', 'is typing...') .option('--bot ', 'Use specific bot') .option('--pretty', 'Pretty print JSON output') .action(typingAction), ) .addCommand( new Command('replies') .description('Get thread replies') .argument('', 'Channel ID or name') .argument('', 'Thread timestamp') .option('--limit ', 'Number of replies to fetch', '100') .option('--bot ', 'Use specific bot') .option('--pretty', 'Pretty print JSON output') .action(repliesAction), )