sns-auto-builder 1.0.5 → 1.0.7
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/bin/sns-auto-builder.mjs
CHANGED
|
@@ -28,6 +28,13 @@ function workspaceDir() {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// 매 실행 때 최신으로 덮어쓰는 것 = 도구 자체.
|
|
31
|
+
// 빌더 전용 CDP 포트. 9222 는 크롬 디버깅의 관례 포트라 사용자 본인의 크롬,
|
|
32
|
+
// chrome-devtools MCP, 다른 자동화 도구가 이미 쓰고 있기 쉽다. 겹치면 한쪽이
|
|
33
|
+
// ::1 을, 다른 쪽이 127.0.0.1 을 잡아서 **엉뚱한 브라우저에 붙는다** — 조용히
|
|
34
|
+
// 사용자 개인 크롬을 조종하게 되므로 관례 포트를 피한다.
|
|
35
|
+
// scripts/chatgpt-image-gen.js 가 같은 기본값과 같은 환경변수를 쓴다.
|
|
36
|
+
const CDP_PORT = process.env.SNS_BUILDER_CDP_PORT || '19222';
|
|
37
|
+
|
|
31
38
|
const TOOL_FILES = ['server.mjs', 'index.html', 'CLAUDE.md'];
|
|
32
39
|
const TOOL_DIRS = ['scripts', '.claude', 'templates', 'knowledge'];
|
|
33
40
|
|
|
@@ -131,8 +138,13 @@ if (argv.includes('--login')) {
|
|
|
131
138
|
console.log(` 로그인만 하고 창은 그대로 두거나 닫으면 됩니다.\n`);
|
|
132
139
|
// 포트를 반드시 붙인다. Chrome 은 user-data-dir 당 인스턴스 하나만 띄우므로,
|
|
133
140
|
// 포트 없이 뜬 창이 남으면 빌더가 그 프로필로 포트를 못 연다.
|
|
141
|
+
//
|
|
142
|
+
// 9222 가 아니라 CDP_PORT 인 이유: 9222 는 크롬 디버깅의 관례 포트라 사용자
|
|
143
|
+
// 본인의 크롬이나 다른 도구가 이미 쓰고 있는 경우가 있다. 실제로 한쪽이
|
|
144
|
+
// ::1:9222 를, 다른 한쪽이 127.0.0.1:9222 를 잡아서, 빌더가 사용자 개인
|
|
145
|
+
// 크롬에 붙을 뻔했다. chatgpt-image-gen.js 와 같은 값을 써야 한다.
|
|
134
146
|
spawn(exe, [
|
|
135
|
-
|
|
147
|
+
`--remote-debugging-port=${CDP_PORT}`,
|
|
136
148
|
`--user-data-dir=${profile}`,
|
|
137
149
|
'--no-first-run', '--no-default-browser-check',
|
|
138
150
|
'https://chatgpt.com',
|
package/package.json
CHANGED
|
@@ -38,7 +38,14 @@ function checkBat(name, buf) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// 확장자 화이트리스트. dist 안에서 claude 를 한 번 실행했더니 .claude/.omc 가
|
|
42
|
+
// 생겨서 zip 빌드가 깨진 적이 있다. 팀원에게 갈 것만 명시적으로 고른다.
|
|
43
|
+
const files = readdirSync(DIST, { withFileTypes: true })
|
|
44
|
+
.filter((e) => e.isFile() && e.name !== OUT && /\.(bat|txt)$/.test(e.name))
|
|
45
|
+
.map((e) => e.name)
|
|
46
|
+
.sort();
|
|
47
|
+
|
|
48
|
+
if (files.length !== 4) throw new Error(`4개여야 하는데 ${files.length}개: ${files.join(', ')}`);
|
|
42
49
|
const locals = [];
|
|
43
50
|
const central = [];
|
|
44
51
|
let offset = 0;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* 브라우저:
|
|
25
25
|
* 기본 — .chrome-profile 로 Chrome 을 직접 띄운다. 그 프로필로 이미 Chrome 이
|
|
26
26
|
* 떠 있으면(예: chrome-devtools MCP) 프로필이 잠겨 실패한다. 그때는
|
|
27
|
-
* --browser-url http://127.0.0.1:
|
|
27
|
+
* --browser-url http://127.0.0.1:19222 로 떠 있는 Chrome 에 붙어라.
|
|
28
28
|
*/
|
|
29
29
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, statSync } from 'node:fs';
|
|
30
30
|
import { join, resolve, dirname } from 'node:path';
|
|
@@ -35,7 +35,12 @@ const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
35
35
|
const BASE_W = 1080, BASE_H = 1350, SCALE = 2; // openai-image-gen.js / html-carousel-gen.js 와 동일
|
|
36
36
|
const CHATGPT = 'https://chatgpt.com/';
|
|
37
37
|
const PROFILE = join(REPO_ROOT, '.chrome-profile');
|
|
38
|
-
|
|
38
|
+
// 빌더 전용 CDP 포트. bin/sns-auto-builder.mjs 의 CDP_PORT 와 같은 값이어야 한다.
|
|
39
|
+
// 9222(크롬 디버깅 관례 포트)를 쓰다가, 사용자 본인 크롬이 127.0.0.1:9222 를 잡고
|
|
40
|
+
// 빌더 크롬은 ::1:9222 만 잡은 적이 있다. 그 상태에서 여기가 127.0.0.1 로 붙으면
|
|
41
|
+
// **사용자 개인 크롬을 조종하게 된다.** 관례 포트를 피하는 이유다.
|
|
42
|
+
const CDP_PORT = process.env.SNS_BUILDER_CDP_PORT || '19222';
|
|
43
|
+
const DEBUG_URL = `http://127.0.0.1:${CDP_PORT}`;
|
|
39
44
|
|
|
40
45
|
// 이미지 안에 한글이 들어가므로 정확도 가드를 붙인다 (openai-image-gen.js 의 KOREAN 과 같은 역할).
|
|
41
46
|
const KOREAN = '한글은 오타 없이 정확히 그대로 렌더링할 것. 지정하지 않은 문구는 넣지 말 것.';
|
|
@@ -156,13 +161,22 @@ async function waitForComposer(page) {
|
|
|
156
161
|
// 조용히 틀리느니 시끄럽게 멈추는 게 낫다.
|
|
157
162
|
async function attachRef(page, refPaths) {
|
|
158
163
|
const want = refPaths.length;
|
|
159
|
-
//
|
|
164
|
+
// 화면에 input[type=file] 이 네 개쯤 있다. **accept 로 고른다.**
|
|
165
|
+
//
|
|
166
|
+
// 예전에는 "form 안에 있는 것"을 골랐는데, ChatGPT 가 이미지 업로드 input 을
|
|
167
|
+
// form 밖으로 옮기면서 form 안에는 accept 없는 다른 input 만 남았다. 거기에
|
|
168
|
+
// 파일을 넣으면 아무 일도 안 일어나고, 썸네일을 2분 기다리다 실패한다
|
|
169
|
+
// (증상: "크롬은 떴는데 프롬프트를 입력하지 않는다").
|
|
160
170
|
const pickInput = async () => {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
171
|
+
for (const sel of [
|
|
172
|
+
'input[type="file"][data-testid="upload-photos-input"]', // 현재 ChatGPT
|
|
173
|
+
'input[type="file"][accept*="image"]', // testid 가 바뀌어도 살아남는 조건
|
|
174
|
+
'input[type="file"]',
|
|
175
|
+
]) {
|
|
176
|
+
const h = await page.$(sel);
|
|
177
|
+
if (h) return h;
|
|
164
178
|
}
|
|
165
|
-
return
|
|
179
|
+
return null;
|
|
166
180
|
};
|
|
167
181
|
|
|
168
182
|
for (let attempt = 1; attempt <= 2; attempt++) {
|