Communitygithub.com

terryso/wechat-channels-video

Ego Lite 세션을 사용해 위챗 채널스(视频号)에 동영상 초안을 저장하는 스킬입니다. 로그인 확인 후 동영상을 업로드하고 설명, 짧은 제목, 태그, 위치, 썸네일을 입력한 뒤 초안만 저장합니다. 사람의 QR 코드 스캔을 위한 핸드오프를 지원합니다.

wechat-channels-video란 무엇인가요?

이 스킬은 AI 에이전트(Claude Code, Cursor 등)가 Ego Lite 브라우저 자동화 도구를 사용하여 위챗 채널스(视频号) 관리자 페이지에 동영상 초안을 저장할 수 있도록 설계되었습니다. 사용자가 '视频号' 또는 'Channels assistant'에 게시해 달라고 요청할 때 사용됩니다. 스킬은 로그인 상태 확인(check-login), 동영상 업로드, 설명 및 짧은 제목 입력, 태그/위치/썸네일 설정, 초안 저장(save draft only)의 전 과정을 자동화합니다. 중요한 점은 '발행(Publish)' 버튼을 누르지 않고 초안까지만 저장하며, 사람이 QR 코드를 스캔하여 직접 발행하도록 핸드오프(handOff)합니다. 세션 만료가 빠르므로 매 작업 전 로그인 확인이 필수이며, 로그인되지 않은 경우 사용자에게 Ego Lite에서 QR 코드를 스캔하도록 안내합니다. wujie shadow DOM 조작, DataTransfer를 이용한 파일 업로드, execCommand를 이용한 텍스트 입력 등 복잡한 웹 상호작용을 포함합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/terryso/ego-skills/tree/main/skills/wechat-channels-video

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

wechat-channels-video은(는) 무엇을 하나요?

Ego Lite 세션을 사용해 视频号助手에 동영상 초안을 저장합니다. '발행'을 클릭하지 않습니다(QR 발행은 사람이 직접).

먼저 Ego 설치

Ego Lite를 먼저 설치하고 ego-browser가 PATH에 있어야 합니다. 없으면 soft-fail 처리하거나 사용자에게 설치를 알리고, 절대 브라우저를 강제로 실행하지 마세요.

게시 전: 로그인 게이트 (필수)

위챗 채널스 로그인 상태는 매우 빨리 만료됩니다. 에이전트는 업로드나 양식 작성 전에 반드시 다음을 실행해야 합니다:

node scripts/check-login.mjs
# 사람이 QR을 스캔할 수 있도록 창을 열어둘 경우:
node scripts/check-login.mjs --keep
종료 코드의미에이전트 동작
0로그인됨login_tip을 사용자에게 알리고 계속 진행
2로그인되지 않음 / ego-browser 없음how_to_login / how_to_login_zh를 표시하고 중단. 사람이 Ego에서 QR을 스캔한 후 check-login 재실행
1기타 오류JSON error 보고, 발행된 것처럼 속이지 않음

자세한 내용은 references/login.md를 참조하세요. 별도의 cookie-healthcheck 스킬을 만들지 마세요.

입력 (범용, 로컬 제품 경로 없음)

호출자는 동영상 및 텍스트 필드를 제공합니다. references/inputs.md 참조. 본 스킬은 절대 ~/… 비즈니스 디렉토리를 하드코딩하지 않습니다.

최소 필요: 로컬 video 경로, description, short_title. 선택 사항: tags, cover, 위치/원본/활동.

CLI 간단 스크립트 (안정적인 부분)

ego-browser nodejs는 shell argv를 전달하지 않습니다. check-login은 임시 entry + ego-browser nodejs -e로 처리되었습니다.

# 저장소 루트
node skills/wechat-channels-video/scripts/check-login.mjs
node skills/wechat-channels-video/scripts/check-login.mjs --keep
node skills/wechat-channels-video/scripts/serve-file.mjs --file /absolute/path/to/video.mp4 --port 18765

