Several tweaks.
Buffer responses on repeated requests (especially useful for '!') Remove some noisy logging Add the admin-only !take Add CANNOT_VOTE to users object
This commit is contained in:
parent
2d2e0c9368
commit
35e401cd0b
|
@ -140,11 +140,9 @@ const defaultAccess = { hidden: false, condition: alwaysAccessible }
|
|||
*/
|
||||
const command = (commandNames, helpText, action, { hidden, condition } = defaultAccess) => {
|
||||
if (!hidden) {
|
||||
console.log(`Initializing command '${commandNames[0]}'`)
|
||||
commandHelpText += `\n${commandNames.toString().replace(/,/g, ', ')} - ${helpText}\n`
|
||||
shortCommandHelpText += `\n${commandNames.toString().replace(/,/g, ', ')}`
|
||||
} else if (condition === adminOnly.condition) {
|
||||
console.log(`Initializing admin command '${commandNames[0]}'`)
|
||||
} else {
|
||||
hiddenCommands++
|
||||
}
|
||||
|
@ -243,7 +241,6 @@ const cardGames = {
|
|||
help: 'Search for Yu-Gi-Oh cards: !ygo <card name>',
|
||||
fetch: async name => {
|
||||
const url = `https://db.ygoprodeck.com/api/v7/cardinfo.php?fname=${name}`;
|
||||
console.log('yugioh url', url)
|
||||
return url
|
||||
},
|
||||
getCardData: ({ data }) => data,
|
||||
|
@ -293,7 +290,6 @@ Object.entries(cardGames).forEach(async ([gameName, cardGame]) => {
|
|||
// return say('Please specify a card name!')
|
||||
// }
|
||||
arg = arg.trim()
|
||||
console.log('arg', arg)
|
||||
if (cardGame.cards && !cardGame.fetch) {
|
||||
const fileName = cardGame.cards.find(name => name?.toLowerCase().replaceAll(/_/g, ' ').startsWith(arg.toLowerCase()))
|
||||
if (fileName) {
|
||||
|
@ -326,7 +322,6 @@ Object.entries(cardGames).forEach(async ([gameName, cardGame]) => {
|
|||
const name = cardGame.getCardName(card)
|
||||
const fileName = gameName + '/' + name
|
||||
if (existsSync(fileName)) {
|
||||
console.log(`Using cached file: ${fileName}`)
|
||||
return postCard(event, name, fileName)
|
||||
}
|
||||
const file = createWriteStream(fileName)
|
||||
|
@ -334,7 +329,6 @@ Object.entries(cardGames).forEach(async ([gameName, cardGame]) => {
|
|||
response.pipe(file)
|
||||
file.on('finish', async () => {
|
||||
await file.close()
|
||||
console.log(event.channel)
|
||||
await postCard(event, name, fileName)
|
||||
}).on('error', err => {
|
||||
console.error(err)
|
||||
|
@ -448,21 +442,84 @@ const buildHorrorSay = ({ say, event, commandName, c }) => async message => {
|
|||
}
|
||||
|
||||
const buildSayWithPayload = ({ say, event }) => async msg => {
|
||||
const { user, text } = event
|
||||
|
||||
const payload = {
|
||||
event: {
|
||||
text: event.text,
|
||||
user: event.user
|
||||
text,
|
||||
user
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(msg) === 'string') {
|
||||
return say(slack.encodeData('commandPayload', payload) + msg)
|
||||
const userBuff = (messageBuffer[user] ??= { buffer: [], lastSendTs: [] })
|
||||
const currentTs = Date.now()
|
||||
const lastSendWasRecent = userBuff.lastSendTs.every(ts => ts > (currentTs - falloffMs))
|
||||
|
||||
const doStringSay = currentMsg => {
|
||||
let sending = ''
|
||||
const append = text => {
|
||||
if (sending) {
|
||||
sending += '\n'
|
||||
}
|
||||
sending += text;
|
||||
}
|
||||
if (userBuff.buffer.length) {
|
||||
let dupCount = 0
|
||||
let lastMessage = null
|
||||
const close = () => {
|
||||
if (dupCount) {
|
||||
append('\n' + lastMessage + `\n<message duplicated ${dupCount} time${dupCount === 1 ? '' : 's'}>`)
|
||||
dupCount = 0
|
||||
} else if (lastMessage !== null) {
|
||||
append('\n' + lastMessage)
|
||||
}
|
||||
}
|
||||
userBuff.buffer.forEach(buffered => {
|
||||
if (buffered === lastMessage) {
|
||||
dupCount++
|
||||
return
|
||||
}
|
||||
|
||||
close()
|
||||
lastMessage = buffered
|
||||
})
|
||||
close()
|
||||
}
|
||||
if (currentMsg) {
|
||||
append(currentMsg)
|
||||
}
|
||||
userBuff.buffer = []
|
||||
if (userBuff.lastSendTs.length > bucketSize) {
|
||||
userBuff.lastSendTs.shift()
|
||||
}
|
||||
userBuff.lastSendTs.push(currentTs)
|
||||
if (!sending) {
|
||||
return
|
||||
}
|
||||
return say(slack.encodeData('commandPayload', payload) + sending)
|
||||
}
|
||||
|
||||
|
||||
if (lastSendWasRecent) {
|
||||
// Note: Drops buffered payloads
|
||||
userBuff.buffer.push(msg)
|
||||
clearTimeout(userBuff.timeoutId)
|
||||
userBuff.timeoutId = setTimeout(() => doStringSay(null), falloffMs)
|
||||
return
|
||||
} else {
|
||||
return doStringSay(msg)
|
||||
}
|
||||
}
|
||||
|
||||
return say({
|
||||
...msg,
|
||||
text: slack.encodeData('commandPayload', payload) + msg.text
|
||||
})
|
||||
}
|
||||
|
||||
command(['!ping'], 'Ping', async ({ say }) => say('Hello!'), adminOnly)
|
||||
|
||||
const userHasTheGift = user => userHasCheckedQuackgrade(user, 'theGift')
|
||||
|
||||
command(
|
||||
|
@ -490,7 +547,6 @@ const noWinner = 'NO WINNER'
|
|||
const getPollWinner = async ({ channel, ts }) => {
|
||||
try {
|
||||
const msg = await slack.getMessage({ channel, ts })
|
||||
console.log('pollWinner message', JSON.stringify(msg.messages[0]))
|
||||
let texts = []
|
||||
let maxVotes = 0
|
||||
for (let i = 1; i < msg.messages[0].blocks.length; i++) {
|
||||
|
@ -500,11 +556,8 @@ const getPollWinner = async ({ channel, ts }) => {
|
|||
continue
|
||||
}
|
||||
votes = votes.split('@').length - 1
|
||||
console.log(`${votes} votes for:`)
|
||||
text = text.replace(/^\s*:[a-z]*: /, '')
|
||||
text = text.replace(/\s+`\d+`$/, '')
|
||||
console.log(`TEXT: '${text}'`)
|
||||
console.log(``)
|
||||
if (votes > maxVotes) {
|
||||
maxVotes = votes
|
||||
texts = [text]
|
||||
|
@ -512,7 +565,6 @@ const getPollWinner = async ({ channel, ts }) => {
|
|||
texts.push(text)
|
||||
}
|
||||
}
|
||||
console.log('TEXTS', texts)
|
||||
if (texts.length === 1) {
|
||||
return [texts[0], false]
|
||||
} else if (texts.length > 1) {
|
||||
|
@ -552,13 +604,11 @@ command(
|
|||
async ({ args, say, user }) => {
|
||||
try {
|
||||
const msg = await slack.getMessage({channel: slack.temperatureChannelId, ts: args[0]})
|
||||
console.log(JSON.stringify(msg?.messages[0]))
|
||||
} catch (e) {console.error('!getmsg error', e)}
|
||||
}
|
||||
)
|
||||
|
||||
const messageHandler = async ({ event, say, isRecycle = false, skipCounting }) => {
|
||||
console.log('messageHandler')
|
||||
if (event?.subtype === 'bot_message') {
|
||||
return botMessageHandler({ event, say })
|
||||
}
|
||||
|
@ -566,7 +616,6 @@ const messageHandler = async ({ event, say, isRecycle = false, skipCounting }) =
|
|||
const words = event?.text?.split(/\s+/) || []
|
||||
const [commandName, ...args] = words
|
||||
const c = commands.get(commandName)
|
||||
console.log('getUser')
|
||||
let user = await getUser(event.user)
|
||||
if (user.isDisabled && c.condition !== alwaysAlwaysAccessible) {
|
||||
return
|
||||
|
@ -633,7 +682,6 @@ const messageHandler = async ({ event, say, isRecycle = false, skipCounting }) =
|
|||
}
|
||||
}
|
||||
}
|
||||
console.log('getCoins')
|
||||
Object.entries(users).forEach(([id, usr]) => usr.coins = getCoins(id))
|
||||
//user.coins = getCoins(event.user)
|
||||
const isAdmin = event.user?.includes(slack.users.Admin)
|
||||
|
@ -824,7 +872,7 @@ slack.app.action('lightningStrike', async ({ body, ack }) => {
|
|||
blocks: []
|
||||
})
|
||||
await ack()
|
||||
return slack.messageAdmin(`Lighting bottled by <@${body.user.id}>`)
|
||||
// return slack.messageAdmin(`Lighting bottled by <@${body.user.id}>`)
|
||||
})
|
||||
|
||||
slack.onMessage(async msg => {
|
||||
|
@ -1139,7 +1187,7 @@ const doMine = async ({ user, userId, say }) => {
|
|||
diff = 500 + secondsOfCps(60 * 60, 0.2)
|
||||
prefix = `:gem: You found a lucky gem worth ${commas(diff)} HVAC!\n`
|
||||
addAchievement(user, 'luckyGem', say)
|
||||
await slack.messageAdmin(`${slack.users[userId]} FOUND A LUCKY GEM COIN WORTH ${commas(diff)} HVAC!`)
|
||||
// await slack.messageAdmin(`${slack.users[userId]} FOUND A LUCKY GEM COIN WORTH ${commas(diff)} HVAC!`)
|
||||
} else if (random > 0.986) {
|
||||
diff = 50 + secondsOfCps(60 * 5, 0.1)
|
||||
prefix = `:goldbrick: You found a lucky gold coin worth ${commas(diff)} HVAC!\n`
|
||||
|
@ -1163,7 +1211,7 @@ command(
|
|||
'Mine HVAC coins',
|
||||
async ({ say, user, userId }) => {
|
||||
await say(await doMine({ user, userId, say }))
|
||||
if ((lbIndex++) % 20 == 0) {
|
||||
if ((lbIndex++) % 100 == 0) {
|
||||
return updateAllLeaderboards()
|
||||
}
|
||||
}
|
||||
|
@ -1257,7 +1305,6 @@ command(
|
|||
} else {
|
||||
outcome = 'lost'
|
||||
}
|
||||
console.log(`They ${outcome}`)
|
||||
//saveGame()
|
||||
await say(`You bet ${commas(n)} coins and ${outcome}! You now have ${commas(user.coins)}.`)
|
||||
if (outcome === 'lost' && user.lostBetMessage) {
|
||||
|
@ -1266,7 +1313,7 @@ command(
|
|||
await trueSay(user.wonBetMessage)
|
||||
}
|
||||
return updateAllLeaderboards()
|
||||
}
|
||||
}, dmsOnly
|
||||
)
|
||||
|
||||
const emojiRegex = /^:[^:\s]*:$/
|
||||
|
@ -1278,7 +1325,6 @@ const validEmoji = async emojiText => {
|
|||
const validEmojis = (await getEmojis()).emoji
|
||||
const noColons = emojiText.replace(/:/g, '')
|
||||
|
||||
// console.log('validEmojis', validEmojis)
|
||||
return !!validEmojis[noColons]
|
||||
}
|
||||
const getEmojis = async () => await slack.app.client.emoji.list()
|
||||
|
@ -1368,7 +1414,6 @@ command(
|
|||
if (!args[0]) {
|
||||
return say(upgradeText2(user))
|
||||
}
|
||||
console.log({args: args.join(' ')})
|
||||
const matcher = fuzzyMatcher(args.join(' '))
|
||||
const u = Object.entries(upgrades).find(([name, upgrade]) => matcher.test(name) || matcher.test(upgrade.name))
|
||||
if (!u) {
|
||||
|
@ -1418,7 +1463,6 @@ const upgradeBlock = upgradeName => {
|
|||
const upgradeButton = async ({ body, ack, say, payload }) => {
|
||||
await ack()
|
||||
const upgrade = payload.action_id.substring(8)
|
||||
console.log(`upgradeButton ${upgrade} clicked`)
|
||||
const event = {
|
||||
user: body.user.id
|
||||
}
|
||||
|
@ -1574,7 +1618,6 @@ command(
|
|||
'Donate coins to a fellow player\n' +
|
||||
' Send coins by saying \'!gift @player coin_amount\'',
|
||||
async ({ event, args, say, user, haunted }) => {
|
||||
return say(`I'm sorry, but you people can't be trusted anymore.`)
|
||||
if (haunted) {
|
||||
return say(`!give doesn't work while you're haunted.`)
|
||||
}
|
||||
|
@ -1624,13 +1667,55 @@ command(
|
|||
const last = gifted.pop()
|
||||
recipients = gifted.map(t => users[t].name).join(', ') + ', and ' + users[last].name
|
||||
} else {
|
||||
console.log('gifted', gifted)
|
||||
console.log('users[gifted[0]]', users[gifted[0]])
|
||||
recipients = users[gifted[0]].name
|
||||
console.log('recipients', recipients)
|
||||
}
|
||||
await say(`Gifted ${commas(individualAmount)} HVAC to ${recipients}`)
|
||||
}
|
||||
}, adminOnly
|
||||
)
|
||||
|
||||
command(
|
||||
['!take'],
|
||||
'Take coins from a player\n' +
|
||||
' Take coins by saying \'!take @player coin_amount\'',
|
||||
async ({ event, args, say, user, haunted }) => {
|
||||
if (haunted) {
|
||||
return say(`!give doesn't work while you're haunted.`)
|
||||
}
|
||||
let [target, ...amountText] = args
|
||||
amountText = amountText.join(' ')
|
||||
const targetId = idFromWord(target)
|
||||
const targets = [targetId]
|
||||
if (targetId === event?.user) {
|
||||
return say(':thonk:')
|
||||
}
|
||||
if (!targetId) {
|
||||
return say('Target must be a valid @')
|
||||
}
|
||||
const individualAmount = parseAll(amountText, user.coins, user)
|
||||
const totalAmount = individualAmount
|
||||
|
||||
let victims = []
|
||||
for (const targetId of targets) {
|
||||
const targetUser = await getUser(targetId)
|
||||
targetUser.coins -= individualAmount
|
||||
victims.push(targetId)
|
||||
user.coins += individualAmount
|
||||
}
|
||||
if (!totalAmount || totalAmount < 0) {
|
||||
return say('Amount must be a positive integer!')
|
||||
}
|
||||
if (user.coins < totalAmount) {
|
||||
return say(`You don't have that many coins! You have ${commas(user.coins)} HVAC.`)
|
||||
}
|
||||
let losers
|
||||
if (victims.length > 1) {
|
||||
const last = victims.pop()
|
||||
losers = victims.map(t => users[t].name).join(', ') + ', and ' + users[last].name
|
||||
} else {
|
||||
losers = users[victims[0]].name
|
||||
}
|
||||
await say(`Took ${commas(individualAmount)} HVAC from ${losers}`)
|
||||
}, adminOnly
|
||||
)
|
||||
|
||||
const getChaosMessage = (user, { channel_type }, prefix = '', postfix = '') => {
|
||||
|
@ -1862,7 +1947,6 @@ command(
|
|||
owner: null
|
||||
}
|
||||
nfts.push(newNft)
|
||||
console.log('addedNft', newNft)
|
||||
}, adminOnly)
|
||||
|
||||
command(
|
||||
|
@ -1938,13 +2022,10 @@ command(
|
|||
return
|
||||
}
|
||||
let targetId = idFromWord(target)
|
||||
console.log({ user: event.user, target, targetId })
|
||||
if (event.user === targetId) {
|
||||
return say('What, are you trying to steal from yourself? What, are you stupid?')
|
||||
}
|
||||
if (!targetId) {
|
||||
targetId = slack.users.Admin
|
||||
}
|
||||
targetId = slack.users.Admin
|
||||
if (user.coins < amount) {
|
||||
return
|
||||
}
|
||||
|
@ -2013,13 +2094,11 @@ command(
|
|||
args = rest
|
||||
}
|
||||
|
||||
console.log({args, channel})
|
||||
const target = idFromWord(args[0])
|
||||
const [, ...rest] = args
|
||||
const userInfo = await slack.app.client.users.info({
|
||||
user: target
|
||||
})
|
||||
console.log(userInfo)
|
||||
return slack.app.client.chat.postMessage({
|
||||
channel,
|
||||
text: rest.join(' '),
|
||||
|
@ -2126,12 +2205,8 @@ const updateStonkPrices = () => {
|
|||
|
||||
// TODO: Gotta take into account wrapping around to the end of the year
|
||||
Object.entries(stonkMarket.stonks).forEach(([, stonk]) => {
|
||||
console.log(stonk.pattern)
|
||||
console.log('try set')
|
||||
for (let i = stonkMarket.lastDay; i < today; i++) {
|
||||
console.log('set lastPrice')
|
||||
stonk.lastPrice = stonk.price
|
||||
console.log(stonk.pattern, stonkPatterns)
|
||||
stonk.price *= 1 + ((stonkPatterns[stonk.pattern] || stonkPatterns.duk)[stonk.index] / 100)
|
||||
stonk.index++
|
||||
if (stonk.index >= stonkPatterns[stonk.pattern]?.length) {
|
||||
|
|
|
@ -61,7 +61,13 @@ const parseOr = (parseable, fallback) => {
|
|||
}
|
||||
}
|
||||
|
||||
const makeBackup = () => {
|
||||
let lastBackupTs = 0
|
||||
const makeBackup = (force) => {
|
||||
const currentTs = Date.now()
|
||||
if (lastBackupTs > (currentTs - 60000) && !force) {
|
||||
return
|
||||
}
|
||||
lastBackupTs = currentTs
|
||||
const fileName = saveDir + 'backups/' + saveFile + new Date().toLocaleString().replace(/[^a-z0-9]/gi, '_')
|
||||
console.log(`Making backup file: ${fileName}`)
|
||||
fs.writeFileSync(fileName, JSON.stringify(game))
|
||||
|
@ -209,6 +215,9 @@ const parseAll = (str, allNum, user) => {
|
|||
if (str.match(/^\d+$/)) {
|
||||
return parseInt(str)
|
||||
}
|
||||
if (allNum && str.match(/^some$/)) {
|
||||
return Math.floor(Math.random() * allNum)
|
||||
}
|
||||
if (allNum && str.match(/^\d+%$/)) {
|
||||
const percent = parseFloat(str) / 100
|
||||
if (percent > 1 || percent < 0) {
|
||||
|
|
|
@ -122,9 +122,9 @@ app.event('message', async ({ event, context, client, say }) => {
|
|||
for (const listener of messageListeners) {
|
||||
listener({ event, say })
|
||||
}
|
||||
if (event.user) {
|
||||
console.log('MSG', users[event.user], "'" + event.text + "'", new Date().toLocaleTimeString())
|
||||
}
|
||||
// if (event.user) {
|
||||
// console.log('MSG', users[event.user], "'" + event.text + "'", new Date().toLocaleTimeString())
|
||||
// }
|
||||
if (event.user === users.Admin && event.channel === 'D0347Q4H9FE') {
|
||||
if (event.text === '!!kill') {
|
||||
saveGame('!!kill', true)
|
||||
|
@ -198,15 +198,17 @@ app.event('message', async ({ event, context, client, say }) => {
|
|||
}))
|
||||
|
||||
const reactCounts = {}
|
||||
Object.entries(reactPosters).forEach(([id, votes]) => {
|
||||
console.log(`VOTES FROM ${id}:`, votes)
|
||||
votes = votes.filter(v => [goodEmoji, hotterEmoji, colderEmoji].find(emoji => v.startsWith(emoji)))
|
||||
if (votes.length === 1) {
|
||||
const name = votes[0].replace(/:.*/g, '')
|
||||
reactCounts[name] ??= 0
|
||||
reactCounts[name] += 1
|
||||
}
|
||||
})
|
||||
Object.entries(reactPosters)
|
||||
.filter(([id]) => !users.CANNOT_VOTE?.includes(users[id]))
|
||||
.forEach(([id, votes]) => {
|
||||
console.log(`VOTES FROM ${id}:`, votes)
|
||||
votes = votes.filter(v => [goodEmoji, hotterEmoji, colderEmoji].find(emoji => v.startsWith(emoji)))
|
||||
if (votes.length === 1) {
|
||||
const name = votes[0].replace(/:.*/g, '')
|
||||
reactCounts[name] ??= 0
|
||||
reactCounts[name] += 1
|
||||
}
|
||||
})
|
||||
console.log('REACT COUNTS', JSON.stringify(reactCounts))
|
||||
|
||||
const contentVotes = reactCounts[goodEmoji] || 0
|
||||
|
|
Loading…
Reference in New Issue