mirror of
https://github.com/qwerinope/qweribot.git
synced 2025-12-19 01:01:39 +01:00
handle user bans on widget, add tnt cheer, bugfixes
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { EventSubChannelChatMessageEvent, EventSubChannelChatMessageDeleteEvent } from "@twurple/eventsub-base";
|
||||
import { EventSubChannelChatMessageEvent, EventSubChannelChatMessageDeleteEvent, EventSubChannelBanEvent } from "@twurple/eventsub-base";
|
||||
import { sendTwitchEvent } from ".";
|
||||
|
||||
export async function addMessageToChatWidget(msg: EventSubChannelChatMessageEvent) {
|
||||
sendTwitchEvent({
|
||||
await sendTwitchEvent({
|
||||
function: 'createMessage',
|
||||
messageParts: msg.messageParts,
|
||||
displayName: msg.chatterDisplayName,
|
||||
@@ -14,8 +14,15 @@ export async function addMessageToChatWidget(msg: EventSubChannelChatMessageEven
|
||||
};
|
||||
|
||||
export async function deleteMessageFromChatWidget(msg: EventSubChannelChatMessageDeleteEvent) {
|
||||
sendTwitchEvent({
|
||||
await sendTwitchEvent({
|
||||
function: 'deleteMessage',
|
||||
messageId: msg.messageId
|
||||
})
|
||||
};
|
||||
|
||||
export async function deleteBannedUserMessagesFromChatWidget(msg: EventSubChannelBanEvent) {
|
||||
sendTwitchEvent({
|
||||
function: 'userBan',
|
||||
chatterId: msg.userId
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,14 +12,20 @@ export type deleteMessageEvent = {
|
||||
function: 'deleteMessage';
|
||||
messageId: string;
|
||||
};
|
||||
export type userBanEvent = {
|
||||
function: 'userBan';
|
||||
chatterId: string;
|
||||
};
|
||||
export type serverNotificationEvent = {
|
||||
function: 'serverNotification';
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type twitchEventData = createMessageEvent |
|
||||
deleteMessageEvent |
|
||||
serverNotificationEvent;
|
||||
export type twitchEventData =
|
||||
createMessageEvent
|
||||
| deleteMessageEvent
|
||||
| userBanEvent
|
||||
| serverNotificationEvent;
|
||||
|
||||
// The types below are taken straight from @twurple/eventsub-base
|
||||
// I would import this from the package, but that's impossible
|
||||
|
||||
@@ -18,10 +18,14 @@ socket.onmessage = event => {
|
||||
case 'createMessage':
|
||||
const newMessageElement = parseMessage(data);
|
||||
newMessageElement.id = data.messageId;
|
||||
newMessageElement.classList.add(data.chatterId);
|
||||
document.querySelector("#message-container")?.appendChild(newMessageElement);
|
||||
break;
|
||||
case 'deleteMessage':
|
||||
document.querySelector(`#${CSS.escape(data.messageId)}`)?.remove();
|
||||
document.querySelectorAll(`#${CSS.escape(data.messageId)}`).forEach(msg => msg.remove());
|
||||
break;
|
||||
case 'userBan':
|
||||
document.querySelectorAll(`.${CSS.escape(data.chatterId)}`).forEach(msg => msg.remove());
|
||||
break;
|
||||
case 'serverNotification':
|
||||
console.log(data.message);
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
import { Cheer } from ".";
|
||||
import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"
|
||||
import { changeItemCount } from "../items";
|
||||
import { Cheer, handleNoTarget } from ".";
|
||||
import { sendMessage } from "../commands";
|
||||
import { getUserRecord } from "../db/dbUser";
|
||||
import { User } from "../user";
|
||||
import { timeout } from "../lib/timeout";
|
||||
import { createTimeoutRecord } from "../db/dbTimeouts";
|
||||
import logger from "../lib/logger";
|
||||
import { parseCheerArgs } from "../lib/parseCommandArgs";
|
||||
|
||||
const ITEMNAME = 'silverbullet';
|
||||
|
||||
export default new Cheer('execute', 6666, async (msg, user) => {
|
||||
const args = parseCheerArgs(msg.messageText);
|
||||
if (!args[0]) { await handleNoExecuteTarget(msg, user, false); return; };
|
||||
if (!args[0]) { await handleNoTarget(msg, user, ITEMNAME, false); return; };
|
||||
const target = await User.initUsername(args[0].toLowerCase());
|
||||
if (!target) { await handleNoExecuteTarget(msg, user, false); return; };
|
||||
if (!target) { await handleNoTarget(msg, user, ITEMNAME, false); return; };
|
||||
await getUserRecord(target);
|
||||
|
||||
const result = await timeout(target, `You got executed by ${user.displayName}!`, 60 * 60 * 24);
|
||||
if (result.status) await Promise.all([
|
||||
sendMessage(`${target.displayName} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`),
|
||||
createTimeoutRecord(user, target, 'silverbullet'),
|
||||
createTimeoutRecord(user, target, ITEMNAME),
|
||||
]);
|
||||
else {
|
||||
await handleNoExecuteTarget(msg, user);
|
||||
await handleNoTarget(msg, user, ITEMNAME);
|
||||
switch (result.reason) {
|
||||
case "banned":
|
||||
await sendMessage(`${target.displayName} is already timed out/banned`, msg.messageId);
|
||||
@@ -40,15 +39,3 @@ export default new Cheer('execute', 6666, async (msg, user) => {
|
||||
};
|
||||
});
|
||||
|
||||
async function handleNoExecuteTarget(msg: EventSubChannelChatMessageEvent, user: User, silent = true) {
|
||||
if (await user.itemLock()) {
|
||||
await sendMessage(`Cannot give ${user.displayName} a silver bullet`, msg.messageId);
|
||||
logger.err(`Failed to give ${user.displayName} a silver bullet for their cheer`);
|
||||
return;
|
||||
};
|
||||
await user.setLock();
|
||||
const userRecord = await getUserRecord(user);
|
||||
if (!silent) await sendMessage('No (valid) target specified. You got a silver bullet!', msg.messageId);
|
||||
await changeItemCount(user, userRecord, 'silverbullet', 1);
|
||||
await user.clearLock();
|
||||
};
|
||||
|
||||
@@ -27,3 +27,21 @@ for (const file of files) {
|
||||
|
||||
export default cheers;
|
||||
export { namedcheers };
|
||||
|
||||
import { sendMessage } from '../commands';
|
||||
import logger from '../lib/logger';
|
||||
import { getUserRecord } from '../db/dbUser';
|
||||
import { changeItemCount } from '../items';
|
||||
|
||||
export async function handleNoTarget(msg: EventSubChannelChatMessageEvent, user: User, itemname: string, 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`);
|
||||
return;
|
||||
};
|
||||
await user.setLock();
|
||||
const userRecord = await getUserRecord(user);
|
||||
if (!silent) await sendMessage(`No (valid) target specified. You got a ${itemname}!`, msg.messageId);
|
||||
await changeItemCount(user, userRecord, itemname, 1);
|
||||
await user.clearLock();
|
||||
}
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
import { Cheer } from ".";
|
||||
import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"
|
||||
import { changeItemCount } from "../items";
|
||||
import { Cheer, handleNoTarget } from ".";
|
||||
import { sendMessage } from "../commands";
|
||||
import { getUserRecord } from "../db/dbUser";
|
||||
import { User } from "../user";
|
||||
import { timeout } from "../lib/timeout";
|
||||
import { createTimeoutRecord } from "../db/dbTimeouts";
|
||||
import logger from "../lib/logger";
|
||||
import { parseCheerArgs } from "../lib/parseCommandArgs";
|
||||
|
||||
const ITEMNAME = 'blaster';
|
||||
|
||||
export default new Cheer('timeout', 100, async (msg, user) => {
|
||||
const args = parseCheerArgs(msg.messageText);
|
||||
if (!args[0]) { await handleNoBlasterTarget(msg, user, false); return; };
|
||||
if (!args[0]) { await handleNoTarget(msg, user, ITEMNAME, false); return; };
|
||||
const target = await User.initUsername(args[0].toLowerCase());
|
||||
if (!target) { await handleNoBlasterTarget(msg, user, false); return; };
|
||||
if (!target) { await handleNoTarget(msg, user, ITEMNAME, false); return; };
|
||||
await getUserRecord(target);
|
||||
|
||||
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`),
|
||||
createTimeoutRecord(user, target, 'blaster'),
|
||||
createTimeoutRecord(user, target, ITEMNAME)
|
||||
]);
|
||||
else {
|
||||
await handleNoBlasterTarget(msg, user);
|
||||
await handleNoTarget(msg, user, ITEMNAME);
|
||||
switch (result.reason) {
|
||||
case "banned":
|
||||
await sendMessage(`${target.displayName} is already timed out/banned`, msg.messageId);
|
||||
@@ -39,16 +38,3 @@ export default new Cheer('timeout', 100, async (msg, user) => {
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
async function handleNoBlasterTarget(msg: EventSubChannelChatMessageEvent, user: User, silent = true) {
|
||||
if (await user.itemLock()) {
|
||||
await sendMessage(`Cannot give ${user.displayName} a blaster`, msg.messageId);
|
||||
logger.err(`Failed to give ${user.displayName} a blaster for their cheer`);
|
||||
return;
|
||||
};
|
||||
await user.setLock();
|
||||
const userRecord = await getUserRecord(user);
|
||||
if (!silent) await sendMessage('No (valid) target specified. You got a blaster!', msg.messageId);
|
||||
await changeItemCount(user, userRecord, 'blaster', 1);
|
||||
await user.clearLock();
|
||||
};
|
||||
|
||||
30
src/cheers/tnt.ts
Normal file
30
src/cheers/tnt.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Cheer, handleNoTarget } from ".";
|
||||
import { sendMessage } from "../commands";
|
||||
import { getUserRecord } from "../db/dbUser";
|
||||
import { User } from "../user";
|
||||
import { timeout } from "../lib/timeout";
|
||||
import { createTimeoutRecord } from "../db/dbTimeouts";
|
||||
import { getTNTTargets } from "../items/tnt";
|
||||
import { redis } from "bun";
|
||||
|
||||
const ITEMNAME = 'tnt';
|
||||
|
||||
export default new Cheer('tnt', 1000, async (msg, user) => {
|
||||
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); handleNoTarget(msg, user, ITEMNAME); return; };
|
||||
const targets = getTNTTargets(vulntargets);
|
||||
|
||||
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
|
||||
await Promise.all([
|
||||
timeout(target!, `You got hit by ${user.displayName}'s TNT!`, 60),
|
||||
redis.del(`user:${targetid}:vulnerable`),
|
||||
sendMessage(`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`),
|
||||
createTimeoutRecord(user, target!, ITEMNAME),
|
||||
]);
|
||||
}));
|
||||
|
||||
await sendMessage(`RIPBOZO ${user.displayName} exploded ${targets.length} chatter${targets.length === 1 ? '' : 's'} with their TNT RIPBOZO`);
|
||||
});
|
||||
|
||||
6
src/events/banned.ts
Normal file
6
src/events/banned.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { eventSub, streamerId } from "..";
|
||||
import { deleteBannedUserMessagesFromChatWidget } from "../chatwidget/message";
|
||||
|
||||
eventSub.onChannelBan(streamerId, async msg => {
|
||||
deleteBannedUserMessagesFromChatWidget(msg);
|
||||
});
|
||||
@@ -62,7 +62,7 @@ export async function handleCheer(msg: EventSubChannelChatMessageEvent, bits: nu
|
||||
const selection = cheers.get(bits);
|
||||
if (!selection) return;
|
||||
|
||||
if (await redis.sismember('disabledcheers', selection.name)) { await sendMessage(`The ${selection.name} cheer is disabled`); return; };
|
||||
if (await redis.sismember('disabledcheers', selection.name)) { await sendMessage(`The ${selection.name} cheer is disabled! Sorry!`, msg.messageId); return; };
|
||||
try {
|
||||
selection.execute(msg, user);
|
||||
} catch (err) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import logger from "./lib/logger";
|
||||
import { addInvuln } from "./lib/invuln";
|
||||
|
||||
const CHATTERINTENTS = ["user:read:chat", "user:write:chat", "user:bot"];
|
||||
const STREAMERINTENTS = ["user:read:chat", "moderation:read", "channel:manage:moderators", "moderator:manage:banned_users", "bits:read"];
|
||||
const STREAMERINTENTS = ["user:read:chat", "moderation:read", "channel:manage:moderators", "moderator:manage:banned_users", "bits:read", "channel:moderate"];
|
||||
|
||||
export const singleUserMode = process.env.CHATTER_IS_STREAMER === 'true';
|
||||
export const chatterId = process.env.CHATTER_ID ?? "";
|
||||
|
||||
@@ -27,7 +27,7 @@ export default new Item(ITEMNAME, 'TNT', 's',
|
||||
await getUserRecord(target!); // make sure the user record exist in the database
|
||||
await Promise.all([
|
||||
timeout(target!, `You got hit by ${user.displayName}'s TNT!`, 60),
|
||||
redis.del(targetid),
|
||||
redis.del(`user:${targetid}:vulnerable`),
|
||||
sendMessage(`wybuh ${target?.displayName} got hit by ${user.displayName}'s TNT wybuh`),
|
||||
createTimeoutRecord(user, target!, ITEMNAME),
|
||||
]);
|
||||
@@ -42,7 +42,7 @@ export default new Item(ITEMNAME, 'TNT', 's',
|
||||
}
|
||||
);
|
||||
|
||||
function getTNTTargets<T>(arr: T[]): T[] {
|
||||
export function getTNTTargets<T>(arr: T[]): T[] {
|
||||
if (arr.length <= 5) {
|
||||
return arr;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user