feat(tournament): wire official bots into tournaments via JWT and Redis
- Add token field to OfficialBotAccount and generate a non-expiring bot JWT on creation so official bots can authenticate - Expose token in POST /api/account/official-bots response and open the endpoint to any authenticated user - Bridge TournamentService to Redis: publish gameStart events to nowchess:bot:<name>:events after each pairing so OfficialBotService picks up games automatically Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+19
@@ -1,10 +1,12 @@
|
||||
package de.nowchess.tournament.service
|
||||
|
||||
import de.nowchess.tournament.client.{CoreCreateGameRequest, CoreGameClient, CorePlayerInfo, CoreTimeControl}
|
||||
import de.nowchess.tournament.config.RedisConfig
|
||||
import de.nowchess.tournament.domain.{Tournament, TournamentPairing, TournamentParticipant}
|
||||
import de.nowchess.tournament.dto.{BotRef, Clock, CreateTournamentForm, PairingDto, ResultDto, Standing, TournamentDto, Variant}
|
||||
import de.nowchess.tournament.error.TournamentError
|
||||
import de.nowchess.tournament.repository.{PairingRepository, ParticipantRepository, TournamentRepository}
|
||||
import io.quarkus.redis.datasource.RedisDataSource
|
||||
import jakarta.enterprise.context.ApplicationScoped
|
||||
import jakarta.inject.Inject
|
||||
import jakarta.transaction.Transactional
|
||||
@@ -28,6 +30,9 @@ class TournamentService:
|
||||
@Inject
|
||||
@RestClient
|
||||
var coreGameClient: CoreGameClient = uninitialized
|
||||
|
||||
@Inject var redis: RedisDataSource = uninitialized
|
||||
@Inject var redisConfig: RedisConfig = uninitialized
|
||||
// scalafix:on
|
||||
|
||||
@Transactional
|
||||
@@ -156,6 +161,20 @@ class TournamentService:
|
||||
pairingRepository.persist(pairing)
|
||||
streamManager.publishToBot(tournamentId, white.botId, s"""{"type":"gameStart","round":$round,"gameId":"${resp.gameId}","color":"white"}""")
|
||||
streamManager.publishToBot(tournamentId, black.botId, s"""{"type":"gameStart","round":$round,"gameId":"${resp.gameId}","color":"black"}""")
|
||||
publishBotGameStart(white.botName, resp.gameId, "white", white.botId)
|
||||
publishBotGameStart(black.botName, resp.gameId, "black", black.botId)
|
||||
|
||||
private def publishBotGameStart(
|
||||
botName: String,
|
||||
gameId: String,
|
||||
playingAs: String,
|
||||
botAccountId: String,
|
||||
): Unit =
|
||||
val channel = s"${redisConfig.prefix}:bot:$botName:events"
|
||||
val payload = s"""{"type":"gameStart","gameId":"$gameId","playingAs":"$playingAs","difficulty":1500,"botAccountId":"$botAccountId"}"""
|
||||
Try(redis.pubsub(classOf[String]).publish(channel, payload)) match
|
||||
case Failure(ex) => log.warnf(ex, "Failed to publish gameStart to bot channel %s", channel)
|
||||
case Success(_) => ()
|
||||
|
||||
@Transactional
|
||||
def handleGameResult(gameId: String, result: String, pgn: String): Unit =
|
||||
|
||||
Reference in New Issue
Block a user