added item shop, nerf lootbox, fix bugs

This commit is contained in:
2025-09-19 02:06:18 +02:00
parent 6a76c52acc
commit 9ce00d7a11
16 changed files with 171 additions and 93 deletions

View File

@@ -64,6 +64,8 @@ When using/giving an item or qbucks the itemlock will be set at the start of the
Admins can toggle the itemlock on chatters with the [`itemlock`](#administrative-commands) command. This will stop a chatter from giving, receiving and using items and qweribucks.
It will NOT stop them from using items by cheering, but if that cheer item usage fails, they will not be given an equivalent item as compensation.
The only ways to get items is through the `getloot` command or by buying them with qbucks.
Items can be used with the alias as a command (example: `blast qwerinope`) or with the [`use` command](#qweribucksitem-commands).
When an Item is used it is removed from the inventory of the chatter.
@@ -78,10 +80,10 @@ ITEM|RATE
`grenade`|`1/5`
`blaster`|`1/5`
`tnt`|`1/20`
`silver bullet`|`1/250`
`silver bullet`|`1/1000`
Each of these rates get pulled 5 times, then the result is added to your inventory.
It's theoretically possible to get 5 of each item.
Each of these rates get pulled 3 times, then the result is added to your inventory.
It's theoretically possible to get 3 of each item.
### Chatterbot/streamerbot
@@ -104,24 +106,25 @@ COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE
`seiso`|Get a seiso rating|anyone|`seiso`|:white_check_mark:
`backshot`|'Backshot' a random previous chatter|anyone|`backshot`|:white_check_mark:
`roulette`|Play russian roulette for a 5 minute timeout|anyone|`roulette`|:white_check_mark:
`timeout {target}`|Times targeted user out for 60 seconds (costs 100 qweribucks)|anyone|`timeout`|:white_check_mark:
`stats [target]`|Get timeout and some item stats for yourself or specified user this month|anyone|`stats` `monthlystats`|:white_check_mark:
`alltime [target]`|Get timeout and some item stats for yourself or specified user of all time|anyone|`alltime` `alltimestats`|:white_check_mark:
`monthlyleaderboard`|Get the K/D leaderboard for this month [(info)](#leaderboards)|anyone|`monthlyleaderboard` `kdleaderboard` `leaderboard`|:white_check_mark:
`alltimeleaderboard`|Get the K/D leaderboard of all time [(info)](#leaderboards)|anyone|`alltimeleaderboard` `alltimekdleaderboard`|:white_check_mark:
`qbucksleaderboard`|Get the current qbucks leaderboard [(info)](#leaderboards)|anyone|`qbucksleaderboard` `moneyleaderboard` `baltop`|:white_check_mark:
### Qweribucks/Item commands
COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE
-|-|-|-|-
`getloot`|Get a random assortment of items and qbucks every 10 minutes. [(drop rates)](#lootbox)|anyone|`getloot` `loot` `dig`|:white_check_mark:
`getbalance [target]`|Get balance of target or self|anyone|`getbalance` `balance` `qbucks` `qweribucks` `wallet` `getwallet`|:white_check_mark:
`donate {target} {amount}`|Give the targeted user some or all of your qweribucks|anyone|`donate`|:white_check_mark:
`iteminfo {item}`|Get item function and aliases|anyone|`iteminfo` `itemhelp` `info`|:white_check_mark:
`inventory [target]`|Get inventory contents of target or self|anyone|`inventory` `inv` `pocket`|:white_check_mark:
`getprices`|Get the current price of items in the shop|anyone|`getprices` `prices` `shop`|:white_check_mark:
`buyitem {item} [amount]`|Buy one or more items for some qbucks. Prices are [here](#items)|anyone|`buyitem` `buy` `purchase`|:white_check_mark:
`getbalance [target]`|Get balance of target or self|anyone|`getbalance` `balance` `qbucks` `qweribucks` `wallet` `getwallet`|:white_check_mark:
`give {target} {item} {amount}`|Give targeted user amount of items|anyone|`give`|:white_check_mark:
`donate {target} {amount}`|Give the targeted user some or all of your qweribucks|anyone|`donate`|:white_check_mark:
`use {item} ...`|Use item. More info at [The items section](#items)|anyone|`use`|:x:
`monthlyleaderboard`|Get the K/D leaderboard for this month [(info)](#leaderboards)|anyone|`monthlyleaderboard` `kdleaderboard` `leaderboard`|:white_check_mark:
`alltimeleaderboard`|Get the K/D leaderboard of all time [(info)](#leaderboards)|anyone|`alltimeleaderboard` `alltimekdleaderboard`|:white_check_mark:
`qbucksleaderboard`|Get the current qbucks leaderboard [(info)](#leaderboards)|anyone|`qbucksleaderboard` `moneyleaderboard` `baltop`|:white_check_mark:
`admindonate {target} {amount}`|Gives the targeted user amount of qweribucks|admins|`admindonate`|:white_check_mark:
`admingive {target} {item} {amount}`|Give targeted user amount of new items|admins|`admingive`|:white_check_mark:
@@ -149,12 +152,12 @@ COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE
## Items
NAME|COMMAND|FUNCTION|ALIASES
-|-|-|-
Blaster|`blaster {target}`|Times targeted user out for 60 seconds|`blaster` `blast`
Silver Bullet|`silverbullet {target}`|Times targeted user out for 24 hours|`silverbullet` `execute` `{blastin}`
Grenade|`grenade`|Times a random vulnerable chatter out for 60 seconds|`grenade`
TNT|`tnt`|Give 5-10 random chatters 60 second timeouts|`tnt`
NAME|COMMAND|FUNCTION|ALIASES|COST
-|-|-|-|-
Blaster|`blaster {target}`|Times targeted user out for 60 seconds|`blaster` `blast`|100
Silver Bullet|`silverbullet {target}`|Times targeted user out for 24 hours|`silverbullet` `execute` `{blastin}`|6666
Grenade|`grenade`|Times a random vulnerable chatter out for 60 seconds|`grenade`|99
TNT|`tnt`|Give 5-10 random chatters 60 second timeouts|`tnt`|1000
## Cheers

View File

@@ -31,14 +31,12 @@ export default cheers;
export { namedcheers };
import { sendMessage } from 'commands';
import logger from 'lib/logger';
import { getUserRecord } from 'db/dbUser';
import { changeItemCount, type items } from 'items';
export async function handleNoTarget(msg: EventSubChannelChatMessageEvent, user: User, itemname: items, silent = true) {
if (await user.itemLock()) {
await sendMessage(`Cannot give ${user.displayName} a ${itemname}`, msg.messageId);
logger.err(`Failed to give ${user.displayName} a ${itemname} for their cheer`);
await sendMessage(`Cannot give ${user.displayName} a ${itemname} (itemlock)`, msg.messageId);
return;
};
await user.setLock();

View File

@@ -17,7 +17,7 @@ export default new Command({
if (!args[1]) { await sendMessage('Please specify the amount qweribucks you want to give', msg.messageId); return; };
const amount = parseInt(args[1]);
if (isNaN(amount)) { await sendMessage(`'${args[1]}' is not a valid amount`); return; };
if (await target.itemLock()) { await sendMessage('Cannot give qweribucks: item lock is set', msg.messageId); return; };
if (await target.itemLock()) { await sendMessage('Cannot give qweribucks (itemlock)', msg.messageId); return; };
await target.setLock();
const data = await changeBalance(target, userRecord, amount);
if (!data) {

View File

@@ -20,7 +20,7 @@ export default new Command({
if (!args[2]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; };
const amount = parseInt(args[2]);
if (isNaN(amount)) { await sendMessage(`'${args[2]}' is not a valid amount`); return; };
if (await target.itemLock()) { await sendMessage('Cannot give item: item lock is set', msg.messageId); return; };
if (await target.itemLock()) { await sendMessage('Cannot give item (itemlock)', msg.messageId); return; };
await target.setLock();
const data = await changeItemCount(target, userRecord, item.name, amount);
if (data) {

37
src/commands/buyitem.ts Normal file
View File

@@ -0,0 +1,37 @@
import { Command, sendMessage } from "commands";
import parseCommandArgs from "lib/parseCommandArgs";
import items from "items";
import { getUserRecord, updateUserRecord } from "db/dbUser";
export default new Command({
name: 'buyitem',
aliases: ['buyitem', 'buy', 'purchase'],
usertype: 'chatter',
execution: async (msg, user) => {
const args = parseCommandArgs(msg.messageText);
if (!args[0]) { await sendMessage(`Specify the item you'd like to buy`, msg.messageId); return; };
const selecteditem = items.get(args[0].toLowerCase());
if (!selecteditem) { await sendMessage(`'${args[0]}' is not a valid item`, msg.messageId); return; };
const amount = args[1] ? parseInt(args[1]) : 1;
if (isNaN(amount) || amount < 1) { await sendMessage(`'${args[1]}' is not a valid amount to buy`, msg.messageId); return; };
const totalcost = amount * selecteditem.price;
if (await user.itemLock()) { await sendMessage('Cannot buy item (itemlock)', msg.messageId); return; };
await user.setLock();
const userRecord = await getUserRecord(user);
if (userRecord.balance < totalcost) { await sendMessage(`You don't have enough qbucks to buy ${amount} ${selecteditem.prettyName}${amount === 1 ? '' : selecteditem.plural}! You have ${userRecord.balance}, need ${totalcost}`); await user.clearLock(); return; };
if (userRecord.inventory[selecteditem.name]) userRecord.inventory[selecteditem.name]! += amount
else userRecord.inventory[selecteditem.name] = amount;
userRecord.balance -= totalcost;
await Promise.all([
updateUserRecord(user, userRecord),
sendMessage(`${user.displayName} bought ${amount} ${selecteditem.prettyName}${amount === 1 ? '' : selecteditem.plural} for ${totalcost} qbucks. They now have ${userRecord.inventory[selecteditem.name]} ${selecteditem.prettyName}${userRecord.inventory[selecteditem.name] === 1 ? '' : selecteditem.plural} and ${userRecord.balance} qbucks`, msg.messageId)
]);
await user.clearLock();
}
});

View File

@@ -1,5 +1,4 @@
import { Command, sendMessage } from "commands";
import type { userRecord } from "db/connection";
import { getUserRecord } from "db/dbUser";
import parseCommandArgs from "lib/parseCommandArgs";
import { changeBalance } from "lib/changeBalance";
@@ -24,7 +23,7 @@ export default new Command({
const userRecord = await getUserRecord(user);
if (userRecord.balance < amount) { await sendMessage(`You can't give qweribucks you don't have!`, msg.messageId); return; };
if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give qweribucks', msg.messageId); return; };
if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give qweribucks (itemlock)', msg.messageId); return; };
await Promise.all([
user.setLock(),
@@ -37,7 +36,7 @@ export default new Command({
]);
if (!data.includes(false)) {
const { balance: newamount } = data[0] as userRecord;
const { balance: newamount } = data[0];
await sendMessage(`${user.displayName} gave ${amount} qweribuck${amount === 1 ? '' : 's'} to ${target.displayName}. They now have ${newamount} qweribuck${newamount === 1 ? '' : 's'}`, msg.messageId);
} else {
// TODO: Rewrite this section

View File

@@ -49,14 +49,13 @@ export default new Command({
grenade: 0,
blaster: 0,
tnt: 0,
silverbullet: 0
};
for (let i = 0; i < 5; i++) {
for (let i = 0; i < 3; i++) {
if (Math.floor(Math.random() * 5) === 0) itemDiff.grenade! += 1;
if (Math.floor(Math.random() * 5) === 0) itemDiff.blaster! += 1;
if (Math.floor(Math.random() * 25) === 0) itemDiff.tnt! += 1;
if (Math.floor(Math.random() * 250) === 0) itemDiff.silverbullet! += 1;
if (Math.floor(Math.random() * 1000) === 0) itemDiff.silverbullet! += 1;
};
for (const [item, amount] of Object.entries(itemDiff) as [items, number][]) {

12
src/commands/getprices.ts Normal file
View File

@@ -0,0 +1,12 @@
import { Command, sendMessage } from "commands";
import { itemObjectArray } from "items";
export default new Command({
name: 'getprices',
aliases: ['getprices', 'prices', 'shop'],
usertype: 'chatter',
execution: async msg => {
const txt = itemObjectArray.toSorted((a, b) => a.price - b.price).map(item => `${item.prettyName}: ${item.price}`);
await sendMessage(`Prices: ${txt.join(' | ')}`, msg.messageId);
}
});

View File

@@ -1,5 +1,4 @@
import { Command, sendMessage } from "commands";
import type { userRecord } from "db/connection";
import { getUserRecord } from "db/dbUser";
import items, { changeItemCount } from "items";
import parseCommandArgs from "lib/parseCommandArgs";
@@ -26,7 +25,7 @@ export default new Command({
const userRecord = await getUserRecord(user);
if (userRecord.inventory[item.name]! < amount) { await sendMessage(`You can't give items you don't have!`, msg.messageId); return; };
if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give item', msg.messageId); return; };
if (await user.itemLock() || await target.itemLock()) { await sendMessage('Cannot give item (itemlock)', msg.messageId); return; };
await Promise.all([
user.setLock(),
@@ -38,14 +37,14 @@ export default new Command({
await changeItemCount(user, userRecord, item.name, -amount)
]);
if (!data.includes(false)) {
const tempdata = data[0] as userRecord;
if (data[0] !== false && data[1] !== false) {
const tempdata = data[0];
const newamount = tempdata.inventory[item.name]!;
await sendMessage(`${user.displayName} gave ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)} to ${target.displayName}. They now have ${newamount} ${item.prettyName + (newamount === 1 ? '' : item.plural)}`, msg.messageId);
} else {
// TODO: Rewrite this section
await sendMessage(`Failed to give ${target.displayName} ${amount} ${item.prettyName + (amount === 1 ? '' : item.plural)}`, msg.messageId);
logger.warn(`WARNING: Item donation failed: target success: ${data[0] !== false}, donator success: ${data[1] !== false}`);
logger.warn(`WARNING: Item donation failed: target success: ${data[0] !== false ? "yes" : "no"}, donator success: ${data[1] !== false ? "yes" : "no"}`);
};
await user.clearLock();
await target.clearLock();

View File

@@ -1,46 +0,0 @@
import { Command, sendMessage } from "commands";
import { getUserRecord } from "db/dbUser";
import parseCommandArgs from "lib/parseCommandArgs";
import User from "user";
import { timeout } from "lib/timeout";
import { changeBalance } from "lib/changeBalance";
import { createTimeoutRecord } from "db/dbTimeouts";
export default new Command({
name: 'timeout',
aliases: ['timeout'],
usertype: 'chatter',
execution: async (msg, user) => {
const userObj = await getUserRecord(user);
if (userObj.balance < 100) { await sendMessage(`You don't have enough qweribucks (need 100, have ${userObj.balance})`, msg.messageId); return; };
const messagequery = parseCommandArgs(msg.messageText);
if (!messagequery[0]) { await sendMessage('Please specify a target'); return; };
const target = await User.initUsername(messagequery[0].toLowerCase());
if (!target) { await sendMessage(`${messagequery[0]} doesn't exist`); return; };
await getUserRecord(target); // make sure the user record exist in the database
const result = await timeout(target, `You got BLASTED by ${user.displayName}`, 60);
if (result.status) {
await Promise.all([
sendMessage(`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`),
changeBalance(user, userObj, -100),
createTimeoutRecord(user, target, 'blaster')
]);
} else {
switch (result.reason) {
case "banned":
await sendMessage(`${target.displayName} is already timed out/banned`, msg.messageId);
break;
case "illegal":
await Promise.all([
sendMessage(`${user.displayName} Nou Nou Nou`),
timeout(user, 'nah', 60)
]);
break;
case "unknown":
await sendMessage('Something went wrong...', msg.messageId);
break;
};
};
}
});

View File

@@ -16,17 +16,20 @@ export default new Item({
plural: 's',
description: 'Times a specific person out for 60 seconds',
aliases: ['blaster', 'blast'],
price: 100,
execution: async (msg, user) => {
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any blasters!`, msg.messageId); return; };
const messagequery = parseCommandArgs(msg.messageText);
if (!messagequery[0]) { await sendMessage('Please specify a target'); return; };
const target = await User.initUsername(messagequery[0].toLowerCase());
if (!target) { await sendMessage(`${messagequery[0]} doesn't exist`); return; };
await getUserRecord(target); // make sure the user record exist in the database
if (await user.itemLock()) { await sendMessage('Cannot use an item right now', msg.messageId); return; };
if (await user.itemLock()) { await sendMessage('Cannot use an item (itemlock)', msg.messageId); return; };
await user.setLock();
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any blasters!`, msg.messageId); await user.clearLock(); return; };
const result = await timeout(target, `You got blasted by ${user.displayName}!`, 60);
if (result.status) await Promise.all([
sendMessage(`GOTTEM ${target.displayName} got BLASTED by ${user.displayName} GOTTEM`),

View File

@@ -16,9 +16,8 @@ export default new Item({
plural: 's',
description: 'Give a random chatter a 60s timeout',
aliases: ['grenade'],
price: 99,
execution: async (msg, user) => {
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any grenades!`, msg.messageId); return; };
const targets = await redis.keys(`user:*:vulnerable`);
if (targets.length === 0) { await sendMessage('No vulnerable chatters to blow up', msg.messageId); return; };
const selection = targets[Math.floor(Math.random() * targets.length)]!;
@@ -26,8 +25,12 @@ export default new Item({
await getUserRecord(target!); // make sure the user record exist in the database
if (await user.itemLock()) { await sendMessage('Cannot use an item right now', msg.messageId); return; };
if (await user.itemLock()) { await sendMessage('Cannot use an item (itemlock)', msg.messageId); return; };
await user.setLock();
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any grenades!`, msg.messageId); await user.clearLock(); return; };
await Promise.all([
timeout(target!, `You got hit by ${user.displayName}'s grenade!`, 60),
sendMessage(`wybuh ${target?.displayName} got hit by ${user.displayName}'s grenade wybuh`),

View File

@@ -10,6 +10,7 @@ type itemOptions = {
description: string;
execution: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise<void>;
specialaliases?: string[];
price: number;
};
export class Item {
@@ -20,6 +21,7 @@ export class Item {
public readonly aliases: string[];
public readonly specialaliases: string[];
public readonly usertype: userType;
public readonly price: number;
public readonly execute: (message: EventSubChannelChatMessageEvent, sender: User, args?: specialExecuteArgs) => Promise<void>;
public readonly disableable: boolean;
@@ -34,12 +36,14 @@ export class Item {
this.execute = options.execution;
this.disableable = true;
this.specialaliases = options.specialaliases ?? [];
this.price = options.price;
};
};
import { readdir } from 'node:fs/promises';
import { updateUserRecord, type inventoryUpdate } from "db/dbUser";
const itemMap = new Map<string, Item>;
const itemAliasMap = new Map<string, Item>;
const itemObjectArray: Item[] = []
const specialAliasItems = new Map<string, Item>;
const emptyInventory: inventory = {};
const itemarray: items[] = [];
@@ -51,16 +55,17 @@ for (const file of files) {
const item: Item = await import(import.meta.dir + '/' + file.slice(0, -3)).then(a => a.default);
emptyInventory[item.name] = 0;
itemarray.push(item.name);
itemObjectArray.push(item);
for (const alias of item.aliases) {
itemMap.set(alias, item); // Since it's not a primitive type the map is filled with references to the item, not the actual object
itemAliasMap.set(alias, item); // Since it's not a primitive type the map is filled with references to the item, not the actual object
};
for (const alias of item.specialaliases) {
specialAliasItems.set(alias, item);
};
};
export default itemMap;
export { emptyInventory, itemarray, specialAliasItems };
export default itemAliasMap;
export { emptyInventory, itemarray, specialAliasItems, itemObjectArray };
export type items = "blaster" | "silverbullet" | "grenade" | "tnt";
export type inventory = {

View File

@@ -17,17 +17,20 @@ export default new Item({
description: 'Times a specific person out for 24 hours',
aliases: ['execute', 'silverbullet'],
specialaliases: ['blastin'],
price: 6666,
execution: async (msg, user, specialargs) => {
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any silver bullets!`, msg.messageId); return; };
const messagequery = parseCommandArgs(msg.messageText, specialargs?.activation);
if (!messagequery[0]) { await sendMessage('Please specify a target'); return; };
const target = await User.initUsername(messagequery[0].toLowerCase());
if (!target) { await sendMessage(`${messagequery[0]} doesn't exist`); return; };
await getUserRecord(target); // make sure the user record exist in the database
if (await user.itemLock()) { await sendMessage('Cannot use an item right now', msg.messageId); return; };
if (await user.itemLock()) { await sendMessage('Cannot use an item (itemlock)', msg.messageId); return; };
await user.setLock();
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any silver bullets!`, msg.messageId); await user.clearLock(); return; };
const result = await timeout(target, `You got blasted by ${user.displayName}!`, 60 * 60 * 24);
if (result.status) await Promise.all([
sendMessage(`${target.displayName} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`),

View File

@@ -16,16 +16,18 @@ export default new Item({
plural: 's',
description: 'Give 5-10 random chatters 60 second timeouts',
aliases: ['tnt'],
price: 1000,
execution: async (msg, user) => {
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any TNTs!`, msg.messageId); return; };
const vulntargets = await redis.keys('user:*:vulnerable').then(a => a.map(b => b.slice(5, -11)));
if (vulntargets.length === 0) { await sendMessage('No vulnerable chatters to blow up', msg.messageId); return; };
const targets = getTNTTargets(vulntargets);
if (await user.itemLock()) { await sendMessage('Cannot use an item right now', msg.messageId); return; };
if (await user.itemLock()) { await sendMessage('Cannot use an item (itemlock)', msg.messageId); return; };
await user.setLock();
const userObj = await getUserRecord(user);
if (userObj.inventory[ITEMNAME]! < 1) { await sendMessage(`You don't have any TNTs!`, msg.messageId); await user.clearLock(); return; };
await Promise.all(targets.map(async targetid => {
const target = await User.initUserId(targetid);
await getUserRecord(target!); // make sure the user record exist in the database

61
src/migrate.ts Normal file
View File

@@ -0,0 +1,61 @@
import PocketBase from "pocketbase";
import { type inventory, type items } from "items"
const pb = new PocketBase('qweribot-main:8091');
import db from "db/connection";
import * as schema from "db/schema";
export type userRecord = {
id: string;
username: string;
balance: number;
inventory: inventory;
lastlootbox: string;
};
export type usedItemRecord = {
id?: string;
user: string;
item: items;
created: string;
};
export type timeoutRecord = {
id?: string;
user: string;
target: string;
item: items;
created: string;
};
const pbusers = await pb.collection<userRecord>('users').getFullList();
for (const pbuser of pbusers) {
await db.insert(schema.users).values({
id: parseInt(pbuser.id),
username: pbuser.username,
balance: pbuser.balance,
inventory: pbuser.inventory,
lastlootbox: new Date(Date.parse(pbuser.lastlootbox))
});
console.log(`Migrated users row of ${pbuser.username} to the new database`)
};
const pbuseditems = await pb.collection<usedItemRecord>('usedItems').getFullList();
for (const pbuseditem of pbuseditems) {
await db.insert(schema.usedItems).values({
user: parseInt(pbuseditem.user),
item: pbuseditem.item,
created: new Date(Date.parse(pbuseditem.created))
});
console.log(`Migrated usedItem row of user: ${pbuseditem.user} and item: ${pbuseditem.item} to the new database`)
};
const pbtimeouts = await pb.collection<timeoutRecord>('timeouts').getFullList();
for (const pbtimeout of pbtimeouts) {
await db.insert(schema.timeouts).values({
user: parseInt(pbtimeout.user),
target: parseInt(pbtimeout.target),
item: pbtimeout.item,
created: new Date(Date.parse(pbtimeout.created))
});
console.log(`Migrated timeout row of user: ${pbtimeout.user} shooting user: ${pbtimeout.target} with item: ${pbtimeout.item}`)
};