Compare commits

...

2 Commits

17 changed files with 36 additions and 51 deletions

View File

@@ -1,7 +1,7 @@
services: services:
valkey: valkey:
image: valkey/valkey:alpine image: valkey/valkey:alpine
container_name: valkey container_name: qweribot-valkey
ports: ports:
- 6379:6379 - 6379:6379
restart: no restart: no
@@ -10,11 +10,11 @@ services:
environment: environment:
- VALKEY_EXTRA_FLAGS=--save 60 1 - VALKEY_EXTRA_FLAGS=--save 60 1
postgres: postgres:
container_name: postgres container_name: qweribot-postgres
image: postgres:latest image: postgres:latest
restart: unless-stopped restart: unless-stopped
env_file: env_file:
- .env.development - .env
ports: ports:
- "5432:5432" - "5432:5432"
volumes: volumes:

View File

@@ -1,20 +0,0 @@
FROM alpine:latest
ARG PB_VERSION=0.28.4
ARG PB_ZIPNAME=pocketbase_${PB_VERSION}_linux_amd64.zip
RUN apk add --no-cache \
unzip \
ca-certificates
ADD https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/${PB_ZIPNAME} /tmp/${PB_ZIPNAME}
ADD https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/checksums.txt /tmp/checksums.txt
WORKDIR /tmp
RUN grep ${PB_ZIPNAME} checksums.txt | sha256sum -c
RUN unzip /tmp/${PB_ZIPNAME} -d /pb/
COPY ./pb_migrations /pb/pb_migrations
COPY ./pb_hooks /pb/pb_hooks
EXPOSE 8090
CMD ["/pb/pocketbase", "serve", "--http=0.0.0.0:8090"]

View File

@@ -45,5 +45,5 @@ export default new Cheer('execute', 6666, async (msg, user) => {
break; break;
}; };
}; };
}); }, true);

View File

@@ -30,4 +30,4 @@ export default new Cheer('grenade', 99, async (msg, user) => {
target: target?.displayName! target: target?.displayName!
}) })
]); ]);
}); }, true);

View File

@@ -5,10 +5,12 @@ export class Cheer {
public readonly name: string; public readonly name: string;
public readonly amount: number; public readonly amount: number;
public readonly execute: (msg: EventSubChannelChatMessageEvent, sender: User) => Promise<void>; public readonly execute: (msg: EventSubChannelChatMessageEvent, sender: User) => Promise<void>;
constructor(name: string, amount: number, execution: (msg: EventSubChannelChatMessageEvent, sender: User) => Promise<void>) { public readonly isItem: boolean;
constructor(name: string, amount: number, execution: (msg: EventSubChannelChatMessageEvent, sender: User) => Promise<void>, isItem = false) {
this.name = name.toLowerCase(); this.name = name.toLowerCase();
this.amount = amount; this.amount = amount;
this.execute = execution; this.execute = execution;
this.isItem = isItem;
}; };
}; };
@@ -31,9 +33,9 @@ export { namedcheers };
import { sendMessage } from 'commands'; import { sendMessage } from 'commands';
import logger from 'lib/logger'; import logger from 'lib/logger';
import { getUserRecord } from 'db/dbUser'; import { getUserRecord } from 'db/dbUser';
import { changeItemCount } from 'items'; import { changeItemCount, type items } from 'items';
export async function handleNoTarget(msg: EventSubChannelChatMessageEvent, user: User, itemname: string, silent = true) { export async function handleNoTarget(msg: EventSubChannelChatMessageEvent, user: User, itemname: items, silent = true) {
if (await user.itemLock()) { if (await user.itemLock()) {
await sendMessage(`Cannot give ${user.displayName} a ${itemname}`, msg.messageId); await sendMessage(`Cannot give ${user.displayName} a ${itemname}`, msg.messageId);
logger.err(`Failed to give ${user.displayName} a ${itemname} for their cheer`); logger.err(`Failed to give ${user.displayName} a ${itemname} for their cheer`);

View File

@@ -46,4 +46,4 @@ export default new Cheer('timeout', 100, async (msg, user) => {
break; break;
}; };
}; };
}); }, true);

View File

