mirror of
https://github.com/qwerinope/qweribot.git
synced 2025-12-18 15:01:38 +01:00
add better aniv timeouts, add aniv dodges, fix blank user target bug
This commit is contained in:
10
README.md
10
README.md
@@ -48,6 +48,13 @@ If you've been timed out, you can ghost whisper a message to the chatterbot and
|
||||
You can only send one message every 5 minutes.
|
||||
Try to bargain for your release with the chatter that shot you, or just call them names.
|
||||
|
||||
### Aniv timeouts
|
||||
|
||||
When chatter `a_n_i_v` (a_normal_imyt_viewer) or `a_n_e_e_v` sends a message it's stored in the database.
|
||||
If then someone copies them, they might get timed out.
|
||||
These timeouts and dodges are stored. You can get your stats with the `anivtimeouts` command.
|
||||
The current dodge rate is `1/2`, and the timeout duration range is between `30` and `60` seconds.
|
||||
|
||||
### Leaderboards
|
||||
|
||||
There are 3 types of leaderboards: monthlyKD, alltimeKD and qbucks.
|
||||
@@ -126,6 +133,7 @@ COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE
|
||||
`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:
|
||||
`anivtimeouts`|Get the amount of timeouts, dodges and dodge percentage from aniv timeouts [(info)](#aniv-timeouts)|anyone|`anivtimeouts` `anivtimeout`|:white_check_mark:
|
||||
|
||||
### Qweribucks/Item commands
|
||||
|
||||
@@ -174,8 +182,8 @@ COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE
|
||||
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 30 minutes|`silverbullet` `execute` `{blastin}`|666
|
||||
Grenade|`grenade`|Times a random vulnerable chatter out for 60 seconds|`grenade`|99
|
||||
Silver Bullet|`silverbullet {target}`|Times targeted user out for 30 minutes|`silverbullet` `execute` `{blastin}`|666
|
||||
TNT|`tnt`|Give 5-10 random chatters 60 second timeouts|`tnt`|1000
|
||||
|
||||
## Cheers
|
||||
|
||||
19
src/commands/anivtimeouts.ts
Normal file
19
src/commands/anivtimeouts.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Command, sendMessage } from "commands";
|
||||
import { getAnivTimeouts } from "db/dbAnivTimeouts";
|
||||
import parseCommandArgs from "lib/parseCommandArgs";
|
||||
import User from "user";
|
||||
|
||||
export default new Command({
|
||||
name: 'anivtimeouts',
|
||||
aliases: ['anivtimeouts', 'anivtimeout'],
|
||||
usertype: 'chatter',
|
||||
execution: async (msg, user) => {
|
||||
const args = parseCommandArgs(msg.messageText);
|
||||
const target = args[0] ? await User.initUsername(args[0].toLowerCase()) : user;
|
||||
if (!target) { await sendMessage(`Chatter ${args[0]} doesn't exist!`, msg.messageId); return; };
|
||||
const { dodge, dead } = await getAnivTimeouts(target);
|
||||
const percentage = ((dodge / (dead + dodge)) * 100);
|
||||
const message = `Aniv timeouts of ${target.displayName}: Dodge: ${dodge}, Timeout: ${dead}. Dodge percentage: ${isNaN(percentage) ? "0" : percentage.toFixed(1)}%`;
|
||||
await sendMessage(message, msg.messageId);
|
||||
}
|
||||
});
|
||||
@@ -2,12 +2,31 @@ import db from "db/connection";
|
||||
import User from "user";
|
||||
import { anivTimeouts } from "db/schema";
|
||||
import { type anivBots } from "lib/handleAnivMessage";
|
||||
import { count, eq, and } from "drizzle-orm";
|
||||
|
||||
/** To create a dodge record, set the duration to 0 */
|
||||
export async function createAnivTimeoutRecord(message: string, anivBot: anivBots, user: User, duration: number) {
|
||||
await db.insert(anivTimeouts).values({
|
||||
message,
|
||||
anivBot,
|
||||
user: parseInt(user.id),
|
||||
duration
|
||||
duration,
|
||||
timeout: duration !== 0
|
||||
});
|
||||
};
|
||||
|
||||
export async function getAnivTimeouts(user: User) {
|
||||
let [dodge, dead] = await Promise.all([
|
||||
db.select({
|
||||
dodge: count()
|
||||
}).from(anivTimeouts).where(and(eq(anivTimeouts.user, parseInt(user.id)), eq(anivTimeouts.timeout, false))).then(a => a[0]?.dodge),
|
||||
db.select({
|
||||
dead: count()
|
||||
}).from(anivTimeouts).where(and(eq(anivTimeouts.user, parseInt(user.id)), eq(anivTimeouts.timeout, true))).then(a => a[0]?.dead)
|
||||
]);
|
||||
|
||||
if (!dodge) dodge = 0;
|
||||
if (!dead) dead = 0;
|
||||
|
||||
return { dodge, dead };
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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 { boolean, integer, jsonb, pgTable, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
|
||||
import type { anivBots } from "lib/handleAnivMessage";
|
||||
import { relations } from "drizzle-orm";
|
||||
|
||||
@@ -95,8 +95,9 @@ export const anivTimeouts = pgTable('anivTimeouts', {
|
||||
user: integer().notNull().references(() => users.id),
|
||||
message: varchar().notNull(),
|
||||
anivBot: varchar().$type<anivBots>().notNull(),
|
||||
duration: integer().notNull(),
|
||||
created: timestamp().defaultNow().notNull()
|
||||
duration: integer(),
|
||||
created: timestamp().defaultNow().notNull(),
|
||||
timeout: boolean().default(true)
|
||||
});
|
||||
|
||||
export const anivTimeoutsRelations = relations(anivTimeouts, ({ one }) => ({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"
|
||||
import { streamerId, eventSub, commandPrefix, streamerUsers, chatterId } from "main";
|
||||
import { streamerId, eventSub, commandPrefix, streamerUsers } from "main";
|
||||
import User from "user";
|
||||
import commands, { Command, sendMessage, specialAliasCommands } from "commands";
|
||||
import { redis } from "bun";
|
||||
@@ -30,7 +30,7 @@ async function parseChatMessage(msg: EventSubChannelChatMessageEvent) {
|
||||
|
||||
if (await redis.exists(`user:${user?.id}:bot`)) return; // Ignore all bot commands
|
||||
|
||||
if (!await redis.exists(`user:${user?.id}:haschatted`) && !msg.sourceMessageId) {
|
||||
if (!await redis.exists(`user:${user?.id}:haschatted`) && !msg.sourceMessageId) { // The msg.sourceMessageId checks if the message is from shared chat. shared chat should be ignored
|
||||
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`);
|
||||
await redis.set(`user:${user?.id}:haschatted`, "1");
|
||||
await redis.set(`user:${user?.id}:welcomemessageid`, message.id);
|
||||
@@ -69,8 +69,7 @@ async function handleChatMessage(msg: EventSubChannelChatMessageEvent, user: Use
|
||||
|
||||
try {
|
||||
await selection.execute(msg, user, { activation });
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
logger.err(err as string);
|
||||
await sendMessage('ERROR: Something went wrong', msg.messageId);
|
||||
await user.clearLock();
|
||||
|
||||
@@ -42,10 +42,19 @@ export default async function handleMessage(msg: EventSubChannelChatMessageEvent
|
||||
await redis.set('anivmessages', JSON.stringify(data));
|
||||
} else {
|
||||
const data = await isAnivMessage(msg.messageText);
|
||||
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, data.anivbot, user, 30)
|
||||
]);
|
||||
if (data.isAnivMessage) {
|
||||
if (Math.random() > 0.5) { // 1/2 chance to dodge aniv timeout
|
||||
await createAnivTimeoutRecord(msg.messageText, data.anivbot, user, 0)
|
||||
return;
|
||||
};
|
||||
|
||||
const duration = Math.floor(Math.random() * 30) + 30 // minimum timeout of 30 sec, maximum of 60 sec
|
||||
|
||||
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, data.anivbot, user, duration)
|
||||
]);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,9 +5,9 @@ export default function parseCommandArgs(input: string, specialAlias?: string) {
|
||||
let nice = '';
|
||||
let sliceLength = 0;
|
||||
if (specialAlias) {
|
||||
nice = input.toLowerCase().slice(specialAlias.length).trim();
|
||||
nice = input.toLowerCase().slice(specialAlias.length).replace(/[^\x00-\x7F]/g, '').trim();
|
||||
} else {
|
||||
nice = input.toLowerCase().slice(commandPrefix.length).trim();
|
||||
nice = input.toLowerCase().slice(commandPrefix.length).replace(/[^\x00-\x7F]/g, '').trim();
|
||||
sliceLength = nice.startsWith('use') ? 2 : 1;
|
||||
}
|
||||
return nice.split(' ').slice(sliceLength).map(a => a.replaceAll(/!/gi, ''));
|
||||
@@ -17,7 +17,7 @@ export function parseCheerArgs(input: string) {
|
||||
const nice = input.toLowerCase().trim();
|
||||
|
||||
// This is for the test command. Remove the command prefix, the command, the whitespace after and the amount of fake bits
|
||||
if (nice.startsWith(commandPrefix + 'testcheer')) return nice.slice(commandPrefix.length + 'testcheer'.length + 1).split(' ').slice(1);
|
||||
if (nice.startsWith(commandPrefix + 'testcheer')) return nice.slice(commandPrefix.length + 'testcheer'.length + 1).replaceAll(/\W/g, '').split(' ').slice(1);
|
||||
|
||||
// This is for actual cheers. Remove all 'cheerx' parts of the message
|
||||
return nice.split(' ').filter(a => !/cheer[0-9]+/i.test(a));
|
||||
|
||||
Reference in New Issue
Block a user