2021-02-19 17:44:38 -08:00
/ * T h e A r t i f i c e r w a s b u i l t i n m e m o r y o f B a b k a
* With love , Ean
*
* December 21 , 2020
* /
import {
// Discordeno deps
2022-05-20 01:43:22 -07:00
cache ,
cacheHandlers ,
2022-06-26 19:53:25 -07:00
// imagescript
is ,
2022-05-04 23:49:06 -07:00
// Log4Deno deps
2022-05-27 21:48:34 -07:00
log ,
2022-05-20 01:43:22 -07:00
LT ,
} from '../deps.ts' ;
2022-06-25 13:26:48 -07:00
import { PastCommandCount } from './mod.d.ts' ;
2022-06-26 19:53:25 -07:00
import { dbClient , weekDays } from './db.ts' ;
2022-06-25 13:26:48 -07:00
import utils from './utils.ts' ;
2022-05-20 01:43:22 -07:00
import config from '../config.ts' ;
2021-02-19 17:44:38 -08:00
2021-11-21 19:14:57 -08:00
// getRandomStatus() returns status as string
2021-02-19 17:44:38 -08:00
// Gets a new random status for the bot
2021-11-21 19:14:57 -08:00
const getRandomStatus = async ( ) : Promise < string > = > {
2022-05-20 01:43:22 -07:00
let status = '' ;
2021-02-19 17:44:38 -08:00
switch ( Math . floor ( ( Math . random ( ) * 4 ) + 1 ) ) {
case 1 :
status = ` ${ config . prefix } help for commands ` ;
break ;
case 2 :
status = ` Running V ${ config . version } ` ;
break ;
case 3 :
status = ` ${ config . prefix } info to learn more ` ;
break ;
2021-11-21 19:14:57 -08:00
default : {
2022-05-20 01:43:22 -07:00
const cachedCount = await cacheHandlers . size ( 'guilds' ) ;
2021-11-21 19:14:57 -08:00
status = ` Rolling dice for ${ cachedCount + cache . dispatchedGuildIds . size } servers ` ;
2021-02-19 17:44:38 -08:00
break ;
2021-11-21 19:14:57 -08:00
}
2021-02-19 17:44:38 -08:00
}
2022-05-20 01:43:22 -07:00
2021-02-19 17:44:38 -08:00
return status ;
} ;
2022-06-26 19:53:25 -07:00
// updateListStatistics(bot ID, current guild count) returns nothing, posts to botlists
2021-03-13 12:10:35 -08:00
// Sends the current server count to all bot list sites we are listed on
2021-11-21 19:14:57 -08:00
const updateListStatistics = ( botID : bigint , serverCount : number ) : void = > {
2022-05-20 01:43:22 -07:00
config . botLists . forEach ( async ( e ) = > {
log ( LT . LOG , ` Updating statistics for ${ JSON . stringify ( e ) } ` ) ;
2021-03-13 12:10:35 -08:00
if ( e . enabled ) {
const tempHeaders = new Headers ( ) ;
tempHeaders . append ( e . headers [ 0 ] . header , e . headers [ 0 ] . value ) ;
2022-05-20 01:43:22 -07:00
tempHeaders . append ( 'Content-Type' , 'application/json' ) ;
2021-03-13 12:10:35 -08:00
// ?{} is a template used in config, just need to replace it with the real value
2022-05-20 01:43:22 -07:00
const response = await fetch ( e . apiUrl . replace ( '?{bot_id}' , botID . toString ( ) ) , {
'method' : 'POST' ,
'headers' : tempHeaders ,
'body' : JSON . stringify ( e . body ) . replace ( '"?{server_count}"' , serverCount . toString ( ) ) , // ?{server_count} needs the "" removed from around it aswell to make sure its sent as a number
2021-03-13 12:10:35 -08:00
} ) ;
2022-05-04 23:49:06 -07:00
log ( LT . INFO , ` Posted server count to ${ e . name } . Results: ${ JSON . stringify ( response ) } ` ) ;
2021-03-13 12:10:35 -08:00
}
} ) ;
} ;
2022-06-25 13:26:48 -07:00
// Keep one week of data
const hoursToKeep = 7 * 24 ;
2022-06-26 17:18:41 -07:00
const previousHours : Array < Array < PastCommandCount > > = [ ] ;
2022-06-26 19:53:25 -07:00
// updateHourlyRates() returns nothing, updates DB directly
2022-06-25 13:26:48 -07:00
// Updates the hourlyRate for command usage
const updateHourlyRates = async ( ) = > {
try {
2022-06-26 19:53:25 -07:00
const newestHour = await dbClient . query ( 'SELECT command, count FROM command_cnt ORDER BY command;' ) . catch ( ( e ) = > utils . commonLoggers . dbError ( 'intervals.ts:71' , 'query' , e ) ) ;
2022-06-25 13:26:48 -07:00
previousHours . push ( newestHour ) ;
if ( previousHours . length > 1 ) {
const oldestHour = previousHours [ 0 ] ;
2022-06-26 17:18:41 -07:00
const computedDiff : Array < PastCommandCount > = [ ] ;
2022-06-25 13:26:48 -07:00
for ( let i = 0 ; i < newestHour . length ; i ++ ) {
computedDiff . push ( {
command : newestHour [ i ] . command ,
count : ( newestHour [ i ] . count - oldestHour [ i ] . count ) ,
} ) ;
log ( LT . LOG , ` Updating hourlyRate | Computing diffs: ${ JSON . stringify ( computedDiff ) } ` ) ;
}
// Update DB
computedDiff . forEach ( async ( cmd ) = > {
log ( LT . LOG , ` Updating hourlyRate | Storing to DB: ${ JSON . stringify ( cmd ) } ` ) ;
2022-06-26 17:18:41 -07:00
await dbClient . execute ( ` UPDATE command_cnt SET hourlyRate = ? WHERE command = ? ` , [ cmd . count / previousHours . length , cmd . command ] ) . catch ( ( e ) = >
utils . commonLoggers . dbError ( 'intervals.ts:88' , 'update' , e )
) ;
2022-06-25 13:26:48 -07:00
} ) ;
}
if ( previousHours . length > hoursToKeep ) {
previousHours . unshift ( ) ;
}
} catch ( e ) {
2022-06-26 17:18:41 -07:00
log ( LT . ERROR , ` Something went wrong in previousHours interval | Error: ${ e . name } - ${ e . message } ` ) ;
2022-06-25 13:26:48 -07:00
}
} ;
2022-06-26 19:53:25 -07:00
// getPercentOfRange(min, max, val) returns number
// Gets a percent value of where val lies in the min-max range
const getPercentOfRange = ( minVal : number , maxVal : number , val : number ) : number = > {
const localMax = maxVal - minVal ;
const localVal = val - minVal ;
return localVal / localMax ;
} ;
// Pixel locations in heatmap-base.png, pixel locations are 0 based
// dayPixels holds the left and right (AKA X Coord) pixel locations for each col (ex: [leftPX, rightPX])
const dayPixels : Array < Array < number > > = [
[ 72 , 159 ] ,
[ 163 , 260 ] ,
[ 264 , 359 ] ,
[ 363 , 497 ] ,
[ 501 , 608 ] ,
[ 612 , 686 ] ,
[ 690 , 800 ] ,
] ;
// hourPixels holds the top and bottom (AKA Y Coord) pixel locations for each row (ex: [topPX, botPX])
const hourPixels : Array < Array < number > > = [
[ 29 , 49 ] ,
[ 51 , 72 ] ,
[ 74 , 95 ] ,
[ 97 , 118 ] ,
[ 120 , 141 ] ,
[ 143 , 164 ] ,
[ 166 , 187 ] ,
[ 189 , 209 ] ,
[ 211 , 232 ] ,
[ 234 , 254 ] ,
[ 256 , 277 ] ,
[ 279 , 299 ] ,
[ 301 , 322 ] ,
[ 324 , 345 ] ,
[ 347 , 368 ] ,
[ 370 , 391 ] ,
[ 393 , 413 ] ,
[ 415 , 436 ] ,
[ 438 , 459 ] ,
[ 461 , 482 ] ,
[ 484 , 505 ] ,
[ 507 , 528 ] ,
[ 530 , 550 ] ,
[ 552 , 572 ] ,
] ;
// updateHeatmap() returns nothing, creates new heatmap.png
// Updates the heatmap image with latest data from the db
const updateHeatmapPng = async ( ) = > {
const baseHeatmap = Deno . readFileSync ( './src/endpoints/gets/heatmap-base.png' ) ;
const heatmap = await is . decode ( baseHeatmap ) ;
if ( heatmap instanceof is . Image ) {
// Get latest data from DB
const heatmapData = await dbClient . query ( 'SELECT * FROM roll_time_heatmap ORDER BY hour;' ) . catch ( ( e ) = > utils . commonLoggers . dbError ( 'intervals.ts:148' , 'query' , e ) ) ;
let minRollCnt = Infinity ;
let maxRollCnt = 0 ;
// determine min and max values
for ( let hour = 0 ; hour < heatmapData . length ; hour ++ ) {
for ( let day = 0 ; day < weekDays . length ; day ++ ) {
const rollCnt = heatmapData [ hour ] [ weekDays [ day ] ] ;
log ( LT . LOG , ` updateHeatmapPng | finding min/max | min: ${ minRollCnt } max: ${ maxRollCnt } curr: ${ rollCnt } ` ) ;
if ( rollCnt > maxRollCnt ) {
maxRollCnt = rollCnt ;
}
if ( rollCnt < minRollCnt ) {
minRollCnt = rollCnt ;
}
}
}
// Apply values to image
for ( let hour = 0 ; hour < heatmapData . length ; hour ++ ) {
for ( let day = 0 ; day < weekDays . length ; day ++ ) {
log ( LT . LOG , ` updateHeatmapPng | putting ${ weekDays [ day ] } ${ hour } :00 into image ` ) ;
const percent = getPercentOfRange ( minRollCnt , maxRollCnt , heatmapData [ hour ] [ weekDays [ day ] ] ) ;
heatmap . drawBox (
dayPixels [ day ] [ 0 ] + 1 ,
hourPixels [ hour ] [ 0 ] + 1 ,
dayPixels [ day ] [ 1 ] - dayPixels [ day ] [ 0 ] + 1 ,
hourPixels [ hour ] [ 1 ] - hourPixels [ hour ] [ 0 ] + 1 ,
is . Image . rgbToColor (
255 * ( 1 - percent ) ,
255 * percent ,
0 ,
) ,
) ;
}
}
Deno . writeFileSync ( './src/endpoints/gets/heatmap.png' , await heatmap . encode ( ) ) ;
}
} ;
export default {
getRandomStatus ,
updateListStatistics ,
updateHourlyRates ,
updateHeatmapPng ,
} ;