v2.2.297: stocks 목록 클라우드 백업 — Sheets _backup 탭 자동 백업 + /stocks backup·restore
로컬 .astra/stocks.json 뿐이던 워치리스트를 spreadsheet _backup 탭에 원본 JSON 그대로 자동 백업(변경 시 30초 디바운스). 새 컴퓨터에서는 /stocks restore 한 번으로 복원. sheetsApi 에 ensureSheetTab/clearSheetRange 추가, writeStocksStore 성공 시 변경 리스너 발화로 모든 변경 경로 포착. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { AIService } from '../../core/services';
|
||||
import { classifyAll } from './signalClassifier';
|
||||
import { writeStocksStore } from './stocksStore';
|
||||
import { syncToSheets } from './sheetsSync';
|
||||
import { backupToSheet, restoreFromSheet } from './backupSync';
|
||||
import { judgeStock } from './llmJudge';
|
||||
import { sendStocksReport, buildReportText } from './telegramReport';
|
||||
import { runOnceNow } from './stocksWatcher';
|
||||
@@ -27,6 +28,8 @@ import type { ClassifiedStock, Stock } from './types';
|
||||
* /stocks check — 현재가 갱신 (Yahoo)
|
||||
* /stocks signal — 매수사정권 종목만
|
||||
* /stocks sync — Google Sheets 동기화
|
||||
* /stocks backup — 원본 목록을 Sheets `_backup` 탭에 백업
|
||||
* /stocks restore — `_backup` 탭에서 목록 복원 (기기 이전용)
|
||||
* /stocks add <심볼> <이름> [투자성향]
|
||||
* /stocks remove <심볼>
|
||||
* /stocks judge <심볼> — LLM 4-criteria 평가
|
||||
@@ -116,6 +119,25 @@ async function cmdSync(view: Webview | undefined, context: vscode.ExtensionConte
|
||||
}
|
||||
}
|
||||
|
||||
async function cmdBackup(view: Webview | undefined, context: vscode.ExtensionContext): Promise<void> {
|
||||
chunk(view, '\n☁️ Google Sheets `_backup` 탭으로 백업 중...\n');
|
||||
const r = await backupToSheet(context);
|
||||
chunk(view, r.ok
|
||||
? `\n✅ 백업 완료: ${r.count}개 종목. 새 컴퓨터에서는 \`/stocks restore\` 로 복원하세요.\n`
|
||||
: `\n❌ 백업 실패: ${r.reason}\n`);
|
||||
}
|
||||
|
||||
async function cmdRestore(view: Webview | undefined, context: vscode.ExtensionContext): Promise<void> {
|
||||
chunk(view, '\n☁️ Google Sheets `_backup` 탭에서 복원 중...\n');
|
||||
const r = await restoreFromSheet(context);
|
||||
if (!r.ok) {
|
||||
chunk(view, `\n❌ 복원 실패: ${r.reason}\n`);
|
||||
return;
|
||||
}
|
||||
const when = r.backedUpAt ? ` (백업 시각: ${r.backedUpAt})` : '';
|
||||
chunk(view, `\n✅ 복원 완료: ${r.count}개 종목${when} — 기존 로컬 ${r.previousCount}개를 교체했습니다.\n`);
|
||||
}
|
||||
|
||||
async function cmdAdd(arg: string, view: Webview | undefined): Promise<void> {
|
||||
const parts = arg.split(/\s+/);
|
||||
if (parts.length < 2) {
|
||||
@@ -645,6 +667,8 @@ function cmdHelp(view: Webview | undefined): void {
|
||||
' `/stocks check` — 현재가 갱신',
|
||||
' `/stocks signal` — 매수사정권 종목만',
|
||||
' `/stocks sync` — Google Sheets 동기화',
|
||||
' `/stocks backup` — 목록 원본을 Sheets `_backup` 탭에 백업 (변경 시 자동 백업도 됨)',
|
||||
' `/stocks restore` — `_backup` 탭에서 목록 복원 (새 컴퓨터 이전용)',
|
||||
' `/stocks add <심볼> <이름>` — 종목 추가 (예: `add 005930 삼성전자` / `add AAPL Apple`)',
|
||||
' `/stocks remove <심볼>` — 종목 제거',
|
||||
' `/stocks judge <심볼>` — LLM 4-criteria 평가 (stocks.json 등록 종목)',
|
||||
@@ -683,6 +707,12 @@ export async function handleStocksCommand(
|
||||
case 'sync':
|
||||
if (!context) { chunk(view, '\n❌ ExtensionContext 없음 (sync 불가).\n'); return true; }
|
||||
await cmdSync(view, context); return true;
|
||||
case 'backup':
|
||||
if (!context) { chunk(view, '\n❌ ExtensionContext 없음 (backup 불가).\n'); return true; }
|
||||
await cmdBackup(view, context); return true;
|
||||
case 'restore':
|
||||
if (!context) { chunk(view, '\n❌ ExtensionContext 없음 (restore 불가).\n'); return true; }
|
||||
await cmdRestore(view, context); return true;
|
||||
case 'add': await cmdAdd(rest, view); return true;
|
||||
case 'remove': case 'rm': await cmdRemove(rest, view); return true;
|
||||
case 'judge': await cmdJudge(rest, view); return true;
|
||||
|
||||
Reference in New Issue
Block a user