Skip to content

Commit

Permalink
feat: live match win probability (stratz) (#375)
Browse files Browse the repository at this point in the history
  • Loading branch information
Geczy authored Dec 10, 2023
2 parents 8288c78 + 20a4c3c commit 70698e6
Show file tree
Hide file tree
Showing 13 changed files with 596 additions and 15 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ TLS_CERT="-----BEGIN CERTIFICATE-----
TLS_KEY="-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----"

# Optional https://stratz.com/api token used for win probability calculation
STRATZ_TOKEN=""
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ services:
- NEW_RELIC_LICENSE_KEY
- NODE_ENV
- STEAM_WEB_API
- STRATZ_TOKEN
- TWITCH_BOT_PROVIDERID
- TWITCH_CLIENT_ID
- TWITCH_CLIENT_SECRET
Expand Down
4 changes: 4 additions & 0 deletions packages/dota/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,5 +206,9 @@
"commit": "Server running version {{version}}, here's what's missing compared to the latest version: {{- url}}",
"unknown": "Couldn't find the last git commit, here's the repo {{- url}}"
},
"winprobability": {
"winProbabilityDataNotAvailable": "Win probability is not available yet · Try again in {{remainingCooldown}}s",
"winProbability": "{{winRate}}% win probability {{emote}} at {{gameTime}}:00 ⏲ · Next update in {{remainingCooldown}}s"
},
"xpm": "Live XPM for {{- heroName}}: {{num}}"
}
25 changes: 20 additions & 5 deletions packages/dota/src/db/getDBUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default async function getDBUser({

if (lookingupToken.has(lookupToken)) return null

logger.info('[GSI] Haven’t cached user token yet, checking db', { ip, token: lookupToken })
logger.info('[GSI] Haven’t cached user token yet, checking db', { ip, lookupToken })
lookingupToken.set(lookupToken, true)

if (!lookupToken) {
Expand All @@ -39,17 +39,32 @@ export default async function getDBUser({
}

let userId = token || null
if (providerAccountId) {
const { data } = await supabase
if (providerAccountId || lookupToken) {
const { data, error } = await supabase
.from('accounts')
.select('userId')
.eq('providerAccountId', providerAccountId)
.eq('providerAccountId', providerAccountId || lookupToken)
.single()
userId = data?.userId ?? null

if (error) {
logger.error('[USER] 2 Error checking auth', {
lookupToken,
providerAccountId,
error,
})
invalidTokens.add(lookupToken)
deleteLookupToken(lookupToken)
return null
}
}

if (!userId) {
logger.error('[USER] 2 Error checking auth', { token: lookupToken, error: 'No token' })
logger.error('[USER] 2 Error checking auth', {
lookupToken,
providerAccountId,
error: 'No token',
})
invalidTokens.add(lookupToken)
deleteLookupToken(lookupToken)
return null
Expand Down
139 changes: 136 additions & 3 deletions packages/dota/src/db/supabase-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export interface Database {
{
foreignKeyName: 'accounts_userId_fkey'
columns: ['userId']
isOneToOne: true
referencedRelation: 'users'
referencedColumns: ['id']
},
Expand Down Expand Up @@ -134,6 +135,7 @@ export interface Database {
{
foreignKeyName: 'bets_userId_fkey'
columns: ['userId']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
Expand Down Expand Up @@ -168,12 +170,43 @@ export interface Database {
{
foreignKeyName: 'mods_mod_user_id_fkey'
columns: ['mod_user_id']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
{
foreignKeyName: 'mods_streamer_user_id_fkey'
columns: ['streamer_user_id']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
]
}
sessions: {
Row: {
expires: string
id: string
sessionToken: string
userId: string
}
Insert: {
expires: string
id: string
sessionToken: string
userId: string
}
Update: {
expires?: string
id?: string
sessionToken?: string
userId?: string
}
Relationships: [
{
foreignKeyName: 'sessions_userId_fkey'
columns: ['userId']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
Expand Down Expand Up @@ -208,6 +241,7 @@ export interface Database {
{
foreignKeyName: 'settings_userId_fkey'
columns: ['userId']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
Expand Down Expand Up @@ -251,6 +285,7 @@ export interface Database {
{
foreignKeyName: 'steam_accounts_userId_fkey'
columns: ['userId']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
Expand Down Expand Up @@ -300,6 +335,7 @@ export interface Database {
{
foreignKeyName: 'streams_userId_fkey'
columns: ['userId']
isOneToOne: true
referencedRelation: 'users'
referencedColumns: ['id']
},
Expand All @@ -315,14 +351,16 @@ export interface Database {
followers: number | null
id: string
image: string | null
kick: number | null
locale: string
mmr: number
name: string
name: string | null
steam32Id: number | null
stream_delay: number | null
stream_online: boolean
stream_start_date: string | null
updated_at: string
youtube: string | null
}
Insert: {
beta_tester?: boolean
Expand All @@ -333,14 +371,16 @@ export interface Database {
followers?: number | null
id?: string
image?: string | null
kick?: number | null
locale?: string
mmr?: number
name?: string
name?: string | null
steam32Id?: number | null
stream_delay?: number | null
stream_online?: boolean
stream_start_date?: string | null
updated_at?: string
youtube?: string | null
}
Update: {
beta_tester?: boolean
Expand All @@ -351,14 +391,34 @@ export interface Database {
followers?: number | null
id?: string
image?: string | null
kick?: number | null
locale?: string
mmr?: number
name?: string
name?: string | null
steam32Id?: number | null
stream_delay?: number | null
stream_online?: boolean
stream_start_date?: string | null
updated_at?: string
youtube?: string | null
}
Relationships: []
}
verificationtokens: {
Row: {
expires: string
identifier: string
token: string
}
Insert: {
expires: string
identifier: string
token: string
}
Update: {
expires?: string
identifier?: string
token?: string
}
Relationships: []
}
Expand Down Expand Up @@ -391,3 +451,76 @@ export interface Database {
}
}
}

export type Tables<
PublicTableNameOrOptions extends
| keyof (Database['public']['Tables'] & Database['public']['Views'])
| { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof (Database[PublicTableNameOrOptions['schema']]['Tables'] &
Database[PublicTableNameOrOptions['schema']]['Views'])
: never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
? (Database[PublicTableNameOrOptions['schema']]['Tables'] &
Database[PublicTableNameOrOptions['schema']]['Views'])[TableName] extends {
Row: infer R
}
? R
: never
: PublicTableNameOrOptions extends keyof (Database['public']['Tables'] &
Database['public']['Views'])
? (Database['public']['Tables'] & Database['public']['Views'])[PublicTableNameOrOptions] extends {
Row: infer R
}
? R
: never
: never

export type TablesInsert<
PublicTableNameOrOptions extends keyof Database['public']['Tables'] | { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicTableNameOrOptions['schema']]['Tables']
: never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
? Database[PublicTableNameOrOptions['schema']]['Tables'][TableName] extends {
Insert: infer I
}
? I
: never
: PublicTableNameOrOptions extends keyof Database['public']['Tables']
? Database['public']['Tables'][PublicTableNameOrOptions] extends {
Insert: infer I
}
? I
: never
: never

export type TablesUpdate<
PublicTableNameOrOptions extends keyof Database['public']['Tables'] | { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicTableNameOrOptions['schema']]['Tables']
: never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
? Database[PublicTableNameOrOptions['schema']]['Tables'][TableName] extends {
Update: infer U
}
? U
: never
: PublicTableNameOrOptions extends keyof Database['public']['Tables']
? Database['public']['Tables'][PublicTableNameOrOptions] extends {
Update: infer U
}
? U
: never
: never

export type Enums<
PublicEnumNameOrOptions extends keyof Database['public']['Enums'] | { schema: keyof Database },
EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicEnumNameOrOptions['schema']]['Enums']
: never = never,
> = PublicEnumNameOrOptions extends { schema: keyof Database }
? Database[PublicEnumNameOrOptions['schema']]['Enums'][EnumName]
: PublicEnumNameOrOptions extends keyof Database['public']['Enums']
? Database['public']['Enums'][PublicEnumNameOrOptions]
: never
4 changes: 4 additions & 0 deletions packages/dota/src/dota/lib/DelayedCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ export const DelayedCommands: { command: string; key: SettingKeys }[] = [
command: '!items',
key: DBSettings.commandItems,
},
{
command: '!wp',
key: DBSettings.commandWinProbability,
},
]
61 changes: 61 additions & 0 deletions packages/dota/src/stratz/livematch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import axios from 'axios'

const STRATZ_GQL = 'https://api.stratz.com/graphql'

const LiveMatchDetailsQuery = `
query GetLiveMatch($matchId: Long!) {
live {
match(id: $matchId) {
liveWinRateValues {
time
winRate
}
completed
isUpdating
}
}
}
`

type StratzLiveMatchResponse = {
data: {
live: {
match?: {
liveWinRateValues: Array<{
time: number
winRate: number
}>
completed: boolean
isUpdating: boolean
}
}
}
}

export const GetLiveMatch = async (
matchId: number,
): Promise<StratzLiveMatchResponse | undefined> => {
if (!process.env.STRATZ_TOKEN) {
return
}

try {
const response = await axios.post<StratzLiveMatchResponse>(
STRATZ_GQL,
{
query: LiveMatchDetailsQuery,
variables: { matchId }, // Pass the matchId as a variable
},
{
headers: {
Authorization: `Bearer ${process.env.STRATZ_TOKEN}`,
},
},
)

return response.data
} catch (error) {
// console.error(error?.response?.data?.errors ?? error?.data ?? error)
return undefined
}
}
1 change: 1 addition & 0 deletions packages/dota/src/twitch/commandLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ import './commands/toggle.js'
import './commands/version.js'
import './commands/wl.js'
import './commands/xpm.js'
import './commands/winprobability.js'
Loading

0 comments on commit 70698e6

Please sign in to comment.