Merge #2: New items: revive and super revive

This commit is contained in:
2025-04-13 20:30:48 +02:00
committed by GitHub
9 changed files with 114 additions and 9 deletions

View File

@@ -31,6 +31,8 @@ ITEM|FUNCTION|ALIASES
-|-|- -|-|-
`blaster {target}`|Times the target user out for 60 seconds|`!blast, !blaster` `blaster {target}`|Times the target user out for 60 seconds|`!blast, !blaster`
`silverbullet {target}`|Times the target user out for 24 hours|`!execute, !silverbullet` `silverbullet {target}`|Times the target user out for 24 hours|`!execute, !silverbullet`
`revive {target}`|Reduce timeout timer of target by 30 seconds|`!revive, !heal`
`superrevive {target}`|Reduce timeout timer of target by 12|`!superrevive, !superheal`
`grenade`|Times a random chatter out for 60 seconds|`!grenade` `grenade`|Times a random chatter out for 60 seconds|`!grenade`
`tnt`|Times out 1 to 10 chatters for 60 seconds|`!tnt` `tnt`|Times out 1 to 10 chatters for 60 seconds|`!tnt`
`lootbox`|Gives the user some qbucks, and possibly some items|`!lootbox` `lootbox`|Gives the user some qbucks, and possibly some items|`!lootbox`

View File

