콘텐츠로 이동

Bluesky, X/Twitter, Reddit

멘션, DM, 답글에 응답하는 오픈 웹 소셜 채널입니다.

이 페이지에서는 Revka의 세 가지 오픈 웹 소셜 채널인 Bluesky (AT Protocol), X/Twitter (API v2), Reddit (OAuth2)을 설명합니다. 워크스페이스 채팅이나 메시징 앱과 달리, 이 채널들은 공개 소셜 네트워크에서 동작합니다. 에이전트는 자신의 알림 피드를 감시하고, @멘션, 답글, 또는 (X와 Reddit의 경우) 다이렉트 메시지를 받았을 때 응답합니다. 각 플랫폼의 정확한 설정 키, 인증 모델, 멘션 기반 동작이 필요할 때 이 페이지를 참조하십시오.

세 채널 모두 폴링 방식으로 동작합니다. 공개 인바운드 포트가 필요하지 않으며 — Revka가 짧은 간격으로 플랫폼 API에 아웃바운드로 연결하여 새 알림을 가져오므로 노출할 웹훅이 없습니다. 세 채널 모두 항상 컴파일에 포함되어 있으며(별도의 Cargo 기능 플래그 없음), ~/.revka/config.toml[channels_config] 아래에서 설정한 후 데몬을 재시작하면 변경 사항이 적용됩니다. 모든 채널에 공통으로 적용되는 트레이트 모델, 전달 모드, 허용 목록 의미에 대해서는 채널 개요를 참조하십시오.

채널인증수신 방식폴링 간격트리거 조건DM
Bluesky앱 비밀번호 → JWT알림 폴링5초멘션, 답글없음
X/TwitterOAuth 2.0 bearer 토큰멘션 타임라인 폴링15초멘션발신 전용
RedditOAuth2 refresh 토큰받은편지함 폴링5초사용자명 멘션, 댓글 답글, DM있음

Bluesky 채널은 https://bsky.social/xrpc를 통해 AT Protocol을 사용합니다. 핸들과 앱 비밀번호로 인증하고, 5초마다 알림 피드를 폴링하며, 원본 게시물에 스레드로 연결되는 답글을 게시합니다. mention 또는 reply 이유에 해당하는 알림만 처리하며 — 좋아요, 팔로우, 리포스트는 무시됩니다.

[channels_config.bluesky]
handle = "mybot.bsky.social"
app_password = "xxxx-xxxx-xxxx-xxxx"
필드타입기본값설명
handlestring봇의 Bluesky 핸들(예: mybot.bsky.social). 필수.
app_passwordstringBluesky 설정에서 생성한 앱 전용 비밀번호. 필수.

Bluesky는 계정의 메인 비밀번호를 사용하지 않습니다. Bluesky 클라이언트의 설정 → 개인정보 및 보안 → 앱 비밀번호에서 범위가 제한되고 개별 취소 가능한 앱 비밀번호를 생성한 후 app_password에 입력하십시오.

시작 시 Revka는 핸들과 앱 비밀번호로 com.atproto.server.createSession을 호출하여 단기 액세스 JWT와 장기 리프레시 JWT를 받습니다. AT Protocol 액세스 토큰은 약 두 시간 동안 유효하며, Revka는 만료 전에 com.atproto.server.refreshSession을 통해 갱신합니다. 갱신에 실패하면 자동으로 전체 재인증을 수행합니다. 토큰은 직접 관리할 필요가 없으며 — 앱 비밀번호만 관리하면 됩니다.

  • Revka는 5초마다 app.bsky.notification.listNotifications를 폴링합니다(한 번에 25개).
  • mentionreply 알림만 처리됩니다. 봇 자신의 게시물과 이미 읽은 알림은 건너뜁니다.
  • 처리된 각 알림은 app.bsky.notification.updateSeen을 통해 확인 처리되므로 재처리되지 않습니다.
  • 답글은 com.atproto.repo.createRecord를 사용하여 app.bsky.feed.post 컬렉션에 생성되며, 올바르게 스레드되도록 reply의 root/parent가 설정됩니다.
  • 게시물은 Bluesky의 300자 제한으로 제한되며, 더 긴 에이전트 출력은 끝에 ...가 붙어 잘립니다.

이 채널은 DM을 지원하지 않습니다 — 공개 멘션과 답글을 통해서만 동작합니다.

X/Twitter 채널은 OAuth 2.0 앱 전용 bearer 토큰을 사용하여 https://api.x.com/2의 X(Twitter) API v2를 호출합니다. 인증된 봇 계정의 멘션을 감시하고, 앞에 오는 @bot 토큰을 제거한 후 스레드 내에서 답글을 작성합니다. 발신 기능으로 다이렉트 메시지 전송도 지원합니다.

[channels_config.twitter]
bearer_token = "AAAA..."
allowed_users = ["*"]
필드타입기본값설명
bearer_tokenstringX 개발자 앱의 OAuth 2.0 앱 전용(앱 레벨) bearer 토큰. 필수.
allowed_usersarray[]상호작용이 허용된 사용자명 또는 숫자 사용자 ID 목록. []이면 전체 거부, ["*"]이면 전체 허용.

Bearer 토큰은 앱 레벨이며 특정 최종 사용자에 종속되지 않습니다. X 개발자 앱을 생성한 후 OAuth 2.0 bearer 토큰을 bearer_token에 복사하십시오. 시작 시 Revka는 GET /2/users/me를 호출하여 인증된 계정의 사용자 ID를 확인합니다 — 이 호출은 토큰 유효성 검사(헬스 체크 역할도 함)와 봇에 속한 멘션 식별을 동시에 수행합니다.

  • Revka는 15초마다 GET /2/users/{id}/mentions를 폴링하며 author_id, conversation_id, created_at을 요청하고 작성자 사용자명을 확장합니다. since_id를 사용하여 마지막으로 확인한 트윗보다 최신 트윗만 반환받습니다.
  • 봇 자신의 트윗은 건너뛰며, 10,000개 항목의 중복 제거 집합으로 동일한 트윗의 재처리를 방지합니다.
  • 발신자(확인된 사용자명, 없으면 작성자 ID)가 allowed_users에 대해 검사됩니다.
  • 텍스트 앞에 오는 @bot(및 다른 앞선 @멘션)은 모델에 전달되기 전에 제거됩니다. 제거 후 내용이 남지 않으면 해당 멘션은 무시됩니다.
  • 답글은 reply.in_reply_to_tweet_id와 함께 POST /2/tweets를 통해 게시됩니다. 280자 트윗 제한을 초과하는 출력은 단어 경계에서 분할되어 각 트윗이 이전 트윗에 연결되는 답글 스레드로 작성됩니다.

아웃바운드 send는 수신자 접두사에 따라 동작을 선택합니다:

  • tweet:<id> (또는 트윗 ID 단독) → POST /2/tweets를 통한 스레드 답글.
  • dm:<user_id>POST /2/dm_conversations/with/{user_id}/messages를 통한 다이렉트 메시지.

이 채널의 인바운드 트래픽은 멘션 기반이며, DM은 주로 에이전트나 워크플로우가 활용할 수 있는 아웃바운드 기능입니다.

Reddit 채널은 OAuth2 봇으로, 5초마다 계정의 읽지 않은 받은편지함을 폴링하여 사용자명 멘션, 댓글 답글, 개인 메시지(DM) 세 가지 항목을 처리합니다. 댓글에는 댓글로, DM에는 DM으로 답합니다. 선택적 서브레딧 필터를 사용하면 특정 커뮤니티로만 범위를 좁힐 수 있습니다.

[channels_config.reddit]
client_id = "reddit-client-id"
client_secret = "reddit-client-secret"
refresh_token = "reddit-refresh-token"
username = "MyBotName"
subreddit = "MySubreddit" # optional
필드타입기본값설명
client_idstringReddit 앱의 OAuth2 클라이언트 ID. 필수.
client_secretstringReddit 앱의 OAuth2 클라이언트 시크릿. 필수.
refresh_tokenstring지속적인 액세스를 위한 장기 OAuth2 리프레시 토큰. 필수.
usernamestringu/ 접두사 없이 입력한 봇의 Reddit 사용자명. 자기 메시지 필터링에 사용됨. 필수.
subredditstring선택적 필터(r/ 접두사 없이 입력). 설정하면 해당 서브레딧의 항목만 처리됨.