@@ -23,16 +23,18 @@ export default new Cheer('tnt', 1000, async (msg, user) => {
timeout(target!, `You got hit by ${user.displayName}'s TNT!`, 60), timeout(target!, `You got hit by ${user.displayName}'s TNT!`, 60),
redis.del(`user:${targetid}:vulnerable`), redis.del(`user:${targetid}:vulnerable`),
sendMessage(`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`), sendMessage(`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`),
createTimeoutRecord(user, target!, ITEMNAME), createTimeoutRecord(user, target!, ITEMNAME)
createCheerEventRecord(user, ITEMNAME),
]); ]);
})); }));
await playAlert({
name: 'tntExplosion', await Promise.all([
user: user.displayName, createCheerEventRecord(user, ITEMNAME),
targets playAlert({
}) name: 'tntExplosion',
user: user.displayName,
targets
})
]);
await sendMessage(`RIPBOZO ${user.displayName} exploded ${targets.length} chatter${targets.length === 1 ? '' : 's'} with their TNT RIPBOZO`); await sendMessage(`RIPBOZO ${user.displayName} exploded ${targets.length} chatter${targets.length === 1 ? '' : 's'} with their TNT RIPBOZO`);
}); }, true);

View File

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

View File

@@ -19,7 +19,7 @@ export default new Command({
if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; }; if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; };
if (!args[2]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; }; if (!args[2]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; };
const amount = parseInt(args[2]); const amount = parseInt(args[2]);
if (isNaN(amount)) { await sendMessage(`${args[2]} is not a valid amount`); return; }; 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: item lock is set', msg.messageId); return; };
await target.setLock(); await target.setLock();
const data = await changeItemCount(target, userRecord, item.name, amount); const data = await changeItemCount(target, userRecord, item.name, amount);

View File

