Cursor user data commands logger update

This commit is contained in:
Hri7566 2023-10-27 14:53:14 -04:00
parent 9aaa43e7db
commit aef1e208a4
17 changed files with 598 additions and 56 deletions

View File

@ -1,16 +1,32 @@
import { Inventory, User } from "@prisma/client";
import { createUser, readUser } from "../data/user";
import { ServiceAgent } from "../services/ServiceAgent";
import { Command } from "./Command";
import { CommandGroup } from "./CommandGroup";
import { Prefix } from "./Prefix";
import { createInventory, readInventory } from "../data/inventory";
export interface CommandMessage<T = unknown> {
m: "command";
a: string;
argv: string[];
argc: number;
p: {
_id: string;
platformId: string;
name: string;
color: string;
};
originalMessage: T;
user: NonNullable<User>;
inventory: NonNullable<Inventory>;
}
export type BaseCommandMessage<T = unknown> = Omit<
CommandMessage<T>,
"user" | "inventory"
>;
export class CommandHandler {
public static commandGroups = new Array<CommandGroup>();
public static prefixes = new Array<Prefix>(
@ -29,9 +45,39 @@ export class CommandHandler {
}
public static async handleCommand(
msg: CommandMessage,
msg: Omit<CommandMessage, "user" | "inventory">,
agent: ServiceAgent<unknown>
) {
// Get user data
let user = await readUser(msg.p._id);
if (!user) {
await createUser({
id: msg.p._id,
platform: agent.platform,
platformId: msg.p.platformId,
name: msg.p.name
});
user = await readUser(msg.p._id);
if (!user)
return "Somehow, something has gone terribly wrong and I can't create user data for you. I can't run your command now.";
}
// Get inventory data
let inventory = await readInventory(msg.p._id);
if (!inventory) {
await createInventory({
userId: msg.p._id,
items: []
});
inventory = await readInventory(msg.p._id);
if (!inventory)
return "You have no inventory and I have been told I can't give you one. Sorry, your command won't work without it.";
}
let usedPrefix: Prefix | undefined;
for (const prefix of this.prefixes) {
@ -40,6 +86,7 @@ export class CommandHandler {
if (prefix.spaced) {
msg.argv.splice(0, 1);
msg.argc--;
}
break;
@ -67,8 +114,11 @@ export class CommandHandler {
if (!usedCommand) return;
(msg as CommandMessage).user = user;
(msg as CommandMessage).inventory = inventory;
try {
const out = usedCommand.callback(msg, agent);
const out = usedCommand.callback(msg as CommandMessage, agent);
if (out) return out;
} catch (err) {
console.error(err);

View File

@ -1,10 +1,10 @@
import { Command } from "../../Command";
export const help = new Command(
export const about = new Command(
"about",
["about", "info"],
"get about bozo",
"{prefix}about",
"about",
(msg, agent) => {
return `This is a dumb chat bot`;
}

View File

@ -1,11 +1,46 @@
import { Command } from "../../Command";
import { CommandHandler } from "../../CommandHandler";
export const help = new Command(
"help",
["help", "h", "commands", "cmds"],
"get help bozo",
"{prefix}help",
"help [command]",
(msg, agent) => {
return "test";
if (msg.argv[1]) {
// Get command usage
let command: Command | undefined;
commandGroupLoop: for (const commandGroup of CommandHandler.commandGroups) {
commandLoop: for (const cmd of commandGroup.commands) {
if (cmd.aliases.includes(msg.argv[1])) {
command = cmd;
break commandGroupLoop;
}
}
}
if (!command) return `Command "${msg.argv[1]}" not found.`;
return `🌟 Description: ${command.description} | 🛠 Usage: ${command.usage}`;
} else {
// Just list commands
const list = CommandHandler.commandGroups.map(commandGroup => {
return (
commandGroup.displayName +
": " +
commandGroup.commands
.map(command => {
if (!command.visible) return;
return command.aliases[0];
})
.filter(val => {
return typeof val !== "undefined";
})
.join(" | ")
);
});
return list.join("\n");
}
}
);

View File

@ -0,0 +1,14 @@
import { MPPAgent } from "../../../services/mpp";
import { Command } from "../../Command";
export const id = new Command(
"id",
["id"],
"get your id bozo",
"id",
(msg, agent) => {
if (!(agent as MPPAgent).client.isConnected) return;
return `ID: \`${(msg.originalMessage as any).p._id}\``;
},
false
);

View File

@ -6,7 +6,7 @@ export const math = new Command(
"math",
["math"],
"math bozo",
"{prefix}math",
"math <expression>",
(msg, agent) => {
try {
const argcat = msg.argv.slice(1, msg.argv.length).join(" ");

View File

@ -0,0 +1,17 @@
import { MPPAgent } from "../../../services/mpp";
import { Command } from "../../Command";
export const memory = new Command(
"memory",
["memory", "mem"],
"get the memory bozo",
"memory",
(msg, agent) => {
return `${(process.memoryUsage().heapUsed / 1000 / 1000).toFixed(
2
)} MB / ${(process.memoryUsage().heapTotal / 1000 / 1000).toFixed(
2
)} MB`;
},
false
);

View File

@ -0,0 +1,14 @@
import { MPPAgent } from "../../../services/mpp";
import { Command } from "../../Command";
export const msg = new Command(
"msg",
["msg"],
"get your msg bozo",
"msg",
(msg, agent) => {
if (!(agent as MPPAgent).client.isConnected) return;
return `${JSON.stringify(msg)}`;
},
false
);

View File

@ -1,14 +1,18 @@
import { CommandGroup } from "./CommandGroup";
import { CommandHandler } from "./CommandHandler";
import { about } from "./commands/general/about";
import { help } from "./commands/general/help";
import { id } from "./commands/utility/id";
import { msg } from "./commands/utility/msg";
import { math } from "./commands/utility/math";
import { memory } from "./commands/utility/memory";
export function loadCommands() {
const general = new CommandGroup("general", "General");
general.addCommands([help]);
const general = new CommandGroup("general", "General");
general.addCommands([help, about]);
CommandHandler.addCommandGroup(general);
const utility = new CommandGroup("utility", "Utility");
utility.addCommands([math]);
const utility = new CommandGroup("utility", "🔨 Utility");
utility.addCommands([math, memory, id, msg]);
CommandHandler.addCommandGroup(utility);
}

26
src/data/inventory.ts Normal file
View File

@ -0,0 +1,26 @@
import { Inventory, Prisma, User } from "@prisma/client";
import { prisma } from "./prisma";
export async function createInventory(data: Omit<Inventory, "id">) {
await prisma.inventory.create({
data: {
userId: data.userId,
items: data.items as any[]
}
});
}
export async function readInventory(userId: Inventory["userId"]) {
return await prisma.inventory.findUnique({ where: { userId: userId } });
}
export async function updateInventory(data: Omit<Inventory, "id">) {
return await prisma.inventory.update({
where: { userId: data.userId },
data: {}
});
}
export async function deleteInventory(userId: Inventory["userId"]) {
return await prisma.inventory.delete({ where: { userId } });
}

3
src/data/prisma.ts Normal file
View File

@ -0,0 +1,3 @@
import { PrismaClient } from "@prisma/client";
export const prisma = new PrismaClient();

18
src/data/user.ts Normal file
View File

@ -0,0 +1,18 @@
import { Prisma, User } from "@prisma/client";
import { prisma } from "./prisma";
export async function createUser(data: User) {
await prisma.user.create({ data });
}
export async function readUser(id: User["id"]) {
return await prisma.user.findUnique({ where: { id } });
}
export async function updateUser(data: User) {
return await prisma.user.update({ where: { id: data.id }, data });
}
export async function deleteUser(id: User["id"]) {
return await prisma.user.delete({ where: { id } });
}

View File

@ -1,7 +1,7 @@
import EventEmitter from "events";
export abstract class ServiceAgent<T> extends EventEmitter {
constructor(public client: T) {
constructor(public platform: string, public client: T) {
super();
this.bindEventListeners();
}

View File

@ -17,6 +17,31 @@ const config = loadConfig("config/services.yml", {
enableSwitchChat: false
});
interface MPPNetConfig {
desiredUser: {
name: string;
color: string;
};
agents: Record<
string,
{ id: string; overrideToken?: string; overrideName?: string }[]
>;
}
const mppConfig = loadConfig<MPPNetConfig>("config/mpp_net_channels.yml", {
desiredUser: {
name: "🟇 𝙎𝙪𝙥𝙚𝙧 Cosmic (*help)",
color: "#1d0054"
},
agents: {
"wss://mppclone.com": [
{
id: "✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧"
}
]
}
});
export class ServiceLoader {
public static agents = new Array<ServiceAgent<unknown>>();
@ -26,14 +51,24 @@ export class ServiceLoader {
public static loadServices() {
if (config.enableMPP) {
// TODO Implement URI and channel configuration
const testAgent = new MPPAgent(
"wss://mppclone.com:8443",
env.MPPNET_TOKEN
);
for (const uri of Object.keys(mppConfig.agents)) {
for (const channel of mppConfig.agents[uri]) {
const mppAgent = new MPPAgent(
uri,
channel.id,
channel.overrideName
? {
name: channel.overrideName,
color: mppConfig.desiredUser.color
}
: mppConfig.desiredUser,
env.MPPNET_TOKEN
);
testAgent.start();
this.addAgent(testAgent);
mppAgent.start();
this.addAgent(mppAgent);
}
}
}
if (config.enableSwitchChat) {

196
src/services/mpp/Cursor.ts Normal file
View File

@ -0,0 +1,196 @@
import { MPPAgent } from ".";
interface Vector2 {
x: number;
y: number;
}
interface CursorProps {
currentAnimation: string;
position: Vector2;
oldPosition: Vector2;
velocity: Vector2;
acceleration: Vector2;
t: number;
ot: number;
dt: number;
gravity: number;
angles: number[];
following: string;
}
export class Cursor {
public visible: boolean = true;
public displayInterval: NodeJS.Timeout;
public updateInterval: NodeJS.Timeout;
public props: CursorProps = {
currentAnimation: "lemniscate",
position: {
x: 50,
y: 50
},
oldPosition: {
x: 0,
y: 0
},
velocity: {
x: 0,
y: 0
},
acceleration: {
x: 0,
y: 0
},
t: Date.now(),
ot: Date.now(),
dt: 0,
gravity: 98,
angles: [],
following: ""
};
constructor(public agent: MPPAgent) {
this.displayInterval = setInterval(() => {
if (
this.props.oldPosition.x !== this.props.position.x ||
this.props.oldPosition.y !== this.props.position.y
) {
this.agent.client.sendArray([
{
m: "m",
x: this.props.position.x.toFixed(2).toString(),
y: this.props.position.y.toFixed(2).toString()
}
]);
}
}, 1000 / 20);
this.updateInterval = setInterval(() => {
switch (this.props.currentAnimation) {
case "bounce":
this.props.oldPosition.x = this.props.position.x;
this.props.oldPosition.y = this.props.position.y;
this.props.t = Date.now();
this.props.dt = (this.props.t - this.props.ot) / 1000;
this.props.acceleration.x = Math.random() * 100 - 50;
if (this.props.position.y < 75) {
this.props.acceleration.y =
Math.random() * 100 - 50 + this.props.gravity;
} else {
this.props.acceleration.y = -(Math.random() * 50);
}
this.props.velocity.x +=
this.props.acceleration.x * this.props.dt;
this.props.velocity.y +=
this.props.acceleration.y * this.props.dt;
this.props.position.x +=
this.props.velocity.x * this.props.dt;
this.props.position.y +=
this.props.velocity.y * this.props.dt;
if (
this.props.position.x >= 100 ||
this.props.position.x <= 0
) {
this.props.velocity.x = -this.props.velocity.x;
}
if (
this.props.position.y >= 100 ||
this.props.position.y <= 0
) {
this.props.velocity.y = -this.props.velocity.y;
}
if (
this.props.position.x <= -5 ||
this.props.position.x >= 105
) {
this.props.position.x = 50;
}
if (
this.props.position.y <= -5 ||
this.props.position.y >= 105
) {
this.props.position.y = 50;
}
this.props.ot = Date.now();
break;
case "constrained":
this.props.oldPosition.x = this.props.position.x;
this.props.oldPosition.y = this.props.position.y;
this.props.t = Date.now();
this.props.dt = (this.props.t - this.props.ot) / 1000;
this.props.acceleration.x = Math.random() * 100 - 50;
this.props.velocity.x +=
this.props.acceleration.x * this.props.dt;
this.props.position.x +=
this.props.velocity.x * this.props.dt;
if (
this.props.position.x >= 100 ||
this.props.position.x <= 0
) {
this.props.velocity.x = -this.props.velocity.x;
}
if (
this.props.position.y >= 100 ||
this.props.position.y <= 0
) {
this.props.velocity.y = -this.props.velocity.y;
}
if (
this.props.position.x <= -5 ||
this.props.position.x >= 105
) {
this.props.position.x = 50;
}
if (
this.props.position.y <= -5 ||
this.props.position.y >= 105
) {
this.props.position.y = 50;
}
this.props.ot = Date.now();
break;
case "lemniscate":
if (!this.props.angles[0]) this.props.angles[0] = 0;
this.props.angles[0] += 1;
if (this.props.angles[0] > 360) this.props.angles[0] = 0;
this.props.position.x =
Math.cos(this.props.angles[0] * (Math.PI / 180)) * 10 +
50;
this.props.position.y =
Math.sin(this.props.angles[0] * (Math.PI / 180) * 3) *
10 +
50;
break;
}
}, 1000 / 60);
}
public show() {
this.visible = true;
}
public hide() {
this.visible = false;
}
}

View File

@ -1,20 +1,21 @@
import Client from "mpp-client-net";
import { ServiceAgent } from "../ServiceAgent";
import { ptr } from "bun:ffi";
let p;
import { CommandHandler } from "../../commands/CommandHandler";
import { Cursor } from "./Cursor";
export class MPPAgent extends ServiceAgent<Client> {
public desiredUser = {
name: "🟇 𝙎𝙪𝙥𝙚𝙧 Cosmic (no commands yet)",
color: "#1d0054"
};
public cursor: Cursor;
public desiredChannel = "nothing";
constructor(uri: string, token: string) {
constructor(
uri: string,
public desiredChannel: string,
public desiredUser: { name: string; color: string },
token: string
) {
const cl = new Client(uri, token);
super(cl);
super("mpp", cl);
this.emit("log", desiredChannel);
this.cursor = new Cursor(this);
}
public start() {
@ -31,31 +32,85 @@ export class MPPAgent extends ServiceAgent<Client> {
this.client.on("hi", msg => {
this.emit("log", msg.u);
this.client.setChannel(this.desiredChannel);
this.fixUser();
});
console.log(
msg.u.name !== this.desiredUser.name ||
msg.u.color !== this.desiredUser.color
this.client.on("t", msg => {
this.fixUser();
});
this.client.on("a", async msg => {
console.log(`${msg.p.name}: ${msg.a}`);
let args = msg.a.split(" ");
const str = await CommandHandler.handleCommand(
{
m: "command",
a: msg.a,
argc: args.length,
argv: args,
p: {
_id: "MPP_" + this.client.uri + "_" + msg.p._id,
name: msg.p.name,
color: msg.p.color,
platformId: msg.p._id
},
originalMessage: msg
},
this
);
if (
msg.u.name !== this.desiredUser.name ||
msg.u.color !== this.desiredUser.color
) {
// setTimeout(() => {
this.client.sendArray([
{
m: "userset",
set: this.desiredUser
if (str) {
if (str.includes("\n")) {
let sp = str.split("\n");
for (const s of sp) {
this.client.sendArray([
{
m: "a",
message: `\u034f${s}`
}
]);
}
]);
// }, 1000);
} else {
this.client.sendArray([
{
m: "a",
message: `\u034f${str}`
}
]);
}
}
});
}
this.client.on("a", msg => {
p = ptr(new TextEncoder().encode(msg.a).buffer);
// handleCommand(p);
console.log(`${msg.p.name}: ${msg.a}`);
});
public fixUser() {
if (!this.client.user) return;
if (
this.client.user.name !== this.desiredUser.name ||
this.client.user.color !== this.desiredUser.color
) {
this.client.sendArray([
{
m: "userset",
set: this.desiredUser
}
]);
}
}
public getParticipant(fuzzy: string) {
for (const p of Object.values(this.client.ppl)) {
if (!p._id.includes(fuzzy) && !p.name.includes(fuzzy)) return;
return p as unknown as {
name: string;
_id: string;
id: string;
color: string;
x: number;
y: number;
};
}
}
}

View File

@ -1,4 +1,8 @@
import { CommandHandler, CommandMessage } from "../../commands/CommandHandler";
import {
BaseCommandMessage,
CommandHandler,
CommandMessage
} from "../../commands/CommandHandler";
import { loadConfig } from "../../util/config";
import { ServiceAgent } from "../ServiceAgent";
import { Client } from "switchchat";
@ -15,7 +19,7 @@ export class SwitchChatAgent extends ServiceAgent<Client> {
constructor(token: string) {
const cl = new Client(token);
super(cl);
super("mc", cl);
this.client.defaultName = this.desiredUser.name;
this.client.defaultFormattingMode = "markdown";
@ -41,12 +45,18 @@ export class SwitchChatAgent extends ServiceAgent<Client> {
} ${cmd.args.join(" ")}`
);
const message: CommandMessage = {
const message: BaseCommandMessage = {
m: "command",
a: `${cmd.command} ${cmd.args.join(" ")}`,
argc: cmd.args.length + 1,
argv: [cmd.command, ...cmd.args],
originalMessage: cmd
originalMessage: cmd,
p: {
_id: "MC_" + cmd.user.uuid,
name: cmd.user.displayName,
color: "#000000",
platformId: cmd.user.uuid
}
};
const out = await CommandHandler.handleCommand(message, this);
@ -54,8 +64,8 @@ export class SwitchChatAgent extends ServiceAgent<Client> {
if (out) await this.client.tell(cmd.user.name, out);
});
this.client.on("rawraw", data => {
console.log(data);
});
// this.client.on("rawraw", data => {
// console.log(data);
// });
}
}

65
src/util/Logger.ts Normal file
View File

@ -0,0 +1,65 @@
// Gray console text
export function unimportant(str: string) {
return `\x1b[90m${str}\x1b[0m`;
}
// Pad time strings
export function padNum(
num: number,
padAmount: number,
padChar: string,
left: boolean = true
) {
return left
? num.toString().padStart(padAmount, padChar)
: num.toString().padEnd(padAmount, padChar);
}
export class Logger {
private static log(method: string, ...args: any[]) {
(console as unknown as Record<string, (..._args: any[]) => any>)[
method
](
unimportant(this.getDate()),
unimportant(this.getHHMMSSMS()),
...args
);
}
public static getHHMMSSMS() {
const ms = Date.now();
const s = ms / 1000;
const m = s / 60;
const h = m / 60;
const ss = padNum(Math.floor(s) % 60, 2, "0");
const mm = padNum(Math.floor(m) % 60, 2, "0");
const hh = padNum(Math.floor(h) % 24, 2, "0");
const ll = padNum(ms % 1000, 3, "0");
return `${hh}:${mm}:${ss}.${ll}`;
}
public static getDate() {
return new Date().toISOString().split("T")[0];
}
constructor(public id: string) {}
public info(...args: any[]) {
Logger.log("log", `[${this.id}]`, `\x1b[34m[info]\x1b[0m`, ...args);
}
public error(...args: any[]) {
Logger.log("error", `[${this.id}]`, `\x1b[31m[error]\x1b[0m`, ...args);
}
public warn(...args: any[]) {
Logger.log("warn", `[${this.id}]`, `\x1b[33m[warn]\x1b[0m`, ...args);
}
public debug(...args: any[]) {
Logger.log("debug", `[${this.id}]`, `\x1b[32m[debug]\x1b[0m`, ...args);
}
}