# 설치된 스킬 디렉토리에서는 상대 경로도 사용 가능
node scripts/check-login.mjs
node scripts/serve-file.mjs --file /absolute/path/to/video.mp4 --port 18765
  • check-login: 유일한 로그인 하드 게이트; 종료 시 기본값 finish({ keep: [] }) (--keep 제외).
  • serve-file: 페이지 fetch를 위한 로컬 CORS 파일 서버; { url, bytes, port } 출력, SIGINT로 종료. 큰 동영상은 base64로 인코딩하지 마세요.

전체 게시 UI를 하나의 거대한 스크립트로 만들지 마세요: wujie, 좌표 클릭, 썸네일 waitForFileChooser는 에이전트가 snapshot/스크린샷을 보고 판단해야 합니다. 스크립트는 결정 가능한 로그인 및 파일 전송만 담당합니다. 양식은 아래 에이전트 단계를 따릅니다.

ego-browser API 빠른 참조

매 ego-browser nodejs는 새 프로세스입니다. TaskSpace / Page는 호출 간에 유지되지만 JS 변수는 유지되지 않습니다.

API설명
taskSpace(name|id)사용자 목표당 하나의 space; spaceId를 기록해 재사용
task.page("p1")첫 화면은 goto로 재사용, 마구 페이지를 열지 마세요
page.snapshot()관찰 (open shadow를 볼 수 있음); 클릭은 wujie 내에서 자주 차단됨
page.evaluate(fn, arg)하나의 JSON 직렬화 가능 인수만 받음 (긴 텍스트는 여기로 전달)
page.mouse.click(x, y)wujie 내 팝업에서 자주 사용
page.waitForFileChooser()썸네일의 유일한 안전한 업로드 경로
task.handOff()사람에게 QR 게시 / 직접 로그인을 넘김
task.finish({ keep: [] })마무리, space 종료; 사람이 계속 볼 필요가 있을 때는 handOff 사용, 장기간 머신 점유 금지

중요: snapshot은 wujie shadow를 볼 수 있음; ref/text 클릭은 pointer events 차단 오류를 발생시킴. wujie 내 동작은 evaluate 안에서 .click() 또는 좌표 mouse.click 사용.

에이전트 흐름 (로그인 통과 후)

0. 게시 페이지로 라우팅

직접 goto /platform/post/create 하지 마세요 (지연 로딩으로 흰 화면). UI 경로를 따르세요:

홈 → 왼쪽 메뉴 '콘텐츠 관리' → '동영상' → 오른쪽 '동영상 게시'

준비 완료: wujie 내에 '동영상 설명', '짧은 제목' 텍스트, 숨겨진 input[type=file][accept*="video"], '초안 저장' 버튼이 있어야 합니다.

const state = await page.evaluate(() => {
  const app = document.querySelector('wujie-app');
  if (!app?.shadowRoot) return { wujie: false };
  const t = app.shadowRoot.textContent || '';
  return {
    wujie: true,
    hasDesc: t.includes('동영상 설명'),
    hasShort: t.includes('짧은 제목'),
    hasUpload: !!app.shadowRoot.querySelector('input[type=file][accept*="video"]'),
    hasSave: t.includes('초안 저장'),
  };
});

1. 동영상 업로드

먼저 serve-file을 시작하고(기본 포트 18765), 페이지에서 fetch + DataTransfer로 숨겨진 파일 input에 주입합니다 (동영상 컴포넌트는 isTrusted 검사를 하지 않음; 썸네일은 함):

const r = await page.evaluate(async (p) => {
  const root = document.querySelector('wujie-app').shadowRoot;
  const input = root.querySelector('input[type=file][accept*="video"]');
  const resp = await fetch(p.url);
  const dt = new DataTransfer();
  dt.items.add(new File([await resp.blob()], p.name, { type: 'video/mp4' }));
  input.files = dt.files;
  input.dispatchEvent(new Event('input', { bubbles: true }));
  input.dispatchEvent(new Event('change', { bubbles: true }));
  return 'injected ' + dt.files[0].size;
}, { url: 'http://127.0.0.1:18765/video.mp4', name: 'video.mp4' });

