Repository navigation
feat: add Battle.net presence detection through BGS - #115
Merged
Merged
Conversation
Java schemas are generated at build time from the bgs.desc descriptor set, with the outer class names and Java packages patched where files would collide.
BgsClient runs the session sequence on an open BgsChannel: Connect, ticket mint between Connect and Logon, Logon, minimal account subscribe, game account selection, friends subscribe and paged sync, then the presence watch once the self presence push arrives. The friends list and the invitations survive across sessions and each resync reports the diff. Friend actions fail at once outside a ready session and never change the local state on their reply.
A sent invitation that vanished while offline is reported with REASON_GONE_WHILE_OFFLINE (-1) instead of 0, which means accepted. A close requested by the client reports CloseReason.LOCAL instead of IO. BgsSession reads static fields through AccessFlag, which the English conventions check accepts.
…detect games Sessions open only with battlenet.sessions.enabled on the active site, close on standby and reopen when the site becomes active. Presence pushes feed the Battle.net game getter; friend events are republished off the session loop. Replaced sessions and sessions needing an admin are logged and counted.
Version column on the service account; the login coordinator reloads and retries its auth state and storage state writes once when an admin edit raced them.
Admin service and REST endpoints to enrol, re-authenticate, edit and delete the Battle.net bot accounts; the BGS session restarts once an interactive login is ready.
Enrol streamers on the first ready bot with room and have it invite them; move links with the bot's friend events (accept, reject, remove), answer received invitations, mark a bot full on a friend cap failure and announce every change as a battlenet.link.changed channel event. Link lookups by BattleTag or account id now return lists, since nothing makes them unique per bot.
…or full links Send the accept/decline of a received invitation once the event's transaction is committed, accept the invitation of a streamer whose link was rejected, and move a link off a bot found full to the next bot with room (deleting it when none is left).
…d OAuth Secondary OAuth link on the signed-in Twitch user: the userinfo id and BattleTag enroll the account with a bot, no token is kept. Adds the connect endpoints (state, leave) and the Battle.net data on the channel dashboard.
Live-updated from BattleNetLinkChanged, with a case per link status, the OAuth connect button, a disconnect action and mock data for the mock channel page.
Adds the bot pool section to the Keys tab: list, add, 2FA code entry, reauth, enable/disable, lift full, change password and delete. The tab refreshes every 3 s while a login is pending. Includes the mock store.
Polling only runs while the Keys tab is shown, including after an in-flight tick. Each bot row can now rename the bot and change its fill order.
settings.gradle.kts includes catapult-bgs, so Gradle refuses to configure the build when its directory is missing from the web builder stage.
…checks The route, convention and access-matrix contexts now enable Battle.net, the matrix pins its user and admin routes, and catapult-web spells each admin path in its call so the route check reads it.
…d ones A re-mint asked while one is queued or running for the same bot now waits for that one, and a queued login whose callers all gave up is dropped before Chromium opens. A BGS session that ends while minting interrupts its mint, so an aborted attempt withdraws instead of logging in later.
…ssion The handshake now has a 15 s read timeout, lifted once connected; the socket is closed on any failure, connect included.
Headless Chromium writes its profile and crash data under $HOME, which a system user created without a home lacks.
The Battle.net link keeps no token, so the authorized client Spring stored in memory after the OAuth callback is removed at once.
The admin bot list now says whether a login waits for the 2FA code. A bot left CODE_REQUIRED by an automatic login shows a hint to re-authenticate instead of a code field that could only answer 409, and the Keys tab stops polling for it.
Deleting a bot now disables the Battle.net getter of every streamer linked through it, as unenrolling does, and tells their dashboards the link is gone once the bot is deleted.
…k controller Controllers hold no repository (ControllerConventionsTest): the Battle.net link controller now reads the caller like the other user routes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Detect the Blizzard game a streamer is playing through Battle.net presence, the same way Minecraft works: Catapult bot accounts are friends with the streamer and read their presence over Battle.net's internal BGS protocol (pushed, no polling).
catapult-bgs(new module, protobuf-java only): TLS framing + RPC, session sequence (connect → ticket → logon → account subscribe → game-account select → friends sync → presence), friends list and actions, presence merging, reconnection with backoff, start watchdog, bounded TLS handshake.battlenet_service_account,battlenet_friend_link, migrations V108/V109 with@Version), headless Chromium login (Playwright) with the 2FA code entered in the admin and trusted cookies stored encrypted in the DB, one BGS session per bot only on the active site (battlenet.sessions.enabled+ SiteRole guard), friend links driven by BGS events (bot invites the streamer and/or the streamer adds the bot), streamer link through Blizzard OAuth2,BattleNetGameGetter, admin API,battlenet.integrationexperiment.eclipse-temurin:25-jre-noblewith Chromium installed at build time; catapult-web builder copies the new module's build file.Modules to restart
catapult-api and catapult-web — deploy both together (shared DTO
BattleNetAccountDtogained a field). New catapult-api image (noble base, Chromium baked in: larger image, check the pod memory limit).Before enabling in production
BATTLENET_ENABLED=true,BATTLENET_CLIENT_ID,BATTLENET_CLIENT_SECRET, andBATTLENET_SESSIONS_ENABLED=trueonly where the site guard runs (never on a second instance sharing the same bots).<web-url>/login/oauth2/code/battlenet.battlenet.integrationexperiment in the admin (created as DRAFT).Verified
Not verified live yet
revokeInvitation, cross-region friendships,OnExternalChallenge.Risk
Replaying Battle.net's client protocol with headless bot accounts goes against Blizzard's terms: bot accounts may be banned. The feature stays behind
battlenet.enabledand thebattlenet.integrationexperiment.