You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现R远程实时监听Discord消息(无需本地Discord客户端)

解决R远程实时监听Discord消息的问题

核心问题修复

你的代码存在两个关键问题,对应解决方案如下:

1. 心跳机制错误(连接40秒失效)

  • 错误点:

    • 心跳包的op码应为1而非2(op=2是身份验证包)
    • 心跳逻辑放在主流程只会执行一次,无法定时发送
    • 未正确使用Discord返回的心跳间隔和消息序列号(seq)
  • 修复方案:
    在收到Discord的Hello消息(op=10)后,用异步定时任务发送心跳包,同时记录每次消息的seq值用于心跳验证。

2. 无需打开Discord客户端

Discord Gateway的WebSocket连接完全独立于本地客户端,只要使用合法的Bot Token(建议用机器人账号Token而非个人账号Token,降低账号风险),无需打开任何Discord客户端即可远程连接。

完整可运行代码

library(websocket)
library(jsonlite)
library(later)

# 替换为你的Bot Token
token <- "YOUR_BOT_TOKEN"
ws <- NULL
heartbeat_interval <- NULL
last_seq <- NULL
heartbeat_timer <- NULL

# 初始化WebSocket连接
init_websocket <- function() {
  ws <<- WebSocket$new("wss://gateway.discord.gg/?v=9&encoding=json")
  
  # 身份验证 payload
  auth_payload <- toJSON(
    list(
      op = 2,
      d = list(
        token = token,
        intents = 513, # 包含GUILDS和GUILD_MESSAGES权限
        properties = list(
          os = "linux",
          browser = "R-websocket",
          device = "R-websocket"
        )
      )
    ),
    auto_unbox = TRUE
  )
  
  # 连接打开时发送身份验证
  ws$onOpen(function(event) {
    cat("连接已打开,发送身份验证...\n")
    ws$send(auth_payload)
  })
  
  # 处理收到的消息
  ws$onMessage(function(event) {
    message <- fromJSON(event$data)
    last_seq <<- message$s # 记录消息序列号
    
    # 处理Hello消息,启动心跳
    if (message$op == 10) {
      heartbeat_interval <<- message$d$heartbeat_interval / 1000
      cat("收到Hello消息,心跳间隔:", heartbeat_interval, "秒\n")
      send_heartbeat()
    }
    
    # 处理消息创建事件(MESSAGE_CREATE)
    if (message$t == "MESSAGE_CREATE") {
      content <- message$d$content
      author <- message$d$author$username
      cat("[", author, "] ", content, "\n", sep = "")
    }
    
    # 处理心跳确认(仅日志)
    if (message$op == 11) {
      cat("心跳确认收到\n")
    }
  })
  
  # 处理连接关闭,自动重连
  ws$onClose(function(event) {
    cat("连接关闭,错误码:", event$code, ",原因:", event$reason, "\n")
    cat("正在尝试重连...\n")
    later(init_websocket, delay = 5) # 5秒后重连
  })
  
  # 处理连接错误
  ws$onError(function(event) {
    cat("连接错误:", event$message, "\n")
  })
}

# 发送心跳包
send_heartbeat <- function() {
  heartbeat_payload <- toJSON(
    list(
      op = 1,
      d = last_seq # 使用最后收到的序列号,首次为NULL
    ),
    auto_unbox = TRUE
  )
  cat("发送心跳...\n")
  ws$send(heartbeat_payload)
  
  # 定时发送下一次心跳(间隔减1秒避免超时)
  heartbeat_timer <<- later(send_heartbeat, delay = heartbeat_interval - 1)
}

# 启动连接
init_websocket()

# 保持R会话运行(避免脚本结束)
while (TRUE) {
  later::run_now(timeout = 1)
  Sys.sleep(1)
}

关键说明

  • 依赖包:用later包实现异步定时任务,替代原代码中无效的轮询逻辑,确保心跳包按时发送
  • Intents权限:intents=513是GUILDS(1)和GUILD_MESSAGES(512)的权限总和,需在Discord开发者门户的Bot设置中开启对应Privileged Gateway Intents
  • Token安全:不要将Token硬编码在公开代码中,建议用环境变量加载(如token <- Sys.getenv("DISCORD_BOT_TOKEN"))
  • 重连机制:代码包含自动重连逻辑,连接意外断开时会尝试重新连接

内容的提问来源于stack exchange,提问作者Camilo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:46:15