Zalo Personal (비공식)

상태: 실험적. 이 연동은 OpenClaw 내부의 네이티브 zca-js를 통해 개인 Zalo 계정을 자동화합니다.

경고: 비공식 연동이며 계정 정지/차단이 발생할 수 있습니다. 사용에 따른 위험은 본인에게 있습니다.

플러그인 필요

Zalo Personal은 플러그인으로 제공되며 기본 코어에 포함되지 않습니다.

  • CLI로 설치: openclaw plugins install @openclaw/zalouser
  • 소스 체크아웃에서: openclaw plugins install ./extensions/zalouser
  • 자세한 내용: Plugins

외부 zca/openzca CLI 바이너리가 필요하지 않습니다.

빠른 설정 (초보자)

  1. 플러그인을 설치합니다 (위 참조).
  2. 로그인합니다 (QR, 게이트웨이 머신에서):
    • openclaw channels login --channel zalouser
    • Zalo 모바일 앱으로 QR 코드를 스캔합니다.
  3. 채널을 활성화합니다:
{
  channels: {
    zalouser: {
      enabled: true,
      dmPolicy: "pairing",
    },
  },
}
  1. 게이트웨이를 재시작합니다 (또는 온보딩을 완료합니다).
  2. DM 접근은 기본적으로 페어링입니다. 첫 연락 시 페어링 코드를 승인하세요.

기능 설명

  • zca-js를 통해 완전히 프로세스 내에서 실행됩니다.
  • 네이티브 이벤트 리스너를 사용하여 인바운드 메시지를 수신합니다.
  • JS API를 통해 직접 응답합니다 (텍스트/미디어/링크).
  • Zalo Bot API를 사용할 수 없는 “개인 계정” 사용 사례를 위해 설계되었습니다.

이름 규칙

채널 ID는 zalouser로, 개인 Zalo 사용자 계정(비공식)을 자동화한다는 것을 명시합니다. zalo는 향후 공식 Zalo API 연동을 위해 예약되어 있습니다.

ID 찾기 (디렉토리)

디렉토리 CLI를 사용하여 피어/그룹과 해당 ID를 검색합니다:

openclaw directory self --channel zalouser
openclaw directory peers list --channel zalouser --query "name"
openclaw directory groups list --channel zalouser --query "work"

제한

  • 아웃바운드 텍스트는 약 2000자로 분할됩니다 (Zalo 클라이언트 제한).
  • 스트리밍은 기본적으로 차단됩니다.

접근 제어 (DM)

channels.zalouser.dmPolicy 지원: pairing | allowlist | open | disabled (기본값: pairing).

channels.zalouser.allowFrom은 사용자 ID 또는 이름을 허용합니다. 온보딩 중에 플러그인의 프로세스 내 연락처 조회를 사용하여 이름이 ID로 변환됩니다.

승인:

  • openclaw pairing list zalouser
  • openclaw pairing approve zalouser <code>

그룹 접근 (선택)

  • 기본값: channels.zalouser.groupPolicy = "open" (그룹 허용). 미설정 시 channels.defaults.groupPolicy로 기본값을 재정의합니다.
  • 허용 목록으로 제한:
    • channels.zalouser.groupPolicy = "allowlist"
    • channels.zalouser.groups (키는 안정적인 그룹 ID여야 함; 가능한 경우 시작 시 이름이 ID로 변환됨)
    • channels.zalouser.groupAllowFrom (허용된 그룹에서 봇을 트리거할 수 있는 발신자 제어)
  • 모든 그룹 차단: channels.zalouser.groupPolicy = "disabled".
  • 설정 마법사가 그룹 허용 목록을 물을 수 있습니다.
  • 시작 시 OpenClaw가 허용 목록의 그룹/사용자 이름을 ID로 변환하고 매핑을 로그에 기록합니다.
  • 그룹 허용 목록 매칭은 기본적으로 ID 전용입니다. 변환되지 않은 이름은 channels.zalouser.dangerouslyAllowNameMatching: true가 활성화되지 않는 한 인증에 무시됩니다.
  • channels.zalouser.dangerouslyAllowNameMatching: true는 변경 가능한 그룹 이름 매칭을 다시 활성화하는 비상 호환성 모드입니다.
  • groupAllowFrom이 미설정이면 런타임이 그룹 발신자 확인에 allowFrom으로 폴백합니다.
  • 발신자 확인은 일반 그룹 메시지와 제어 명령(예: /new, /reset)에 모두 적용됩니다.

예시:

{
  channels: {
    zalouser: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["1471383327500481391"],
      groups: {
        "123456789": { allow: true },
        "Work Chat": { allow: true },
      },
    },
  },
}

그룹 멘션 게이팅

  • channels.zalouser.groups.<group>.requireMention은 그룹 응답에 멘션이 필요한지 제어합니다.
  • 해석 순서: 정확한 그룹 ID/이름 -> 정규화된 그룹 슬러그 -> * -> 기본값 (true).
  • 허용 목록 그룹과 오픈 그룹 모드 모두에 적용됩니다.
  • 인가된 제어 명령(예: /new)은 멘션 게이팅을 우회할 수 있습니다.
  • 멘션이 필요하여 건너뛴 그룹 메시지는 대기 중인 그룹 히스토리로 저장되며 다음 처리된 그룹 메시지에 포함됩니다.
  • 그룹 히스토리 제한은 messages.groupChat.historyLimit(폴백 50)을 기본값으로 합니다. channels.zalouser.historyLimit으로 계정별로 재정의할 수 있습니다.

예시:

{
  channels: {
    zalouser: {
      groupPolicy: "allowlist",
      groups: {
        "*": { allow: true, requireMention: true },
        "Work Chat": { allow: true, requireMention: false },
      },
    },
  },
}

다중 계정

계정은 OpenClaw 상태의 zalouser 프로필에 매핑됩니다. 예시:

{
  channels: {
    zalouser: {
      enabled: true,
      defaultAccount: "default",
      accounts: {
        work: { enabled: true, profile: "work" },
      },
    },
  },
}

타이핑, 리액션, 전달 확인

  • OpenClaw는 응답 발송 전에 타이핑 이벤트를 전송합니다(최선의 노력).
  • 메시지 리액션 액션 react은 채널 액션에서 zalouser에 대해 지원됩니다.
    • 특정 리액션 이모지를 메시지에서 제거하려면 remove: true를 사용합니다.
    • 리액션 의미론: Reactions
  • 이벤트 메타데이터가 포함된 인바운드 메시지의 경우, OpenClaw가 전달 + 확인 응답을 전송합니다(최선의 노력).

문제 해결

로그인이 유지되지 않는 경우:

  • openclaw channels status --probe
  • 재로그인: openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser

허용 목록/그룹 이름이 변환되지 않는 경우:

  • allowFrom/groupAllowFrom/groups에 숫자 ID를 사용하거나, 정확한 친구/그룹 이름을 사용하세요.

이전 CLI 기반 설정에서 업그레이드한 경우:

  • 기존 외부 zca 프로세스 관련 설정을 제거하세요.
  • 채널은 이제 외부 CLI 바이너리 없이 OpenClaw 내에서 완전히 실행됩니다.