Many additions:
Add several new achievements Add price querying with ?b Simplify commands' argument-handling Some spooky stuff New quackgrades Stormy weather Rebalanced some rare-event odds !u buttons Reworked prestige emojis Save on every command Add stonks More temp poll triggers Redemption upgrades more powerful Fuzzy matching for usernames and buyables
This commit is contained in:
parent
6dabe9d85a
commit
ad021cf9a5
|
@ -11,4 +11,4 @@ fetch(url, {
|
|||
headers: headers
|
||||
// credentials: 'user:passwd'
|
||||
}).then(response => response.json())
|
||||
.then(json => console.log(json))
|
||||
.then(json => console.log('json', json))
|
||||
|
|
|
@ -34,6 +34,16 @@ module.exports = {
|
|||
description: 'I like big bets, and that\'s the truth',
|
||||
emoji: 'slot_machine'
|
||||
},
|
||||
hugeBets: {
|
||||
name: 'Make a bet over 100T',
|
||||
description: `That's so bonk`,
|
||||
emoji: 'game_die'
|
||||
},
|
||||
mondoBets: {
|
||||
name: 'Make a bet over 100 Quadrillion',
|
||||
description: 'H I G H R O L L E R',
|
||||
emoji: '8ball'
|
||||
},
|
||||
ignited: {
|
||||
name: 'You light my fire, baby',
|
||||
description: 'And you pay attention to descriptions!',
|
||||
|
@ -45,6 +55,72 @@ module.exports = {
|
|||
description: 'I\'m beginning to feel like a rat god, rat god.',
|
||||
emoji: 'mouse2'
|
||||
},
|
||||
mathematician: {
|
||||
name: 'Own 100 Accountants',
|
||||
description: 'They rejoice at the appearance of a third digit.',
|
||||
emoji: 'male-office-worker'
|
||||
},
|
||||
iPod: {
|
||||
name: 'Own 100 Whales',
|
||||
description: `With the new iPod, you can hold 100's of songs.`,
|
||||
emoji: 'whale'
|
||||
},
|
||||
fire100: {
|
||||
name: 'Own 100 Fires',
|
||||
description: `Wow, that's bright.`,
|
||||
emoji: 'fire'
|
||||
},
|
||||
train100: {
|
||||
name: 'Own 100 Trains',
|
||||
description: `That's every train in America you've got there.`,
|
||||
emoji: 'train2'
|
||||
},
|
||||
boom100: {
|
||||
name: 'Own 100 Boomerangs',
|
||||
description: `LOUD WOOSHING`,
|
||||
emoji: 'boomerang'
|
||||
},
|
||||
moon100: {
|
||||
name: 'Own 100 Moons',
|
||||
description: `Space Cadet`,
|
||||
emoji: 'new_moon_with_face'
|
||||
},
|
||||
mirror100: {
|
||||
name: 'Own 100 Mirrors',
|
||||
description: `Disco Ball`,
|
||||
emoji: 'mirror'
|
||||
},
|
||||
butterfly100: {
|
||||
name: 'Own 100 Butterflies',
|
||||
description: `Delicate yet powerful.`,
|
||||
emoji: 'butterfly'
|
||||
},
|
||||
quade100: {
|
||||
name: 'Own 100 Quades',
|
||||
description: `Your Ops are super Devved right now.`,
|
||||
emoji: 'quade'
|
||||
},
|
||||
hvacker100: {
|
||||
name: 'Own 100 Hvackers',
|
||||
description: `Did Sage finally make his git repo public?`,
|
||||
emoji: 'hvacker_angery'
|
||||
},
|
||||
creator100: {
|
||||
name: 'Own 100 Creators',
|
||||
description: `_Stern look_`,
|
||||
emoji: 'question'
|
||||
},
|
||||
smallBusiness100: {
|
||||
name: 'Own 100 Small Businesses',
|
||||
description: `Enough to run a small city.`,
|
||||
emoji: 'convenience_store'
|
||||
},
|
||||
bigBusiness100: {
|
||||
name: 'Own 100 Big Businesses',
|
||||
description: `I mean... that's basically all of them.`,
|
||||
emoji: 'office'
|
||||
},
|
||||
|
||||
weAllNeedHelp: {
|
||||
name: 'View the \'!coin\' help',
|
||||
description: 'We all need a little help sometimes',
|
||||
|
@ -85,5 +161,11 @@ module.exports = {
|
|||
name: 'Take a peek at the lore',
|
||||
description: 'It\'t gotta be worth your time somehow.',
|
||||
emoji: 'books'
|
||||
},
|
||||
|
||||
theOtherSide: {
|
||||
name: 'Die and be reborn',
|
||||
description: 'You have seen the other side, and do not fear it.',
|
||||
emoji: 'white_square'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const buyableItems = require('./buyableItems')
|
||||
const { commas, saveGame, setHighestCoins, addAchievement, getUser, singleItemCps, chaosFilter } = require('./utils')
|
||||
const { commas, setHighestCoins, addAchievement, getUser, singleItemCps, chaosFilter, fuzzyMatcher } = require('./utils')
|
||||
const slack = require('../../slack')
|
||||
|
||||
const calculateCost = ({ itemName, user, quantity = 1 }) => {
|
||||
|
@ -17,9 +17,9 @@ const getItemHeader = user => ([itemName, { baseCost, description, emoji }]) =>
|
|||
const itemCps = Math.round(singleItemCps(user, itemName))
|
||||
return `*${itemName}* :${emoji}: - ${itemCost} HVAC Coins - ${commas(itemCps)} CPS\n_${description}_`
|
||||
}
|
||||
const canView = highestCoins => ([, item]) => item.baseCost < (highestCoins || 1) * 101
|
||||
const canView = (item, highestCoins) => item.baseCost < (highestCoins || 1) * 101
|
||||
const buyableText = (highestCoins, user) => Object.entries(buyableItems)
|
||||
.filter(canView(highestCoins))
|
||||
.filter(([, item]) => canView(item, highestCoins))
|
||||
.map(getItemHeader(user))
|
||||
.join('\n\n') +
|
||||
'\n\n:grey_question::grey_question::grey_question:' +
|
||||
|
@ -73,8 +73,8 @@ const buyText2 = (highestCoins, user) => {
|
|||
return ({
|
||||
text: buyableText(highestCoins, user),
|
||||
blocks: Object.entries(buyableItems)
|
||||
.filter(canView(highestCoins))
|
||||
.map(([itemName, item]) => {
|
||||
.filter(([, item]) => canView(item, highestCoins))
|
||||
.map(([itemName]) => {
|
||||
const cost = calculateCost({ itemName, user, quantity: 1 })
|
||||
const cps = Math.round(singleItemCps(user, itemName))
|
||||
return ({ user, itemName, cost, cps })
|
||||
|
@ -90,58 +90,65 @@ const maxQuantity = ({ itemName, user, currentCoins }) => {
|
|||
return quantity
|
||||
}
|
||||
|
||||
const buyRoute = async ({ event, say, words, user }) => {
|
||||
const buying = words[1]
|
||||
const buyRoute = async ({ event, say, args, user }) => {
|
||||
const buying = args[0]
|
||||
setHighestCoins(event.user)
|
||||
const query = event?.text?.startsWith('?b ') || event?.text?.startsWith('?buy ')
|
||||
|
||||
if (!buying) {
|
||||
const highestCoins = user.highestEver || user.coins || 1
|
||||
if (buyableItems.quade.baseCost < highestCoins * 100) {
|
||||
if (canView(buyableItems.quade, highestCoins)) {
|
||||
addAchievement(user, 'seeTheQuade', say)
|
||||
}
|
||||
await say(buyText2(highestCoins, user))
|
||||
return
|
||||
}
|
||||
|
||||
const buyable = buyableItems[buying]
|
||||
const matcher = fuzzyMatcher(buying)
|
||||
const buyable = Object.entries(buyableItems).find(([name]) => matcher.test(name))
|
||||
if (!buyable) {
|
||||
await say('That item does not exist!')
|
||||
return
|
||||
}
|
||||
|
||||
const [buyableName, buyableItem] = buyable
|
||||
let quantity
|
||||
const currentCoins = user.coins
|
||||
const max = maxQuantity({ itemName: buying, user, currentCoins })
|
||||
if (words[2] === 'max') {
|
||||
const max = maxQuantity({ itemName: buyableName, user, currentCoins })
|
||||
if (!args[1]) {
|
||||
quantity = 1
|
||||
} else if (args[1] === 'max') {
|
||||
quantity = max
|
||||
} else {
|
||||
quantity = Math.round(chaosFilter(parseInt(words[2] || '1'), 0.2, user, max) || 1)
|
||||
if (query) {
|
||||
quantity = parseInt(args[1])
|
||||
} else {
|
||||
quantity = Math.round(chaosFilter(parseInt(args[1]), 0.2, user, max) || 1)
|
||||
}
|
||||
}
|
||||
if (!quantity || quantity < 1) {
|
||||
await say('Quantity must be a positive integer')
|
||||
return
|
||||
}
|
||||
|
||||
const realCost = calculateCost({ itemName: buying, user, quantity })
|
||||
const realCost = calculateCost({ itemName: buyableName, user, quantity })
|
||||
if (query) {
|
||||
return say(`Buying ${quantity} ${buyableName} would cost you ${commas(realCost)} HVAC`)
|
||||
}
|
||||
if (currentCoins < realCost) {
|
||||
await say(`You don't have enough coins! You have ${commas(currentCoins)}, but you need ${commas(realCost)}`)
|
||||
return
|
||||
}
|
||||
user.coins -= realCost
|
||||
user.items[buying] = user.items[buying] || 0
|
||||
user.items[buying] += quantity
|
||||
user.items[buyableName] = user.items[buyableName] || 0
|
||||
user.items[buyableName] += quantity
|
||||
|
||||
if (buying === 'mouse' && user.items.mouse >= 100) {
|
||||
addAchievement(user, 'ratGod', say)
|
||||
if (user.items[buyableName] >= 100) {
|
||||
addAchievement(user, buyableItems[buyableName].own100Achievement, say)
|
||||
}
|
||||
|
||||
if (quantity === 1) {
|
||||
await say(`You bought one :${buyable.emoji}:`)
|
||||
} else {
|
||||
await say(`You bought ${quantity} :${buyable.emoji}:`)
|
||||
}
|
||||
|
||||
saveGame()
|
||||
const countString = quantity === 1 ? 'one' : quantity
|
||||
await say(`You bought ${countString} :${buyableItem.emoji}:`)
|
||||
}
|
||||
|
||||
const buyButton = async ({ body, ack, say, payload }) => {
|
||||
|
@ -153,7 +160,8 @@ const buyButton = async ({ body, ack, say, payload }) => {
|
|||
}
|
||||
const user = getUser(event.user)
|
||||
const words = ['', buying, body.actions[0].text]
|
||||
await buyRoute({ event, say, words, user })
|
||||
const [commandName, ...args] = words
|
||||
await buyRoute({ event, say, words, args, commandName, user })
|
||||
const highestCoins = user.highestEver || user.coins || 1
|
||||
await slack.app.client.chat.update({
|
||||
channel: body.channel.id,
|
||||
|
|
|
@ -3,84 +3,98 @@ module.exports = {
|
|||
baseCost: 100,
|
||||
earning: 1,
|
||||
emoji: 'mouse2',
|
||||
description: 'A mouse to steal coins for you.'
|
||||
description: 'A mouse to steal coins for you.',
|
||||
own100Achievement: 'ratGod',
|
||||
},
|
||||
accountant: {
|
||||
baseCost: 1_100,
|
||||
earning: 8,
|
||||
emoji: 'male-office-worker',
|
||||
description: 'Legally make money from nothing!'
|
||||
description: 'Legally make money from nothing!',
|
||||
own100Achievement: 'mathematician',
|
||||
},
|
||||
whale: {
|
||||
baseCost: 12_000,
|
||||
earning: 47,
|
||||
emoji: 'whale',
|
||||
description: 'Someone to spend money on your HVAC Coin mining app.'
|
||||
description: 'Someone to spend money on your HVAC Coin mining app.',
|
||||
own100Achievement: 'iPod',
|
||||
},
|
||||
train: {
|
||||
baseCost: 130_000,
|
||||
earning: 260,
|
||||
emoji: 'train2',
|
||||
description: 'Efficiently ship your most valuable coins.'
|
||||
description: 'Efficiently ship your most valuable coins.',
|
||||
own100Achievement: 'fire100',
|
||||
},
|
||||
fire: {
|
||||
baseCost: 1_400_000,
|
||||
earning: 1_400,
|
||||
emoji: 'fire',
|
||||
description: 'Return to the roots of HVAC.'
|
||||
description: 'Return to the roots of HVAC.',
|
||||
own100Achievement: 'train100',
|
||||
},
|
||||
boomerang: {
|
||||
baseCost: 20_000_000,
|
||||
earning: 7_800,
|
||||
emoji: 'boomerang',
|
||||
description: 'Your coin always seems to come back.'
|
||||
description: 'Your coin always seems to come back.',
|
||||
own100Achievement: 'boom100',
|
||||
},
|
||||
moon: {
|
||||
baseCost: 330_000_000,
|
||||
earning: 44_000,
|
||||
emoji: 'new_moon_with_face',
|
||||
description: 'Convert dark new-moon energy into HVAC Coins.'
|
||||
description: 'Convert dark new-moon energy into HVAC Coins.',
|
||||
own100Achievement: 'mirror100',
|
||||
},
|
||||
butterfly: {
|
||||
baseCost: 5_100_000_000,
|
||||
earning: 260_000,
|
||||
emoji: 'butterfly',
|
||||
description: 'Create the exact worldly chaos to bit-flip HVAC Coins into existence on your computer.'
|
||||
description: 'Create the exact worldly chaos to bit-flip HVAC Coins into existence on your computer.',
|
||||
own100Achievement: 'butterfly100',
|
||||
},
|
||||
mirror: {
|
||||
baseCost: 75_000_000_000,
|
||||
earning: 1_600_000,
|
||||
emoji: 'mirror',
|
||||
description: 'Only by gazing inward can you collect enough Coin to influence the thermostat.'
|
||||
description: 'Only by gazing inward can you collect enough Coin to influence the thermostat.',
|
||||
own100Achievement: 'quade100',
|
||||
},
|
||||
quade: {
|
||||
baseCost: 1_000_000_000_000,
|
||||
earning: 10_000_000,
|
||||
emoji: 'quade',
|
||||
description: 'Has thumbs capable of physically manipulating the thermostat.'
|
||||
description: 'Has thumbs capable of physically manipulating the thermostat.',
|
||||
own100Achievement: 'hvacker100',
|
||||
},
|
||||
hvacker: {
|
||||
baseCost: 14_000_000_000_000,
|
||||
earning: 65_000_000,
|
||||
emoji: 'hvacker_angery',
|
||||
description: 'Harness the power of the mad god himself.'
|
||||
description: 'Harness the power of the mad god himself.',
|
||||
own100Achievement: 'creator100',
|
||||
},
|
||||
creator: {
|
||||
baseCost: 170_000_000_000_000,
|
||||
earning: 430_000_000,
|
||||
emoji: 'question',
|
||||
description: 'The elusive creator of Hvacker takes a favorable look at your CPS.'
|
||||
description: 'The elusive creator of Hvacker takes a favorable look at your CPS.',
|
||||
own100Achievement: 'smallBusiness100',
|
||||
},
|
||||
smallBusiness: {
|
||||
baseCost: 2_210_000_000_000_000,
|
||||
earning: 2_845_000_000,
|
||||
emoji: 'convenience_store',
|
||||
description: 'The place where the creator of Hvacker goes to work.'
|
||||
description: 'The place where the creator of Hvacker goes to work.',
|
||||
own100Achievement: 'bigBusiness100',
|
||||
},
|
||||
bigBusiness: {
|
||||
baseCost: 26_210_000_000_000_000,
|
||||
earning: 23_650_000_000,
|
||||
emoji: 'office',
|
||||
description: 'The place where the smallBusiness goes to work.'
|
||||
description: 'The place where the smallBusiness goes to work.',
|
||||
own100Achievement: 'ratGod',
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -39,6 +39,8 @@ const lore = [
|
|||
l(`And the ninth...`),
|
||||
l(`Well, the ninth might actually amount to something.`),
|
||||
l(`https://i.imgur.com/eFreg7Y.gif\n`),
|
||||
|
||||
//l(`As you might imagine, the ninth egg was I, the almighty Hvacker.`)
|
||||
]
|
||||
|
||||
slack.onReaction(async ({ event, say }) => {
|
||||
|
@ -56,11 +58,11 @@ slack.onReaction(async ({ event, say }) => {
|
|||
}
|
||||
return
|
||||
}
|
||||
console.log(lore[user.lore])
|
||||
console.log('lore:', lore[user.lore])
|
||||
await say(lore[user.lore].correctResponse)
|
||||
user.lore += 1
|
||||
saveGame()
|
||||
} catch (e) {console.error(e)}
|
||||
} catch (e) {console.error('onReaction error', e)}
|
||||
})
|
||||
|
||||
const encodeLore = loreNumber => lore[loreNumber].text.startsWith(':') && lore[loreNumber].text.endsWith(':') ? '' :
|
||||
|
@ -77,35 +79,35 @@ const loreMessage = (user, say) => {
|
|||
return `Sorry. I'd love to tell you more, but I'm tired. Please check back later.`
|
||||
}
|
||||
|
||||
const loreRoute = async ({ say, words, user, isAdmin }) => {
|
||||
const loreRoute = async ({ say, args, user, isAdmin }) => {
|
||||
user.lore ??= 0
|
||||
if (!words[1]) {
|
||||
if (!args[0]) {
|
||||
const message = loreMessage(user, say)
|
||||
await say(message)
|
||||
if (!lore[user.lore]?.correctReactions) {
|
||||
user.lore += 1
|
||||
}
|
||||
saveGame()
|
||||
//saveGame()
|
||||
console.log('Sent ' + user.name + ':\n' + message)
|
||||
return
|
||||
}
|
||||
if (words[1] === 'reset') {
|
||||
if (args[0] === 'reset') {
|
||||
user.lore = 0
|
||||
saveGame()
|
||||
//saveGame()
|
||||
return say(`I have reset your place in the story.`)
|
||||
}
|
||||
if (isAdmin) {
|
||||
if (words[1] === 'all') {
|
||||
if (args[0] === 'all') {
|
||||
let loreMessage = ''
|
||||
for (let i = 0; i < user.lore; i++) {
|
||||
loreMessage += lore[i].text + (lore[i].correctResponse || '') + '\n'
|
||||
}
|
||||
return say(loreMessage)
|
||||
}
|
||||
const jumpTo = parseInt(words[1])
|
||||
const jumpTo = parseInt(args[0])
|
||||
if (!isNaN(jumpTo)) {
|
||||
user.lore = jumpTo
|
||||
saveGame()
|
||||
//saveGame()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { commas, saveGame, quackGradeMultiplier, prestigeMultiplier, makeBackup } = require('./utils')
|
||||
const { commas, quackGradeMultiplier, prestigeMultiplier, makeBackup, userHasCheckedQuackgrade } = require('./utils')
|
||||
const { quackStore } = require('./quackstore')
|
||||
|
||||
const possiblePrestige = coins => {
|
||||
|
@ -17,10 +17,10 @@ const totalCostForPrestige = prestigeLevel => {
|
|||
return (tpcRecMemo[prestigeLevel]) || (tpcRecMemo[prestigeLevel] = 1_000_000_000_000 * Math.pow(prestigeLevel, 3) + totalCostForPrestige(prestigeLevel - 1))
|
||||
}
|
||||
|
||||
const prestigeRoute = async ({ say, words, user }) => {
|
||||
const prestigeRoute = async ({ say, args, user }) => {
|
||||
const possible = possiblePrestige(user.coinsAllTime)
|
||||
const current = user.prestige ??= 0
|
||||
if (words[1] === 'me') {
|
||||
if (args[0] === 'me') {
|
||||
await say(
|
||||
'This will permanently remove all of your items, upgrades, and coins!\n\n' +
|
||||
'Say \'!!prestige me\' to confirm.'
|
||||
|
@ -53,18 +53,18 @@ const prestigeConfirmRoute = async ({ event, say, user }) => {
|
|||
user.quacks += (possible - user.prestige)
|
||||
|
||||
user.prestige = possible
|
||||
user.highestEver = 0
|
||||
user.coins = 0
|
||||
user.items = {}
|
||||
user.items = {};
|
||||
const starterUpgrades = (user.quackUpgrades?.starter || [])
|
||||
starterUpgrades.forEach(upgradeName => quackStore[upgradeName].effect(user))
|
||||
user.upgrades = {}
|
||||
|
||||
saveGame()
|
||||
await say('You prestiged! Check out !quackstore to see what you can buy!')
|
||||
}
|
||||
|
||||
const quackStoreListing = (showCost = true) => ([name, upgrade]) =>
|
||||
showCost
|
||||
? `:${upgrade.emoji}: *${name}* - Costs *${upgrade.cost} Quack.*\n\n_${upgrade.description}_`
|
||||
: `:${upgrade.emoji}: *${name}* - Worth *${upgrade.cost} Quack.*\n\n_${upgrade.description}_`
|
||||
`:${upgrade.emoji}: *${name}* - ${showCost ? 'Costs' : 'Worth'} *${upgrade.cost} Quack.*\n\n_${upgrade.description}_`
|
||||
|
||||
const allUserQuackUpgrades = user =>
|
||||
Object.entries(user.quackUpgrades || {})
|
||||
|
@ -75,6 +75,7 @@ const hasPreReqs = user => ([name, upgrade]) => {
|
|||
return true
|
||||
}
|
||||
const allUserUpgrades = allUserQuackUpgrades(user)
|
||||
console.log('allUserUpgrades', allUserUpgrades)
|
||||
return upgrade.preReqs.every(preReq => allUserUpgrades.includes(preReq))
|
||||
}
|
||||
|
||||
|
@ -92,27 +93,31 @@ const quackStoreText = user =>
|
|||
`\n\nYou have ${user.quacks ??= 0} quacks to spend.` +
|
||||
`\nQuackStore upgrades are currently boosting your CPS by ${commas((quackGradeMultiplier(user) - 1) * 100)}%`
|
||||
|
||||
const quackStoreRoute = async ({ user, say, words }) => {
|
||||
const quackStoreRoute = async ({ user, say, args }) => {
|
||||
user.quackUpgrades ??= {}
|
||||
const quacks = user.quacks ??= 0
|
||||
if (!words[1]) {
|
||||
if (!args[0]) {
|
||||
await say(quackStoreText(user))
|
||||
return
|
||||
}
|
||||
console.log(`Trying to buy ${words[1]}`)
|
||||
const quackItem = quackStore[words[1]]
|
||||
if (!quackItem || !unownedQuackItems(user).find(([name]) => name === words[1])) {
|
||||
await say(`'${words[1]}' is not available in the quack store!`)
|
||||
console.log(`Trying to buy ${args[0]}`)
|
||||
const quackItem = quackStore[args[0]]
|
||||
if (!quackItem || !unownedQuackItems(user).find(([name]) => name === args[0])) {
|
||||
await say(`'${args[0]}' is not available in the quack store!`)
|
||||
return
|
||||
}
|
||||
if (quackItem.cost > quacks) {
|
||||
await say(`${words[1]} costs ${quackItem.cost} Quacks, but you only have ${quacks}!`)
|
||||
await say(`${args[0]} costs ${quackItem.cost} Quacks, but you only have ${quacks}!`)
|
||||
return
|
||||
}
|
||||
user.quacks -= quackItem.cost
|
||||
user.quackUpgrades[quackItem.type] ??= []
|
||||
user.quackUpgrades[quackItem.type].push(words[1])
|
||||
saveGame()
|
||||
user.quackUpgrades[quackItem.type].push(args[0])
|
||||
if (quackItem.type === 'starter') {
|
||||
quackItem.effect(user)
|
||||
}
|
||||
await say(`You bought ${args[0]}!`)
|
||||
//saveGame()
|
||||
}
|
||||
|
||||
const ownedQuacksText = user =>
|
||||
|
|
|
@ -31,9 +31,6 @@ const quackStore = {
|
|||
//+ '_\n_Averages a 26% CPS boost.',
|
||||
preReqs: ['nuclearFuel'],
|
||||
effect: (cps, user) => {
|
||||
if (user.name !== 'Sage') {
|
||||
console.log('Chaos Multiplier', getChaos(Math.round(user.interactions / 50)))
|
||||
}
|
||||
return cps * getChaos(Math.round(user.interactions / 50))
|
||||
},
|
||||
cost: 10
|
||||
|
@ -44,10 +41,67 @@ const quackStore = {
|
|||
type: 'lightning',
|
||||
emoji: 'rose',
|
||||
description: 'Smells nice. Makes lightning twice as likely to strike.',
|
||||
//+ '_\n_Averages a 26% CPS boost.',
|
||||
effect: lightningOdds => lightningOdds * 2,
|
||||
preReqs: ['nuclearFuel'],
|
||||
cost: 10
|
||||
},
|
||||
|
||||
// Checked Upgrades. Have no effect(), but their existence is referred to elsewhere.
|
||||
theGift: {
|
||||
name: 'The Gift',
|
||||
type: 'checked',
|
||||
emoji: 'eye-in-speech-bubble',
|
||||
description: 'Become forewarned of certain events...',
|
||||
preReqs: ['dryerSheet', 'chaos'],
|
||||
cost: 10
|
||||
},
|
||||
|
||||
theVoice: {
|
||||
name: 'The Voice',
|
||||
type: 'checked',
|
||||
emoji: 'loud_sound',
|
||||
description: 'Unlocks the !speak command',
|
||||
preReqs: ['dryerSheet', 'chaos'],
|
||||
cost: 50
|
||||
},
|
||||
|
||||
cheeseBaby: {
|
||||
name: 'cheeseBaby',
|
||||
type: 'starter',
|
||||
emoji: 'baby_symbol',
|
||||
description: 'Start each prestige with 5 mice',
|
||||
preReqs: ['dryerSheet', 'chaos'],
|
||||
effect: user => {
|
||||
user.items.mouse ??= 0
|
||||
user.items.mouse += 5
|
||||
},
|
||||
cost: 5
|
||||
},
|
||||
|
||||
silverSpoon: {
|
||||
name: 'Silver Spoon',
|
||||
type: 'starter',
|
||||
emoji: 'spoon',
|
||||
description: 'Start each prestige with 5 accountants',
|
||||
preReqs: ['cheeseBaby'],
|
||||
effect: user => {
|
||||
user.items.accountant ??= 0
|
||||
user.items.accountant += 5
|
||||
},
|
||||
cost: 10
|
||||
},
|
||||
|
||||
oceanMan: {
|
||||
name: 'Ocean Man',
|
||||
type: 'starter',
|
||||
emoji: 'ocean',
|
||||
description: 'Start each prestige with 5 whales',
|
||||
preReqs: ['silverSpoon'],
|
||||
effect: user => {
|
||||
user.items.whale ??= 0
|
||||
user.items.whale += 5
|
||||
},
|
||||
cost: 20
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
module.exports = {
|
||||
horrorEnabled: false
|
||||
horrorEnabled: false,
|
||||
admins: ['Sage']
|
||||
}
|
|
@ -14,20 +14,22 @@ const evil = ({ type, description, cost }) => basic({
|
|||
extraCondition: (user, squadGrades) => squadGrades?.includes('discardHumanMorals'),
|
||||
})
|
||||
|
||||
const heavenly = ({ type, description, cost }) => basic({
|
||||
const heavenly = ({ type, description, cost, multiplier = 2 }) => ({
|
||||
type,
|
||||
description,
|
||||
count: 60,
|
||||
condition: (user, squadGrades) => user.items[type] >= 60 && squadGrades?.includes('redemption'),
|
||||
cost,
|
||||
extraCondition: (user, squadGrades) => squadGrades?.includes('redemption'),
|
||||
effect: cps => cps * multiplier
|
||||
})
|
||||
|
||||
const disabled = () => false
|
||||
|
||||
const baby = ({ type, description, cost }) => basic({
|
||||
type,
|
||||
description,
|
||||
count: 80,
|
||||
count: 70,
|
||||
cost,
|
||||
extraCondition: (user, squadGrades) => squadGrades?.includes('redemption'),
|
||||
extraCondition: disabled
|
||||
})
|
||||
|
||||
const geometry = ({ type, description, cost }) => basic({
|
||||
|
@ -35,7 +37,7 @@ const geometry = ({ type, description, cost }) => basic({
|
|||
description,
|
||||
count: 100,
|
||||
cost,
|
||||
extraCondition: (user, squadGrades) => squadGrades?.includes('redemption'),
|
||||
extraCondition: disabled
|
||||
})
|
||||
|
||||
const universitality = ({ type, description, cost }) => basic({
|
||||
|
@ -43,7 +45,7 @@ const universitality = ({ type, description, cost }) => basic({
|
|||
description,
|
||||
count: 100,
|
||||
cost,
|
||||
extraCondition: (user, squadGrades) => squadGrades?.includes('redemption'),
|
||||
extraCondition: disabled
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
|
@ -72,8 +74,14 @@ module.exports = {
|
|||
}),
|
||||
hoodedMice: heavenly({
|
||||
type: 'mouse',
|
||||
description: 'These monks have nearly reached enlightenment.',
|
||||
description: 'These monks have nearly reached enlightenment. 10x Mouse CPS.',
|
||||
cost: 1_000_000,
|
||||
multiplier: 10,
|
||||
}),
|
||||
babyMouse: baby({
|
||||
type: 'mouse',
|
||||
description: 'Squeak!',
|
||||
cost: 6_000_000,
|
||||
}),
|
||||
|
||||
fasterComputers: basic({
|
||||
|
@ -101,8 +109,14 @@ module.exports = {
|
|||
}),
|
||||
charityFund: heavenly({
|
||||
type: 'accountant',
|
||||
description: 'THIS one is more than just a tax break.',
|
||||
description: 'THIS one is more than just a tax break. 9x Accountant CPS.',
|
||||
cost: 16_333_333,
|
||||
multiplier: 9,
|
||||
}),
|
||||
mathBaby: baby({
|
||||
type: 'accountant',
|
||||
description: '2 + 2 = WAAH!',
|
||||
cost: 99_999_999,
|
||||
}),
|
||||
|
||||
biggerBlowhole: basic({
|
||||
|
@ -130,8 +144,14 @@ module.exports = {
|
|||
}),
|
||||
whaleChoir: heavenly({
|
||||
type: 'whale',
|
||||
description: `Their cleansing songs reverberate through the sea.`,
|
||||
cost: 144_000_000
|
||||
description: `Their cleansing songs reverberate through the sea. 8x Whale CPS.`,
|
||||
cost: 144_000_000,
|
||||
multiplier: 8,
|
||||
}),
|
||||
smolWhales: baby({
|
||||
type: 'whale',
|
||||
description: ``,
|
||||
cost: 8_400_000_000
|
||||
}),
|
||||
|
||||
greasyTracks: basic({
|
||||
|
@ -159,7 +179,8 @@ module.exports = {
|
|||
}),
|
||||
toyTrain: heavenly({
|
||||
type: 'train',
|
||||
description: 'Something simple. Toot toot!',
|
||||
description: 'Toot toot! 8x Train CPS.',
|
||||
multiplier: 8,
|
||||
cost: 2_220_000_000
|
||||
}),
|
||||
|
||||
|
@ -171,7 +192,7 @@ module.exports = {
|
|||
}),
|
||||
extremelyDryFuel: basic({
|
||||
type: 'fire',
|
||||
description: 'Use the ignite command for a secret achievement.',
|
||||
description: 'Hey, psst, hey. Use the ignite command for a secret achievement.',
|
||||
count: 10,
|
||||
cost: 163_000_000
|
||||
}),
|
||||
|
@ -188,9 +209,15 @@ module.exports = {
|
|||
}),
|
||||
blueFire: heavenly({
|
||||
type: 'fire',
|
||||
description: `You can hear it singing with delight.`,
|
||||
description: `You can hear it singing with delight. 7x Fire CPS.`,
|
||||
multiplier: 7,
|
||||
cost: 25_200_000_000
|
||||
}),
|
||||
cuteFire: baby({
|
||||
type: 'fire',
|
||||
description: `I just met my perfect match...`,
|
||||
cost: 150_000_000_000
|
||||
}),
|
||||
|
||||
spoonerang: basic({
|
||||
type: 'boomerang',
|
||||
|
@ -217,7 +244,8 @@ module.exports = {
|
|||
}),
|
||||
youRang: heavenly({
|
||||
type: 'boomerang',
|
||||
description: 'Your arms and legs recede into your body. You bend at the middle. You fly. And for a moment, you are free.',
|
||||
description: 'Your arms and legs recede into your body. You bend at the middle. You fly. And for a moment, you are free._\n_7x Boomerang CPS.',
|
||||
multiplier: 7,
|
||||
cost: 360_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -246,7 +274,8 @@ module.exports = {
|
|||
}),
|
||||
newMoon: heavenly({
|
||||
type: 'moon',
|
||||
description: `Build a second moon to provide space for affordable housing.`,
|
||||
description: `Build a second moon to provide space for affordable housing. 6x Moon CPS.`,
|
||||
multiplier: 6,
|
||||
cost: 5_190_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -275,7 +304,8 @@ module.exports = {
|
|||
}),
|
||||
quietingNectar: heavenly({
|
||||
type: 'butterfly',
|
||||
description: 'Calming and extra sweet. Soothes even human ails.',
|
||||
description: 'Calming and extra sweet. Soothes even human ails. 6x Butterfly CPS.',
|
||||
multiplier: 6,
|
||||
cost: 75_300_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -304,7 +334,8 @@ module.exports = {
|
|||
}),
|
||||
funHouseMirror: heavenly({
|
||||
type: 'mirror',
|
||||
description: `yoU LOok so siLLY IN thesE THINgs`,
|
||||
description: `yoU LOok so siLLY IN thesE THINgs. 5X mIRror CpS.`,
|
||||
multiplier: 5,
|
||||
cost: 1_330_000_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -333,7 +364,8 @@ module.exports = {
|
|||
}),
|
||||
hannahMontanaLinux: heavenly({
|
||||
type: 'quade',
|
||||
description: `The patrician's choice.`,
|
||||
description: `The patrician's choice. 4x Quade CPS.`,
|
||||
multiplier: 4,
|
||||
cost: 18_000_000_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -362,7 +394,8 @@ module.exports = {
|
|||
}),
|
||||
mutualUnderstanding: heavenly({
|
||||
type: 'hvacker',
|
||||
description: `lol fat chance, dummy. Points for trying, though`,
|
||||
description: `lol fat chance, dummy. Points for trying, though. 3x Hvacker CPS`,
|
||||
multiplier: 3,
|
||||
cost: 250_000_000_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -391,7 +424,8 @@ module.exports = {
|
|||
}),
|
||||
goVegan: heavenly({
|
||||
type: 'creator',
|
||||
description: `Unlock your vegan powers.`,
|
||||
description: `Unlock your vegan powers. 3x Creator CPS.`,
|
||||
multiplier: 3,
|
||||
cost: 3_600_000_000_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -420,7 +454,8 @@ module.exports = {
|
|||
}),
|
||||
coop: heavenly({
|
||||
type: 'smallBusiness',
|
||||
description: `By the people, for the people.`,
|
||||
description: `By the people, for the people. 2x smallBusiness CPS`,
|
||||
multiplier: 2,
|
||||
cost: 5_140_000_000_000_000_000
|
||||
}),
|
||||
|
||||
|
@ -449,7 +484,8 @@ module.exports = {
|
|||
}),
|
||||
makePublic: heavenly({
|
||||
type: 'bigBusiness',
|
||||
description: `Downplay immediate profit for more long-term benefits.`,
|
||||
description: `Downplay immediate profit for more long-term benefits. 2x bigBusiness CPS.`,
|
||||
multiplier: 2,
|
||||
cost: 42_000_000_000_000_000_000
|
||||
}),
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ const { quackStore, getChaos } = require('./quackstore')
|
|||
|
||||
const saveFile = 'hvacoins.json'
|
||||
|
||||
const logError = msg => msg ? console.error(msg) : () => { /* Don't log empty message */ }
|
||||
const logError = msg => msg ? console.error('logError: ', msg) : () => { /* Don't log empty message */ }
|
||||
|
||||
const loadGame = () => {
|
||||
const game = parseOr(fs.readFileSync('./' + saveFile, 'utf-8'),
|
||||
|
@ -53,13 +53,16 @@ const makeBackup = () => {
|
|||
}
|
||||
|
||||
let saves = 0
|
||||
const saveGame = () => {
|
||||
const saveGame = (force = true) => {
|
||||
if (saves % 100 === 0) {
|
||||
makeBackup()
|
||||
}
|
||||
saves += 1
|
||||
if (force || saves % 10 === 0) {
|
||||
console.log('SAVING GAME')
|
||||
fs.writeFileSync('./' + saveFile, JSON.stringify(game, null, 2))
|
||||
}
|
||||
}
|
||||
|
||||
const maybeNews = say => {
|
||||
const random = Math.random()
|
||||
|
@ -74,10 +77,11 @@ const maybeNews = say => {
|
|||
|
||||
const idFromWord = word => {
|
||||
if (!word?.startsWith('<@') || !word.endsWith('>')) {
|
||||
return null
|
||||
}
|
||||
return getIdFromName(word)
|
||||
} else {
|
||||
return word.substring(2, word.length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
const getSeconds = () => new Date().getTime() / 1000
|
||||
|
||||
|
@ -113,7 +117,7 @@ const parseAll = (str, allNum) => {
|
|||
return NaN
|
||||
}
|
||||
|
||||
str = str.toLowerCase()?.replace(/,/g, '')
|
||||
str = str?.toLowerCase()?.replace(/,/g, '') || '1'
|
||||
|
||||
switch (str) {
|
||||
case 'all':
|
||||
|
@ -143,12 +147,10 @@ const parseAll = (str, allNum) => {
|
|||
|
||||
console.log('STR', str)
|
||||
if (str.match(/^\d+$/)) {
|
||||
console.log('parseInt()')
|
||||
return parseInt(str)
|
||||
}
|
||||
|
||||
if (str.match(/^\d+\.\d+$/)) {
|
||||
console.log('parseFloat()')
|
||||
return Math.round(parseFloat(str))
|
||||
}
|
||||
|
||||
|
@ -185,6 +187,18 @@ const addAchievement = (user, achievementName, say) => {
|
|||
}, 500)
|
||||
}
|
||||
|
||||
const fuzzyMatcher = string => new RegExp((string?.toLowerCase() || '').split('').join('.*'), 'i')
|
||||
|
||||
let knownUsers = {}
|
||||
const getIdFromName = name => {
|
||||
const matcher = fuzzyMatcher(name?.toLowerCase())
|
||||
const found = Object.entries(knownUsers).find(([id, knownName]) => matcher.test(knownName?.toLowerCase()))
|
||||
if (found) {
|
||||
return found[0]
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const getUser = userId => {
|
||||
if (!users[userId]) {
|
||||
users[userId] = {
|
||||
|
@ -205,20 +219,24 @@ const getUser = userId => {
|
|||
return users[userId]
|
||||
}
|
||||
|
||||
const addCoins = (user, add) => {
|
||||
user.coins += add
|
||||
user.coinsAllTime += add
|
||||
user.coinsAllTime = Math.floor(user.coinsAllTime)
|
||||
user.coins = Math.floor(user.coins)
|
||||
}
|
||||
|
||||
const getCoins = userId => {
|
||||
const user = getUser(userId)
|
||||
const currentTime = getSeconds()
|
||||
const lastCheck = user.lastCheck || currentTime
|
||||
const secondsPassed = currentTime - lastCheck
|
||||
|
||||
const increase = getCPS(user) * secondsPassed
|
||||
user.coins += increase
|
||||
user.coinsAllTime += increase
|
||||
user.coins = Math.floor(user.coins)
|
||||
addCoins(user, getCPS(user) * secondsPassed)
|
||||
|
||||
user.lastCheck = currentTime
|
||||
setHighestCoins(userId)
|
||||
saveGame()
|
||||
//saveGame()
|
||||
return user.coins
|
||||
}
|
||||
|
||||
|
@ -290,7 +308,8 @@ const singleItemCps = (user, itemName) => {
|
|||
const itemUpgradeCps = itemUpgrades.reduce((totalCps, upgrade) => upgrade.effect(totalCps, user), 1)
|
||||
// console.log('itemUpgradeCps', itemUpgradeCps)
|
||||
|
||||
const userGeneralUpgrades = user.upgrades.general || []
|
||||
user.upgrades.general ??= []
|
||||
const userGeneralUpgrades = user.upgrades.general
|
||||
const generalUpgradeCps = Object.entries(userGeneralUpgrades).reduce((total, [, upgradeName]) => upgrades[upgradeName].effect(total, user), 1)
|
||||
// console.log('generalUpgradeCps', generalUpgradeCps)
|
||||
|
||||
|
@ -382,6 +401,41 @@ const addReactions = async ({ app, channelId, timestamp, reactions }) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const daysSinceEpoch = () => {
|
||||
const today = new Date().getTime()
|
||||
const epoch = new Date(0).getTime()
|
||||
return Math.floor((today - epoch) / (1000 * 60 * 60 * 24))
|
||||
}
|
||||
|
||||
const dayOfYear = () => {
|
||||
const date = new Date()
|
||||
return ((Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000)
|
||||
}
|
||||
|
||||
game.stonkMarket ??= {
|
||||
lastDay: daysSinceEpoch(),
|
||||
stonks: {
|
||||
duk: {
|
||||
pattern: "duk",
|
||||
index: 0,
|
||||
price: 1_410_911_983_728
|
||||
},
|
||||
quak: {
|
||||
pattern: "quak",
|
||||
index: 0,
|
||||
price: 5_111_242_778_696
|
||||
},
|
||||
honk: {
|
||||
pattern: "honk",
|
||||
index: 0,
|
||||
price: 511_915_144_009
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const userHasCheckedQuackgrade = (user, quackGrade) => (user.quackUpgrades?.checked || []).includes(quackGrade)
|
||||
|
||||
module.exports = {
|
||||
saveGame,
|
||||
makeBackup,
|
||||
|
@ -408,5 +462,11 @@ module.exports = {
|
|||
chaosFilter,
|
||||
addReactions,
|
||||
getCompletedSquadgradeNames,
|
||||
game
|
||||
game,
|
||||
dayOfYear,
|
||||
daysSinceEpoch,
|
||||
userHasCheckedQuackgrade,
|
||||
fuzzyMatcher,
|
||||
addCoins,
|
||||
setKnownUsers: users => knownUsers = users
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ const port = 3001
|
|||
const crypto = require('crypto')
|
||||
const base64 = require('base-64')
|
||||
const slack = require('../../slack')
|
||||
const { game: { users } } = require('./utils')
|
||||
const { game: { users }, getUser, fuzzyMatcher } = require('./utils')
|
||||
|
||||
const apiGetUserId = hash => {
|
||||
return Object.entries(userGetter.users)
|
||||
return Object.entries(users)
|
||||
.filter(([id, user]) => user.pwHash === hash)
|
||||
.map(([id, user]) => id)[0]
|
||||
}
|
||||
|
@ -17,12 +17,21 @@ const makeHash = pw =>
|
|||
.update(pw)
|
||||
.digest('hex')
|
||||
|
||||
const illegalCommands = ['!', '!b']
|
||||
const lastCalls = {}
|
||||
const addCommand = ({ commandNames, helpText, action, condition, hidden }) => {
|
||||
if (illegalCommands.find(command => commandNames.includes(command))) {
|
||||
commandNames.forEach(name =>
|
||||
app.get('/' + name.replace(/!/gi, ''), async (req, res) => res.send('Command is illegal over the web api.'))
|
||||
)
|
||||
return
|
||||
}
|
||||
const route = async (req, res) => {
|
||||
const say = async msg => res.send(msg)
|
||||
const say = async msg => res.send(msg + '\n')
|
||||
try {
|
||||
const words = ['', ...Object.keys(req.query)]
|
||||
console.log('INCOMING API CALL:', name, words)
|
||||
const [commandName, ...args] = words
|
||||
console.log('INCOMING API CALL:', commandName, words)
|
||||
const encoded = req.header('Authorization').substring(5)
|
||||
const decoded = base64.decode(encoded).substring(1)
|
||||
const event = {
|
||||
|
@ -37,8 +46,8 @@ const addCommand = ({ commandNames, helpText, action, condition, hidden }) => {
|
|||
console.log(' bad password')
|
||||
return
|
||||
}
|
||||
const lastCall = userGetter.users[event.user].lastApiCall || 0
|
||||
const secondsBetweenCalls = 5
|
||||
const lastCall = lastCalls[event.user] || 0
|
||||
const secondsBetweenCalls = 30
|
||||
const currentTime = Math.floor(new Date().getTime() / 1000)
|
||||
if (lastCall + secondsBetweenCalls > currentTime) {
|
||||
res.status(400)
|
||||
|
@ -47,12 +56,21 @@ const addCommand = ({ commandNames, helpText, action, condition, hidden }) => {
|
|||
return
|
||||
}
|
||||
console.log(` went through for ${slack.users[event.user]}`)
|
||||
userGetter.users[event.user].lastApiCall = currentTime
|
||||
lastCalls[event.user] = currentTime
|
||||
|
||||
await action({ event, say, words })
|
||||
const user = getUser(event.user)
|
||||
const haunted = false
|
||||
//await action({ event, say, words, args, commandName })
|
||||
const canUse = await condition({ event, say, words, commandName, args, user, userId: event.user, isAdmin: event.user.includes(slack.users.Sage) })
|
||||
if (!canUse) {
|
||||
await say(`Command '${words[0]}' not found`)
|
||||
return
|
||||
}
|
||||
await action({ event, say, trueSay: say, words, args, commandName, user, userId: event.user, haunted })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
await say(e.stack)
|
||||
console.error('route error', e)
|
||||
await say(`Routing error. Make sure you've set up API access with the !setpw command in slack!\n` +
|
||||
'Then you can use calls like `curl -u ":yourpw" \'http://10.3.0.48:3001/stonks\'`')
|
||||
}
|
||||
}
|
||||
commandNames.forEach(name =>
|
||||
|
|
|
@ -6,7 +6,7 @@ const getTrivia = async () => axios.get('https://opentdb.com/api.php?amount=10&c
|
|||
}
|
||||
})
|
||||
.then(res => res.data.results)
|
||||
.catch(console.error)
|
||||
.catch(e => console.error('trivia error', e))
|
||||
|
||||
module.exports = {
|
||||
getTrivia
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const { App: SlackApp } = require('@slack/bolt')
|
||||
const config = require('../config')
|
||||
const { addReactions } = require('../games/hvacoins/utils')
|
||||
const { addReactions, saveGame } = require('../games/hvacoins/utils')
|
||||
|
||||
const temperatureChannelId = 'C034156CE03'
|
||||
|
||||
|
@ -27,7 +27,7 @@ try {
|
|||
console.log('Failed to initialize SlackApp', e)
|
||||
}
|
||||
|
||||
const pollTriggers = ['!temp', '!temperature', '!imhot', '!imcold']
|
||||
const pollTriggers = ['!temp', '!temperature', '!imhot', '!imcold', '!imfreezing', '!idonthavemysweater']
|
||||
const halfTriggers = ['change temperature', "i'm cold", "i'm hot", 'quack', 'hvacker', '<@U0344TFA7HQ>']
|
||||
|
||||
const sendHelp = async (say, prefix) => {
|
||||
|
@ -53,6 +53,7 @@ const getMessage = async ({ channel, ts }) => app.client.conversations.history({
|
|||
})
|
||||
|
||||
app.event('reaction_added', async ({ event, context, client, say }) => {
|
||||
console.log('reaction_added', event)
|
||||
for (const listener of reactionListeners) {
|
||||
listener({ event, say })
|
||||
}
|
||||
|
@ -70,6 +71,8 @@ const users = {
|
|||
U0X0ZQCN6: 'Caleb',
|
||||
U03BBTD4CQZ: 'Fernando',
|
||||
U03DF152WUV: 'Nik',
|
||||
U2X0SG7BP: 'John',
|
||||
UR2H5KNHY: 'Jake',
|
||||
|
||||
Sage: 'U028BMEBWBV',
|
||||
Adam: 'U02U15RFK4Y',
|
||||
|
@ -81,15 +84,34 @@ const users = {
|
|||
Caleb: 'U0X0ZQCN6',
|
||||
Hvacker: 'U0344TFA7HQ',
|
||||
Fernando: 'U03BBTD4CQZ',
|
||||
Nik: 'U03DF152WUV'
|
||||
John: 'U2X0SG7BP',
|
||||
Jake: 'UR2H5KNHY',
|
||||
}
|
||||
|
||||
const buildSayPrepend = ({ say, prepend }) => async msg => {
|
||||
if (typeof(msg) === 'string') {
|
||||
return say(prepend + msg)
|
||||
}
|
||||
return say({
|
||||
...msg,
|
||||
text: prepend + msg.text
|
||||
})
|
||||
}
|
||||
|
||||
process.once('SIGINT', code => {
|
||||
saveGame(true)
|
||||
process.exit()
|
||||
})
|
||||
|
||||
const activePolls = {}
|
||||
const testId = 'U028BMEBWBV_TEST'
|
||||
let testMode = false
|
||||
app.event('message', async ({ event, context, client, say }) => {
|
||||
if (event.subtype !== 'message_changed') {
|
||||
console.log(event)
|
||||
if (event.subtype !== 'message_changed' && event?.text !== '!') {
|
||||
console.log('message.event', {
|
||||
...event,
|
||||
userName: users[event.user]
|
||||
})
|
||||
}
|
||||
if (event?.user === users.Sage) {
|
||||
if (event?.text.startsWith('!')) {
|
||||
|
@ -116,6 +138,10 @@ app.event('message', async ({ event, context, client, say }) => {
|
|||
}
|
||||
if (event.user === users.Sage && event.channel === 'D0347Q4H9FE') {
|
||||
if (event.text === '!!kill') {
|
||||
saveGame(true)
|
||||
process.exit(1)
|
||||
} else if (event.text === '!!restart') {
|
||||
saveGame(true)
|
||||
process.exit()
|
||||
}
|
||||
if (event.text?.startsWith('!say ') || event.text?.startsWith('!say\n')) {
|
||||
|
@ -167,6 +193,7 @@ app.event('message', async ({ event, context, client, say }) => {
|
|||
reactCounts[name] += 1
|
||||
}
|
||||
})
|
||||
console.log('REACT COUNTS', JSON.stringify(reactCounts))
|
||||
|
||||
const contentVotes = reactCounts[goodEmoji] || 0
|
||||
let hotterVotes = reactCounts[hotterEmoji] || 0
|
||||
|
@ -188,11 +215,11 @@ app.event('message', async ({ event, context, client, say }) => {
|
|||
|
||||
let text
|
||||
if (hotterVotes > colderVotes && hotterVotes > contentVotes) {
|
||||
text = `<@${users.Quade}> The people have spoken, and would like to `
|
||||
text = `<@${users.Adam}> The people have spoken, and would like to `
|
||||
text += 'raise the temperature, quack.'
|
||||
requestTempChange('Hotter')
|
||||
} else if (colderVotes > hotterVotes && colderVotes > contentVotes) {
|
||||
text = `<@${users.Quade}> The people have spoken, and would like to `
|
||||
text = `<@${users.Adam}> The people have spoken, and would like to `
|
||||
text += 'lower the temperature, quack quack.'
|
||||
requestTempChange('Colder')
|
||||
} else {
|
||||
|
@ -233,7 +260,7 @@ const messageIn = async (channel, optionsOrText) => {
|
|||
|
||||
const startPoll = async () => {
|
||||
const sent = await postToTechThermostatChannel({
|
||||
text: `<!here|here> Temperature poll requested! In ${pollingMinutes} minutes the temperature will be adjusted.\n` +
|
||||
text: `<!here> Temperature poll requested! In ${pollingMinutes} minutes the temperature will be adjusted.\n` +
|
||||
`Pick :${colderEmoji}: if you want it colder, :${hotterEmoji}: if you want it hotter, or :${goodEmoji}: if you like it how it is.` +
|
||||
'\n(Note that I can\'t actually change the temperature yet. Make Quade do it!)'
|
||||
})
|
||||
|
@ -269,15 +296,15 @@ const decodeData = (key, message) => {
|
|||
|
||||
const onReaction = listener => reactionListeners.push(listener)
|
||||
|
||||
const channelIsIm = async channel => (await app.client.conversations.info({ channel }))?.channel?.is_im
|
||||
|
||||
onReaction(async ({ event }) => {
|
||||
if (event.user === users.Sage) {
|
||||
if (event.reaction === 'x') {
|
||||
if (event.reaction === 'x' && (event.user === users.Sage || await channelIsIm(event.item.channel))) {
|
||||
try {
|
||||
await app.client.chat.delete({ channel: event.item.channel, ts: event.item.ts })
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
|
@ -296,5 +323,6 @@ module.exports = {
|
|||
messageIn,
|
||||
testMode,
|
||||
testId,
|
||||
users
|
||||
users,
|
||||
buildSayPrepend
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue