algokit-mcp 1.0.2 → 1.0.3
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.
- package/README.md +138 -16
- package/dist/api/boj-scraper.js +1 -1
- package/dist/api/boj-scraper.js.map +1 -1
- package/dist/api/programmers-scraper.d.ts +0 -5
- package/dist/api/programmers-scraper.d.ts.map +1 -1
- package/dist/api/programmers-scraper.js +59 -90
- package/dist/api/programmers-scraper.js.map +1 -1
- package/dist/index.js +38 -35
- package/dist/index.js.map +1 -1
- package/dist/tools/boj/analyze-code-submission-boj.d.ts +67 -0
- package/dist/tools/boj/analyze-code-submission-boj.d.ts.map +1 -0
- package/dist/tools/boj/analyze-code-submission-boj.js +91 -0
- package/dist/tools/boj/analyze-code-submission-boj.js.map +1 -0
- package/dist/tools/boj/analyze-problem-boj.d.ts +48 -0
- package/dist/tools/boj/analyze-problem-boj.d.ts.map +1 -0
- package/dist/tools/boj/analyze-problem-boj.js +52 -0
- package/dist/tools/boj/analyze-problem-boj.js.map +1 -0
- package/dist/tools/boj/fetch-problem-content-boj.d.ts +49 -0
- package/dist/tools/boj/fetch-problem-content-boj.d.ts.map +1 -0
- package/dist/tools/boj/fetch-problem-content-boj.js +95 -0
- package/dist/tools/boj/fetch-problem-content-boj.js.map +1 -0
- package/dist/tools/boj/generate-hint-boj.d.ts +42 -0
- package/dist/tools/boj/generate-hint-boj.d.ts.map +1 -0
- package/dist/tools/boj/generate-hint-boj.js +82 -0
- package/dist/tools/boj/generate-hint-boj.js.map +1 -0
- package/dist/tools/boj/generate-review-template-boj.d.ts +48 -0
- package/dist/tools/boj/generate-review-template-boj.d.ts.map +1 -0
- package/dist/tools/boj/generate-review-template-boj.js +52 -0
- package/dist/tools/boj/generate-review-template-boj.js.map +1 -0
- package/dist/tools/boj/get-problem-boj.d.ts +22 -0
- package/dist/tools/boj/get-problem-boj.d.ts.map +1 -0
- package/dist/tools/boj/get-problem-boj.js +89 -0
- package/dist/tools/boj/get-problem-boj.js.map +1 -0
- package/dist/tools/boj/search-problems-boj.d.ts +42 -0
- package/dist/tools/boj/search-problems-boj.d.ts.map +1 -0
- package/dist/tools/boj/search-problems-boj.js +143 -0
- package/dist/tools/boj/search-problems-boj.js.map +1 -0
- package/dist/tools/boj/search-tags-boj.d.ts +22 -0
- package/dist/tools/boj/search-tags-boj.d.ts.map +1 -0
- package/dist/tools/boj/search-tags-boj.js +70 -0
- package/dist/tools/boj/search-tags-boj.js.map +1 -0
- package/dist/tools/get-problem-boj.d.ts +22 -0
- package/dist/tools/get-problem-boj.d.ts.map +1 -0
- package/dist/tools/get-problem-boj.js +89 -0
- package/dist/tools/get-problem-boj.js.map +1 -0
- package/dist/tools/programmers/analyze-code-submission-programmers.d.ts +60 -0
- package/dist/tools/programmers/analyze-code-submission-programmers.d.ts.map +1 -0
- package/dist/tools/programmers/analyze-code-submission-programmers.js +85 -0
- package/dist/tools/programmers/analyze-code-submission-programmers.js.map +1 -0
- package/dist/tools/programmers/analyze-problem-programmers.d.ts +48 -0
- package/dist/tools/programmers/analyze-problem-programmers.d.ts.map +1 -0
- package/dist/tools/programmers/analyze-problem-programmers.js +53 -0
- package/dist/tools/programmers/analyze-problem-programmers.js.map +1 -0
- package/dist/tools/programmers/fetch-problem-content-programmers.d.ts +46 -0
- package/dist/tools/programmers/fetch-problem-content-programmers.d.ts.map +1 -0
- package/dist/tools/programmers/fetch-problem-content-programmers.js +76 -0
- package/dist/tools/programmers/fetch-problem-content-programmers.js.map +1 -0
- package/dist/tools/programmers/generate-hint-programmers.d.ts +42 -0
- package/dist/tools/programmers/generate-hint-programmers.d.ts.map +1 -0
- package/dist/tools/programmers/generate-hint-programmers.js +80 -0
- package/dist/tools/programmers/generate-hint-programmers.js.map +1 -0
- package/dist/tools/programmers/generate-review-template-programmers.d.ts +48 -0
- package/dist/tools/programmers/generate-review-template-programmers.d.ts.map +1 -0
- package/dist/tools/programmers/generate-review-template-programmers.js +53 -0
- package/dist/tools/programmers/generate-review-template-programmers.js.map +1 -0
- package/dist/tools/programmers/get-problem-programmers.d.ts +53 -0
- package/dist/tools/programmers/get-problem-programmers.d.ts.map +1 -0
- package/dist/tools/programmers/get-problem-programmers.js +163 -0
- package/dist/tools/programmers/get-problem-programmers.js.map +1 -0
- package/dist/tools/programmers/search-problems-programmers.d.ts +73 -0
- package/dist/tools/programmers/search-problems-programmers.d.ts.map +1 -0
- package/dist/tools/programmers/search-problems-programmers.js +173 -0
- package/dist/tools/programmers/search-problems-programmers.js.map +1 -0
- package/dist/tools/search-problems-boj.d.ts +42 -0
- package/dist/tools/search-problems-boj.d.ts.map +1 -0
- package/dist/tools/search-problems-boj.js +143 -0
- package/dist/tools/search-problems-boj.js.map +1 -0
- package/dist/tools/search-tags-boj.d.ts +22 -0
- package/dist/tools/search-tags-boj.d.ts.map +1 -0
- package/dist/tools/search-tags-boj.js +70 -0
- package/dist/tools/search-tags-boj.js.map +1 -0
- package/dist/utils/agent-skill-installer.d.ts +9 -0
- package/dist/utils/agent-skill-installer.d.ts.map +1 -0
- package/dist/utils/agent-skill-installer.js +94 -0
- package/dist/utils/agent-skill-installer.js.map +1 -0
- package/dist/utils/claudecode-skill-installer.d.ts +6 -0
- package/dist/utils/claudecode-skill-installer.d.ts.map +1 -0
- package/dist/utils/claudecode-skill-installer.js +70 -0
- package/dist/utils/claudecode-skill-installer.js.map +1 -0
- package/dist/utils/skill-installer.d.ts +6 -0
- package/dist/utils/skill-installer.d.ts.map +1 -0
- package/dist/utils/skill-installer.js +70 -0
- package/dist/utils/skill-installer.js.map +1 -0
- package/dist/utils/tier-converter.d.ts.map +1 -1
- package/dist/utils/tier-converter.js +3 -0
- package/dist/utils/tier-converter.js.map +1 -1
- package/package.json +3 -4
- package/skills/algo:code-review/SKILL.md +134 -0
- package/skills/algo:fetch/SKILL.md +102 -0
- package/skills/algo:hint/SKILL.md +111 -0
- package/skills/algo:review/SKILL.md +123 -0
- package/skills/algo:search/SKILL.md +122 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AlgoKit-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**AI 에이전트와 함께하는 알고리즘 학습 MCP 툴킷 (백준, 프로그래머스 지원)**
|
|
4
4
|
|
|
5
5
|
AI 기반 힌트 생성, 문제 분석, 복습 템플릿 제공으로 효율적인 알고리즘 학습을 지원합니다.
|
|
6
6
|
|
|
@@ -12,9 +12,117 @@ AI 기반 힌트 생성, 문제 분석, 복습 템플릿 제공으로 효율적
|
|
|
12
12
|
- 📝 **복습 템플릿**: 자동 생성되는 마크다운 복습 문서
|
|
13
13
|
- 🧪 **코드 분석**: 제출 코드의 시간/공간 복잡도 분석 및 개선 제안
|
|
14
14
|
|
|
15
|
+
## 플랫폼별 설정 경로
|
|
16
|
+
|
|
17
|
+
| 항목 | Claude Code | Codex | Gemini CLI |
|
|
18
|
+
|------|-------------|-------|------------|
|
|
19
|
+
| **Skills 기능명** | Skills | Agent Skills | Agent Skills |
|
|
20
|
+
| **Skills 호출** | `/skill-name` | `$skill-name` or 자동 | 모델 자율 판단 |
|
|
21
|
+
| **MCP 설정 (프로젝트)** | `.mcp.json` | `.codex/config.toml` | `.gemini/settings.json` |
|
|
22
|
+
| **MCP 설정 (전역)** | `~/.claude.json` | `~/.codex/config.toml` | `~/.gemini/settings.json` |
|
|
23
|
+
| **Skills (프로젝트)** | `.claude/skills/` | `.codex/skills/` | `.gemini/skills/` |
|
|
24
|
+
| **Skills (전역)** | `~/.claude/skills/` | `~/.codex/skills/` | `~/.gemini/skills/` |
|
|
25
|
+
|
|
26
|
+
> Skills는 MCP 서버 첫 기동 시 감지된 플랫폼에 자동 설치됩니다.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
15
30
|
## 설치
|
|
16
31
|
|
|
17
|
-
|
|
32
|
+
> **Skills 자동 설치**: MCP 서버 첫 기동 시 설치된 AI 에이전트를 자동으로 감지하여 Skills를 설치합니다.
|
|
33
|
+
|
|
34
|
+
### Claude Code
|
|
35
|
+
|
|
36
|
+
#### 자동 설치
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 전역 설정 (모든 프로젝트에서 사용)
|
|
40
|
+
claude mcp add --scope user algokit -- npx -y algokit-mcp
|
|
41
|
+
|
|
42
|
+
# 프로젝트 설정 (.mcp.json 생성)
|
|
43
|
+
claude mcp add --scope project algokit -- npx -y algokit-mcp
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### 수동 설치
|
|
49
|
+
|
|
50
|
+
`~/.claude.json` (전역) 편집:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"mcpServers": {
|
|
55
|
+
"algokit": {
|
|
56
|
+
"command": "npx",
|
|
57
|
+
"args": ["-y", "algokit-mcp"]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
또는 프로젝트 루트에 `.mcp.json` 생성 ([예시](.claude/examples/claude-code-config.json)):
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"algokit": {
|
|
69
|
+
"command": "npx",
|
|
70
|
+
"args": ["-y", "algokit-mcp"]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### Skills 위치
|
|
77
|
+
|
|
78
|
+
| 등록 방식 | Skills 위치 |
|
|
79
|
+
|----------|------------|
|
|
80
|
+
| `--scope user` (전역) | `~/.claude/skills/` |
|
|
81
|
+
| `--scope project` (`.mcp.json` 있음) | `<프로젝트>/.claude/skills/` |
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### Codex
|
|
87
|
+
|
|
88
|
+
#### 자동 설치
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# 전역 설치
|
|
92
|
+
codex mcp add algokit -- npx -y algokit-mcp
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### 수동 설치
|
|
96
|
+
|
|
97
|
+
`~/.codex/config.toml` (전역) 또는 `.codex/config.toml` (프로젝트) 편집 ([예시](.claude/examples/codex-config.toml)):
|
|
98
|
+
|
|
99
|
+
```toml
|
|
100
|
+
[mcp.servers.algokit]
|
|
101
|
+
command = "npx"
|
|
102
|
+
args = ["-y", "algokit-mcp"]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Skills 위치
|
|
106
|
+
|
|
107
|
+
| 등록 방식 | Skills 위치 |
|
|
108
|
+
|----------|------------|
|
|
109
|
+
| 프로젝트 (`.codex/` 있음) | `<프로젝트>/.codex/skills/` |
|
|
110
|
+
| 전역 (`~/.codex/` 있음) | `~/.codex/skills/` |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### Gemini CLI
|
|
115
|
+
|
|
116
|
+
#### 자동 설치
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# 전역 설치
|
|
120
|
+
gemini mcp add algokit -- npx -y algokit-mcp
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### 수동 설치
|
|
124
|
+
|
|
125
|
+
`~/.gemini/settings.json` (전역) 또는 `.gemini/settings.json` (프로젝트) 편집 ([예시](.claude/examples/gemini-config.json)):
|
|
18
126
|
|
|
19
127
|
```json
|
|
20
128
|
{
|
|
@@ -27,15 +135,22 @@ AI 기반 힌트 생성, 문제 분석, 복습 템플릿 제공으로 효율적
|
|
|
27
135
|
}
|
|
28
136
|
```
|
|
29
137
|
|
|
138
|
+
#### Skills 위치
|
|
139
|
+
|
|
140
|
+
| 등록 방식 | Skills 위치 |
|
|
141
|
+
|----------|------------|
|
|
142
|
+
| 프로젝트 (`.gemini/` 있음) | `<프로젝트>/.gemini/skills/` |
|
|
143
|
+
| 전역 (`~/.gemini/` 있음) | `~/.gemini/skills/` |
|
|
144
|
+
|
|
30
145
|
## MCP 도구
|
|
31
146
|
|
|
32
147
|
### 백준 (BOJ)
|
|
33
148
|
|
|
34
149
|
| 도구 | 설명 |
|
|
35
150
|
|------|------|
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
151
|
+
| `search_problems_boj` | 문제 검색 (티어, 태그, 키워드) |
|
|
152
|
+
| `get_problem_boj` | 문제 상세 조회 |
|
|
153
|
+
| `search_tags_boj` | 알고리즘 태그 검색 |
|
|
39
154
|
| `fetch_problem_content_boj` | 문제 본문 스크래핑 |
|
|
40
155
|
| `analyze_problem_boj` | 문제 분석 및 힌트 가이드 |
|
|
41
156
|
| `generate_hint_boj` | 3단계 힌트 생성 |
|
|
@@ -46,28 +161,35 @@ AI 기반 힌트 생성, 문제 분석, 복습 템플릿 제공으로 효율적
|
|
|
46
161
|
|
|
47
162
|
| 도구 | 설명 |
|
|
48
163
|
|------|------|
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
164
|
+
| `search_problems_programmers` | 문제 검색 (난이도, 카테고리) |
|
|
165
|
+
| `get_problem_programmers` | 문제 상세 조회 |
|
|
51
166
|
| `fetch_problem_content_programmers` | 문제 본문 스크래핑 |
|
|
52
167
|
| `analyze_problem_programmers` | 문제 분석 |
|
|
53
168
|
| `generate_hint_programmers` | 힌트 생성 |
|
|
54
169
|
| `generate_review_template_programmers` | 복습 템플릿 |
|
|
55
170
|
| `analyze_code_submission_programmers` | 코드 분석 |
|
|
56
171
|
|
|
57
|
-
##
|
|
172
|
+
## Skills
|
|
58
173
|
|
|
59
|
-
**Skill 이름**: `algo:`
|
|
174
|
+
**Skill 이름**: `algo:` (BOJ/프로그래머스 자동 선택)
|
|
60
175
|
|
|
61
|
-
|
|
176
|
+
Claude Code, Codex, Gemini CLI 모두 동일한 `algo:` Skills를 지원합니다.
|
|
177
|
+
MCP 서버 첫 기동 시 감지된 에이전트에 자동으로 설치되며, 수동으로도 설치할 수 있습니다.
|
|
62
178
|
|
|
63
|
-
### 설치
|
|
179
|
+
### 수동 설치
|
|
64
180
|
|
|
65
181
|
```bash
|
|
66
|
-
#
|
|
67
|
-
cp skills/*
|
|
182
|
+
# Claude Code
|
|
183
|
+
cp -r skills/* ~/.claude/skills/ # 전역
|
|
184
|
+
cp -r skills/* .claude/skills/ # 프로젝트
|
|
185
|
+
|
|
186
|
+
# Codex
|
|
187
|
+
cp -r skills/* ~/.codex/skills/ # 전역
|
|
188
|
+
cp -r skills/* .codex/skills/ # 프로젝트
|
|
68
189
|
|
|
69
|
-
#
|
|
70
|
-
cp skills/* ~/.
|
|
190
|
+
# Gemini CLI
|
|
191
|
+
cp -r skills/* ~/.gemini/skills/ # 전역
|
|
192
|
+
cp -r skills/* .gemini/skills/ # 프로젝트
|
|
71
193
|
```
|
|
72
194
|
|
|
73
195
|
### 사용 예시
|
|
@@ -269,7 +391,7 @@ MIT
|
|
|
269
391
|
|
|
270
392
|
<div align="center">
|
|
271
393
|
|
|
272
|
-
**[GitHub](https://github.com/itsme-shawn/AlgoKit-mcp)** • **[Issues](https://github.com/itsme-shawn/algoKit-mcp/issues)** • **[NPM](https://www.npmjs.com/package/algokit-mcp
|
|
394
|
+
**[GitHub](https://github.com/itsme-shawn/AlgoKit-mcp)** • **[Issues](https://github.com/itsme-shawn/algoKit-mcp/issues)** • **[NPM](https://www.npmjs.com/package/algokit-mcp)**
|
|
273
395
|
|
|
274
396
|
|
|
275
397
|
</div>
|
package/dist/api/boj-scraper.js
CHANGED
|
@@ -79,7 +79,7 @@ export class BOJScraper {
|
|
|
79
79
|
// 캐시 확인
|
|
80
80
|
const cached = this.cache.get(problemId);
|
|
81
81
|
if (cached !== undefined) {
|
|
82
|
-
|
|
82
|
+
process.stderr.write(`[BOJScraper] 캐시 히트: 문제 ${problemId}\n`);
|
|
83
83
|
return cached;
|
|
84
84
|
}
|
|
85
85
|
// Rate Limiting (백업 보호, 캐시 미스 시에만)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boj-scraper.js","sourceRoot":"","sources":["../../src/api/boj-scraper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;;GAEG;AACH,MAAM,UAAU,GAAG;IACjB,yBAAyB;IACzB,QAAQ,EAAE,iCAAiC;IAC3C,6CAA6C;IAC7C,UAAU,EAAE,iHAAiH;IAC7H,iBAAiB;IACjB,OAAO,EAAE,KAAK;IACd,aAAa;IACb,WAAW,EAAE,CAAC;IACd,iCAAiC;IACjC,gBAAgB,EAAE,IAAI;CACd,CAAC;AAEX;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAG7B;IACA;IAHT,YACE,OAAe,EACR,IAA+D,EAC/D,aAAuB;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAA2D;QAC/D,kBAAa,GAAb,aAAa,CAAU;QAG9B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,UAAU;IACrB,qCAAqC;IAC7B,eAAe,GAAG,CAAC,CAAC;IAE5B,2BAA2B;IACnB,WAAW,CAAc;IAEjC,wBAAwB;IAChB,KAAK,CAA2B;IAExC;QACE,0CAA0C;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC;YACjC,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;QAEH,2BAA2B;QAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,gBAAgB,CAAC,SAAiB;QACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,aAAa,CACrB,kBAAkB,SAAS,EAAE,EAC7B,aAAa,CACd,CAAC;QACJ,CAAC;QAED,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"boj-scraper.js","sourceRoot":"","sources":["../../src/api/boj-scraper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;;GAEG;AACH,MAAM,UAAU,GAAG;IACjB,yBAAyB;IACzB,QAAQ,EAAE,iCAAiC;IAC3C,6CAA6C;IAC7C,UAAU,EAAE,iHAAiH;IAC7H,iBAAiB;IACjB,OAAO,EAAE,KAAK;IACd,aAAa;IACb,WAAW,EAAE,CAAC;IACd,iCAAiC;IACjC,gBAAgB,EAAE,IAAI;CACd,CAAC;AAEX;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAG7B;IACA;IAHT,YACE,OAAe,EACR,IAA+D,EAC/D,aAAuB;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAA2D;QAC/D,kBAAa,GAAb,aAAa,CAAU;QAG9B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,UAAU;IACrB,qCAAqC;IAC7B,eAAe,GAAG,CAAC,CAAC;IAE5B,2BAA2B;IACnB,WAAW,CAAc;IAEjC,wBAAwB;IAChB,KAAK,CAA2B;IAExC;QACE,0CAA0C;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC;YACjC,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;QAEH,2BAA2B;QAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,gBAAgB,CAAC,SAAiB;QACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,aAAa,CACrB,kBAAkB,SAAS,EAAE,EAC7B,aAAa,CACd,CAAC;QACJ,CAAC;QAED,QAAQ;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,SAAS,IAAI,CAAC,CAAC;YAC9D,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,mCAAmC;QACnC,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAEjC,mCAAmC;QACnC,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAEpC,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC;QAClD,IAAI,SAAkB,CAAC;QAEvB,SAAS;QACT,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;YACnE,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBAE/C,mBAAmB;gBACnB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAElC,SAAS;gBACT,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gBAEhC,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAK,CAAC;gBAElB,eAAe;gBACf,IAAI,KAAK,YAAY,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBACjE,MAAM,KAAK,CAAC;gBACd,CAAC;gBAED,kBAAkB;gBAClB,IAAI,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;oBACrC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,uBAAuB;oBACvE,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;QAED,YAAY;QACZ,MAAM,IAAI,aAAa,CACrB,MAAM,SAAS,MAAM,UAAU,CAAC,WAAW,GAAG,CAAC,iBAAiB,EAChE,eAAe,EACf,SAAS,CACV,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAAC,GAAW;QACzC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;QAE3E,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE;oBACP,YAAY,EAAE,UAAU,CAAC,UAAU;oBACnC,QAAQ,EAAE,WAAW;oBACrB,iBAAiB,EAAE,qCAAqC;iBACzD;aACF,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,SAAS;YACT,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,IAAI,aAAa,CACrB,kBAAkB,GAAG,EAAE,EACvB,WAAW,CACZ,CAAC;YACJ,CAAC;YAED,aAAa;YACb,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,aAAa,CACrB,WAAW,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,EACpD,eAAe,CAChB,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEnC,UAAU;YACV,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBAC/B,MAAM,IAAI,aAAa,CACrB,mBAAmB,EACnB,aAAa,CACd,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,8BAA8B;YAC9B,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,mBAAmB;YACnB,IAAK,KAAe,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC3C,MAAM,IAAI,aAAa,CACrB,kBAAkB,UAAU,CAAC,OAAO,QAAQ,EAC5C,SAAS,EACT,KAAK,CACN,CAAC;YACJ,CAAC;YAED,aAAa;YACb,MAAM,IAAI,aAAa,CACrB,eAAgB,KAAe,CAAC,OAAO,EAAE,EACzC,eAAe,EACf,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,sBAAsB;QAClC,IAAI,IAAI,CAAC,eAAe,KAAK,CAAC,EAAE,CAAC;YAC/B,cAAc;YACd,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC;QAClD,MAAM,SAAS,GAAG,UAAU,CAAC,gBAAgB,GAAG,OAAO,CAAC;QAExD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,EAAU;QACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;;;OAIG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -11,7 +11,6 @@ export declare class ProgrammersScrapeError extends Error {
|
|
|
11
11
|
* 프로그래머스 스크래퍼
|
|
12
12
|
*/
|
|
13
13
|
export declare class ProgrammersScraper {
|
|
14
|
-
private browserPool;
|
|
15
14
|
private rateLimiter;
|
|
16
15
|
private searchCache;
|
|
17
16
|
private problemCache;
|
|
@@ -25,10 +24,6 @@ export declare class ProgrammersScraper {
|
|
|
25
24
|
* @throws {ProgrammersScrapeError}
|
|
26
25
|
*/
|
|
27
26
|
searchProblems(options?: ProgrammersSearchOptions): Promise<ProgrammersProblemSummary[]>;
|
|
28
|
-
/**
|
|
29
|
-
* 검색 URL 생성
|
|
30
|
-
*/
|
|
31
|
-
private buildSearchUrl;
|
|
32
27
|
/**
|
|
33
28
|
* 문제 상세 페이지 HTML 가져오기 (fetch 기반, BOJScraper 패턴)
|
|
34
29
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"programmers-scraper.d.ts","sourceRoot":"","sources":["../../src/api/programmers-scraper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"programmers-scraper.d.ts","sourceRoot":"","sources":["../../src/api/programmers-scraper.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;AAGjC;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAGtC,IAAI,EACP,SAAS,GACT,oBAAoB,GACpB,kBAAkB,GAClB,aAAa;IACV,aAAa,CAAC,EAAE,OAAO;gBAN9B,OAAO,EAAE,MAAM,EACR,IAAI,EACP,SAAS,GACT,oBAAoB,GACpB,kBAAkB,GAClB,aAAa,EACV,aAAa,CAAC,EAAE,OAAO,YAAA;CAKjC;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,WAAW,CAAgD;IACnE,OAAO,CAAC,YAAY,CAA6C;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;;IAc9D;;;;;;OAMG;IACG,cAAc,CAClB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,yBAAyB,EAAE,CAAC;IAgJvC;;;;;;OAMG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8C1D;;OAEG;YACW,iBAAiB;IAsE/B;;OAEG;IACH,OAAO,CAAC,MAAM;IAId;;;;OAIG;IACH,aAAa;;;;IAOb;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;;;;;OAMG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;CA2BvE"}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 프로그래머스 웹 스크래핑 클라이언트
|
|
3
|
+
*
|
|
4
|
+
* 검색: 프로그래머스 내부 JSON API (fetch 기반)
|
|
5
|
+
* 상세 페이지: cheerio (fetch 기반)
|
|
6
|
+
*/
|
|
2
7
|
import { RateLimiter } from '../utils/rate-limiter.js';
|
|
3
8
|
import { LRUCache } from '../utils/lru-cache.js';
|
|
4
9
|
import { parseProgrammersProblemContent } from '../utils/html-parser.js';
|
|
@@ -19,13 +24,11 @@ export class ProgrammersScrapeError extends Error {
|
|
|
19
24
|
* 프로그래머스 스크래퍼
|
|
20
25
|
*/
|
|
21
26
|
export class ProgrammersScraper {
|
|
22
|
-
browserPool;
|
|
23
27
|
rateLimiter;
|
|
24
28
|
searchCache;
|
|
25
29
|
problemCache;
|
|
26
30
|
baseUrl = 'https://school.programmers.co.kr';
|
|
27
31
|
constructor() {
|
|
28
|
-
this.browserPool = BrowserPool.getInstance();
|
|
29
32
|
// 초당 1회 요청 (보수적)
|
|
30
33
|
this.rateLimiter = new RateLimiter({
|
|
31
34
|
capacity: 2,
|
|
@@ -50,121 +53,87 @@ export class ProgrammersScraper {
|
|
|
50
53
|
// 캐시 확인
|
|
51
54
|
const cached = this.searchCache.get(cacheKey);
|
|
52
55
|
if (cached !== undefined) {
|
|
53
|
-
|
|
56
|
+
process.stderr.write('[ProgrammersScraper] 캐시 히트: 검색 결과\n');
|
|
54
57
|
// limit 적용 후 반환
|
|
55
58
|
return limit && limit > 0 ? cached.slice(0, limit) : cached;
|
|
56
59
|
}
|
|
57
60
|
// Rate limiting (캐시 미스 시에만)
|
|
58
61
|
await this.rateLimiter.acquire();
|
|
59
|
-
let browser = null;
|
|
60
62
|
try {
|
|
61
|
-
// 1.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
page,
|
|
69
|
-
query,
|
|
70
|
-
});
|
|
71
|
-
console.log(`[ProgrammersScraper] 검색 URL: ${searchUrl}`);
|
|
72
|
-
// 3. 페이지 이동 및 로딩 대기
|
|
73
|
-
try {
|
|
74
|
-
await browserPage.goto(searchUrl, {
|
|
75
|
-
waitUntil: 'networkidle2',
|
|
76
|
-
timeout: 30000,
|
|
77
|
-
});
|
|
63
|
+
// 1. 프로그래머스 내부 API URL 생성
|
|
64
|
+
const params = new URLSearchParams();
|
|
65
|
+
params.set('page', String(page));
|
|
66
|
+
params.set('perPage', '20');
|
|
67
|
+
params.set('order', order);
|
|
68
|
+
for (const level of levels) {
|
|
69
|
+
params.append('levels[]', String(level));
|
|
78
70
|
}
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
if (query) {
|
|
72
|
+
params.set('search', query);
|
|
81
73
|
}
|
|
82
|
-
|
|
74
|
+
const apiUrl = `${this.baseUrl}/api/v2/school/challenges/?${params.toString()}`;
|
|
75
|
+
process.stderr.write(`[ProgrammersScraper] API URL: ${apiUrl}\n`);
|
|
76
|
+
// 2. API 호출
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
79
|
+
let apiResponse;
|
|
83
80
|
try {
|
|
84
|
-
await
|
|
85
|
-
|
|
81
|
+
const response = await fetch(apiUrl, {
|
|
82
|
+
signal: controller.signal,
|
|
83
|
+
headers: {
|
|
84
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
85
|
+
Accept: 'application/json',
|
|
86
|
+
'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
|
|
87
|
+
},
|
|
86
88
|
});
|
|
89
|
+
clearTimeout(timeoutId);
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
throw new ProgrammersScrapeError(`API 요청 실패: HTTP ${response.status}`, 'NAVIGATION_ERROR');
|
|
92
|
+
}
|
|
93
|
+
apiResponse = await response.json();
|
|
87
94
|
}
|
|
88
95
|
catch (error) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
console.log('[ProgrammersScraper] 검색 결과 없음');
|
|
96
|
-
await browserPage.close();
|
|
97
|
-
return [];
|
|
96
|
+
clearTimeout(timeoutId);
|
|
97
|
+
if (error instanceof ProgrammersScrapeError) {
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
if (error.name === 'AbortError') {
|
|
101
|
+
throw new ProgrammersScrapeError('요청이 타임아웃되었습니다 (10000ms 초과)', 'TIMEOUT', error);
|
|
98
102
|
}
|
|
99
|
-
throw new ProgrammersScrapeError(
|
|
103
|
+
throw new ProgrammersScrapeError(`API 요청 실패: ${error.message}`, 'NAVIGATION_ERROR', error);
|
|
100
104
|
}
|
|
101
|
-
//
|
|
105
|
+
// 3. API 응답 → ProgrammersProblemSummary 매핑
|
|
102
106
|
let problems;
|
|
103
107
|
try {
|
|
104
|
-
problems =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const title = titleLink?.textContent?.trim() || '';
|
|
114
|
-
const category = categoryEl?.textContent?.trim() || '기타';
|
|
115
|
-
const levelClass = levelSpan?.className || '';
|
|
116
|
-
const level = parseInt(levelClass.match(/level-(\d+)/)?.[1] || '0');
|
|
117
|
-
const finishedText = finishedEl?.textContent?.trim() || '0명';
|
|
118
|
-
const finishedCount = parseInt(finishedText.replace(/,/g, '').replace('명', '') || '0');
|
|
119
|
-
const rateText = rateEl?.textContent?.trim() || '0%';
|
|
120
|
-
const acceptanceRate = parseInt(rateText.replace('%', '') || '0');
|
|
121
|
-
return {
|
|
122
|
-
problemId,
|
|
123
|
-
title,
|
|
124
|
-
level,
|
|
125
|
-
category,
|
|
126
|
-
url: `https://school.programmers.co.kr${href}`,
|
|
127
|
-
finishedCount,
|
|
128
|
-
acceptanceRate,
|
|
129
|
-
};
|
|
130
|
-
});
|
|
131
|
-
});
|
|
108
|
+
problems = (apiResponse.result ?? []).map((item) => ({
|
|
109
|
+
problemId: String(item.id),
|
|
110
|
+
title: item.title,
|
|
111
|
+
level: item.level,
|
|
112
|
+
category: item.partTitle,
|
|
113
|
+
finishedCount: item.finishedCount,
|
|
114
|
+
acceptanceRate: item.acceptanceRate,
|
|
115
|
+
url: `${this.baseUrl}/learn/courses/30/lessons/${item.id}`,
|
|
116
|
+
}));
|
|
132
117
|
}
|
|
133
118
|
catch (error) {
|
|
134
119
|
throw new ProgrammersScrapeError('문제 목록 파싱 실패', 'PARSE_ERROR', error);
|
|
135
120
|
}
|
|
136
|
-
|
|
137
|
-
// 6. 캐시에 저장 (limit 적용 전 전체 결과 저장)
|
|
121
|
+
// 4. 캐시에 저장 (limit 적용 전 전체 결과 저장)
|
|
138
122
|
this.searchCache.set(cacheKey, problems);
|
|
139
|
-
//
|
|
123
|
+
// 5. limit 적용
|
|
140
124
|
if (limit && limit > 0) {
|
|
141
125
|
problems = problems.slice(0, limit);
|
|
142
126
|
}
|
|
143
|
-
|
|
127
|
+
process.stderr.write(`[ProgrammersScraper] ${problems.length}개 문제 검색 완료\n`);
|
|
144
128
|
return problems;
|
|
145
129
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
await this.browserPool.release(browser);
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (error instanceof ProgrammersScrapeError) {
|
|
132
|
+
throw error;
|
|
150
133
|
}
|
|
134
|
+
throw new ProgrammersScrapeError(`검색 실패: ${error.message}`, 'NAVIGATION_ERROR', error);
|
|
151
135
|
}
|
|
152
136
|
}
|
|
153
|
-
/**
|
|
154
|
-
* 검색 URL 생성
|
|
155
|
-
*/
|
|
156
|
-
buildSearchUrl(options) {
|
|
157
|
-
const params = new URLSearchParams();
|
|
158
|
-
params.set('order', options.order);
|
|
159
|
-
params.set('page', options.page.toString());
|
|
160
|
-
if (options.levels.length > 0) {
|
|
161
|
-
params.set('levels', options.levels.join(','));
|
|
162
|
-
}
|
|
163
|
-
if (options.query) {
|
|
164
|
-
params.set('query', options.query);
|
|
165
|
-
}
|
|
166
|
-
return `${this.baseUrl}/learn/challenges?${params.toString()}`;
|
|
167
|
-
}
|
|
168
137
|
/**
|
|
169
138
|
* 문제 상세 페이지 HTML 가져오기 (fetch 기반, BOJScraper 패턴)
|
|
170
139
|
*
|
|
@@ -283,7 +252,7 @@ export class ProgrammersScraper {
|
|
|
283
252
|
// 캐시 확인
|
|
284
253
|
const cached = this.problemCache.get(problemId);
|
|
285
254
|
if (cached !== undefined) {
|
|
286
|
-
|
|
255
|
+
process.stderr.write(`[ProgrammersScraper] 캐시 히트: 문제 ${problemId}\n`);
|
|
287
256
|
return cached;
|
|
288
257
|
}
|
|
289
258
|
// 1. HTML 가져오기 (캐시 미스 시에만)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"programmers-scraper.js","sourceRoot":"","sources":["../../src/api/programmers-scraper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"programmers-scraper.js","sourceRoot":"","sources":["../../src/api/programmers-scraper.ts"],"names":[],"mappings":"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"}
|