@@ -15,7 +15,7 @@ export default new Command({
const userKDs: KD[] = []; const userKDs: KD[] = [];
await Promise.all(users.map(async userRecord => { await Promise.all(users.map(async userRecord => {
const user = await User.initUserId(userRecord.id); const user = await User.initUserId(userRecord.id.toString());
if (!user) return; if (!user) return;
const data = await getTimeoutStats(user, false); const data = await getTimeoutStats(user, false);
if (!data) return; if (!data) return;

View File

@@ -19,7 +19,7 @@ export default new Command({
const targetRecord = await getUserRecord(target); const targetRecord = await getUserRecord(target);
if (!args[1]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; }; if (!args[1]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; };
const amount = parseInt(args[1]); const amount = parseInt(args[1]);
if (isNaN(amount) || amount < 1) { await sendMessage(`${args[1]} is not a valid amount`); return; }; if (isNaN(amount) || amount < 1) { await sendMessage(`'${args[1]}' is not a valid amount`); return; };
const userRecord = await getUserRecord(user); const userRecord = await getUserRecord(user);
if (userRecord.balance < amount) { await sendMessage(`You can't give qweribucks you don't have!`, msg.messageId); return; }; if (userRecord.balance < amount) { await sendMessage(`You can't give qweribucks you don't have!`, msg.messageId); return; };

View File

@@ -8,7 +8,7 @@ export default new Command({
execution: async (_msg, user) => { execution: async (_msg, user) => {
await Promise.all([ await Promise.all([
timeout(user, "NO MODME", 60), timeout(user, "NO MODME", 60),
sendMessage(`NO MODME COMMAND!!! UltraMad`) sendMessage(`NO MODME COMMAND!!! UltraMad UltraMad UltraMad`)
]); ]);
} }
}); });

View File

@@ -22,7 +22,7 @@ export default new Command({
if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; }; if (!item) { await sendMessage(`Item ${args[1]} doesn't exist`, msg.messageId); return; };
if (!args[2]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; }; if (!args[2]) { await sendMessage('Please specify the amount of the item you want to give', msg.messageId); return; };
const amount = parseInt(args[2]); const amount = parseInt(args[2]);
if (isNaN(amount) || amount < 1) { await sendMessage(`${args[2]} is not a valid amount`); return; }; if (isNaN(amount) || amount < 1) { await sendMessage(`'${args[2]}' is not a valid amount`); return; };
const userRecord = await getUserRecord(user); 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 (userRecord.inventory[item.name]! < amount) { await sendMessage(`You can't give items you don't have!`, msg.messageId); return; };

View File

@@ -15,7 +15,7 @@ export default new Command({
const userKDs: KD[] = []; const userKDs: KD[] = [];
await Promise.all(users.map(async userRecord => { await Promise.all(users.map(async userRecord => {
const user = await User.initUserId(userRecord.id); const user = await User.initUserId(userRecord.id.toString());
if (!user) return; if (!user) return;
const data = await getTimeoutStats(user, true); const data = await getTimeoutStats(user, true);
if (!data) return; if (!data) return;

View File

@@ -14,7 +14,7 @@ export default new Command({
const txt: string[] = []; const txt: string[] = [];
for (const userRecord of data) { for (const userRecord of data) {
if (userRecord.balance === 0) continue; if (userRecord.balance === 0) continue;
const user = await User.initUserId(userRecord.id); const user = await User.initUserId(userRecord.id.toString());
if (!user) continue; if (!user) continue;
txt.push(`${index}. ${user.displayName}: ${userRecord.balance}`); txt.push(`${index}. ${user.displayName}: ${userRecord.balance}`);
index++; index++;

View File

@@ -28,7 +28,7 @@ async function parseChatMessage(msg: EventSubChannelChatMessageEvent) {
// and both are usable to target the same user (id is the same) // and both are usable to target the same user (id is the same)
// The only problem would be if a user changed their name and someone else took their name right after // The only problem would be if a user changed their name and someone else took their name right after
if (msg.chatterId === chatterId) return; if (msg.chatterId === chatterId && chatterId !== streamerId) return;
if (!await redis.exists(`user:${user?.id}:haschatted`) && !msg.sourceMessageId) { if (!await redis.exists(`user:${user?.id}:haschatted`) && !msg.sourceMessageId) {
const message = await sendMessage(`Welcome ${user?.displayName}. Please note: This chat has PvP, if you get timed out that's part of the qwerinope experience. You have 10 minutes of invincibility. A full list of commands and items can be found here: https://github.com/qwerinope/qweribot/#qweribot`); const message = await sendMessage(`Welcome ${user?.displayName}. Please note: This chat has PvP, if you get timed out that's part of the qwerinope experience. You have 10 minutes of invincibility. A full list of commands and items can be found here: https://github.com/qwerinope/qweribot/#qweribot`);
@@ -68,9 +68,7 @@ async function handleChatMessage(msg: EventSubChannelChatMessageEvent, user: Use
}; };
try { try {
await selection.execute(msg, user, { await selection.execute(msg, user, { activation });
activation
});
} }
catch (err) { catch (err) {
logger.err(err as string); logger.err(err as string);
@@ -105,9 +103,11 @@ export async function handleCheer(msg: EventSubChannelChatMessageEvent, bits: nu
if (!selection) return; if (!selection) return;
if (await redis.sismember('disabledcheers', selection.name)) { await sendMessage(`The ${selection.name} cheer is disabled! Sorry!`, msg.messageId); return; }; if (await redis.sismember('disabledcheers', selection.name)) { await sendMessage(`The ${selection.name} cheer is disabled! Sorry!`, msg.messageId); return; };
if (selection.isItem && await isInvuln(user.id) && !streamerUsers.includes(user.id)) { await sendMessage(`${user.displayName} Is no longer an invuln`); await removeInvuln(user.id); };
try { try {
selection.execute(msg, user); await selection.execute(msg, user);
} catch (err) { } catch (err) {
await sendMessage(`[ERROR]: Something went wrong with cheer execution`);
logger.err(err as string); logger.err(err as string);
}; };
}; };

View File

@@ -45,6 +45,7 @@ export default new Item({
}), }),
changeItemCount(user, userObj, ITEMNAME) changeItemCount(user, userObj, ITEMNAME)
]); ]);
await user.clearLock(); await user.clearLock();
await sendMessage(`RIPBOZO ${user.displayName} exploded ${targets.length} chatter${targets.length === 1 ? '' : 's'} with their TNT RIPBOZO`); await sendMessage(`RIPBOZO ${user.displayName} exploded ${targets.length} chatter${targets.length === 1 ? '' : 's'} with their TNT RIPBOZO`);
} }