fix tsc configs, add realsilverbullets for 6666 bits

This commit is contained in:
2025-12-06 04:51:34 +01:00
parent c37d2f0a8b
commit afbf08f21a
15 changed files with 136 additions and 19 deletions

View File

@@ -217,6 +217,7 @@ NAME|AMOUNT|USAGE|FUNCTION
`superloot`|150|`cheer150`|Get superloot. Details and drop rates can be found [(here)](#lootbox).
`execute`|666|`cheer666 [target]`|Times specified or random vulnerable user out for 30 minutes. On failure gives cheerer a silver bullet
`tnt`|1000|`cheer1000`|Gives 5-10 random vulnerable chatters 60 second timeouts. On failure gives cheerer a TNT
`realsilverbullet`|6666|`cheer6666 [target]`|Times specified or random vulnerable chatter out for 24 hours. On failure gives the user nothing. Get scammed.
## Point Redeems

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.7/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
@@ -19,7 +19,8 @@
"suspicious": {
"noNonNullAssertedOptionalChain": "off",
"noExplicitAny": "off",
"noControlCharactersInRegex": "off"
"noControlCharactersInRegex": "off",
"noTsIgnore": "off"
},
"style": {
"noNonNullAssertion": "off"

View File

@@ -8,6 +8,7 @@
"pg": "^8.16.3"
},
"scripts": {
"check": "biome check && tsc -b",
"start": "NODE_ENV=production bun src/index.ts",
"start-dev": "NODE_ENV=development bun src/index.ts",
"start-discord": "NODE_ENV=production bun src/discord/index.ts",

View File

@@ -1,8 +1,16 @@
import type { EventSubChannelChatMessageEvent } from "@twurple/eventsub-base";
import type User from "user";
export type cheers =
| "execute"
| "grenade"
| "tnt"
| "timeout"
| "superloot"
| "realsilverbullet";
type cheerOptions = {
name: string;
name: cheers;
amount: number;
isItem: boolean;
execute: (
@@ -12,7 +20,7 @@ type cheerOptions = {
};
export class Cheer {
public readonly name: string;
public readonly name: cheers;
public readonly amount: number;
public readonly execute: (
msg: EventSubChannelChatMessageEvent,
@@ -20,7 +28,7 @@ export class Cheer {
) => Promise<void>;
public readonly isItem: boolean;
constructor(options: cheerOptions) {
this.name = options.name.toLowerCase();
this.name = options.name;
this.amount = options.amount;
this.execute = options.execute;
this.isItem = options.isItem;

View File

@@ -0,0 +1,88 @@
import { Cheer } from "cheers";
import { createCheerEventRecord } from "db/dbCheerEvents";
import { createTimeoutRecord } from "db/dbTimeouts";
import { getUserRecord } from "db/dbUser";
import { sendMessage } from "lib/commandUtils";
import { parseCheerArgs } from "lib/parseCommandArgs";
import { redis } from "lib/redis";
import { timeout } from "lib/timeout";
import User from "user";
import { playAlert } from "web/alerts/serverFunctions";
export default new Cheer({
name: "realsilverbullet",
amount: 6666,
isItem: false,
async execute(msg, user) {
const args = parseCheerArgs(msg.messageText);
let target: User | null;
if (!args[0]) {
const vulnsids = await redis.keys("user:*:vulnerable");
const baseusers = vulnsids.map((a) => User.initUserId(a.slice(5, -11)));
const users: User[] = [];
for (const user of baseusers) {
const a = await user;
if (!a) continue;
users.push(a);
}
if (users.length === 0) {
await sendMessage("No vulnerable chatters, -6666 KEKPOINT");
return;
}
target = users[Math.floor(Math.random() * users.length)]!;
await playAlert({
name: "blastinRoulette",
user: user.displayName,
targets: users.map((a) => a.displayName),
finaltarget: target.displayName,
});
await new Promise((res, _) => setTimeout(res, 4000));
} else {
target = await User.initUsername(args[0].toLowerCase());
}
if (!target) {
await sendMessage("dumbass wasted 6666 bits KEKPOINT", msg.messageId);
return;
}
await getUserRecord(target);
const result = await timeout(
target,
`You got fucking DELETED by ${user.displayName}!`,
60 * 60 * 24,
);
if (result.status)
await Promise.all([
sendMessage(
`KEKPOINT KEKPOINT KEKPOINT ${target.displayName.toUpperCase()} RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO RIPBOZO`,
),
createTimeoutRecord(user, target, "realsilverbullet"),
createCheerEventRecord(user, "realsilverbullet"),
playAlert({
name: "userExecution",
user: user.displayName,
target: target.displayName,
}),
]);
else {
switch (result.reason) {
case "banned":
await sendMessage(
`${target.displayName} is already timed out/banned`,
msg.messageId,
);
break;
case "illegal":
await Promise.all([
sendMessage(`${user.displayName} Nou Nou Nou`),
timeout(user, "nah", 60 * 60 * 24),
]);
break;
case "unknown":
await sendMessage("Something went wrong... oops", msg.messageId);
break;
}
}
},
});

View File

@@ -1,4 +1,5 @@
import { Cheer } from "cheers";
import { createCheerEventRecord } from "db/dbCheerEvents";
import { createGetLootRecord } from "db/dbGetLoot";
import { getUserRecord, updateUserRecord } from "db/dbUser";
import itemMap, { type inventory, type items } from "items";
@@ -80,6 +81,7 @@ export default new Cheer({
await Promise.all([
updateUserRecord(user, userData),
sendMessage(message, msg.messageId),
createCheerEventRecord(user, "superloot"),
createGetLootRecord(user, gainedqbucks, itemDiff, "superloot"),
user.clearLock(),
]);

View File

@@ -1,3 +1,4 @@
import type { cheers } from "cheers";
import db from "db/connection";
import { cheerEvents } from "db/schema";
import { and, between, eq, type SQL } from "drizzle-orm";
@@ -6,7 +7,7 @@ import type User from "user";
export async function createCheerEventRecord(
user: User,
cheer: items,
cheer: items | cheers,
): Promise<void> {
await db
.insert(cheerEvents)

View File

@@ -1,3 +1,4 @@
import type { cheers } from "cheers";
import db from "db/connection";
import { timeouts } from "db/schema";
import { and, between, eq, type SQL } from "drizzle-orm";
@@ -7,7 +8,7 @@ import type User from "user";
export async function createTimeoutRecord(
user: User,
target: User,
item: items,
item: items | cheers,
): Promise<void> {
await db.insert(timeouts).values({
user: parseInt(user.id, 10),

View File

@@ -1,4 +1,5 @@
import type { AccessToken } from "@twurple/auth";
import type { cheers as cheertypes } from "cheers";
import { relations } from "drizzle-orm";
import {
boolean,
@@ -42,7 +43,7 @@ export const timeouts = pgTable("timeouts", {
target: integer()
.notNull()
.references(() => users.id),
item: varchar().$type<items>().notNull(),
item: varchar().$type<items | cheertypes>().notNull(),
created: timestamp().defaultNow().notNull(),
});
@@ -80,7 +81,7 @@ export const cheerEvents = pgTable("cheerEvents", {
user: integer()
.notNull()
.references(() => users.id),
event: varchar().$type<items>().notNull(),
event: varchar().$type<items | cheertypes>().notNull(),
created: timestamp().defaultNow().notNull(),
});

View File

@@ -1,7 +1,9 @@
import { Command, type commandOptions } from "lib/commandUtils";
import type User from "user";
interface itemOptions extends commandOptions {
export type items = "blaster" | "silverbullet" | "grenade" | "tnt";
interface itemOptions extends Omit<commandOptions, "usertype"> {
name: items;
prettyName: string;
plural: string;
@@ -10,7 +12,7 @@ interface itemOptions extends commandOptions {
}
export class Item extends Command {
public readonly name: items;
public readonly name: items = "blaster";
public readonly prettyName: string;
public readonly plural: string;
public readonly description: string;
@@ -18,9 +20,11 @@ export class Item extends Command {
/** Creates an item object */
constructor(options: itemOptions) {
options.disableable = true; // Items can always be disabled
options.usertype = "chatter"; // Everyone can use items
super(options);
super({
...options,
usertype: "chatter", // Everyone can use items
disableable: true, // Items can always be disabled
});
this.name = options.name;
this.prettyName = options.prettyName;
this.plural = options.plural;
@@ -59,7 +63,6 @@ for (const file of files) {
export default itemAliasMap;
export { emptyInventory, itemarray, specialAliasItems, itemObjectArray };
export type items = "blaster" | "silverbullet" | "grenade" | "tnt";
export type inventory = {
[key in items]?: number;
};

View File

@@ -59,8 +59,11 @@ export async function getItemStats(target: User, thismonth: boolean) {
}
for (const cheer of cheers) {
if (!returnObj[cheer.event]) returnObj[cheer.event] = 0;
returnObj[cheer.event]! += 1;
if (cheer.event in returnObj) {
if (!returnObj[cheer.event as keyof inventory])
returnObj[cheer.event as keyof inventory] = 0;
returnObj[cheer.event as keyof inventory]! += 1;
}
}
return returnObj;

View File

@@ -1,6 +1,7 @@
import type { alertEventData } from "web/alerts/types";
import type { serverInstruction } from "web/serverTypes";
import AlertManager from "./AlertManager";
// @ts-ignore
import "@fontsource/jersey-15";
import TTSManager from "./TTSManager";

View File

@@ -1,4 +1,6 @@
// @ts-ignore
import "./style.css";
// @ts-ignore
import "@fontsource/jersey-15";
import type { twitchEventData } from "web/chatWidget/websockettypes";

View File

@@ -1,6 +1,7 @@
{
"files": [],
"compilerOptions": {
"noEmit": true,
"baseUrl": "./src",
"paths": {
"lib/*": ["./lib/*"],

View File

@@ -3,7 +3,10 @@
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"lib": ["DOM", "ES2020"]
"moduleResolution": "bundler",
"lib": ["DOM", "ES2022"],
"skipLibCheck": true
},
"include": ["src/web/chatWidget/www/**/*", "src/web/alerts/www/**/*"]
"include": ["src/web/chatWidget/www/**/*", "src/web/alerts/www/**/*"],
"exclude": ["node_modules"]
}