Skip to content

Commit

Permalink
refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
Geczy committed Aug 26, 2023
1 parent 0fc4754 commit 71a2ada
Show file tree
Hide file tree
Showing 25 changed files with 373 additions and 446 deletions.
61 changes: 28 additions & 33 deletions packages/dota/src/dota/GSIHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { chatClient } from '../twitch/index.js'
import { closeTwitchBet } from '../twitch/lib/closeTwitchBet.js'
import { openTwitchBet } from '../twitch/lib/openTwitchBet.js'
import { refundTwitchBet } from '../twitch/lib/refundTwitchBets.js'
import { DotaEvent, Player, SocketClient } from '../types.js'
import { DotaEvent, SocketClient } from '../types.js'
import axios from '../utils/axios.js'
import { steamID64toSteamID32 } from '../utils/index.js'
import { logger } from '../utils/logger.js'
Expand Down Expand Up @@ -77,32 +77,27 @@ export function say(
}

export async function deleteRedisData(client: SocketClient) {
const steam32 = client.steam32Id ?? ''
const { token } = client

const keysToDelete = [
`${token}:passiveMidas`,
`${steam32}:medal`,
`${token}:roshan`,
`${token}:aegis`,
`${token}:treadtoggle`,
`${token}:heroRecords`,
`${token}:playingHero`,
`${token}:playingHeroSlot`,
`${token}:playingTeam`,
`${token}:lobbyType`,
`${token}:passiveTp`,
`${token}:heroRecords`,
`${token}:betsForMatchId`,
`${token}:steamServerId`,
]

const multi = redisClient.client.multi()
keysToDelete.forEach((key) => multi.json.del(key))
keysToDelete.forEach((key) => multi.del(key))
const { steam32Id, token } = client
const matchId =
(await redisClient.client.get(`${token}:betsForMatchId`)) ?? client.gsi?.map?.matchid

try {
await multi.exec()
await redisClient.client
.multi()
.del(`${matchId}:lobbyType`)
.del(`${matchId}:steamServerId`)
.del(`${steam32Id}:medal`)
.del(`${token}:aegis`)
.del(`${token}:betsForMatchId`)
.del(`${token}:heroRecords`)
.del(`${token}:passiveMidas`)
.del(`${token}:passiveTp`)
.del(`${token}:playingHero`)
.del(`${token}:playingHeroSlot`)
.del(`${token}:playingTeam`)
.del(`${token}:roshan`)
.del(`${token}:treadtoggle`)
.exec()
} catch (e) {
logger.error('err deleteRedisData', { e })
}
Expand Down Expand Up @@ -202,6 +197,7 @@ export class GSIHandler {
}

public async resetClientState() {
console.log('resetting all data')
await deleteRedisData(this.client)
this.mapBlocker.resetData()
this.resetPlayerData()
Expand Down Expand Up @@ -230,7 +226,7 @@ export class GSIHandler {
async emitNotablePlayers() {
if (!this.client.stream_online) return

const { matchPlayers } = await getAccountsFromMatch(this.client.gsi)
const { matchPlayers } = await getAccountsFromMatch({ gsi: this.client.gsi })

const enableCountries = getValueOrDefault(
DBSettings.notablePlayersOverlayFlagsCmd,
Expand Down Expand Up @@ -426,31 +422,31 @@ export class GSIHandler {
// 4 Then, tell twitch to close bets based on win result
async openBets(client: SocketClient) {
if (this.openingBets) {
console.log('still opening')
// console.log('still opening')
return
}

// Why open if not playing?
if (client.gsi?.player?.activity !== 'playing') {
console.log(`if (client.gsi?.player?.activity !== 'playing') {`)
// console.log(`if (client.gsi?.player?.activity !== 'playing') {`)
return
}

// Why open if won?
if (client.gsi.map?.win_team !== 'none') {
console.log(`if (client.gsi.map?.win_team !== 'none') {`)
// console.log(`if (client.gsi.map?.win_team !== 'none') {`)
return
}

// We at least want the hero name so it can go in the twitch bet title
if (!client.gsi.hero?.name || !client.gsi.hero.name.length) {
console.log(`if (!client.gsi.hero?.name || !client.gsi.hero.name.length) {`)
// console.log(`if (!client.gsi.hero?.name || !client.gsi.hero.name.length) {`)
return
}

// It's not a live game, so we don't want to open bets nor save it to DB
if (!client.gsi.map.matchid || client.gsi.map.matchid === '0') {
console.log(`if (!client.gsi.map.matchid || client.gsi.map.matchid === '0') {`)
// console.log(`if (!client.gsi.map.matchid || client.gsi.map.matchid === '0') {`)
return
}

Expand All @@ -477,7 +473,6 @@ export class GSIHandler {

// The bet was already made
if (Number(betsForMatchId) >= 0) {
console.log(`if (Number(betsForMatchId) >= 0) {`)
return
}

Expand Down Expand Up @@ -641,7 +636,7 @@ export class GSIHandler {
this.openingBets = false
})
})
.catch(async (e: any) => {
.catch((e: any) => {
logger.error('[BETS] Error opening bet', {
betsForMatchId: client?.gsi?.map?.matchid || '',
channel,
Expand Down
10 changes: 3 additions & 7 deletions packages/dota/src/dota/GSIServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,10 @@ class GSIServer {
app.post('/', validateToken, processChanges('previously'), processChanges('added'), newData)
}

if (process.env.NODE_ENV === 'development') {
this.dota.dota2.on('ready', () => {
logger.info('[SERVER] Connected to dota game coordinator')
setupPostRoute()
} else {
this.dota.dota2.on('ready', () => {
logger.info('[SERVER] Connected to dota game coordinator')
setupPostRoute()
})
}
})

app.get('/', (req: Request, res: Response) => {
res.status(200).json({ status: 'ok' })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.AegisDenied}`, {
if (!isPlayingMatch(dotaClient.client.gsi)) return
if (!dotaClient.client.stream_online) return

const { matchPlayers } = await getAccountsFromMatch(dotaClient.client.gsi)
const { matchPlayers } = await getAccountsFromMatch({ gsi: dotaClient.client.gsi })

const heroName = getHeroNameById(matchPlayers[event.player_id]?.heroid ?? 0, event.player_id)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.AegisPickedUp}`, {
// server time
const expireDate = dotaClient.addSecondsToNow(expireS)

const { matchPlayers } = await getAccountsFromMatch(dotaClient.client.gsi)
const { matchPlayers } = await getAccountsFromMatch({ gsi: dotaClient.client.gsi })

const heroName = getHeroNameById(matchPlayers[event.player_id]?.heroid ?? 0, event.player_id)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { t } from 'i18next'

import { DotaEvent, DotaEventTypes } from '../../../types.js'
import { GSIHandler, redisClient, say } from '../../GSIHandler.js'
import { isDev } from '../../lib/consts.js'
import { getAccountsFromMatch } from '../../lib/getAccountsFromMatch.js'
import { getHeroNameById } from '../../lib/heroes.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
Expand All @@ -13,6 +12,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.BountyPickup}`, {
handler: async (dotaClient: GSIHandler, event: DotaEvent) => {
if (!isPlayingMatch(dotaClient.client.gsi)) return
if (!dotaClient.client.stream_online) return
if (Number(dotaClient.client.gsi?.map?.clock_time) > 120) return

const chattersEnabled = getValueOrDefault(DBSettings.chatter, dotaClient.client.settings)
const {
Expand All @@ -24,14 +24,9 @@ eventHandler.registerEvent(`event:${DotaEventTypes.BountyPickup}`, {
(await redisClient.client.get(`${dotaClient.client.token}:playingTeam`)) ??
dotaClient.client.gsi?.player?.team_name

// Only for first bounties
if (
event.team !== playingTeam ||
(!isDev && Number(dotaClient.client.gsi?.map?.clock_time) > 120)
)
return
if (event.team !== playingTeam) return

const { matchPlayers } = await getAccountsFromMatch(dotaClient.client.gsi)
const { matchPlayers } = await getAccountsFromMatch({ gsi: dotaClient.client.gsi })

if (
typeof matchPlayers[event.player_id]?.heroid !== 'number' ||
Expand Down
2 changes: 1 addition & 1 deletion packages/dota/src/dota/events/gsi-events/event.tip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.Tip}`, {

if (!chattersEnabled || !chatterEnabled) return

const { matchPlayers } = await getAccountsFromMatch(dotaClient.client.gsi)
const { matchPlayers } = await getAccountsFromMatch({ gsi: dotaClient.client.gsi })

const heroName = getHeroNameById(
matchPlayers[event.sender_player_id]?.heroid ?? 0,
Expand Down
67 changes: 37 additions & 30 deletions packages/dota/src/dota/events/gsi-events/newdata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { checkPassiveMidas } from '../../lib/checkMidas.js'
import { checkPassiveTp } from '../../lib/checkPassiveTp.js'
import { calculateManaSaved } from '../../lib/checkTreadToggle.js'
import { DelayedCommands } from '../../lib/consts.js'
import { getAccountsFromMatch } from '../../lib/getAccountsFromMatch.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import eventHandler from '../EventHandler.js'
import minimapParser from '../minimap/parser.js'
Expand Down Expand Up @@ -39,49 +38,57 @@ function chatterMatchFound(client: SocketClient) {
}
}

const steamServerLookupMap = new Map()
const steamDelayDataLookupMap = new Map()

// Runs every gametick
async function saveMatchData(client: SocketClient) {
// This now waits for the bet to complete before checking match data
// Since match data is delayed it will run far fewer than before, when checking actual match id of an ingame match
// the playingBetMatchId is saved when the hero is selected
const betsForMatchId =
(await redisClient.client.get(`${client.token}:betsForMatchId`)) ?? undefined
const betsForMatchId = await redisClient.client.get(`${client.token}:betsForMatchId`)
if (!Number(betsForMatchId)) return

if (!client.steam32Id) return

// did we already come here before?
let steamServerId = await redisClient.client.get(`${betsForMatchId}:steamServerId`)
if (steamServerId) return

// lookup a new steam server id
steamServerId = await server.dota.getUserSteamServer(client.steam32Id)
if (!steamServerId) return

// save the new server id now
await redisClient.client.set(`${betsForMatchId}:steamServerId`, steamServerId)

const delayedData = await server.dota.getDelayedMatchData({
server_steamid: steamServerId,
match_id: betsForMatchId!,
refetchCards: true,
token: client.token,
})

if (!delayedData?.match.match_id) {
logger.info('No match data found!', {
name: client.name,
betsForMatchId,
})
return
let [steamServerId, lobbyType] = await redisClient.client
.multi()
.get(`${betsForMatchId}:steamServerId`)
.get(`${betsForMatchId}:lobbyType`)
.exec()

if (steamServerId && lobbyType) return

if (!steamServerId && !lobbyType) {
if (steamServerLookupMap.has(betsForMatchId)) return

const promise = server.dota.getUserSteamServer(client.steam32Id)
steamServerLookupMap.set(betsForMatchId, promise)
steamServerId = await promise
steamServerLookupMap.delete(betsForMatchId) // Remove the promise once it's resolved

if (!steamServerId) return
await redisClient.client.set(`${betsForMatchId}:steamServerId`, steamServerId.toString())
}

await redisClient.client.set(`${betsForMatchId}:lobbyType`, delayedData.match.lobby_type)
if (steamServerId && !lobbyType) {
if (steamDelayDataLookupMap.has(betsForMatchId)) return

const players = await getAccountsFromMatch(client.gsi)
const promise = server.dota.GetRealTimeStats({
match_id: betsForMatchId!,
refetchCards: true,
steam_server_id: steamServerId.toString(),
token: client.token,
})
steamDelayDataLookupMap.set(betsForMatchId, promise)
const delayedData = await promise
steamDelayDataLookupMap.delete(betsForMatchId) // Remove the promise once it's resolved

// letting people know match data is available
if (players.accountIds.length) chatterMatchFound(client)
if (!delayedData?.match.lobby_type) return
await redisClient.client.set(`${betsForMatchId}:lobbyType`, delayedData.match.lobby_type)
chatterMatchFound(client)
}
}

// Catch all
Expand Down
1 change: 1 addition & 0 deletions packages/dota/src/dota/lib/checkPassiveTp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const PASSIVE_THRESHOLD_SECONDS = 30 * 1000
export async function checkPassiveTp(client: SocketClient) {
if (!isPlayingMatch(client.gsi)) return
if (!client.stream_online) return
if (Number(client.gsi?.map?.clock_time) <= 0) return

const passiveTpData = ((await redisClient.client.json.get(`${client.token}:passiveTp`)) as {
firstNoticedPassive: number
Expand Down
60 changes: 34 additions & 26 deletions packages/dota/src/dota/lib/getAccountsFromMatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,45 @@ import { mongoClient } from '../../steam/index.js'
import { Packet } from '../../types.js'
import { getCurrentMatchPlayers } from './getCurrentMatchPlayers.js'

export async function getAccountsFromMatch(
gsi?: Packet,
searchMatchId?: string,
export async function getAccountsFromMatch({
gsi,
searchMatchId,
searchPlayers,
}: {
gsi?: Packet
searchMatchId?: string
searchPlayers?: {
heroid: number
accountid: number
}[],
) {
const response = (await mongoClient
.collection('delayedGames')
.findOne({ 'match.match_id': searchMatchId || gsi?.map?.matchid })) as unknown as
| delayedGames
| undefined

}[]
} = {}) {
const players = searchPlayers?.length ? searchPlayers : getCurrentMatchPlayers(gsi)

const matchPlayers =
Array.isArray(players) && players.length
? players
: response
? [
...response.teams[0].players.map((a) => ({
heroid: a.heroid,
accountid: Number(a.accountid),
})),
...response.teams[1].players.map((a) => ({
heroid: a.heroid,
accountid: Number(a.accountid),
})),
]
: []
if (Array.isArray(players) && players.length) {
return {
matchPlayers: players,
accountIds: players.map((player) => player.accountid),
}
}

const matchId = searchMatchId || gsi?.map?.matchid
const response = await mongoClient
.collection<delayedGames>('delayedGames')
.findOne({ 'match.match_id': matchId })

let matchPlayers = [] as { heroid: number; accountid: number }[]
if (Array.isArray(response?.teams) && response?.teams.length === 2) {
matchPlayers = [
...response.teams[0].players.map((a) => ({
heroid: a.heroid,
accountid: Number(a.accountid),
})),
...response.teams[1].players.map((a) => ({
heroid: a.heroid,
accountid: Number(a.accountid),
})),
]
}

return {
matchPlayers,
Expand Down
Loading

0 comments on commit 71a2ada

Please sign in to comment.