diff --git a/src/commands/itemAliases.ts b/src/commands/itemAliases.ts index d3c7660..6c70ff6 100644 --- a/src/commands/itemAliases.ts +++ b/src/commands/itemAliases.ts @@ -11,6 +11,8 @@ for (const item of items) { switch (item.name) { case 'blaster': case 'silverbullet': + case 'revive': + case 'superrevive': if (params[0] === undefined) { await say('nice miss bro'); return } await item.execute(user!, say, broadcasterId, params[0].replace(/[@]/g, '')) break diff --git a/src/commands/modme.ts b/src/commands/modme.ts index 2a09b6b..273c07c 100644 --- a/src/commands/modme.ts +++ b/src/commands/modme.ts @@ -1,11 +1,9 @@ import { createBotCommand } from "@twurple/easy-bot"; import api, { broadcasterApi } from "../lib/api"; - -const MODS = process.env.MODS -if (!MODS) { console.error("Please set the MODS environment variable."); process.exit(1) } +import { MODS } from "../lib/timeoutHelper"; 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) else await api.moderation.addModerator(broadcasterId, userId) diff --git a/src/commands/use.ts b/src/commands/use.ts index 0532bc0..23eaac1 100644 --- a/src/commands/use.ts +++ b/src/commands/use.ts @@ -13,6 +13,8 @@ export default createBotCommand('use', async (params, { say, broadcasterId, user switch (selection.name) { case 'blaster': case 'silverbullet': + case 'revive': + case 'superrevive': if (params[1] === undefined) { await say('nice miss bro'); return } await selection.execute(user!, say, broadcasterId, params[1].replace(/[@]/g, '')) break diff --git a/src/items/blasters.ts b/src/items/blasters.ts index f8a4ee1..d6fcdec 100644 --- a/src/items/blasters.ts +++ b/src/items/blasters.ts @@ -17,7 +17,7 @@ export const blaster = { 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) { await say(`${targetname} got blasted by ${user.name}! ${user.name} has ${itemResult.count} blaster${itemResult.count === 1 ? '' : 's'} remaining`) await addTimeoutToDB(user, target!, 'blaster') @@ -52,7 +52,7 @@ export const silverbullet = { const itemResult = await changeItemCount(user, 'silverbullet') 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) { await say(`${target?.name} got deleted.`) await addTimeoutToDB(user, target!, 'silverbullet') diff --git a/src/items/index.ts b/src/items/index.ts index 169e601..85cefdf 100644 --- a/src/items/index.ts +++ b/src/items/index.ts @@ -2,6 +2,7 @@ import { HelixUser } from "@twurple/api" import { blaster, silverbullet } from "./blasters" import { grenade, tnt } from "./explosives" +import { revive, superrevive } from "./revives" import { lootbox } from "./lootbox" import { clipboard } from "./clipboard" @@ -13,6 +14,6 @@ interface item { description: string, execute: (user: HelixUser, say: (args0: string) => Promise, broadcasterId?: string, targetname?: string) => Promise } -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 default data diff --git a/src/items/revives.ts b/src/items/revives.ts new file mode 100644 index 0000000..14945c3 --- /dev/null +++ b/src/items/revives.ts @@ -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: "", + execute: async (user: HelixUser, say: (arg0: string) => Promise, 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: "", + execute: async (user: HelixUser, say: (arg0: string) => Promise, 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 + } + } +} diff --git a/src/lib/timeoutHelper.ts b/src/lib/timeoutHelper.ts index 2d03bd2..c9cf5b1 100644 --- a/src/lib/timeoutHelper.ts +++ b/src/lib/timeoutHelper.ts @@ -3,6 +3,10 @@ import api, { broadcasterApi } from "./api"; import pb from "./pocketbase"; 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' interface statusmessage { @@ -13,7 +17,7 @@ interface statusmessage { /** 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 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 { +export async function timeout(broadcasterid: string, target: HelixUser|null, duration: number, reason: string): Promise { if (!target) return { status: false, reason: 'noexist' } const tmpapi = broadcasterApi ?? api 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 { + 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 = (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 */ 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)