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

如何用discord.py开发追踪Rocket League周游玩时长的机器人?

Discord机器人追踪Rocket League游玩时长解决方案

核心功能实现步骤

1. 检测用户Rocket League游玩状态

Discord API提供用户活动状态(Activity)接口,通过监听用户状态变化或轮询活动列表,可精准检测是否开始/结束游玩Rocket League。

关键要点:

  • 需在Discord开发者门户开启Presence Intent和Server Members Intent(机器人特权网关权限),否则无法获取用户活动数据。
  • Rocket League的活动名称固定为Rocket League,活动类型需匹配PLAYING(区分观看直播、听歌等其他状态)。

代码示例(discord.js):

const fs = require('fs');
const { Client, GatewayIntentBits } = require('discord.js');

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildPresences,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.MessageContent
  ]
});

// 存储用户游玩数据(可替换为SQLite等数据库)
const USER_DATA_PATH = './rl_playtime.json';
let userData = {};

// 初始化数据
try {
  userData = JSON.parse(fs.readFileSync(USER_DATA_PATH, 'utf8'));
} catch (err) {
  fs.writeFileSync(USER_DATA_PATH, JSON.stringify(userData));
}

function saveUserData() {
  fs.writeFileSync(USER_DATA_PATH, JSON.stringify(userData, null, 2));
}

// 监听用户状态变化
client.on('presenceUpdate', (oldPresence, newPresence) => {
  if (!newPresence.guild) return; // 忽略非服务器用户

  // 检查前后状态是否包含Rocket League游玩
  const wasPlayingRL = oldPresence?.activities.some(act => 
    act.name === 'Rocket League' && act.type === 'PLAYING'
  );
  const isPlayingRL = newPresence.activities.some(act => 
    act.name === 'Rocket League' && act.type === 'PLAYING'
  );

  // 开始游玩:记录时间戳
  if (!wasPlayingRL && isPlayingRL) {
    userData[newPresence.user.id] = userData[newPresence.user.id] || { weeklyTotal: 0 };
    userData[newPresence.user.id].lastStartTime = Date.now();
    saveUserData();
  }
  // 结束游玩:计算时长并累加
  else if (wasPlayingRL && !isPlayingRL) {
    const userRecord = userData[newPresence.user.id];
    if (userRecord?.lastStartTime) {
      const duration = Date.now() - userRecord.lastStartTime;
      userRecord.weeklyTotal += duration;
      delete userRecord.lastStartTime;
      saveUserData();
    }
  }
});

2. 追踪一周游玩时长

通过定时任务每周重置数据,确保统计范围始终为当前自然周。

代码示例:

// 每周日UTC 0点重置所有用户的周时长
function resetWeeklyData() {
  const now = new Date();
  if (now.getUTCDay() === 0 && now.getUTCHours() === 0 && now.getUTCMinutes() < 1) {
    Object.keys(userData).forEach(userId => {
      userData[userId].weeklyTotal = 0;
    });
    saveUserData();
    // 可选:发送重置通知到指定频道
    const notifyChannel = client.channels.cache.get('你的通知频道ID');
    notifyChannel?.send('本周Rocket League游玩时长已重置,新一周的排行开始啦!');
  }
}

// 每小时检查一次重置条件
setInterval(resetWeeklyData, 3600000);

3. 响应指令生成排行榜

监听!leaderboard指令,从存储数据中提取用户时长并排序格式化输出。

代码示例:

client.on('messageCreate', (message) => {
  if (message.content !== '!leaderboard') return;

  // 过滤有效数据并按时长降序排序
  const sortedPlayers = Object.entries(userData)
    .filter(([_, data]) => data.weeklyTotal > 0)
    .sort((a, b) => b[1].weeklyTotal - a[1].weeklyTotal);

  if (sortedPlayers.length === 0) {
    return message.reply('本周还没有人玩过Rocket League哦!');
  }

  // 格式化毫秒为小时+分钟
  const formatMs = (ms) => {
    const hours = Math.floor(ms / 3600000);
    const minutes = Math.floor((ms % 3600000) / 60000);
    return `${hours}小时${minutes}分钟`;
  };

  // 生成排行文本
  let leaderboard = '📊 Rocket League本周游玩时长排行 📊\n';
  sortedPlayers.forEach(([userId, data], index) => {
    const member = message.guild.members.cache.get(userId);
    const username = member?.displayName || userId;
    leaderboard += `${index + 1}. ${username}: ${formatMs(data.weeklyTotal)}\n`;
  });

  message.channel.send(leaderboard);
});

client.login('你的机器人Token');

注意事项

  • 部分用户可能开启隐私设置,禁止他人查看活动状态,此类用户无法被追踪,需在逻辑中忽略。
  • 若服务器用户量较大,建议使用SQLite/MySQL替代JSON文件存储,提升数据读写效率。
  • 可扩展支持时区适配,根据服务器所在时区调整周重置时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:45:10