Skip to content

sinnafuls/pubgreport-clips

Repository files navigation

pubgreport-clips

Discord bot that watches pubg.report for clipped moments involving configured PUBG players (kills and deaths) and posts a 30-second inline-playable video to a chosen Discord channel.

What it does

  • Polls api.pubg.report/v1/players/{accountId}/streams on an interval for every tracked player.
  • Filters events to ones where the configured user is the killer ("X just killed Y") or the victim ("X just died to Y").
  • Groups knock + kill events for the same encounter into a single moment so metadata (weapon, distance) merges correctly across them.
  • Resolves the source VOD's HLS playlist via api.pubg.report/v2/vod/{id} (no Twitch authentication needed — same path the site's "save" button uses) and downloads only the relevant 30 seconds via bundled ffmpeg.
  • Posts the clip in a Discord Components V2 container so the inline-playable mp4 sits inside the embed-style border alongside the metadata and link buttons.

Setup

npm install
cp .env.example .env
# fill in BOT_TOKEN, CLIENT_ID, GUILD_ID
npm run deploy   # register the /config slash command
npm run dev      # start polling (or `npm run build && npm start` for prod)

The bot needs only the Guilds gateway intent. When inviting it to a server grant Send Messages, Embed Links, and Attach Files in the target channel.

Discord slash commands

/config users add username:<PUBG name> channel:<#channel>
/config users remove username:<PUBG name>
/config users list
/config users test username:<PUBG name>

add resolves the PUBG name via pubg.report's search endpoint and stores the resulting account.<id>. The existing backlog of clips is marked seen on add so you don't get bombarded with weeks of history. test posts the most recent clip on demand without affecting the seen-id state. All require the Manage Server permission.

Environment variables

Variable Default Notes
BOT_TOKEN Discord bot token (required)
CLIENT_ID Discord application ID (required)
GUILD_ID Optional. If set, slash commands deploy instantly to this guild instead of globally (which can take an hour to propagate).
POLL_INTERVAL_SECONDS 120 Per-cycle poll cadence; clamped to a 15s minimum.
DATA_DIR ./data Where config.json (tracked users + seen IDs) lives.
CLIP_PRE_SECONDS 0 Seconds of lead-in before the pubg.report timestamp.
CLIP_POST_SECONDS 30 Seconds of trail-out after the latest event in the encounter.
CLIP_MAX_HEIGHT 480 Max HLS variant height; bumps to 720 only if 480 isn't published.
CLIP_UPLOAD_CAP_BYTES 25165824 Hard cap on the produced mp4 to stay under Discord's default 25 MB attachment limit.

Self-host with Docker

cp .env.example .env
# fill in .env
docker compose up -d --build
docker compose logs -f dickhead-bot

The data/ directory is volume-mounted so tracked users + seen IDs persist across rebuilds. The @ffmpeg-installer/ffmpeg npm package pulls down the linux-x64 ffmpeg binary at build time, so the runtime image needs nothing extra installed.

Architecture

pubg.report /v1/players/.../streams   →  raw kill/death events
                ↓
        group into clip moments  (knock + kill collapse, kill vs death)
                ↓
pubg.report /v2/vod/{id}                →  CloudFront HLS playlist URL
                ↓
        ffmpeg dual-seek + transcode    →  ~5–10 MB mp4 segment
                ↓
Discord Components V2 container         →  inline player + metadata + buttons

Layout

source/
  index.ts                  entrypoint, dynamic command/event loaders
  config.ts                 env validation
  deploy-commands.ts        REST registrar for /config
  commands/config.ts        /config users add|remove|list|test
  events/                   clientReady, interactionCreate
  services/
    pubgReport.ts           search + streams API client
    vodPlaylist.ts          VOD metadata → HLS URL (with LRU cache)
    clipExtractor.ts        bundled-ffmpeg HLS → mp4 with dual-seek
    tracker.ts              poll loop, moment grouping, message builder
  storage/store.ts          JSON-file backed per-guild user store
  utils/                    twitch URL helpers + logger
  types/                    shared interfaces

Why this approach

The naive choices don't work for inline-playable Discord clips:

  • Twitch VOD URLs (twitch.tv/videos/...) don't auto-embed as Discord players anymore — only clips.twitch.tv/<slug> URLs do.
  • Twitch's createClip API requires a user OAuth token and only works on live streams, not VODs (its videoID variant requires the user account to be clip-eligible, which gates new accounts and can return USER_RESTRICTED).
  • Discord won't render iframe embeds, only video files or whitelisted provider URLs.

The path that actually works without manual auth: take pubg.report's own trick. Their "save" button reads VOD metadata from api.pubg.report/v2/vod/{id}, parses the CloudFront path out of thumbnail_url, and pulls HLS segments directly from Twitch's public CDN. We do the same, then ffmpeg cuts a 30-second window around the kill, transcodes to 480p mp4, and Discord Components V2 lets the resulting attachment sit inside an embed-style container.

About

discord bot to auto send clips from pubg.report

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors