mirror of
https://github.com/qwerinope/qweribot.git
synced 2025-12-19 08:41:39 +01:00
moving to postgres, part 1
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { redis } from "bun";
|
||||
import { Command, sendMessage } from "commands";
|
||||
import { getUserRecord, updateUserRecord } from "db/dbUser";
|
||||
import items from "items";
|
||||
import items, { type inventory, type items } from "items";
|
||||
import { buildTimeString } from "lib/dateManager";
|
||||
import { timeout } from "lib/timeout";
|
||||
import { isInvuln, removeInvuln } from "lib/invuln";
|
||||
@@ -19,7 +19,7 @@ export default new Command({
|
||||
if (await isInvuln(msg.chatterId) && !streamerUsers.includes(msg.chatterId)) { await sendMessage(`You're no longer an invuln because used a lootbox.`, msg.messageId); await removeInvuln(msg.chatterId); };
|
||||
if (await user.itemLock()) { await sendMessage(`Cannot get loot (itemlock)`, msg.messageId); return; };
|
||||
const userData = await getUserRecord(user);
|
||||
const lastlootbox = Date.parse(userData.lastlootbox);
|
||||
const lastlootbox = userData.lastlootbox.getTime();
|
||||
const now = Date.now();
|
||||
if ((lastlootbox + COOLDOWN) > now) {
|
||||
if (await user.greedy()) {
|
||||
@@ -40,12 +40,12 @@ export default new Command({
|
||||
await user.clearGreed();
|
||||
await user.setLock();
|
||||
|
||||
userData.lastlootbox = new Date(now).toISOString();
|
||||
userData.lastlootbox = new Date(now);
|
||||
|
||||
const gainedqbucks = Math.floor(Math.random() * 100) + 50; // range from 50 to 150
|
||||
userData.balance += gainedqbucks;
|
||||
|
||||
const itemDiff = {
|
||||
const itemDiff: inventory = {
|
||||
grenade: 0,
|
||||
blaster: 0,
|
||||
tnt: 0,
|
||||
@@ -53,13 +53,13 @@ export default new Command({
|
||||
};
|
||||
|
||||
for (let i = 0; i < 5; 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() * 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;
|
||||
};
|
||||
|
||||
for (const [item, amount] of Object.entries(itemDiff)) {
|
||||
for (const [item, amount] of Object.entries(itemDiff) as [items, number]) {
|
||||
if (userData.inventory[item]) userData.inventory[item] += amount;
|
||||
else userData.inventory[item] = amount;
|
||||
};
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import pocketbase from "db/connection";
|
||||
import { RedisClient } from "bun";
|
||||
import logger from "lib/logger";
|
||||
|
||||
export async function connectionCheck() {
|
||||
let pbstatus = false;
|
||||
try {
|
||||
await pocketbase.health.check().then(a => a.code === 200);
|
||||
pbstatus = true;
|
||||
} catch { };
|
||||
const tempclient = new RedisClient(undefined, {
|
||||
|
||||
@@ -1,75 +1,18 @@
|
||||
import type { AccessToken } from "@twurple/auth";
|
||||
import PocketBase, { RecordService } from "pocketbase";
|
||||
import type { inventory } from "items";
|
||||
import logger from "lib/logger";
|
||||
import * as schema from "db/schema";
|
||||
|
||||
const pocketbaseurl = process.env.POCKETBASE_URL ?? "localhost:8090";
|
||||
if (pocketbaseurl === "") { logger.enverr("POCKETBASE_URL"); process.exit(1); };
|
||||
// const host = process.env.POSTGRES_HOST ?? "";
|
||||
// if (!host) { logger.enverr("POSTGRES_HOST"); process.exit(1); };
|
||||
//
|
||||
// const user = process.env.POSTGRES_USER ?? "";
|
||||
// if (!user) { logger.enverr("POSTGRES_USER"); process.exit(1); };
|
||||
// const password = process.env.POSTGRES_PASSWORD ?? "";
|
||||
// if (!password) { logger.enverr("POSTGRES_USER"); process.exit(1); };
|
||||
// const database = process.env.POSTGRES_DB ?? "twitchbot";
|
||||
//
|
||||
// const connection = { host, user, password, database };
|
||||
const url = `postgresql://admin:abcdefgh@localhost:5432/twitchbot`;
|
||||
|
||||
export type authRecord = {
|
||||
id: string;
|
||||
accesstoken: AccessToken;
|
||||
};
|
||||
|
||||
export type userRecord = {
|
||||
id: string;
|
||||
username: string; // Don't use this, Use User.username or User.displayName. This is just to make the pocketbase data easier to read.
|
||||
balance: number;
|
||||
inventory: inventory;
|
||||
lastlootbox: string;
|
||||
};
|
||||
|
||||
export type usedItemRecord = {
|
||||
id?: string;
|
||||
user: string;
|
||||
item: string;
|
||||
created: string;
|
||||
};
|
||||
|
||||
export type timeoutRecord = {
|
||||
id?: string;
|
||||
user: string;
|
||||
target: string;
|
||||
item: string;
|
||||
created: string;
|
||||
};
|
||||
|
||||
export type cheerEventRecord = {
|
||||
id?: string;
|
||||
user: string;
|
||||
cheer: string;
|
||||
created: string;
|
||||
};
|
||||
|
||||
export type cheerRecord = {
|
||||
id?: string;
|
||||
user: string;
|
||||
amount: number;
|
||||
};
|
||||
|
||||
export type anivTimeoutRecord = {
|
||||
id?: string;
|
||||
message: string;
|
||||
user: string;
|
||||
duration: number;
|
||||
};
|
||||
|
||||
export type getLootRecord = {
|
||||
id?: string;
|
||||
user: string;
|
||||
qbucks: number;
|
||||
items: inventory;
|
||||
};
|
||||
|
||||
interface TypedPocketBase extends PocketBase {
|
||||
collection(idOrName: 'auth'): RecordService<authRecord>;
|
||||
collection(idOrName: 'users'): RecordService<userRecord>;
|
||||
collection(idOrName: 'usedItems'): RecordService<usedItemRecord>;
|
||||
collection(idOrName: 'timeouts'): RecordService<timeoutRecord>;
|
||||
collection(idOrName: 'cheerEvents'): RecordService<cheerEventRecord>;
|
||||
collection(idOrName: 'cheers'): RecordService<cheerRecord>;
|
||||
collection(idOrName: 'anivTimeouts'): RecordService<anivTimeoutRecord>;
|
||||
collection(idOrName: 'getLoots'): RecordService<getLootRecord>;
|
||||
};
|
||||
|
||||
export default new PocketBase(pocketbaseurl).autoCancellation(false) as TypedPocketBase;
|
||||
import { drizzle } from 'drizzle-orm/bun-sql';
|
||||
export default drizzle(url, {
|
||||
schema
|
||||
});
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import pocketbase from "db/connection";
|
||||
import db from "db/connection";
|
||||
import User from "user";
|
||||
import logger from "lib/logger";
|
||||
import { anivTimeouts } from "db/schema";
|
||||
import { type anivBots } from "lib/handleAnivMessage";
|
||||
|
||||
const pb = pocketbase.collection('anivTimeouts');
|
||||
|
||||
export async function createAnivTimeoutRecord(message: string, user: User, duration: number) {
|
||||
try {
|
||||
await pb.create({ message, user: user.id, duration });
|
||||
} catch (e) {
|
||||
logger.err(`Failed to create anivTimeoutRecord: user: ${user.displayName} message: "${message}" duration: ${duration}`);
|
||||
logger.err(e as string);
|
||||
};
|
||||
export async function createAnivTimeoutRecord(message: string, anivbot: anivBots, user: User, duration: number) {
|
||||
await db.insert(anivTimeouts).values({
|
||||
message,
|
||||
anivBot: anivbot,
|
||||
user: parseInt(user.id),
|
||||
duration
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,38 +1,28 @@
|
||||
import type { AccessToken } from "@twurple/auth";
|
||||
import pocketbase, { type authRecord } from "db/connection";
|
||||
const pb = pocketbase.collection('auth');
|
||||
import db from "db/connection";
|
||||
import { auth } from "db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
export async function createAuthRecord(token: AccessToken, userId: string) {
|
||||
try {
|
||||
const data: authRecord = {
|
||||
accesstoken: token,
|
||||
id: userId
|
||||
};
|
||||
await pb.create(data);
|
||||
} catch (err) { };
|
||||
await db.insert(auth).values({
|
||||
id: parseInt(userId),
|
||||
accesstoken: token
|
||||
});
|
||||
};
|
||||
|
||||
export async function getAuthRecord(userId: string, requiredIntents: string[]) {
|
||||
try {
|
||||
const data = await pb.getOne(userId);
|
||||
if (!requiredIntents.every(intent => data.accesstoken.scope.includes(intent))) return undefined;
|
||||
return { accesstoken: data.accesstoken };
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
};
|
||||
const data = await db.query.auth.findFirst({
|
||||
where: eq(auth.id, parseInt(userId))
|
||||
});
|
||||
if (!data) return undefined;
|
||||
if (!requiredIntents.every(intent => data.accesstoken.scope.includes(intent))) return undefined;
|
||||
return { accesstoken: data.accesstoken };
|
||||
};
|
||||
|
||||
export async function updateAuthRecord(userId: string, newtoken: AccessToken) {
|
||||
try {
|
||||
const newrecord = {
|
||||
accesstoken: newtoken,
|
||||
};
|
||||
await pb.update(userId, newrecord);
|
||||
} catch (err) { };
|
||||
await db.update(auth).set({ accesstoken: newtoken }).where(eq(auth.id, parseInt(userId)));
|
||||
};
|
||||
|
||||
export async function deleteAuthRecord(userId: string): Promise<void> {
|
||||
try {
|
||||
await pb.delete(userId);
|
||||
} catch (err) { };
|
||||
await db.delete(auth).where(eq(auth.id, parseInt(userId)));
|
||||
};
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
import pocketbase from "db/connection";
|
||||
import db from "db/connection";
|
||||
import { cheerEvents } from "db/schema";
|
||||
import { and, between, eq, SQL } from "drizzle-orm";
|
||||
import type { items } from "items";
|
||||
import User from "user";
|
||||
import logger from "lib/logger";
|
||||
const pb = pocketbase.collection('cheerEvents');
|
||||
|
||||
export async function createCheerEventRecord(user: User, cheer: string): Promise<void> {
|
||||
try {
|
||||
await pb.create({ user: user.id, cheer });
|
||||
} catch (e) {
|
||||
logger.err(`Failed to create cheerEvent record in database: user: ${user.id}, cheer: ${cheer}`);
|
||||
logger.err(e as string);
|
||||
};
|
||||
export async function createCheerEventRecord(user: User, cheer: items): Promise<void> {
|
||||
await db.insert(cheerEvents).values({ user: parseInt(user.id), event: cheer });
|
||||
};
|
||||
|
||||
export async function getCheerEvents(user: User, monthData?: string) {
|
||||
try {
|
||||
const monthquery = monthData ? ` && created~"${monthData}"` : '';
|
||||
const data = await pb.getFullList({
|
||||
filter: `user="${user.id}"${monthquery}`
|
||||
});
|
||||
return data;
|
||||
} catch (e) {
|
||||
logger.err(`Failed to get cheerEvents for user: ${user.id}, month: ${monthData}`);
|
||||
logger.err(e as string);
|
||||
let condition: SQL<unknown> | undefined = eq(cheerEvents.user, parseInt(user.id));
|
||||
if (monthData) {
|
||||
const begin = Date.parse(monthData);
|
||||
const end = new Date(begin).setMonth(new Date(begin).getMonth() + 1);
|
||||
condition = and(condition, between(cheerEvents.created, new Date(begin), new Date(end)));
|
||||
};
|
||||
const data = await db.select().from(cheerEvents).where(condition);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
import pocketbase from "db/connection";
|
||||
import db from "db/connection";
|
||||
import { cheers } from "db/schema";
|
||||
import User from "user";
|
||||
import logger from "lib/logger";
|
||||
const pb = pocketbase.collection('cheers');
|
||||
import { and, between, eq, SQL } from "drizzle-orm";
|
||||
|
||||
export async function createCheerRecord(user: User, amount: number): Promise<void> {
|
||||
try {
|
||||
await pb.create({ user: user.id, amount })
|
||||
} catch (e) {
|
||||
logger.err(`Failed to create cheer record in database: user: ${user.id}, amount: ${amount}`);
|
||||
logger.err(e as string);
|
||||
};
|
||||
await db.insert(cheers).values({ user: parseInt(user.id), amount });
|
||||
};
|
||||
|
||||
export async function getCheers(user: User, monthData?: string) {
|
||||
try {
|
||||
const monthquery = monthData ? ` && created~"${monthData}"` : '';
|
||||
const data = await pb.getFullList({
|
||||
filter: `user="${user.id}"${monthquery}`
|
||||
});
|
||||
return data;
|
||||
} catch (e) {
|
||||
logger.err(`Failed to get cheers for user: ${user.id}, month: ${monthData}`);
|
||||
logger.err(e as string);
|
||||
let condition: SQL<unknown> | undefined = eq(cheers.user, parseInt(user.id));
|
||||
if (monthData) {
|
||||
const begin = Date.parse(monthData);
|
||||
const end = new Date(begin).setMonth(new Date(begin).getMonth() + 1);
|
||||
condition = and(condition, between(cheers.created, new Date(begin), new Date(end)));
|
||||
};
|
||||
const data = await db.select().from(cheers).where(condition);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
import pocketbase from "db/connection";
|
||||
import db from "db/connection";
|
||||
import { getLoots } from "db/schema";
|
||||
import type { inventory } from "items";
|
||||
import logger from "lib/logger";
|
||||
import type User from "user";
|
||||
|
||||
const pb = pocketbase.collection('getLoots');
|
||||
|
||||
export async function createGetLootRecord(user: User, qbucks: number, inventory: inventory) {
|
||||
try {
|
||||
await pb.create({
|
||||
user: user.id,
|
||||
qbucks,
|
||||
items: inventory
|
||||
});
|
||||
} catch (e) {
|
||||
logger.err(`Failed to create getLoot record for ${user.displayName}: ${inventory}`);
|
||||
logger.err(e as string);
|
||||
};
|
||||
await db.insert(getLoots).values({
|
||||
user: parseInt(user.id),
|
||||
qbucks: qbucks,
|
||||
items: inventory
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,39 +1,35 @@
|
||||
import pocketbase from "db/connection";
|
||||
import db from "db/connection";
|
||||
import { timeouts } from "db/schema";
|
||||
import User from "user";
|
||||
import logger from "lib/logger";
|
||||
const pb = pocketbase.collection('timeouts');
|
||||
import type { items } from "items";
|
||||
import { and, between, eq, type SQL } from "drizzle-orm";
|
||||
|
||||
export async function createTimeoutRecord(user: User, target: User, item: string): Promise<void> {
|
||||
try {
|
||||
await pb.create({ user: user.id, target: target.id, item });
|
||||
} catch (err) {
|
||||
logger.err(`Failed to create timeout record in database: user: ${user.id}, target: ${target.id}, item: ${item}`);
|
||||
logger.err(err as string);
|
||||
};
|
||||
export async function createTimeoutRecord(user: User, target: User, item: items): Promise<void> {
|
||||
await db.insert(timeouts).values({
|
||||
user: parseInt(user.id),
|
||||
target: parseInt(target.id),
|
||||
item
|
||||
});
|
||||
};
|
||||
|
||||
export async function getTimeoutsAsUser(user: User, monthData?: string) {
|
||||
try {
|
||||
const monthquery = monthData ? ` && created~"${monthData}"` : '';
|
||||
const data = await pb.getFullList({
|
||||
filter: `user="${user.id}"${monthquery}`
|
||||
});
|
||||
return data;
|
||||
} catch (e) {
|
||||
logger.err(`Failed to get timeouts as user: ${user.id}, month: ${monthData}`);
|
||||
logger.err(e as string);
|
||||
let condition: SQL<unknown> | undefined = eq(timeouts.user, parseInt(user.id));
|
||||
if (monthData) {
|
||||
const begin = Date.parse(monthData);
|
||||
const end = new Date(begin).setMonth(new Date(begin).getMonth() + 1);
|
||||
condition = and(condition, between(timeouts.created, new Date(begin), new Date(end)));
|
||||
};
|
||||
const data = await db.select().from(timeouts).where(condition);
|
||||
return data;
|
||||
};
|
||||
|
||||
export async function getTimeoutsAsTarget(user: User, monthData?: string) {
|
||||
try {
|
||||
const monthquery = monthData ? ` && created~"${monthData}"` : '';
|
||||
const data = await pb.getFullList({
|
||||
filter: `target="${user.id}"${monthquery}`
|
||||
});
|
||||
return data;
|
||||
} catch (e) {
|
||||
logger.err(`Failed to get timeouts as target: ${user.id}, month: ${monthData}`);
|
||||
logger.err(e as string);
|
||||
let condition: SQL<unknown> | undefined = eq(timeouts.target, parseInt(user.id));
|
||||
if (monthData) {
|
||||
const begin = Date.parse(monthData);
|
||||
const end = new Date(begin).setMonth(new Date(begin).getMonth() + 1);
|
||||
condition = and(condition, between(timeouts.created, new Date(begin), new Date(end)));
|
||||
};
|
||||
const data = await db.select().from(timeouts).where(condition);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
import pocketbase from "db/connection";
|
||||
import db from "db/connection";
|
||||
import { usedItems } from "db/schema";
|
||||
import User from "user";
|
||||
import logger from "lib/logger";
|
||||
const pb = pocketbase.collection('usedItems');
|
||||
import type { items } from "items";
|
||||
import { and, between, eq, type SQL } from "drizzle-orm";
|
||||
|
||||
export async function createUsedItemRecord(user: User, item: string): Promise<void> {
|
||||
try {
|
||||
await pb.create({ user: user.id, item });
|
||||
} catch (err) {
|
||||
logger.err(`Failed to create usedItem record in database: user: ${user.id}, item: ${item}`);
|
||||
logger.err(err as string);
|
||||
};
|
||||
export async function createUsedItemRecord(user: User, item: items): Promise<void> {
|
||||
await db.insert(usedItems).values({ user: parseInt(user.id), item });
|
||||
};
|
||||
|
||||
export async function getItemsUsed(user: User, monthData?: string) {
|
||||
try {
|
||||
const monthquery = monthData ? ` && created~"${monthData}"` : '';
|
||||
const data = await pb.getFullList({
|
||||
filter: `user="${user.id}"${monthquery}`
|
||||
});
|
||||
return data;
|
||||
} catch (e) {
|
||||
logger.err(`Failed to get items used for user: ${user.id}, month: ${monthData}`);
|
||||
logger.err(e as string);
|
||||
let condition: SQL<unknown> | undefined = eq(usedItems.user, parseInt(user.id));
|
||||
if (monthData) {
|
||||
const begin = Date.parse(monthData);
|
||||
const end = new Date(begin).setMonth(new Date(begin).getMonth() + 1);
|
||||
condition = and(condition, between(usedItems.created, new Date(begin), new Date(end)));
|
||||
};
|
||||
const data = await db.select().from(usedItems).where(condition);
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,58 +1,47 @@
|
||||
import pocketbase, { type userRecord } from "db/connection";
|
||||
import { emptyInventory, itemarray } from "items";
|
||||
import db from "db/connection";
|
||||
import { users } from "db/schema";
|
||||
import { itemarray, type inventory } from "items";
|
||||
import type User from "user";
|
||||
import logger from "lib/logger";
|
||||
|
||||
const pb = pocketbase.collection('users');
|
||||
import { desc, eq } from "drizzle-orm";
|
||||
|
||||
/** Use this function to both ensure existance and to retreive data */
|
||||
export async function getUserRecord(user: User): Promise<userRecord> {
|
||||
try {
|
||||
const data = await pb.getOne(user.id);
|
||||
export async function getUserRecord(user: User) {
|
||||
const data = await db.query.users.findFirst({ where: eq(users.id, parseInt(user.id)) });
|
||||
if (!data) return createUserRecord(user);
|
||||
|
||||
if (Object.keys(data.inventory).sort().toString() !== itemarray.sort().toString()) { // If the items in the user inventory are missing an item.
|
||||
itemarray.forEach(key => {
|
||||
if (!(key in data.inventory)) data.inventory[key] = 0;
|
||||
});
|
||||
};
|
||||
|
||||
return data;
|
||||
} catch (err) {
|
||||
// This gets triggered if the user doesn't exist in the database
|
||||
return await createUserRecord(user);
|
||||
if (Object.keys(data.inventory).sort().toString() !== itemarray.sort().toString()) { // If the items in the user inventory are missing an item.
|
||||
itemarray.forEach(key => {
|
||||
if (!(key in data.inventory)) data.inventory[key] = 0;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export async function getAllUserRecords(): Promise<userRecord[]> {
|
||||
return await pb.getFullList();
|
||||
};
|
||||
|
||||
async function createUserRecord(user: User): Promise<userRecord> {
|
||||
const data = await pb.create({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
balance: 0,
|
||||
inventory: emptyInventory,
|
||||
lastlootbox: new Date(0).toISOString()
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export async function updateUserRecord(user: User, newData: userRecord): Promise<boolean> {
|
||||
try {
|
||||
await pb.update(user.id, newData);
|
||||
return true;
|
||||
} catch (err) {
|
||||
logger.err(err as string);
|
||||
return false;
|
||||
};
|
||||
export async function getAllUserRecords() {
|
||||
return await db.select().from(users);
|
||||
};
|
||||
|
||||
async function createUserRecord(user: User) {
|
||||
return await db.insert(users).values({
|
||||
id: parseInt(user.id),
|
||||
username: user.username
|
||||
}).returning().then(a => {
|
||||
if (!a[0]) throw Error('Something went horribly wrong');
|
||||
return a[0]
|
||||
});
|
||||
};
|
||||
|
||||
export type balanceUpdate = { balance: number; };
|
||||
export type inventoryUpdate = { inventory: inventory; };
|
||||
type updateUser = balanceUpdate | inventoryUpdate;
|
||||
|
||||
export async function updateUserRecord(user: User, newData: updateUser) {
|
||||
await db.update(users).set(newData).where(eq(users.id, parseInt(user.id)));
|
||||
return true;
|
||||
};
|
||||
|
||||
export async function getBalanceLeaderboard() {
|
||||
try {
|
||||
return await pb.getList(1, 10, { sort: '-balance,id' }).then(a => a.items);
|
||||
} catch (err) {
|
||||
logger.err(err as string);
|
||||
};
|
||||
return await db.select().from(users).orderBy(desc(users.balance)).limit(10);
|
||||
};
|
||||
|
||||
64
src/db/schema.ts
Normal file
64
src/db/schema.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { AccessToken } from "@twurple/auth";
|
||||
import type { inventory, items } from "items";
|
||||
|
||||
import { integer, jsonb, pgTable, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
|
||||
import type { anivBots } from "lib/handleAnivMessage";
|
||||
|
||||
export const auth = pgTable('auth', {
|
||||
id: integer().primaryKey(),
|
||||
accesstoken: jsonb().$type<AccessToken>().notNull()
|
||||
});
|
||||
|
||||
export const users = pgTable('users', {
|
||||
id: integer().primaryKey().notNull(),
|
||||
username: varchar().notNull(),
|
||||
balance: integer().default(0).notNull(),
|
||||
inventory: jsonb().$type<inventory>().default({}).notNull(),
|
||||
lastlootbox: timestamp().default(new Date(0)).notNull()
|
||||
});
|
||||
|
||||
export const timeouts = pgTable('timeouts', {
|
||||
id: uuid().defaultRandom().primaryKey(),
|
||||
user: integer().notNull().references(() => users.id),
|
||||
target: integer().notNull().references(() => users.id),
|
||||
item: varchar().$type<items>().notNull(),
|
||||
created: timestamp().defaultNow().notNull()
|
||||
});
|
||||
|
||||
export const usedItems = pgTable('usedItems', {
|
||||
id: uuid().defaultRandom().primaryKey(),
|
||||
user: integer().notNull().references(() => users.id),
|
||||
item: varchar().$type<items>().notNull(),
|
||||
created: timestamp().defaultNow().notNull()
|
||||
});
|
||||
|
||||
export const cheerEvents = pgTable('cheerEvents', {
|
||||
id: uuid().defaultRandom().primaryKey(),
|
||||
user: integer().notNull().references(() => users.id),
|
||||
event: varchar().$type<items>().notNull(),
|
||||
created: timestamp().defaultNow().notNull()
|
||||
});
|
||||
|
||||
export const cheers = pgTable('cheers', {
|
||||
id: uuid().defaultRandom().primaryKey(),
|
||||
user: integer().notNull().references(() => users.id),
|
||||
amount: integer().notNull(),
|
||||
created: timestamp().defaultNow().notNull()
|
||||
});
|
||||
|
||||
export const anivTimeouts = pgTable('anivTimeouts', {
|
||||
id: uuid().defaultRandom().primaryKey(),
|
||||
user: integer().notNull().references(() => users.id),
|
||||
message: varchar().notNull(),
|
||||
anivBot: varchar().$type<anivBots>().notNull(),
|
||||
duration: integer().notNull(),
|
||||
created: timestamp().defaultNow().notNull()
|
||||
});
|
||||
|
||||
export const getLoots = pgTable('getLoots', {
|
||||
id: uuid().defaultRandom().primaryKey(),
|
||||
user: integer().notNull().references(() => users.id),
|
||||
qbucks: integer().notNull(),
|
||||
items: jsonb().$type<inventory>().notNull(),
|
||||
created: timestamp().defaultNow().notNull()
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import User from "user";
|
||||
import { type userType, type specialExecuteArgs } from "commands";
|
||||
|
||||
type itemOptions = {
|
||||
name: string;
|
||||
name: items;
|
||||
aliases: string[];
|
||||
prettyName: string;
|
||||
plural: string;
|
||||
@@ -13,7 +13,7 @@ type itemOptions = {
|
||||
};
|
||||
|
||||
export class Item {
|
||||
public readonly name: string;
|
||||
public readonly name: items;
|
||||
public readonly prettyName: string;
|
||||
public readonly plural: string;
|
||||
public readonly description: string;
|
||||
@@ -25,7 +25,7 @@ export class Item {
|
||||
|
||||
/** Creates an item object */
|
||||
constructor(options: itemOptions) {
|
||||
this.name = options.name.toLowerCase();
|
||||
this.name = options.name;
|
||||
this.prettyName = options.prettyName;
|
||||
this.plural = options.plural;
|
||||
this.description = options.description;
|
||||
@@ -38,12 +38,11 @@ export class Item {
|
||||
};
|
||||
|
||||
import { readdir } from 'node:fs/promises';
|
||||
import type { userRecord } from "db/connection";
|
||||
import { updateUserRecord } from "db/dbUser";
|
||||
const items = new Map<string, Item>;
|
||||
import { updateUserRecord, type inventoryUpdate } from "db/dbUser";
|
||||
const itemMap = new Map<string, Item>;
|
||||
const specialAliasItems = new Map<string, Item>;
|
||||
const emptyInventory: inventory = {};
|
||||
const itemarray: string[] = [];
|
||||
const itemarray: items[] = [];
|
||||
|
||||
const files = await readdir(import.meta.dir);
|
||||
for (const file of files) {
|
||||
@@ -53,20 +52,22 @@ for (const file of files) {
|
||||
emptyInventory[item.name] = 0;
|
||||
itemarray.push(item.name);
|
||||
for (const alias of item.aliases) {
|
||||
items.set(alias, item); // Since it's not a primitive type the map is filled with references to the item, not the actual object
|
||||
itemMap.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 items;
|
||||
export default itemMap;
|
||||
export { emptyInventory, itemarray, specialAliasItems };
|
||||
|
||||
export type items = "blaster" | "silverbullet" | "grenade" | "tnt";
|
||||
export type inventory = {
|
||||
[key: string]: number;
|
||||
[key in items]?: number;
|
||||
};
|
||||
|
||||
export async function changeItemCount(user: User, userRecord: userRecord, itemname: string, amount = -1): Promise<false | userRecord> {
|
||||
export async function changeItemCount(user: User, userRecord: inventoryUpdate, itemname: items, amount = -1): Promise<false | inventoryUpdate> {
|
||||
userRecord.inventory[itemname] = userRecord.inventory[itemname]! += amount;
|
||||
if (userRecord.inventory[itemname] < 0) return false;
|
||||
await updateUserRecord(user, userRecord);
|
||||
|
||||
@@ -20,7 +20,7 @@ export default new Item({
|
||||
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);
|
||||
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; };
|
||||
|
||||
@@ -5,7 +5,7 @@ import { timeout } from "lib/timeout";
|
||||
import { sendMessage } from "commands";
|
||||
import { createAnivTimeoutRecord } from "db/dbAnivTimeouts";
|
||||
|
||||
const ANIVNAMES = ['a_n_e_e_v', 'a_n_i_v'];
|
||||
const ANIVNAMES: anivBots[] = ['a_n_e_e_v', 'a_n_i_v'];
|
||||
|
||||
type anivMessageStore = {
|
||||
[key: string]: string;
|
||||
@@ -14,13 +14,15 @@ type anivMessageStore = {
|
||||
type IsAnivMessage = {
|
||||
isAnivMessage: true;
|
||||
message: string;
|
||||
anivbot: string;
|
||||
anivbot: anivBots;
|
||||
};
|
||||
|
||||
type isNotAnivMessage = {
|
||||
isAnivMessage: false;
|
||||
};
|
||||
|
||||
export type anivBots = 'a_n_i_v' | 'a_n_e_e_v';
|
||||
|
||||
type anivMessageResult = IsAnivMessage | isNotAnivMessage;
|
||||
|
||||
async function isAnivMessage(message: string): Promise<anivMessageResult> {
|
||||
@@ -34,7 +36,7 @@ async function isAnivMessage(message: string): Promise<anivMessageResult> {
|
||||
};
|
||||
|
||||
export default async function handleMessage(msg: EventSubChannelChatMessageEvent, user: User) {
|
||||
if (ANIVNAMES.includes(user.displayName)) {
|
||||
if (ANIVNAMES.map(a => a.toLowerCase()).includes(user.username)) {
|
||||
const data: anivMessageStore = await redis.get('anivmessages').then(a => a === null ? {} : JSON.parse(a));
|
||||
data[user.displayName] = msg.messageText;
|
||||
await redis.set('anivmessages', JSON.stringify(data));
|
||||
@@ -43,7 +45,7 @@ export default async function handleMessage(msg: EventSubChannelChatMessageEvent
|
||||
if (data.isAnivMessage) await Promise.all([
|
||||
timeout(user, 'copied an aniv message', 30),
|
||||
sendMessage(`${user.displayName} got timed out for copying an ${data.anivbot} message`),
|
||||
createAnivTimeoutRecord(msg.messageText, user, 30)
|
||||
createAnivTimeoutRecord(msg.messageText, data.anivbot, user, 30)
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user