검증은 DOM만 확인: '转发/赞/评论' 미리보기 카드, 진행률 100% 안정화. performance 리소스에서 업로드 POST는 잡히지 않습니다. 업로드 중에는 양식을 작성하지 마세요; wujie가 잠시 null이 되면 기다렸다가 다시 확인하고, 새로고침하지 마세요.

1.5 체크포인트: 먼저 초안 저장

업로드 완료 후 즉시 '초안 저장'을 한 번 클릭한 다음, 설명/짧은 제목/위치를 입력하고 마지막에 다시 저장합니다. 중간에 문제가 생겨 큰 파일을 다시 업로드하는 것을 방지합니다.

2. 설명 + 태그

설명은 .input-editor (contenteditable 아님). execCommand 사용; 텍스트는 evaluate 두 번째 인수로 전달:

await page.evaluate((p) => {
  const ed = document.querySelector('wujie-app').shadowRoot.querySelector('.input-editor');
  ed.focus();
  document.execCommand('selectAll', false, null);
  document.execCommand('delete', false, null);
  document.execCommand('insertText', false, p.desc);
}, { desc });
await page.evaluate((p) => {
  const ed = document.querySelector('wujie-app').shadowRoot.querySelector('.input-editor');
  ed.focus();
  document.execCommand('insertParagraph');
  document.execCommand('insertText', false, p.tags);
  ed.blur();
}, { tags });

3. 짧은 제목

실제 <input>이므로 반드시 native setter를 사용; input.value로 검증 (innerText에는 input 값이 없음).

4. 위치

기본적으로 도시가 포함됩니다. 안전한 방법: mouse.click으로 열기 → snapshot/스크린샷 → '위치 표시 안 함' 클릭 → 필드 다시 읽어 확인. evaluate 좌표가 숨겨진 레이어를 클릭할 수 있습니다.

5. 초안 저장 (종점)

'초안 저장' 클릭. 성공 신호: '저장됨' + 하단 버튼이 회색으로 변함. 그런 다음 goto로 초안함 확인. 초안함이 보이기 전에 편집기를 떠나지 마세요.

선택 사항: 원본 표시, 활동 검색 (native setter로 검색어 입력; 검색 결과 없으면 '활동 참여 안 함' 선택).

6. 썸네일 (선택 사항)

유일한 안전한 방법: waitForFileChooser() + 신뢰할 수 있는 '썸네일 업로드' 클릭 + chooser.setFiles(<절대 경로>). input.files 합성 / OS 파일 선택기 방식은 실제로 실패했습니다. 확인 버튼이 돌아가는 것을 멈추고 미리보기가 기본 프레임으로 돌아가지 않을 때까지 기다린 후 초안 저장.

7. 마무리

  • serve-file 중지 (포트 해제).
  • 사람이 게시해야 함: 초안함에서 handOff().
  • 그렇지 않으면 finish({ keep: [] }), space를 장기간 점유하지 마세요.

주의사항 목록

  1. wujie shadow: wujie-app.shadowRoot에서 시작.
  2. create 직접 링크 흰 화면: UI 경로로 게시 페이지 진입.
  3. wujie 내 ref/text 클릭 차단됨 → evaluate 또는 좌표 클릭 사용.
  4. 긴 텍스트는 evaluate 파라미터로만 전달.
  5. 설명은 execCommand 사용; 짧은 제목은 native setter 사용.
  6. 위치는 두 단계 좌표 + 다시 읽어 검증.
  7. 썸네일은 waitForFileChooser만 가능.
  8. 업로드 검증은 DOM만 확인; 업로드 후 먼저 초안 저장.
  9. 초안이 저장되기 전에 네비게이션으로 떠나지 않음.
  10. 로그인 페이지 '로딩 실패'는 허위 경보; handOff로 사람이 QR 스캔.
  11. 게시할 때마다 check-login; exit 2면 반드시 중단.
  12. 게시는 사람이 하는 최종 단계; 본 스킬은 초안까지만.

테스트

npm test

관련 스킬