kawazu
Version:
kawazu CLI tool for real-time chat in your editor
659 lines (641 loc) • 33.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCodechatPath = getCodechatPath;
exports.createCodechatFile = createCodechatFile;
exports.createCodechatFileIfNotExists = createCodechatFileIfNotExists;
exports.appendMessageToFile = appendMessageToFile;
exports.readFileContent = readFileContent;
exports.ensureDirectory = ensureDirectory;
exports.isValidRoomSlug = isValidRoomSlug;
exports.getCurrentRoomFromCodechat = getCurrentRoomFromCodechat;
exports.getCodechatFiles = getCodechatFiles;
exports.clearInputArea = clearInputArea;
exports.createCommandHelpFile = createCommandHelpFile;
exports.loadMessageHistory = loadMessageHistory;
exports.loadMoreMessageHistory = loadMoreMessageHistory;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const node_fetch_1 = __importDefault(require("node-fetch"));
const chalk_1 = __importDefault(require("chalk"));
const message_1 = require("./message");
function getCodechatPath(roomSlug, workingDir = process.cwd()) {
return path.join(workingDir, `${roomSlug}.codechat`);
}
async function createCodechatFile(filePath, roomSlug, username) {
const initialContent = `================================================================================
File: ${roomSlug}.codechat
================================================================================
Room: ${roomSlug}
User: ${username}
Messages: 最新10件まで表示
💭 「チャットを開始しましょう!」
📜 過去のメッセージを読み込み中...
================================================================================
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
メッセージを下の線上に書いて保存(Ctrl+S)してください
------------------------------------------------------------------------------>
メッセージを上の線上に書き
`;
await fs.writeFile(filePath, initialContent, 'utf8');
// コマンドヘルプファイルを作成
await createCommandHelpFile(path.dirname(filePath), roomSlug);
}
// 新しい関数:ファイル存在チェック付きの安全な作成
async function createCodechatFileIfNotExists(filePath, roomSlug, username) {
try {
// ファイルの存在をチェック
const fileExists = await fs.pathExists(filePath);
if (fileExists) {
console.log(`📄 既存のチャットファイルが見つかりました: ${path.basename(filePath)}`);
// 既存ファイルのユーザー名を更新(必要に応じて)
await updateUsernameInExistingFile(filePath, username);
// コマンドヘルプファイルは常に最新にする
await createCommandHelpFile(path.dirname(filePath), roomSlug);
return { created: false, existed: true };
}
else {
console.log(`📝 新しいチャットファイルを作成中: ${path.basename(filePath)}`);
await createCodechatFile(filePath, roomSlug, username);
return { created: true, existed: false };
}
}
catch (error) {
console.error('ファイル作成チェックエラー:', error);
// エラーの場合は安全のため新しいファイルを作成
await createCodechatFile(filePath, roomSlug, username);
return { created: true, existed: false };
}
}
// 既存ファイルのユーザー名を更新
async function updateUsernameInExistingFile(filePath, newUsername) {
try {
const content = await fs.readFile(filePath, 'utf8');
// ヘッダー部分のユーザー名を更新
const userLineRegex = /^ User: .+$/m;
const updatedContent = content.replace(userLineRegex, ` User: ${newUsername}`);
if (content !== updatedContent) {
await fs.writeFile(filePath, updatedContent, 'utf8');
console.log(`👤 ファイル内のユーザー名を更新しました: ${newUsername}`);
}
}
catch (error) {
console.error('ユーザー名更新エラー:', error);
// エラーは無視(ファイルが存在することが重要)
}
}
async function appendMessageToFile(filePath, message) {
try {
console.log(`🔍 ファイル書き込み開始: ${path.basename(filePath)}`);
console.log(`📝 追加するメッセージ: "${message.substring(0, 100)}${message.length > 100 ? '...' : ''}"`);
// ファイルの内容を読み取り
const currentContent = await fs.readFile(filePath, 'utf8');
console.log(`📂 現在のファイルサイズ: ${currentContent.length}文字`);
// 新しい形式の境界を特定
const headerEnd = '================================================================================';
const inputLineStart = '------------------------------------------------------------------------------>';
const firstHeaderIndex = currentContent.indexOf(headerEnd);
const secondHeaderIndex = currentContent.indexOf(headerEnd, firstHeaderIndex + 1);
const thirdHeaderIndex = currentContent.indexOf(headerEnd, secondHeaderIndex + 1);
const inputLineIndex = currentContent.lastIndexOf(inputLineStart);
console.log(`🔍 ファイル構造解析:`, {
firstHeaderIndex,
secondHeaderIndex,
thirdHeaderIndex,
inputLineIndex,
validStructure: firstHeaderIndex !== -1 && secondHeaderIndex !== -1 && thirdHeaderIndex !== -1 && inputLineIndex !== -1
});
if (firstHeaderIndex !== -1 && secondHeaderIndex !== -1 && thirdHeaderIndex !== -1 && inputLineIndex !== -1) {
// ヘッダー部分
const headerPart = currentContent.substring(0, secondHeaderIndex + headerEnd.length);
// 現在のメッセージ部分
const messagePart = currentContent.substring(secondHeaderIndex + headerEnd.length, thirdHeaderIndex);
// フッター部分(入力エリア以降)
const footerStart = currentContent.substring(thirdHeaderIndex);
console.log(`🔍 ファイル構造分割完了:`, {
headerLength: headerPart.length,
messagePartLength: messagePart.length,
footerLength: footerStart.length
});
// 既存のメッセージを抽出
const existingMessages = extractMessagesFromContent(messagePart);
console.log(`📜 既存メッセージ数: ${existingMessages.length}`);
// 新しいメッセージを追加
existingMessages.push(message);
console.log(chalk_1.default.green(`📝 メッセージ追加後: ${existingMessages.length}件`));
// 最新10件のみを保持
const limitedMessages = existingMessages.slice(-10);
console.log(chalk_1.default.blue(`📊 制限後のメッセージ数: ${limitedMessages.length}件(最新10件まで表示)`));
console.log(`🔍 制限後の最初のメッセージ: "${limitedMessages[0]?.substring(0, 30)}..."`);
console.log(`🔍 制限後の最後のメッセージ: "${limitedMessages[limitedMessages.length - 1]?.substring(0, 30)}..."`);
// 新しいメッセージ部分を構築(最新メッセージが上に来るように逆順処理)
const newMessagePart = buildMessageContentWithReverse(limitedMessages);
console.log(`🔧 新しいメッセージ部分のサイズ: ${newMessagePart.length}文字`);
// ファイル全体を再構築
const newContent = headerPart + '\n' + newMessagePart + '\n' + footerStart;
console.log(`📄 新しいファイルサイズ: ${newContent.length}文字`);
await fs.writeFile(filePath, newContent, 'utf8');
console.log(chalk_1.default.green(`✅ ファイル書き込み完了: ${path.basename(filePath)} (${limitedMessages.length}件の履歴を維持)`));
}
else {
console.error(`❌ ファイル形式が認識できません:`, {
filePath,
contentLength: currentContent.length,
headerEndCount: (currentContent.match(new RegExp(headerEnd, 'g')) || []).length,
inputLineCount: (currentContent.match(new RegExp(inputLineStart, 'g')) || []).length
});
// フォールバック: メッセージを最後に追加
const fallbackContent = currentContent + '\n' + message;
await fs.writeFile(filePath, fallbackContent, 'utf8');
console.log(`⚠️ フォールバック書き込み完了`);
}
}
catch (error) {
console.error(`❌ ファイル書き込みエラー:`, {
filePath,
message: message.substring(0, 100),
error: error.message,
stack: error.stack
});
// 重要なエラーの場合は再スロー
throw error;
}
}
function extractMessagesFromContent(messageSection) {
const messages = [];
const lines = messageSection.split('\n');
let currentMessage = '';
let collectingMessage = false;
console.log(`🔍 メッセージ抽出開始: ${lines.length}行を処理`);
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
console.log(`🔍 処理中の行 ${i}: "${line}"`);
// メッセージの開始を検出(名前 アイコン 時刻の形式)
// より厳密なパターンマッチング
const messageStartPattern = /^[^\s]+\s+[^\s]+\s+\d{1,2}:\d{2}/;
const ansiPattern = /^\[[0-9;]+m[^\s]+\s+[^\s]+.*\[[0-9;]*m/;
if (messageStartPattern.test(line) || ansiPattern.test(line)) {
console.log(`🔍 メッセージ開始を検出: "${line}"`);
// 前のメッセージを保存
if (currentMessage.trim()) {
messages.push(currentMessage.trim());
console.log(`📝 メッセージ保存: "${currentMessage.trim().substring(0, 30)}..."`);
}
currentMessage = line;
collectingMessage = true;
}
else if (collectingMessage && line.trim() !== '') {
// メッセージの続きを追加(インデントされた行)
currentMessage += '\n' + line;
console.log(`📝 メッセージ続行: "${line}"`);
}
else if (collectingMessage && line.trim() === '') {
// 空行でメッセージ終了
if (currentMessage.trim()) {
messages.push(currentMessage.trim());
console.log(`📝 メッセージ終了・保存: "${currentMessage.trim().substring(0, 30)}..."`);
}
currentMessage = '';
collectingMessage = false;
}
}
// 最後のメッセージを保存
if (currentMessage.trim()) {
messages.push(currentMessage.trim());
console.log(`📝 最後のメッセージ保存: "${currentMessage.trim().substring(0, 30)}..."`);
}
// フィルタリング前後のメッセージ数を記録
const unfilteredCount = messages.length;
const filteredMessages = messages.filter(msg => {
const isValid = msg.length > 0 &&
!msg.includes('💭 チャットを開始しましょう!') &&
!msg.includes('💭 「チャットを開始しましょう!」') &&
!msg.includes('古いメッセージは自動削除されます');
if (!isValid) {
console.log(`🗑️ フィルタで除外: "${msg.substring(0, 30)}..."`);
}
return isValid;
});
console.log(`📊 メッセージ抽出結果: ${unfilteredCount}件 → ${filteredMessages.length}件`);
return filteredMessages;
}
function extractExistingMessages(historySection) {
const messages = [];
const lines = historySection.split('\n');
let currentMessage = '';
let insideMessage = false;
for (const line of lines) {
// メッセージの開始を検出(┌─ で始まる行)
if (line.includes('┌─') && !line.includes('チャット履歴')) {
if (currentMessage.trim()) {
messages.push(currentMessage.trim());
}
currentMessage = line + '\n';
insideMessage = true;
}
else if (insideMessage) {
currentMessage += line + '\n';
// メッセージの終了を検出(└─ で始まる行)
if (line.includes('└─')) {
messages.push(currentMessage.trim());
currentMessage = '';
insideMessage = false;
}
}
}
return messages.filter(msg => msg.length > 0 && !msg.includes('💭 チャットを開始しましょう!') && !msg.includes('💭 「チャットを開始しましょう!」'));
}
function buildMessageContent(messages) {
if (messages.length === 0) {
return '💭 「チャットを開始しましょう!」';
}
// メッセージを最新順(新しいものを上)で表示するために逆順にする
const reversedMessages = [...messages].reverse();
// 7つ以上のメッセージがある場合は、古いメッセージ削除の表示を追加
let content = '';
if (messages.length >= 7) {
content += '▼ 古いメッセージは自動削除されます(7つまで表示、最新順)\n\n';
}
// メッセージを追加(最新が上に来るように)
for (let i = 0; i < reversedMessages.length; i++) {
content += reversedMessages[i];
if (i < reversedMessages.length - 1) {
content += '\n';
}
}
return content;
}
function buildMessageContentWithoutReverse(messages) {
if (messages.length === 0) {
return '💭 「チャットを開始しましょう!」';
}
// 7つ以上のメッセージがある場合は、古いメッセージ削除の表示を追加
let content = '';
if (messages.length >= 7) {
content += '▼ 古いメッセージは自動削除されます(7つまで表示、最新順)\n\n';
}
// メッセージを追加(既に正しい順序なので逆順処理なし)
for (let i = 0; i < messages.length; i++) {
content += messages[i];
if (i < messages.length - 1) {
content += '\n';
}
}
return content;
}
function buildMessageContentWithReverse(messages) {
if (messages.length === 0) {
return '💭 「チャットを開始しましょう!」';
}
// 10件以上のメッセージがある場合は、古いメッセージ削除の表示を追加
let content = '';
if (messages.length >= 10) {
content += '▼ 最新10件のメッセージを表示中(古いメッセージは自動削除されます)\n\n';
}
else if (messages.length >= 5) {
content += `▼ ${messages.length}件のメッセージ履歴を表示中\n\n`;
}
// メッセージを逆順で追加(最新メッセージが上に来るように)
const reversedMessages = [...messages].reverse();
console.log(`🔄 メッセージ順序逆転: ${messages.length}件 → 最新が上`);
for (let i = 0; i < reversedMessages.length; i++) {
content += reversedMessages[i];
if (i < reversedMessages.length - 1) {
content += '\n';
}
}
return content;
}
function buildChatHistory(messages) {
const chatHistoryStart = '╔═ チャット履歴 ═════════════════════════════════════════════════════════════╗';
const chatHistoryEnd = '╚═══════════════════════════════════════════════════════════════════════════╝';
let historyContent = chatHistoryStart + '\n';
if (messages.length === 0) {
// メッセージがない場合は初期状態
for (let i = 0; i < 18; i++) {
if (i === 9) {
historyContent += '║ 💭 「チャットを開始しましょう!」 ║\n';
}
else {
historyContent += '║ ║\n';
}
}
}
else {
// メッセージを最新順で表示(逆順処理は呼び出し側で実施済み前提)
let lineCount = 0;
const maxLines = 18;
for (const message of messages) {
const messageLines = message.split('\n');
// メッセージの前に空行を追加
if (lineCount > 0 && lineCount < maxLines) {
historyContent += '║ ║\n';
lineCount++;
}
// メッセージを追加
for (const line of messageLines) {
if (lineCount < maxLines) {
historyContent += line + '\n';
lineCount++;
}
}
}
// 残りの行を空行で埋める
while (lineCount < maxLines) {
historyContent += '║ ║\n';
lineCount++;
}
}
historyContent += chatHistoryEnd;
return historyContent;
}
async function readFileContent(filePath) {
try {
return await fs.readFile(filePath, 'utf8');
}
catch (error) {
console.error('ファイル読み取りエラー:', error);
return '';
}
}
async function ensureDirectory(dirPath) {
await fs.ensureDir(dirPath);
}
function isValidRoomSlug(slug) {
return /^[a-zA-Z0-9-_]+$/.test(slug);
}
async function getCurrentRoomFromCodechat() {
try {
const currentDir = process.cwd();
const files = await fs.readdir(currentDir);
// .codechatファイルを探す
const codechatFiles = files.filter(file => file.endsWith('.codechat'));
if (codechatFiles.length === 0) {
return null;
}
// 最初の.codechatファイルからルーム名を抽出
const codechatFile = codechatFiles[0];
const roomSlug = codechatFile.replace('.codechat', '');
return roomSlug;
}
catch (error) {
console.error('ルーム情報取得エラー:', error);
return null;
}
}
async function getCodechatFiles() {
try {
const currentDir = process.cwd();
const files = await fs.readdir(currentDir);
return files.filter(file => file.endsWith('.codechat'));
}
catch (error) {
console.error('ファイル一覧取得エラー:', error);
return [];
}
}
async function clearInputArea(filePath) {
try {
const currentContent = await fs.readFile(filePath, 'utf8');
// 入力線の上の部分をクリア
const inputLineStart = '------------------------------------------------------------------------------>';
const inputLineIndex = currentContent.lastIndexOf(inputLineStart);
if (inputLineIndex !== -1) {
// 入力線より前の部分を取得
const beforeInputLine = currentContent.substring(0, inputLineIndex);
// 最後の区切り線(================)を見つける
const lastSeparator = '================================================================================';
const lastSeparatorIndex = beforeInputLine.lastIndexOf(lastSeparator);
if (lastSeparatorIndex !== -1) {
const beforeMessages = beforeInputLine.substring(0, lastSeparatorIndex + lastSeparator.length);
const inputArea = currentContent.substring(inputLineIndex);
// 入力エリアをクリア(空行2つ + 入力線以降)
const cleanContent = beforeMessages + '\n\n\n' + inputArea;
await fs.writeFile(filePath, cleanContent, 'utf8');
}
}
}
catch (error) {
console.error('入力エリアクリアエラー:', error);
}
}
async function createCommandHelpFile(dirPath, roomSlug) {
const helpFilePath = path.join(dirPath, `${roomSlug}-commands.kawazu`);
const helpContent = `================================================================================
Kawazu コマンドリファレンス - ${roomSlug}
================================================================================
📋 基本操作:
• メッセージ送信: .codechatファイルで編集後 Ctrl+S
• チャット終了: Ctrl+C
🔧 利用可能なコマンド:
📁 ファイル共有:
kawazu share /path/to/file.js
└─ ファイルを他の参加者と共有(承認が必要)
👤 ユーザー情報:
kawazu profile ユーザー名
└─ 指定ユーザーのプロフィールを表示
🏠 ルーム操作:
kawazu list
└─ 参加可能なルーム一覧を表示
kawazu create "新しいルーム名"
└─ 新しいルームを作成
🔐 認証・プラン:
kawazu login
└─ Webアプリアカウントでログイン
kawazu logout
└─ ログアウト
kawazu whoami
└─ 現在のユーザー情報を表示
kawazu plan
└─ サブスクリプションプラン情報を確認
💬 メッセージ形式:
• プレーンテキスト
• コードブロック: \`\`\`言語名 で開始
• 絵文字対応
📊 制限事項:
• メッセージ履歴: 50件まで(古いものは自動削除、SNSのように過去のメッセージも表示)
• ファイル共有: プランに応じた容量制限
• ルーム作成数: プランに応じた制限
================================================================================
`;
await fs.writeFile(helpFilePath, helpContent, 'utf8');
console.log(`📖 コマンドヘルプファイルを作成しました: ${roomSlug}-commands.kawazu`);
}
// メッセージ履歴を取得してファイルに反映する関数(SNSのように全履歴を表示)
async function loadMessageHistory(codechatFile, roomSlug, serverUrl, limit = 50 // 入室時に十分なメッセージを取得
) {
try {
console.log(chalk_1.default.blue('📜 メッセージ履歴を取得中...'));
console.log(chalk_1.default.gray(`🔍 API URL: ${serverUrl}/api/messages/${roomSlug}?limit=${limit}`));
// サーバーからメッセージ履歴を取得
const response = await (0, node_fetch_1.default)(`${serverUrl}/api/messages/${roomSlug}?limit=${limit}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
console.log(chalk_1.default.gray(`🔍 API応答ステータス: ${response.status}`));
if (!response.ok) {
const errorText = await response.text();
console.log(chalk_1.default.yellow('⚠️ メッセージ履歴の取得に失敗しました (サーバー応答: ' + response.status + ')'));
console.log(chalk_1.default.gray(' エラー詳細:', errorText));
return;
}
const result = await response.json();
console.log(chalk_1.default.gray('🔍 API応答:', JSON.stringify(result, null, 2)));
if (!result.success || !result.data || !result.data.messages) {
console.log(chalk_1.default.yellow('⚠️ メッセージ履歴が見つかりませんでした'));
console.log(chalk_1.default.gray(' 応答構造:', { success: result.success, hasData: !!result.data, hasMessages: !!(result.data && result.data.messages) }));
return;
}
const messages = result.data.messages;
if (messages.length === 0) {
console.log(chalk_1.default.gray('💭 まだメッセージがありません'));
return;
}
console.log(chalk_1.default.green(`📜 ${messages.length}件のメッセージ履歴を取得しました`));
// メッセージを適切な形式にフォーマット
const formattedMessages = [];
for (const message of messages) {
const formattedMessage = (0, message_1.formatMessage)(message.username, message.content, message.created_at, false // 履歴のメッセージは他人のメッセージとして扱う
);
formattedMessages.push(formattedMessage);
}
// 既存のファイル内容を読み取り
const currentContent = await fs.readFile(codechatFile, 'utf8');
// ファイルの構造を解析
const headerEnd = '================================================================================';
const inputLineStart = '------------------------------------------------------------------------------>';
const firstHeaderIndex = currentContent.indexOf(headerEnd);
const secondHeaderIndex = currentContent.indexOf(headerEnd, firstHeaderIndex + 1);
const thirdHeaderIndex = currentContent.indexOf(headerEnd, secondHeaderIndex + 1);
const inputLineIndex = currentContent.lastIndexOf(inputLineStart);
if (firstHeaderIndex !== -1 && secondHeaderIndex !== -1 && thirdHeaderIndex !== -1 && inputLineIndex !== -1) {
// ヘッダー部分
const headerPart = currentContent.substring(0, secondHeaderIndex + headerEnd.length);
// フッター部分(入力エリア以降)
const footerStart = currentContent.substring(thirdHeaderIndex);
// 最新10件のメッセージを取得
const limitedMessages = formattedMessages.slice(-10);
console.log(chalk_1.default.blue(`📊 履歴読み込み: ${formattedMessages.length}件 → ${limitedMessages.length}件を表示(最新10件まで表示)`));
// メッセージ部分を構築(最新メッセージが上に来るように)
const messageContent = buildMessageContentWithReverse(limitedMessages);
// ファイル全体を再構築
const newContent = headerPart + '\n' + messageContent + '\n' + footerStart;
await fs.writeFile(codechatFile, newContent, 'utf8');
console.log(chalk_1.default.green(`✅ メッセージ履歴をファイルに反映しました (${limitedMessages.length}件の履歴を表示)`));
}
else {
console.log(chalk_1.default.yellow('⚠️ ファイル形式が予期した構造と異なります'));
}
}
catch (error) {
console.log(chalk_1.default.yellow(`⚠️ メッセージ履歴の取得中にエラーが発生しました: ${error.message}`));
console.log(chalk_1.default.gray('新しいメッセージの投稿は正常に動作します'));
}
}
// 追加のメッセージ履歴を取得する関数(「もっと読み込む」機能)
async function loadMoreMessageHistory(codechatFile, roomSlug, serverUrl, offset = 0, limit = 100) {
try {
console.log(chalk_1.default.blue(`📜 追加のメッセージ履歴を取得中(${offset}件目から${limit}件)...`));
// サーバーからメッセージ履歴を取得(オフセット付き)
const response = await (0, node_fetch_1.default)(`${serverUrl}/api/messages/${roomSlug}?limit=${limit}&offset=${offset}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
console.log(chalk_1.default.yellow('⚠️ 追加メッセージ履歴の取得に失敗しました (サーバー応答: ' + response.status + ')'));
return;
}
const result = await response.json();
if (!result.success || !result.data || !result.data.messages) {
console.log(chalk_1.default.yellow('⚠️ 追加メッセージ履歴が見つかりませんでした'));
return;
}
const newMessages = result.data.messages;
if (newMessages.length === 0) {
console.log(chalk_1.default.gray('💭 これ以上古いメッセージはありません'));
return;
}
console.log(chalk_1.default.green(`📜 ${newMessages.length}件の追加メッセージ履歴を取得しました`));
// 既存のファイル内容を読み取り
const currentContent = await fs.readFile(codechatFile, 'utf8');
// 既存のメッセージを抽出
const headerEnd = '================================================================================';
const inputLineStart = '------------------------------------------------------------------------------>';
const firstHeaderIndex = currentContent.indexOf(headerEnd);
const secondHeaderIndex = currentContent.indexOf(headerEnd, firstHeaderIndex + 1);
const thirdHeaderIndex = currentContent.indexOf(headerEnd, secondHeaderIndex + 1);
const inputLineIndex = currentContent.lastIndexOf(inputLineStart);
if (firstHeaderIndex !== -1 && secondHeaderIndex !== -1 && thirdHeaderIndex !== -1 && inputLineIndex !== -1) {
// ヘッダー部分
const headerPart = currentContent.substring(0, secondHeaderIndex + headerEnd.length);
// 現在のメッセージ部分
const currentMessagePart = currentContent.substring(secondHeaderIndex + headerEnd.length, thirdHeaderIndex);
// フッター部分(入力エリア以降)
const footerStart = currentContent.substring(thirdHeaderIndex);
// 既存のメッセージを抽出
const existingMessages = extractMessagesFromContent(currentMessagePart);
// 新しいメッセージを適切な形式にフォーマット
const formattedNewMessages = [];
for (const message of newMessages) {
const formattedMessage = (0, message_1.formatMessage)(message.username, message.content, message.created_at, false);
formattedNewMessages.push(formattedMessage);
}
// 古いメッセージを既存のメッセージの前に追加
const allMessages = [...formattedNewMessages, ...existingMessages];
// 最新100件まで保持(ファイルサイズ制限を考慮)
const limitedMessages = allMessages.slice(-100);
console.log(chalk_1.default.blue(`📊 追加読み込み後: ${allMessages.length}件 → ${limitedMessages.length}件を表示`));
// メッセージ部分を構築
const messageContent = buildMessageContentWithReverse(limitedMessages);
// ファイル全体を再構築
const newContent = headerPart + '\n' + messageContent + '\n' + footerStart;
await fs.writeFile(codechatFile, newContent, 'utf8');
console.log(chalk_1.default.green(`✅ 追加メッセージ履歴をファイルに反映しました (${newMessages.length}件の古いメッセージを追加)`));
}
else {
console.log(chalk_1.default.yellow('⚠️ ファイル形式が予期した構造と異なります'));
}
}
catch (error) {
console.log(chalk_1.default.yellow(`⚠️ 追加メッセージ履歴の取得中にエラーが発生しました: ${error.message}`));
}
}