Update script.sh for new host.

Disable !lotr and !lotrOld
Re-enable API and make some tweaks to clean up responses
Move saveDir to /hvacker-saves
Disable API rate limit
This commit is contained in:
Sage Vaillancourt 2023-12-29 16:09:54 -05:00
parent f5277ae9de
commit edfea51bfa
5 changed files with 132 additions and 68 deletions

View File

@ -2,11 +2,13 @@
export NVM_DIR="$HOME/.nvm" export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
cd /home/sagevaillancourt/git/hvacker cd /home/sage/projects/hvacker || exit 1
whereis npm whereis npm
npm start | while read line; do npm start | while read line; do
echo "$line" echo "$line"
if [[ "$line" == *"app http request failed getaddrinfo ENOTFOUND slack.com"* ]]; then if [[ "$line" == *"app http request failed getaddrinfo ENOTFOUND slack.com"* ]] ||
[[ "$line" == *"node:internal/errors"* ]] ||
[[ "$line" == *"Cannot set headers after"* ]]; then
systemctl restart hvacker systemctl restart hvacker
exit 1 exit 1
fi fi

View File

@ -210,38 +210,38 @@ const cardGames = {
getCardName: card => card.name, getCardName: card => card.name,
getCardImageUrl: card => card.card_images[0].image_url getCardImageUrl: card => card.card_images[0].image_url
}, },
lotrOld: { // lotrOld: {
names: ['!lotrOld'], // names: ['!lotrOld'],
help: 'Search for Lord of the Rings cards: !lotrOld <card name>', // help: 'Search for Lord of the Rings cards: !lotrOld <card name>',
cards: async () => JSON.parse(readFileSync('lotrOld/lotr_cards.json').toString()), // cards: async () => JSON.parse(readFileSync('lotrOld/lotr_cards.json').toString()),
fetch: async name => ({ json: () => { // fetch: async name => ({ json: () => {
const matcher = fuzzyMatcher(name?.toLowerCase()) // const matcher = fuzzyMatcher(name?.toLowerCase())
const exact = cardGames.lotrOld.cards.filter(card => card.name?.toLowerCase() === name.toLowerCase()) // const exact = cardGames.lotrOld.cards.filter(card => card.name?.toLowerCase() === name.toLowerCase())
if (exact.length) { // if (exact.length) {
return exact // return exact
} // }
return cardGames.lotrOld.cards.filter(card => matcher.test(card.name)) // return cardGames.lotrOld.cards.filter(card => matcher.test(card.name))
} }), // } }),
getCardData: data => data, // getCardData: data => data,
getCardName: card => card.name, // getCardName: card => card.name,
getCardImageUrl: card => 'https://ringsdb.com' + card.imagesrc // getCardImageUrl: card => 'https://ringsdb.com' + card.imagesrc
}, // },
lotr: { // lotr: {
names: ['!lotr'], // names: ['!lotr'],
help: 'Search for Lord of the Rings cards: !lotr <card name>', // help: 'Search for Lord of the Rings cards: !lotr <card name>',
cards: async () => JSON.parse(readFileSync('lotr/cards.json').toString()), // cards: async () => JSON.parse(readFileSync('lotr/cards.json').toString()),
fetch: async name => ({ json: () => { // fetch: async name => ({ json: () => {
const matcher = fuzzyMatcher(name?.toLowerCase()) // const matcher = fuzzyMatcher(name?.toLowerCase())
const exact = cardGames.lotr.cards.filter(card => card.name?.toLowerCase() === name.toLowerCase()) // const exact = cardGames.lotr.cards.filter(card => card.name?.toLowerCase() === name.toLowerCase())
if (exact.length) { // if (exact.length) {
return [exact[0]] // return [exact[0]]
} // }
return cardGames.lotr.cards.filter(card => matcher.test(card.name)).filter(card => !card.name.includes('(')) // return cardGames.lotr.cards.filter(card => matcher.test(card.name)).filter(card => !card.name.includes('('))
} }), // } }),
getCardData: data => data, // getCardData: data => data,
getCardName: card => card.name, // getCardName: card => card.name,
getCardImageUrl: card => 'https://lotrtcgwiki.com/wiki/_media/cards:' + card.id + '.jpg' // getCardImageUrl: card => 'https://lotrtcgwiki.com/wiki/_media/cards:' + card.id + '.jpg'
}, // },
playingCards: { playingCards: {
names: ['!playing', '!pc'], names: ['!playing', '!pc'],
help: 'Search for playing cards cards: !pc <card name>', help: 'Search for playing cards cards: !pc <card name>',
@ -1122,7 +1122,7 @@ command(
'Mine HVAC coins', 'Mine HVAC coins',
async ({ say, user, userId }) => { async ({ say, user, userId }) => {
await say(await doMine({ user, userId, say })) await say(await doMine({ user, userId, say }))
if ((lbIndex++) % 5 == 0) { if ((lbIndex++) % 20 == 0) {
return updateAllLeaderboards() return updateAllLeaderboards()
} }
} }
@ -1573,7 +1573,10 @@ command(
const last = gifted.pop() const last = gifted.pop()
recipients = gifted.map(t => users[t].name).join(', ') + ', and ' + users[last].name recipients = gifted.map(t => users[t].name).join(', ') + ', and ' + users[last].name
} else { } else {
recipients = users[recipients[0]].name 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}`) await say(`Gifted ${commas(individualAmount)} HVAC to ${recipients}`)
} }
@ -2257,7 +2260,7 @@ command(
adminOnly adminOnly
) )
//webapi.launch() webapi.launch()
module.exports = { module.exports = {
command, command,

View File

@ -5,17 +5,22 @@ const buyableItems = require('./buyableItems')
const { quackStore, getChaos } = require('./quackstore') const { quackStore, getChaos } = require('./quackstore')
const slack = require("../../slack"); const slack = require("../../slack");
let slackUsers
const setSlackUsers = users => {
slackUsers = users
}
let upgrades let upgrades
const setUpgrades = upg => { const setUpgrades = upg => {
upgrades = upg upgrades = upg
} }
const saveFile = 'hvacoins.json' const saveFile = 'hvacoins.json'
const saveDir = '/hvacker-saves/'
const logError = msg => msg ? console.error('logError: ', msg) : () => { /* Don't log empty message */ } const logError = msg => msg ? console.error('logError: ', msg) : () => { /* Don't log empty message */ }
const loadGame = () => { const loadGame = () => {
const game = parseOr(fs.readFileSync('./' + saveFile, 'utf-8'), const game = parseOr(fs.readFileSync(saveDir + saveFile, 'utf-8'),
() => ({ () => ({
users: {}, users: {},
nfts: [], nfts: [],
@ -55,7 +60,7 @@ const parseOr = (parseable, fallback) => {
} }
const makeBackup = () => { const makeBackup = () => {
const fileName = './backups/' + saveFile + new Date().toLocaleString().replace(/[^a-z0-9]/gi, '_') const fileName = saveDir + 'backups/' + saveFile + new Date().toLocaleString().replace(/[^a-z0-9]/gi, '_')
console.log(`Making backup file: ${fileName}`) console.log(`Making backup file: ${fileName}`)
fs.writeFileSync(fileName, JSON.stringify(game)) fs.writeFileSync(fileName, JSON.stringify(game))
} }
@ -73,7 +78,7 @@ const saveGame = (after, force = true) => {
console.log('SAVING GAME') console.log('SAVING GAME')
} }
fs.writeFileSync('./' + saveFile, JSON.stringify(game, null, 2)) fs.writeFileSync(saveDir + saveFile, JSON.stringify(game, null, 2))
} }
} }
@ -258,6 +263,7 @@ const getUser = (userId, updateCoins = false) => {
users[userId].coinsAllTime ??= users[userId].coins users[userId].coinsAllTime ??= users[userId].coins
users[userId].prestige ??= 0 users[userId].prestige ??= 0
users[userId].startDate ??= new Date() users[userId].startDate ??= new Date()
// users[userId].name ??= slack.users[userId]
if (updateCoins) { if (updateCoins) {
users[userId].coins = getCoins(userId) users[userId].coins = getCoins(userId)
} }
@ -610,5 +616,6 @@ module.exports = {
petBoost, petBoost,
updateAll, updateAll,
setSlackAppClientChatUpdate: update => slackAppClientChatUpdate = update, setSlackAppClientChatUpdate: update => slackAppClientChatUpdate = update,
setUpgrades setUpgrades,
setSlackUsers
} }

View File

@ -17,48 +17,97 @@ const makeHash = pw =>
.update(pw) .update(pw)
.digest('hex') .digest('hex')
const illegalCommands = ['!', '!b'] const emojiMaps = [
['mouse2', '🐭'],
['male-office-worker', '🧑‍💼'],
['whale', '🐋'],
['train2', '🚂'],
['fire', '🔥'],
['boomerang', '🪃'],
['new_moon_with_face', '🌚'],
['butterfly', '🦋'],
['mirror', '🪞'],
['quade', '🧔‍♂️'],
['hvacker_angery', '🦆'],
['grey_question', '❓'],
['convenience_store', '🏪'],
['office', '🏢'],
['japanese_castle', '🏯']
]
app.get('/alive', (req, res) => {
res.send('OK')
})
const illegalCommands = ['!', '!c', '!coin', '!mine']
const lastCalls = {} const lastCalls = {}
const addCommand = ({ commandNames, helpText, action, condition, hidden }) => { const addCommand = ({ commandNames, helpText, action, condition, hidden }) => {
if (illegalCommands.find(command => commandNames.includes(command))) { const route = async (req, res) => {
commandNames.forEach(name => let sent
app.get('/' + name.replace(/!/gi, ''), async (req, res) => res.send('Command is illegal over the web api.')) const say = async msg => {
) if (sent) {
console.log('attempted double-send of', { msg })
return return
} }
const route = async (req, res) => { const isObj = typeof msg === 'object'
const say = async msg => res.send(msg + '\n') if (isObj) {
msg = JSON.stringify(msg, null, 2)
}
for (const entry of emojiMaps) {
msg = msg.replaceAll(`:${entry[0]}:`, entry[1])
}
msg = msg.replaceAll(/\*([^*]+)\*/g, '$1')
.replaceAll(/_([^_]+)_/g, '$1')
res.send((typeof msg === 'object' ? JSON.stringify(msg, null, 2) : msg) + '\n')
sent = true
}
try { try {
const words = ['', ...Object.keys(req.query)] const keys = [...Object.keys(req.query)]
keys.reverse()
const words = [commandNames[0], ...keys]
console.log({ words })
const [commandName, ...args] = words const [commandName, ...args] = words
console.log('INCOMING API CALL:', commandName, words) console.log('INCOMING API CALL:', commandName, words)
const encoded = req.header('Authorization').substring(5) const encoded = req.header('Authorization').substring(5)
const decoded = base64.decode(encoded).substring(1) const decoded = base64.decode(encoded).substring(1)
const hash = makeHash(decoded)
console.log({ hash })
const event = { const event = {
user: apiGetUserId(makeHash(decoded)) user: apiGetUserId(hash)
}
const user = getUser(event.user)
if (user.name !== 'TEST-USER' && illegalCommands.includes(commandName?.toLowerCase())) {
res.send('Command is illegal over the web api!')
return
} }
if (!event.user) { if (!event.user) {
res.status(400) res.status(400)
res.send( res.send(
'User does not exist, or does not have a password.\n' + 'User with that password does not exist, or user does not have a password.\n' +
'See \'!setpw help\' for assistance.' 'See \'!setpw help\' for assistance.\n'
) )
console.log(' bad password') console.log(' bad password')
return return
} }
const lastCall = lastCalls[event.user] || 0 // const lastCall = lastCalls[event.user] || 0
const secondsBetweenCalls = 30 // const secondsBetweenCalls = 2
const currentTime = Math.floor(new Date().getTime() / 1000) // const currentTime = Math.floor(new Date().getTime() / 1000)
if (lastCall + secondsBetweenCalls > currentTime) { // if (lastCall + secondsBetweenCalls > currentTime) {
res.status(400) // res.status(400)
res.send(`Must have at least ${secondsBetweenCalls}s between api calls`) // res.send(`Must have at least ${secondsBetweenCalls}s between api calls`)
console.log(' rate limited') // console.log(' rate limited')
// return
// }
// console.log(` went through for ${slack.users[event.user]}`)
// lastCalls[event.user] = currentTime
if (words[1] === 'help') {
await say(commandNames.map(name => `\`${name}\``).join(', ') + ': ' + helpText)
if (commandNames.includes('!coin')) {
addAchievement(user, 'weAllNeedHelp', say)
}
return return
} }
console.log(` went through for ${slack.users[event.user]}`)
lastCalls[event.user] = currentTime
const user = getUser(event.user)
const haunted = false const haunted = false
//await action({ event, say, words, args, commandName }) //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.Admin) }) const canUse = await condition({ event, say, words, commandName, args, user, userId: event.user, isAdmin: event.user.includes(slack.users.Admin) })
@ -69,12 +118,14 @@ const addCommand = ({ commandNames, helpText, action, condition, hidden }) => {
await action({ event, say, trueSay: say, words, args, commandName, user, userId: event.user, haunted }) await action({ event, say, trueSay: say, words, args, commandName, user, userId: event.user, haunted })
} catch (e) { } catch (e) {
console.error('route error', e) console.error('route error', e)
const example = "`curl --location-trusted -u ':your-pw' quacker.sagev.space/lb`"
await say(`Routing error. Make sure you've set up API access with the !setpw command in slack!\n` + 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\'`') `Then you can use calls like ${example}\n` +
`N.b. --location-trusted is needed because quacker.sagev.space is technically a redirect, and your headers need to be forwarded.`)
} }
} }
commandNames.forEach(name => commandNames.forEach(name => name !== '!!help' &&
app.get('/' + name.replace(/!/gi, ''), route) app.get('/' + name.replace(/!/gi, ''), async (req, res) => console.log('route', name.replace('/' + /!/gi, '')) || await route(req, res))
) )
} }

View File

@ -1,7 +1,7 @@
const { App: SlackApp } = require('@slack/bolt') const { App: SlackApp } = require('@slack/bolt')
const config = require('../config') const config = require('../config')
const fs = require('fs') const fs = require('fs')
const { addReactions, saveGame, setSlackAppClientChatUpdate, parseOr } = require('../games/hvacoins/utils') const { addReactions, saveGame, setSlackAppClientChatUpdate, parseOr, setSlackUsers } = require('../games/hvacoins/utils')
const temperatureChannelId = 'C034156CE03' const temperatureChannelId = 'C034156CE03'
const dailyStandupChannelId = 'C03L533AU3Z' const dailyStandupChannelId = 'C03L533AU3Z'
@ -333,6 +333,7 @@ onReaction(async ({ event }) => {
}) })
setSlackAppClientChatUpdate(app.client.chat.update) setSlackAppClientChatUpdate(app.client.chat.update)
setSlackUsers(users)
module.exports = { module.exports = {
app, app,