From 89f8ea19f183814b8e4ab56ce6e670742ab24a8d Mon Sep 17 00:00:00 2001 From: kappa Date: Sun, 18 Jan 2026 13:12:26 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Email=20Routing=20MIME=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=20=EA=B0=9C=EC=84=A0=20+=20=EB=A0=88=EA=B1=B0?= =?UTF-8?q?=EC=8B=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Email Routing에서 수신한 이메일 파싱 수정 - Quoted-Printable UTF-8 디코딩 함수 추가 - HTML
태그를 줄바꿈으로 변환 - SMS 키워드 위치 기반 본문 추출 - 레거시 코드 삭제 - /api/bank-notification 엔드포인트 제거 (Email Routing으로 대체) - BANK_API_SECRET 관련 코드 및 문서 제거 - DEPOSIT_AGENT_ID 제거 (Assistants API → 코드 직접 처리) - CLI 테스트 클라이언트 개선 - .env 파일 자동 로드 지원 - WEBHOOK_SECRET 환경변수 불필요 - 문서 업데이트 - NAMECHEAP_API_KEY 설명 명확화 (래퍼 인증 키) - CLI 테스트 섹션 추가 Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 51 ++++---------- README.md | 114 +++++++++++++++--------------- scripts/chat.ts | 18 ++++- src/deposit-agent.ts | 5 +- src/index.ts | 157 +++++++++++++----------------------------- src/openai-service.ts | 11 +-- src/types.ts | 1 - wrangler.toml | 14 ++-- 8 files changed, 156 insertions(+), 215 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 35f6a25..056ca56 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,5 +1,8 @@ # CLAUDE.md +> 🔧 **개발자용 문서**: 기술 상세, 코드 패턴, 트러블슈팅 +> 📖 **[README.md](./README.md)**: 기능 소개, 배포 가이드, 사용법 + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Auto-Read on Start @@ -69,8 +72,8 @@ npm run chat # CLI 테스트 클라이언트 **CLI 테스트 클라이언트:** ```bash -# 환경변수 설정 -export WEBHOOK_SECRET="..." # Vault: secret/data/telegram-bot +# .env 파일 생성 (최초 1회) +echo 'WEBHOOK_SECRET=...' > .env # Vault: secret/data/telegram-bot # 대화형 모드 npm run chat @@ -84,6 +87,7 @@ npm run chat "날씨 알려줘" wrangler secret put BOT_TOKEN # Telegram Bot Token wrangler secret put WEBHOOK_SECRET # Webhook 검증용 wrangler secret put OPENAI_API_KEY # OpenAI API 키 +wrangler secret put NAMECHEAP_API_KEY # namecheap-api 래퍼 인증 키 ``` **Webhook 설정:** @@ -223,7 +227,7 @@ Telegram Webhook → Security Validation → Command/Message Router | 문서 | `lookup_docs` | Context7 | 문서, 사용법, API | | 도메인 | `manage_domain` | 코드 직접 처리 → Namecheap | 도메인, 네임서버, WHOIS | | 도메인 추천 | `suggest_domains` | GPT + Namecheap | **도메인 추천, 도메인 제안, 도메인 아이디어** | -| 예치금 | `manage_deposit` | 코드 직접 처리 → D1 | **입금, 충전, 잔액, 계좌, 송금** | +| 예치금 | `manage_deposit` | 코드 직접 처리 | **입금, 충전, 잔액, 계좌, 송금** | **Data Layer (D1 SQLite):** | 테이블 | 용도 | 주요 컬럼 | @@ -351,18 +355,6 @@ case 'new_tool': **로그:** `[search_web] 번역: "판골린 VPN" → "Pangolin VPN"` -### Deposit Agent 프롬프트 수정 방법 -```bash -# Vault에서 API 키 조회 -curl -s -H "X-Vault-Token: hvs.xxx" https://vault.anvil.it.com/v1/secret/data/openai - -# Assistant 프롬프트 업데이트 -curl -X POST 'https://api.openai.com/v1/assistants/asst_XMoVGU7ZwRpUPI6PHGvRNm8E' \ - -H 'Authorization: Bearer sk-xxx' \ - -H 'OpenAI-Beta: assistants=v2' \ - -d @update-agent.json -``` - --- ## Configuration @@ -375,7 +367,6 @@ curl -X POST 'https://api.openai.com/v1/assistants/asst_XMoVGU7ZwRpUPI6PHGvRNm8E | `DOMAIN_OWNER_ID` | - | 도메인 관리 권한 Telegram ID | | `DEPOSIT_ADMIN_ID` | - | 예치금 관리 권한 Telegram ID | | `WEBHOOK_SECRET` | - | Telegram Webhook 인증 (wrangler secret, Vault: telegram-bot) | -| `BANK_API_SECRET` | - | 입금 알림 API 인증 키 (wrangler secret) | | `BRAVE_API_KEY` | - | Brave Search API 키 (wrangler secret) | | `DEPOSIT_API_SECRET` | - | Deposit API 인증 키 (namecheap-api용, wrangler secret) | @@ -392,8 +383,7 @@ curl -X POST 'https://api.openai.com/v1/assistants/asst_XMoVGU7ZwRpUPI6PHGvRNm8E | wttr.in | 날씨 | wttr.in | - | | Brave Search | 검색 | api.search.brave.com | Free AI 플랜 (2,000/월) | | Vault | API 키 관리 | vault.anvil.it.com | - | -| Gmail | 입금 SMS 수신 | deposit.anvil@gmail.com | Apps Script 연동 | -| Apps Script | Gmail → Worker 연동 | script.google.com | 1분마다 실행, message_id 중복 방지 | +| Email Routing | 입금 SMS 수신 | Cloudflare Email Routing | Worker email handler로 직접 처리 | ### Cloudflare AI Gateway @@ -423,10 +413,8 @@ URL: gateway.ai.cloudflare.com/v1/{account_id}/telegram-bot/openai/... ↓ 매칭 O → confirmed + 잔액↑ | 매칭 X → pending -[시나리오 2: SMS 먼저 - Gmail → Apps Script → Worker] -은행 SMS → Gmail(deposit.anvil@gmail.com) → Apps Script (1분마다) - ↓ - POST /api/bank-notification +[시나리오 2: SMS 먼저 - Email Routing] +은행 SMS → 메일 전달 → Cloudflare Email Routing → Worker (email handler) ↓ 파싱 → bank_notifications 저장 ↓ @@ -442,22 +430,9 @@ URL: gateway.ai.cloudflare.com/v1/{account_id}/telegram-bot/openai/... | 자동 매칭 성공 | ✅ 입금액 + 현재 잔액 | ✅ 입금 정보 + 매칭 완료 | | 매칭 대기 (SMS만) | - | ✅ 입금 정보 + 대기 상태 | -**Gmail → Worker 연동:** -- Gmail 계정: `deposit.anvil@gmail.com` -- Apps Script: 1분마다 `is:unread 입금` 검색 → Worker API 호출 -- 중복 방지: Gmail message_id 기반 - -**API 엔드포인트:** -``` -POST /api/bank-notification -Content-Type: application/json - -{ - "content": "[Web발신]\n하나,01/16, 23:30\n427******27104\n입금5원\n황병하", - "messageId": "19bc737b3415596a", - "secret": "BANK_API_SECRET 값" -} -``` +**Email Routing 설정:** +- Cloudflare Dashboard → Email → Email Routing → Routes +- 수신 주소 → Worker: `telegram-summary-bot` 라우팅 **입금 계좌:** 하나은행 427-910018-27104 (주식회사 아이언클래드) - Vault 경로: `secret/companies/ironclad-corp` diff --git a/README.md b/README.md index 4af20bf..1a2d408 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ > Cloudflare Workers + D1 + OpenAI를 활용한 사용자 프로필 기반 텔레그램 봇 +**📖 이 문서**: 기능 소개, 배포 가이드, 사용법 (사용자/운영자용) +**🔧 [CLAUDE.md](./CLAUDE.md)**: 기술 상세, 코드 패턴, 트러블슈팅 (개발자용) + ## 목차 1. [개요](#개요) @@ -26,8 +29,7 @@ - **Context7 연동**: 프로그래밍 라이브러리 공식 문서 실시간 조회 - **동적 도구 로딩**: 메시지 키워드 기반으로 필요한 도구만 선택하여 토큰 절약 - **도메인 추천**: GPT가 창의적 도메인 생성 → 가용성 자동 확인 → 가격과 함께 제안 -- **Deposit Agent**: OpenAI Assistants API 기반 예치금 관리 에이전트 연동 -- **예치금 시스템**: 은행 입금 자동 감지 + 사용자 신고 매칭으로 자동 충전 +- **예치금 시스템**: 코드 직접 처리, 은행 입금 자동 감지 + 사용자 신고 매칭으로 자동 충전 - **Email Worker**: SMS → 메일 → 자동 파싱으로 입금 알림 처리 - **무한 컨텍스트**: 슬라이딩 윈도우(3개)로 프로필 유지, 무제한 대화 기억 - **개인화 응답**: 프로필 기반으로 맞춤형 AI 응답 제공 @@ -43,7 +45,7 @@ | **Context7** | 라이브러리 문서 조회 API | | **도메인 관리** | 코드 직접 처리 → Namecheap API | | **도메인 추천** | GPT + Namecheap API (코드 레벨) | -| **Deposit Agent** | 예치금 관리 (OpenAI Assistants) | +| **예치금 관리** | 코드 직접 처리 → D1 | | **Namecheap API** | 도메인 조회/가용성/가격 백엔드 | | **Email Workers** | SMS → 메일 파싱 (입금 알림) | | **Workers AI** | 폴백용 (Llama 3.1 8B) | @@ -148,7 +150,7 @@ OpenAI Function Calling을 통해 AI가 자동으로 필요한 도구를 호출 | **문서** | "React hooks 사용법", "OpenAI API 예제" | Context7 | | **도메인** | "도메인 목록", "anvil.it.com 네임서버", ".com 가격", "google.com whois" | 코드 직접 처리 + WHOIS API | | **도메인 추천** | "커피숍 도메인 추천해줘", "스타트업 도메인 아이디어" | GPT + Namecheap | -| **예치금** | "잔액 확인", "충전하고 싶어", "10000원 입금했어" | D1 + Email Worker | +| **예치금** | "잔액 확인", "충전하고 싶어", "10000원 입금했어" | 코드 직접 처리 | ### 동작 방식 @@ -168,6 +170,31 @@ OpenAI: 날씨 데이터를 자연어로 응답 생성 응답: "🌤 서울 날씨\n온도: 5°C\n습도: 45%..." ``` +### 동적 도구 로딩 + +메시지 키워드를 분석하여 필요한 도구만 선택적으로 로딩합니다. (토큰 40% 절약) + +| 카테고리 | 도구 | 감지 패턴 | +|----------|------|-----------| +| domain | manage_domain, suggest_domains | 도메인, 네임서버, whois, .com | +| deposit | manage_deposit | 입금, 충전, 잔액, 계좌 | +| weather | get_weather | 날씨, 기온, 비, 눈 | +| search | search_web, lookup_docs | 검색, 찾아, 뭐야, 가격 | +| utility | get_current_time, calculate | (항상 포함) | + +패턴 매칭 없으면 전체 도구 사용 (폴백) + +### AI Gateway + +OpenAI API 호출을 Cloudflare AI Gateway를 통해 프록시하여 지역 제한을 우회합니다. + +``` +Gateway ID: telegram-bot +URL: gateway.ai.cloudflare.com/v1/{account_id}/telegram-bot/openai/... +``` + +**대시보드**: Cloudflare Dashboard → AI → AI Gateway → telegram-bot + --- ## 예치금 시스템 @@ -202,7 +229,7 @@ OpenAI: 날씨 데이터를 자연어로 응답 생성 ``` [시나리오 2: 은행 SMS가 먼저 도착] -은행 SMS → Gmail → Apps Script +은행 SMS → 메일 전달 → Cloudflare Email Routing → Worker (email handler) │ ▼ ┌──────────────────┐ @@ -280,57 +307,23 @@ OpenAI: 날씨 데이터를 자연어로 응답 생성 감사합니다! 🎉 ``` -### Gmail → Apps Script → Worker 연동 +### Cloudflare Email Routing -SMS를 Gmail로 전달받아 Apps Script에서 Worker API를 호출합니다. +SMS를 메일로 전달받아 Worker에서 직접 처리합니다. **흐름:** ``` -은행 SMS → Gmail(deposit.anvil@gmail.com) → Apps Script (1분마다) - ↓ - POST /api/bank-notification → DB 저장 → 자동 매칭 - ↓ - 매칭 성공 → 사용자/관리자 Telegram 알림 +은행 SMS → 메일 전달 → Cloudflare Email Routing → Worker (email handler) + ↓ + SMS 파싱 → DB 저장 → 자동 매칭 + ↓ + 매칭 성공 → 사용자/관리자 Telegram 알림 ``` -**Apps Script 코드:** -```javascript -function checkBankEmails() { - var threads = GmailApp.search('is:unread 입금', 0, 10); - - for (var i = 0; i < threads.length; i++) { - var messages = threads[i].getMessages(); - - for (var j = 0; j < messages.length; j++) { - var message = messages[j]; - if (!message.isUnread()) continue; - - var messageId = message.getId(); - var body = message.getPlainBody(); - - try { - UrlFetchApp.fetch( - 'https://telegram-summary-bot.kappa-d8e.workers.dev/api/bank-notification', - { - method: 'POST', - contentType: 'application/json', - payload: JSON.stringify({ - content: body, - messageId: messageId, - secret: 'BANK_API_SECRET 값' - }) - } - ); - } catch (e) { - console.log('Error: ' + e); - } - } - threads[i].markRead(); - } -} -``` - -**트리거 설정:** 시간 기반 → 분 타이머 → 1분마다 +**설정 방법:** +1. Cloudflare Dashboard → Email → Email Routing → Routes +2. 수신 주소 설정 (예: `deposit@your-domain.com`) +3. Worker로 라우팅: `telegram-summary-bot` **지원 은행 SMS 패턴:** - 하나은행 (Web발신): `[Web발신] 하나,01/16, 23:30 427******27104 입금5원 황병하` @@ -540,14 +533,14 @@ wrangler secret put WEBHOOK_SECRET # OpenAI API Key (필수) wrangler secret put OPENAI_API_KEY -# 입금 알림 API Secret (Apps Script 연동용) -wrangler secret put BANK_API_SECRET - # Brave Search API Key wrangler secret put BRAVE_API_KEY # Deposit API Secret (namecheap-api 연동용) wrangler secret put DEPOSIT_API_SECRET + +# namecheap-api 래퍼 인증 키 (도메인 추천용) +wrangler secret put NAMECHEAP_API_KEY ``` ### Vault 연동 (선택) @@ -582,6 +575,19 @@ curl https://telegram-summary-bot.kappa-d8e.workers.dev/setup-webhook curl https://telegram-summary-bot.kappa-d8e.workers.dev/webhook-info ``` +### 6. CLI 테스트 (선택) + +```bash +# .env 파일 생성 (최초 1회) +echo 'WEBHOOK_SECRET=...' > .env # Vault: secret/telegram-bot + +# 대화형 모드 +npm run chat + +# 단일 메시지 모드 +npm run chat "안녕" +``` + --- ## 보안 설정 @@ -680,7 +686,7 @@ database_id = "c285bb5b-888b-405d-b36f-475ae5aed20e" | `/webhook-info` | GET | Webhook 상태 | | `/setup-webhook` | GET | Webhook 설정 | | `/webhook` | POST | Telegram Webhook | -| `/api/bank-notification` | POST | 입금 알림 API (Apps Script 연동) | +| `/api/bank-notification` | POST | 입금 알림 API (레거시, Email Routing으로 대체) | | `/api/deposit/balance` | GET | 예치금 잔액 조회 (namecheap-api용) | | `/api/deposit/deduct` | POST | 예치금 차감 (namecheap-api용) | diff --git a/scripts/chat.ts b/scripts/chat.ts index d9051f4..bfba813 100644 --- a/scripts/chat.ts +++ b/scripts/chat.ts @@ -2,11 +2,25 @@ /** * Telegram Bot CLI Chat Client * - Worker의 /api/test 엔드포인트를 통해 직접 대화 - * - 사용법: npx tsx scripts/chat.ts - * 또는: npx tsx scripts/chat.ts "메시지" + * - 사용법: npm run chat + * 또는: npm run chat "메시지" */ import * as readline from 'readline'; +import * as fs from 'fs'; +import * as path from 'path'; + +// .env 파일 로드 +const envPath = path.join(process.cwd(), '.env'); +if (fs.existsSync(envPath)) { + const envContent = fs.readFileSync(envPath, 'utf-8'); + for (const line of envContent.split('\n')) { + const [key, ...valueParts] = line.split('='); + if (key && valueParts.length > 0) { + process.env[key.trim()] = valueParts.join('=').trim(); + } + } +} const WORKER_URL = process.env.WORKER_URL || 'https://telegram-summary-bot.kappa-d8e.workers.dev'; const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; diff --git a/src/deposit-agent.ts b/src/deposit-agent.ts index f92594d..07e6adf 100644 --- a/src/deposit-agent.ts +++ b/src/deposit-agent.ts @@ -1,5 +1,8 @@ /** - * Deposit Agent - 예치금 관리 에이전트 (OpenAI Assistants API) + * Deposit Agent - 예치금 관리 (코드 직접 처리) + * + * 변경 이력: + * - 2026-01: Assistants API → 코드 직접 처리로 변경 (지역 제한 우회, 응답 일관성) * * 기능: * - 잔액 조회 diff --git a/src/index.ts b/src/index.ts index 62a3365..cc442ce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -169,112 +169,6 @@ export default { } } - // Bank Notification API (Gmail → Apps Script → Worker) - if (url.pathname === '/api/bank-notification' && request.method === 'POST') { - try { - const body = await request.json() as { content: string; secret?: string; messageId?: string }; - - // 간단한 인증 (BANK_API_SECRET 또는 WEBHOOK_SECRET 사용) - const apiSecret = (env as any).BANK_API_SECRET || env.WEBHOOK_SECRET; - if (apiSecret && body.secret !== apiSecret) { - return Response.json({ error: 'Unauthorized' }, { status: 401 }); - } - - console.log('[API] Bank notification received:', body.content?.slice(0, 100)); - - // 메일 ID로 중복 체크 - if (body.messageId) { - const existing = await env.DB.prepare( - 'SELECT id FROM bank_notifications WHERE message_id = ?' - ).bind(body.messageId).first(); - - if (existing) { - console.log('[API] 중복 메일 무시:', body.messageId); - return Response.json({ success: true, duplicate: true, messageId: body.messageId }); - } - } - - // SMS 파싱 - const notification = parseBankSMS(body.content || ''); - if (!notification) { - console.log('[API] 파싱 실패:', body.content); - return Response.json({ error: 'Parse failed', content: body.content }, { status: 400 }); - } - - console.log('[API] 파싱 결과:', notification); - - // DB에 저장 - const insertResult = await env.DB.prepare( - `INSERT INTO bank_notifications (bank_name, depositor_name, amount, balance_after, transaction_time, raw_message, message_id) - VALUES (?, ?, ?, ?, ?, ?, ?)` - ).bind( - notification.bankName, - notification.depositorName, - notification.amount, - notification.balanceAfter || null, - notification.transactionTime?.toISOString() || null, - notification.rawMessage, - body.messageId || null - ).run(); - - const notificationId = insertResult.meta.last_row_id; - console.log('[API] 알림 저장 완료, ID:', notificationId); - - // 자동 매칭 시도 - const matched = await tryAutoMatch(env.DB, notificationId as number, notification); - - // 매칭 성공 시 사용자에게 알림 - if (matched && env.BOT_TOKEN) { - const user = await env.DB.prepare( - 'SELECT telegram_id FROM users WHERE id = ?' - ).bind(matched.userId).first<{ telegram_id: string }>(); - - if (user) { - // 업데이트된 잔액 조회 - const deposit = await env.DB.prepare( - 'SELECT balance FROM user_deposits WHERE user_id = ?' - ).bind(matched.userId).first<{ balance: number }>(); - - await sendMessage( - env.BOT_TOKEN, - parseInt(user.telegram_id), - `✅ 입금 확인 완료!\n\n` + - `입금액: ${matched.amount.toLocaleString()}원\n` + - `현재 잔액: ${(deposit?.balance || 0).toLocaleString()}원\n\n` + - `감사합니다! 🎉` - ); - } - } - - // 관리자에게 알림 - if (env.BOT_TOKEN && env.DEPOSIT_ADMIN_ID) { - const statusMsg = matched - ? `✅ 자동 매칭 완료! (거래 #${matched.transactionId})` - : '⏳ 매칭 대기 중 (사용자 입금 신고 필요)'; - - await sendMessage( - env.BOT_TOKEN, - parseInt(env.DEPOSIT_ADMIN_ID), - `🏦 입금 알림\n\n` + - `은행: ${notification.bankName}\n` + - `입금자: ${notification.depositorName}\n` + - `금액: ${notification.amount.toLocaleString()}원\n` + - `${notification.balanceAfter ? `잔액: ${notification.balanceAfter.toLocaleString()}원\n` : ''}` + - `\n${statusMsg}` - ); - } - - return Response.json({ - success: true, - notification, - matched: !!matched - }); - } catch (error) { - console.error('[API] Bank notification error:', error); - return Response.json({ error: String(error) }, { status: 500 }); - } - } - // Deposit API - 잔액 조회 (namecheap-api 전용) if (url.pathname === '/api/deposit/balance' && request.method === 'GET') { try { @@ -497,7 +391,7 @@ Documentation: https://github.com/your-repo // SMS 내용 파싱 const notification = parseBankSMS(rawEmail); if (!notification) { - console.log('[Email] 은행 SMS 파싱 실패:', rawEmail.slice(0, 200)); + console.log('[Email] 은행 SMS 파싱 실패'); return; } @@ -568,10 +462,55 @@ Documentation: https://github.com/your-repo }, }; +// Quoted-Printable UTF-8 디코딩 +function decodeQuotedPrintableUTF8(str: string): string { + // 줄 연속 문자 제거 + str = str.replace(/=\r?\n/g, ''); + + // =XX 패턴을 바이트로 변환 + const bytes: number[] = []; + let i = 0; + while (i < str.length) { + if (str[i] === '=' && i + 2 < str.length) { + const hex = str.slice(i + 1, i + 3); + if (/^[0-9A-Fa-f]{2}$/.test(hex)) { + bytes.push(parseInt(hex, 16)); + i += 3; + continue; + } + } + bytes.push(str.charCodeAt(i)); + i++; + } + + // UTF-8 바이트를 문자열로 변환 + try { + return new TextDecoder('utf-8').decode(new Uint8Array(bytes)); + } catch { + return str; + } +} + // 은행 SMS 파싱 함수 function parseBankSMS(content: string): BankNotification | null { - // 이메일에서 SMS 본문 추출 (여러 줄에 걸쳐 있을 수 있음) - const text = content.replace(/\r\n/g, '\n').replace(/=\n/g, ''); + // MIME 이메일 전처리 + let text = content; + + // Quoted-Printable UTF-8 디코딩 + text = decodeQuotedPrintableUTF8(text); + + // HTML
태그를 줄바꿈으로 변환 + text = text.replace(//gi, '\n'); + + // 줄바꿈 정규화 + text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); + + // [Web발신] 또는 은행 키워드가 있는 부분만 추출 + const smsStartMatch = text.match(/\[Web발신\]|\[하나은행\]|\[KB\]|\[신한\]|\[우리\]|\[농협\]/); + if (smsStartMatch && smsStartMatch.index !== undefined) { + // SMS 시작점부터 500자 추출 + text = text.slice(smsStartMatch.index, smsStartMatch.index + 500); + } // 하나은행 Web발신 패턴 (여러 줄): // [Web발신] diff --git a/src/openai-service.ts b/src/openai-service.ts index 804229a..457befd 100644 --- a/src/openai-service.ts +++ b/src/openai-service.ts @@ -253,8 +253,7 @@ function selectToolsForMessage(message: string): typeof tools { } // 도메인 추천 함수 -async function suggestDomains(keywords: string, apiKey: string): Promise { - const namecheapApiKey = '05426957210b42e752950f565ea82a3f48df9cccfdce9d82cd9817011968076e'; +async function suggestDomains(keywords: string, apiKey: string, namecheapApiKey: string): Promise { const namecheapApiUrl = 'https://namecheap-api.anvil.it.com'; const TARGET_COUNT = 10; const MAX_RETRIES = 3; @@ -1123,11 +1122,15 @@ async function executeTool(name: string, args: Record, env?: Env console.log('[suggest_domains] 시작:', { keywords }); if (!env?.OPENAI_API_KEY) { - return '🚫 도메인 추천 기능이 설정되지 않았습니다.'; + return '🚫 도메인 추천 기능이 설정되지 않았습니다. (OPENAI_API_KEY 미설정)'; + } + + if (!env?.NAMECHEAP_API_KEY) { + return '🚫 도메인 추천 기능이 설정되지 않았습니다. (NAMECHEAP_API_KEY 미설정)'; } try { - const result = await suggestDomains(keywords, env.OPENAI_API_KEY); + const result = await suggestDomains(keywords, env.OPENAI_API_KEY, env.NAMECHEAP_API_KEY); console.log('[suggest_domains] 완료:', result?.slice(0, 100)); return result; } catch (error) { diff --git a/src/types.ts b/src/types.ts index d7cdd6f..dd5aac6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,7 +9,6 @@ export interface Env { OPENAI_API_KEY?: string; NAMECHEAP_API_KEY?: string; DOMAIN_OWNER_ID?: string; - DEPOSIT_AGENT_ID?: string; DEPOSIT_ADMIN_ID?: string; BRAVE_API_KEY?: string; DEPOSIT_API_SECRET?: string; diff --git a/wrangler.toml b/wrangler.toml index caaa418..c5b1988 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -6,12 +6,11 @@ compatibility_date = "2024-01-01" binding = "AI" [vars] -SUMMARY_THRESHOLD = "20" -MAX_SUMMARIES_PER_USER = "3" -N8N_WEBHOOK_URL = "https://n8n.anvil.it.com" -DOMAIN_OWNER_ID = "821596605" -DEPOSIT_AGENT_ID = "asst_XMoVGU7ZwRpUPI6PHGvRNm8E" -DEPOSIT_ADMIN_ID = "821596605" +SUMMARY_THRESHOLD = "20" # 프로필 업데이트 주기 (메시지 수) +MAX_SUMMARIES_PER_USER = "3" # 유지할 프로필 버전 수 (슬라이딩 윈도우) +N8N_WEBHOOK_URL = "https://n8n.anvil.it.com" # n8n 연동 (선택) +DOMAIN_OWNER_ID = "821596605" # 도메인 관리 권한 Telegram ID +DEPOSIT_ADMIN_ID = "821596605" # 예치금 관리 권한 Telegram ID [[d1_databases]] binding = "DB" @@ -27,3 +26,6 @@ database_id = "c285bb5b-888b-405d-b36f-475ae5aed20e" # - BOT_TOKEN: Telegram Bot Token # - WEBHOOK_SECRET: Webhook 검증용 시크릿 # - OPENAI_API_KEY: OpenAI API 키 +# - NAMECHEAP_API_KEY: namecheap-api 래퍼 인증 키 (도메인 추천용) +# - BRAVE_API_KEY: Brave Search API 키 +# - DEPOSIT_API_SECRET: Deposit API 인증 키 (namecheap-api 연동)