@@ -11,6 +11,8 @@ for (const item of items) {
switch (item.name) { switch (item.name) {
case 'blaster': case 'blaster':
case 'silverbullet': case 'silverbullet':
case 'revive':
case 'superrevive':
if (params[0] === undefined) { await say('nice miss bro'); return } if (params[0] === undefined) { await say('nice miss bro'); return }
await item.execute(user!, say, broadcasterId, params[0].replace(/[@]/g, '')) await item.execute(user!, say, broadcasterId, params[0].replace(/[@]/g, ''))
break break

View File

@@ -5,5 +5,5 @@ export default createBotCommand('iteminfo', async (params, { say }) => {
if (params[0] === undefined) { await say('No item specified!'); return } if (params[0] === undefined) { await say('No item specified!'); return }
const selection = items.find(item => item.aliases.includes(params[0].toLowerCase())) const selection = items.find(item => item.aliases.includes(params[0].toLowerCase()))
if (!selection) { await say('Item not found'); return } if (!selection) { await say('Item not found'); return }
await say(selection[1].description) await say(selection.description)
}, { aliases: ['item'] }) }, { aliases: ['item'] })

View File

@@ -1,11 +1,9 @@
import { createBotCommand } from "@twurple/easy-bot"; import { createBotCommand } from "@twurple/easy-bot";
import api, { broadcasterApi } from "../lib/api"; import api, { broadcasterApi } from "../lib/api";
import { MODS } from "../lib/timeoutHelper";
const MODS = process.env.MODS
if (!MODS) { console.error("Please set the MODS environment variable."); process.exit(1) }
export default createBotCommand('modme', async (_params, { userName, broadcasterId, userId }) => { export default createBotCommand('modme', async (_params, { userName, broadcasterId, userId }) => {
if (!MODS.includes(userName)) return if (!MODS!.includes(userName)) return
if (broadcasterApi) await broadcasterApi.moderation.addModerator(broadcasterId, userId) if (broadcasterApi) await broadcasterApi.moderation.addModerator(broadcasterId, userId)
else await api.moderation.addModerator(broadcasterId, userId) else await api.moderation.addModerator(broadcasterId, userId)

View File

@@ -13,6 +13,8 @@ export default createBotCommand('use', async (params, { say, broadcasterId, user
switch (selection.name) { switch (selection.name) {
case 'blaster': case 'blaster':
case 'silverbullet': case 'silverbullet':
case 'revive':
case 'superrevive':
if (params[1] === undefined) { await say('nice miss bro'); return } if (params[1] === undefined) { await say('nice miss bro'); return }
await selection.execute(user!, say, broadcasterId, params[1].replace(/[@]/g, '')) await selection.execute(user!, say, broadcasterId, params[1].replace(/[@]/g, ''))
break break

View File

@@ -17,7 +17,7 @@ export const blaster = {
if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no blasters!'); return } if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no blasters!'); return }
const result = await timeout(broadcasterId, target!, 60, `You got blasted by ${user.name}`) const result = await timeout(broadcasterId, target, 60, `You got blasted by ${user.name}`)
if (result.status) { if (result.status) {
await say(`${targetname} got blasted by ${user.name}! ${user.name} has ${itemResult.count} blaster${itemResult.count === 1 ? '' : 's'} remaining`) await say(`${targetname} got blasted by ${user.name}! ${user.name} has ${itemResult.count} blaster${itemResult.count === 1 ? '' : 's'} remaining`)
await addTimeoutToDB(user, target!, 'blaster') await addTimeoutToDB(user, target!, 'blaster')
@@ -52,7 +52,7 @@ export const silverbullet = {
const itemResult = await changeItemCount(user, 'silverbullet') const itemResult = await changeItemCount(user, 'silverbullet')
if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no silver bullets!'); return } if (!itemResult.result && itemResult.reason === 'negative') { await say('You have no silver bullets!'); return }
const result = await timeout(broadcasterId, target!, 60 * 60 * 24, `You got hit by a silver bullet fired by ${user.name}`) const result = await timeout(broadcasterId, target, 60 * 60 * 24, `You got hit by a silver bullet fired by ${user.name}`)
if (result.status) { if (result.status) {
await say(`${target?.name} got deleted.`) await say(`${target?.name} got deleted.`)
await addTimeoutToDB(user, target!, 'silverbullet') await addTimeoutToDB(user, target!, 'silverbullet')

View File

@@ -2,6 +2,7 @@ import { HelixUser } from "@twurple/api"
import { blaster, silverbullet } from "./blasters" import { blaster, silverbullet } from "./blasters"
import { grenade, tnt } from "./explosives" import { grenade, tnt } from "./explosives"
import { revive, superrevive } from "./revives"
import { lootbox } from "./lootbox" import { lootbox } from "./lootbox"
import { clipboard } from "./clipboard" import { clipboard } from "./clipboard"
@@ -13,6 +14,6 @@ interface item {
description: string, description: string,
execute: (user: HelixUser, say: (args0: string) => Promise<void>, broadcasterId?: string, targetname?: string) => Promise<void> execute: (user: HelixUser, say: (args0: string) => Promise<void>, broadcasterId?: string, targetname?: string) => Promise<void>
} }
const data = [blaster, silverbullet, grenade, tnt, lootbox, clipboard] as item[] const data = [blaster, silverbullet, grenade, tnt, revive, superrevive, lootbox, clipboard] as item[]
export const ITEMS = data.map(item => item.name) export const ITEMS = data.map(item => item.name)
export default data export default data

73
src/items/revives.ts Normal file
View File

@@ -0,0 +1,73 @@
import { HelixUser } from "@twurple/api"
import api from "../lib/api"
import { changeItemCount } from "../lib/items"
import { reviveTarget } from "../lib/timeoutHelper"
import { addUsedItem, updateInventory } from "../lib/userHelper"
export const revive = {
name: 'revive',
prettyname: 'Revive',
aliases: ['revive', 'heal'],
plural: 's',
description: "Use: revive {target}, Function: Reduce timeout timer of target by 30 seconds. Aliases: !revive, !heal",
execute: async (user: HelixUser, say: (arg0: string) => Promise<void>, broadcasterId: string, targetname: string) => {
const target = await api.users.getUserByName(targetname)
const itemResult = await changeItemCount(user, 'revive')
if (!itemResult.result) { await say('You have no revives!'); return }
const reviveResult = await reviveTarget(broadcasterId, target, 30)
if (reviveResult.status) { await updateInventory(user, itemResult.inv!); await addUsedItem(target!, 'revive') }
switch (reviveResult.reason) {
case 'noexist':
await say(`${targetname} does not exist`)
break
case 'notbanned':
await say(`${targetname} doesn't need revives`)
break
case 'unknown':
await say("Something went wrong!")
break
case 'healed':
await say(`${targetname} got healed for 30 seconds by ${user.name}`)
break
case 'revived':
await say(`${targetname} got revived by ${user.name}`)
break
}
}
}
export const superrevive = {
name: 'superrevive',
prettyname: 'Super Revive',
aliases: ['superrevive', 'superheal'],
plural: 's',
description: "Use: superrevive {target}, Function: Reduce timeout timer of target by 12 hours. Aliases: !superrevive, !superheal",
execute: async (user: HelixUser, say: (arg0: string) => Promise<void>, broadcasterId: string, targetname: string) => {
const target = await api.users.getUserByName(targetname)
const itemResult = await changeItemCount(user, 'superrevive')
if (!itemResult.result) { await say('You have no revives!'); return }
const reviveResult = await reviveTarget(broadcasterId, target, 60 * 60 * 12)
if (reviveResult.status) { await updateInventory(user, itemResult.inv!); await addUsedItem(target!, 'superrevive') }
switch (reviveResult.reason) {
case 'noexist':
await say(`${targetname} does not exist`)
break
case 'notbanned':
await say(`${targetname} doesn't need revives`)
break
case 'unknown':
await say("Something went wrong!")
break
case 'healed':
await say(`${targetname} got healed for 12 hours by ${user.name}`)
break
case 'revived':
await say(`${targetname} got revived by ${user.name}`)
break
}
}
}

View File

@@ -3,6 +3,10 @@ import api, { broadcasterApi } from "./api";
import pb from "./pocketbase"; import pb from "./pocketbase";
import { DBValidation } from "./userHelper"; import { DBValidation } from "./userHelper";
const MODSSTRING = process.env.MODS
if (!MODSSTRING) { console.error("Please set the MODS environment variable."); process.exit(1) }
export const MODS = MODSSTRING.split(',')
type shooter = 'blaster' | 'grenade' | 'silverbullet' | 'tnt' type shooter = 'blaster' | 'grenade' | 'silverbullet' | 'tnt'
interface statusmessage { interface statusmessage {
@@ -13,7 +17,7 @@ interface statusmessage {
/** Ban a specific user out by another user for specified amout of time, with specific reason /** Ban a specific user out by another user for specified amout of time, with specific reason
* If the user does not exist or is already banned return status: false * If the user does not exist or is already banned return status: false
* If the user is a moderator, make sure they get their status back after timeout has elapsed */ * If the user is a moderator, make sure they get their status back after timeout has elapsed */
export async function timeout(broadcasterid: string, target: HelixUser, duration: number, reason: string): Promise<statusmessage> { export async function timeout(broadcasterid: string, target: HelixUser|null, duration: number, reason: string): Promise<statusmessage> {
if (!target) return { status: false, reason: 'noexist' } if (!target) return { status: false, reason: 'noexist' }
const tmpapi = broadcasterApi ?? api const tmpapi = broadcasterApi ?? api
if (target.name === process.env.BOT_NAME) return { status: false, reason: 'unknown' } if (target.name === process.env.BOT_NAME) return { status: false, reason: 'unknown' }
@@ -33,6 +37,29 @@ export async function timeout(broadcasterid: string, target: HelixUser, duration
} }
} }
/** Revive a specific target for a certain amount of time */
export async function reviveTarget(broadcasterId: string, target: HelixUser|null, duration: number): Promise<statusmessage> {
if (!target) return { status: false, reason: 'noexist' }
const tmpapi = broadcasterApi ?? api
const bandata = await tmpapi.moderation.getBannedUsers(broadcasterId, { userId: target.id })
if (!bandata.data[0]) return { status: false, reason: 'notbanned' }
const newduration = Math.floor((Date.parse(bandata.data[0].expiryDate?.toString()!) - Date.now()) / 1000 - duration) // (timestamp to freedom - current timestamp) / 1000 (to seconds) - duration
try {
if (newduration < 3) { // If the target is going to be unbanned in duration + 3 seconds, unban them anyway
await tmpapi.moderation.unbanUser(broadcasterId, target)
if (MODS.includes(target.name)) remodMod(broadcasterId, target, 0, tmpapi)
return {status: true, reason: 'revived'}
} else {
await tmpapi.moderation.banUser(broadcasterId, { duration: newduration, reason: bandata.data[0].reason!, user: target })
if (MODS.includes(target.name)) remodMod(broadcasterId, target, newduration * 1000 , tmpapi)
return { status: true, reason: 'healed' }
}
} catch (err) {
console.error(err)
return { status: false, reason: 'unknown' }
}
}
/** Add an entry to the timeouts table */ /** Add an entry to the timeouts table */
export async function addTimeoutToDB(attacker: HelixUser, target: HelixUser, source: shooter) { export async function addTimeoutToDB(attacker: HelixUser, target: HelixUser, source: shooter) {
// This has passed the existance check so there's no need to check if the users exist (twitch) // This has passed the existance check so there's no need to check if the users exist (twitch)