Reddit은 단기 액세스 토큰을 발급하므로, Revka는 지속적인 액세스를 위해 리프레시 토큰을 사용합니다. 시작 시 및 액세스 토큰 만료가 임박할 때마다, Revka는 HTTP Basic 인증(client_id:client_secret)과 grant_type=refresh_token을 사용하여 https://www.reddit.com/api/v1/access_token에 POST 요청을 보내고, 반환된 액세스 토큰을 https://oauth.reddit.com에 대한 bearer 자격 증명으로 사용합니다. 토큰은 캐시되며 만료 60초 전에 자동으로 갱신됩니다. Reddit의 요구 사항에 따라 모든 요청에 설명적인 User-Agent가 포함됩니다.

  • Revka는 5초마다 GET /message/unread를 폴링하고(한 번에 25개), 가져온 항목을 POST /api/read_message로 읽음 처리하여 재처리를 방지합니다.
  • 봇 자신이 작성한 항목(username에 대해 대소문자 구분 없이 일치)과 본문이 비어 있는 항목은 건너뜁니다.
  • subreddit이 설정된 경우, 다른 서브레딧의 항목은 무시됩니다.
  • 답글 라우팅은 항목 유형에 따라 결정됩니다:
    • 댓글 답글 / 멘션 (Reddit fullname t1_…, t3_…, t4_…) → thing_id와 함께 POST /api/comment를 통한 공개 댓글.
    • 다이렉트 메시지POST /api/compose를 통해 작성자에게 보내는 비공개 답글(기본 제목 Message from Revka).

X/Twitter는 표준 규칙에 따라 allowed_users를 사용합니다:

  • 빈 목록([])은 모든 발신자를 거부합니다.
  • "*" 항목 하나는 모든 발신자를 허용합니다.
  • 그 외의 경우, 목록에 있는 사용자명 또는 숫자 사용자 ID만 허용됩니다.

Bluesky와 Reddit은 자체 allowed_users 필드를 제공하지 않습니다. Bluesky는 자기 자신이 아닌 모든 mention/reply에 응답하며, Reddit은 자기 자신이 아닌 모든 받은편지함 항목에 응답합니다(선택적으로 subreddit으로 범위 제한 가능). 먼저 전달이 정상적으로 이루어지는지 확인한 후, subreddit 필터(Reddit) 또는 X의 allowed_users를 사용하여 에이전트가 응답할 대상을 좁히십시오. 채널 전반의 전체 허용 목록 모델에 대해서는 채널 개요를 참조하십시오.

  • 봇이 연결되지만 응답하지 않습니다. 지원되는 트리거 유형인지 확인하십시오. Bluesky와 Reddit은 멘션/답글/DM에 반응하며 좋아요나 추천에는 반응하지 않습니다. X의 경우, 발신자가 allowed_users를 통과하는지 확인하십시오(테스트 중에는 ["*"]를 사용하십시오).
  • X 봇이 응답을 멈춥니다. 로그에서 429 속도 제한 대기를 확인하십시오. 무료 플랜은 쉽게 한도가 초과됩니다. 시작 시 및 헬스 체크로 실행되는 users/me 호출로 bearer 토큰을 검증하십시오.
  • 부팅 시 Reddit 인증에 실패합니다. 토큰 갱신 실패는 refresh_token, client_id, 또는 client_secret이 잘못되었거나 취소되었음을 의미합니다 — 외부 OAuth2 흐름을 다시 실행하여 새 리프레시 토큰을 발급받으십시오.
  • Bluesky 인증에 실패합니다. Bluesky 설정에서 앱 비밀번호를 재생성하십시오. 만료되거나 취소된 앱 비밀번호는 createSession을 실패하게 만듭니다.

채널별 로그 상세도를 높여 진단하십시오:

Terminal window
RUST_LOG=revka::channels::bluesky=debug,revka::channels::twitter=debug,revka::channels::reddit=debug revka daemon