mirror of
https://gitlab.com/qwerinope/qweribot.git
synced 2026-02-04 13:56:57 +01:00
rename bot directory to src, add chatwidget
This commit is contained in:
6
src/events/deleteMessage.ts
Normal file
6
src/events/deleteMessage.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { eventSub, streamerId } from "..";
|
||||
import { deleteMessageFromChatWidget } from "../chatwidget/message";
|
||||
|
||||
eventSub.onChannelChatMessageDelete(streamerId, streamerId, async msg => {
|
||||
deleteMessageFromChatWidget(msg);
|
||||
});
|
||||
67
src/events/index.ts
Normal file
67
src/events/index.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import kleur from "kleur";
|
||||
import { eventSub, streamerApi, streamerId } from "..";
|
||||
import logger from "../lib/logger";
|
||||
|
||||
eventSub.onRevoke(event => {
|
||||
logger.ok(`Successfully revoked EventSub subscription: ${kleur.underline(event.id)}`);
|
||||
});
|
||||
|
||||
eventSub.onSubscriptionCreateSuccess(event => {
|
||||
logger.ok(`Successfully created EventSub subscription: ${kleur.underline(event.id)}`);
|
||||
deleteDuplicateSubscriptions.refresh();
|
||||
});
|
||||
|
||||
eventSub.onSubscriptionCreateFailure(event => {
|
||||
logger.err(`Failed to create EventSub subscription: ${kleur.underline(event.id)}`);
|
||||
});
|
||||
|
||||
eventSub.onSubscriptionDeleteSuccess(event => {
|
||||
logger.ok(`Successfully deleted EventSub subscription: ${kleur.underline(event.id)}`);
|
||||
});
|
||||
|
||||
eventSub.onSubscriptionDeleteFailure(event => {
|
||||
logger.err(`Failed to delete EventSub subscription: ${kleur.underline(event.id)}`);
|
||||
});
|
||||
|
||||
import { readdir } from 'node:fs/promises';
|
||||
const files = await readdir(import.meta.dir);
|
||||
for (const file of files) {
|
||||
if (!file.endsWith('.ts')) continue;
|
||||
if (file === import.meta.file) continue;
|
||||
await import(import.meta.dir + '/' + file.slice(0, -3));
|
||||
};
|
||||
|
||||
eventSub.start();
|
||||
|
||||
import { getAuthRecord } from "../db/dbAuth";
|
||||
import { StaticAuthProvider } from "@twurple/auth";
|
||||
import { ApiClient, HelixEventSubSubscription } from "@twurple/api";
|
||||
|
||||
const deleteDuplicateSubscriptions = setTimeout(async () => {
|
||||
logger.info('Deleting all double subscriptions');
|
||||
const tokendata = await streamerApi.getTokenInfo();
|
||||
const authdata = await getAuthRecord(streamerId, []);
|
||||
const tempauth = new StaticAuthProvider(tokendata.clientId, authdata?.accesstoken.accessToken!);
|
||||
const tempapi: ApiClient = new ApiClient({ authProvider: tempauth });
|
||||
logger.info('Created the temporary API client');
|
||||
const subs = await tempapi.eventSub.getSubscriptionsForStatus('enabled');
|
||||
const seen = new Map();
|
||||
const duplicates: HelixEventSubSubscription[] = [];
|
||||
|
||||
for (const sub of subs.data) {
|
||||
if (seen.has(sub.type)) {
|
||||
if (!duplicates.some(o => o.type === sub.type)) {
|
||||
duplicates.push(seen.get(sub.type));
|
||||
};
|
||||
} else {
|
||||
seen.set(sub.type, sub);
|
||||
};
|
||||
};
|
||||
|
||||
for (const sub of duplicates) {
|
||||
await tempapi.eventSub.deleteSubscription(sub.id);
|
||||
logger.ok(`Deleted sub: id: ${sub.id}, type: ${sub.type}`);
|
||||
};
|
||||
if (duplicates.length === 0) logger.ok('No duplicate subscriptions found');
|
||||
else logger.ok('Deleted all duplicate EventSub subscriptions');
|
||||
}, 5000);
|
||||
72
src/events/message.ts
Normal file
72
src/events/message.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base"
|
||||
import { chatterId, streamerId, eventSub, commandPrefix, singleUserMode, streamerUsers } from "..";
|
||||
import { User } from "../user";
|
||||
import commands, { sendMessage } from "../commands";
|
||||
import { redis } from "bun";
|
||||
import { isAdmin } from "../lib/admins";
|
||||
import cheers from "../cheers";
|
||||
import logger from "../lib/logger";
|
||||
import { addMessageToChatWidget } from "../chatwidget/message";
|
||||
|
||||
logger.info(`Loaded the following commands: ${commands.keys().toArray().join(', ')}`);
|
||||
|
||||
eventSub.onChannelChatMessage(streamerId, streamerId, parseChatMessage);
|
||||
|
||||
async function parseChatMessage(msg: EventSubChannelChatMessageEvent) {
|
||||
addMessageToChatWidget(msg);
|
||||
if (!singleUserMode && msg.chatterId === chatterId) return;
|
||||
// return if double user mode is on and the chatter says something, we don't need them
|
||||
|
||||
const user = await User.initUsername(msg.chatterName);
|
||||
|
||||
// Get user from cache or place user in cache
|
||||
// Given the fact that this is the user that chats, this user object always exists and cannot be null
|
||||
//
|
||||
// One of the flaws with the user object is solved by creating the object with the name.
|
||||
// This way, if a user changes their name, the original name stays in the cache for at least 1 hour (extendable by using that name as target for item)
|
||||
// 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
|
||||
|
||||
if (!streamerUsers.includes(msg.chatterId)) user?.makeVulnerable(); // Make the user vulnerable to explosions if not streamerbot or chatterbot
|
||||
|
||||
if (!msg.isCheer && !msg.isRedemption) await handleChatMessage(msg, user!)
|
||||
else if (msg.isCheer && !msg.isRedemption) await handleCheer(msg, msg.bits, user!);
|
||||
};
|
||||
|
||||
async function handleChatMessage(msg: EventSubChannelChatMessageEvent, user: User) {
|
||||
// Parse commands:
|
||||
if (msg.messageText.startsWith(commandPrefix)) {
|
||||
const commandSelection = msg.messageText.slice(commandPrefix.length).split(' ')[0]!;
|
||||
const selected = commands.get(commandSelection.toLowerCase());
|
||||
if (!selected) return;
|
||||
if (await redis.sismember('disabledcommands', selected.name)) return;
|
||||
|
||||
switch (selected.usertype) {
|
||||
case "admin":
|
||||
if (!await isAdmin(user.id)) return;
|
||||
break;
|
||||
case "streamer":
|
||||
if (!streamerUsers.includes(msg.chatterId)) return;
|
||||
break;
|
||||
};
|
||||
|
||||
try { await selected.execute(msg, user); }
|
||||
catch (err) {
|
||||
logger.err(err as string);
|
||||
await sendMessage('ERROR: Something went wrong', msg.messageId);
|
||||
await user.clearLock();
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export async function handleCheer(msg: EventSubChannelChatMessageEvent, bits: number, user: User) {
|
||||
const selection = cheers.get(bits);
|
||||
if (!selection) return;
|
||||
|
||||
if (await redis.sismember('disabledcheers', selection.name)) { await sendMessage(`The ${selection.name} cheer is disabled`); return; };
|
||||
try {
|
||||
selection.execute(msg, user);
|
||||
} catch (err) {
|
||||
logger.err(err as string);
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user