Merge branch 'dev'
This commit is contained in:
commit
1a8a272c87
|
@ -2,7 +2,3 @@
|
||||||
channel:
|
channel:
|
||||||
id: "✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧"
|
id: "✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧"
|
||||||
allowColorChanging: true
|
allowColorChanging: true
|
||||||
- uri: wss://mppclone.com:8443
|
|
||||||
channel:
|
|
||||||
id: "test/fishing"
|
|
||||||
allowColorChanging: true
|
|
||||||
|
|
16
package.json
16
package.json
|
@ -8,22 +8,22 @@
|
||||||
"start-discord": "bun src/discord/index.ts"
|
"start-discord": "bun src/discord/index.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.1.6"
|
"@types/bun": "^1.1.9"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^5.16.1",
|
"@prisma/client": "^5.19.1",
|
||||||
"@trpc/client": "next",
|
"@trpc/client": "next",
|
||||||
"@trpc/server": "next",
|
"@trpc/server": "next",
|
||||||
"@types/node": "^20.14.10",
|
"@types/node": "^20.16.5",
|
||||||
"cli-markdown": "^3.4.0",
|
"cli-markdown": "^3.4.0",
|
||||||
"discord.js": "^14.15.3",
|
"discord.js": "^14.16.2",
|
||||||
"mpp-client-net": "^1.2.0",
|
"mpp-client-net": "^1.2.3",
|
||||||
"prisma": "^5.16.1",
|
"prisma": "^5.19.1",
|
||||||
"trpc-bun-adapter": "^1.1.1",
|
"trpc-bun-adapter": "^1.1.2",
|
||||||
"yaml": "^2.4.5",
|
"yaml": "^2.5.1",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { fid } from "./util/fid";
|
||||||
import { chance } from "./util/chance";
|
import { chance } from "./util/chance";
|
||||||
import { info } from "./general/info";
|
import { info } from "./general/info";
|
||||||
import { burger } from "./util/burger";
|
import { burger } from "./util/burger";
|
||||||
|
import { daily } from "./pokemon/daily";
|
||||||
// import { give } from "./inventory/give";
|
// import { give } from "./inventory/give";
|
||||||
|
|
||||||
interface ICommandGroup {
|
interface ICommandGroup {
|
||||||
|
@ -54,15 +55,23 @@ commandGroups.push(fishingGroup);
|
||||||
const inventoryGroup: ICommandGroup = {
|
const inventoryGroup: ICommandGroup = {
|
||||||
id: "inventory",
|
id: "inventory",
|
||||||
displayName: "Inventory",
|
displayName: "Inventory",
|
||||||
commands: [inventory, take, eat, sack, pokemon, yeet, burger /* give */]
|
commands: [inventory, sack, pokemon, take, eat, yeet, burger /* give */]
|
||||||
};
|
};
|
||||||
|
|
||||||
commandGroups.push(inventoryGroup);
|
commandGroups.push(inventoryGroup);
|
||||||
|
|
||||||
|
const pokemonGroup: ICommandGroup = {
|
||||||
|
id: "pokemon",
|
||||||
|
displayName: "Pokémon",
|
||||||
|
commands: [daily, pokedex]
|
||||||
|
};
|
||||||
|
|
||||||
|
commandGroups.push(pokemonGroup);
|
||||||
|
|
||||||
const utilGroup: ICommandGroup = {
|
const utilGroup: ICommandGroup = {
|
||||||
id: "util",
|
id: "util",
|
||||||
displayName: "Utility",
|
displayName: "Utility",
|
||||||
commands: [data, setcolor, memory, autofish, pokedex, fid, chance]
|
commands: [data, setcolor, memory, autofish, fid, chance]
|
||||||
};
|
};
|
||||||
|
|
||||||
commandGroups.push(utilGroup);
|
commandGroups.push(utilGroup);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import Command from "@server/commands/Command";
|
import Command from "@server/commands/Command";
|
||||||
|
import { logger } from "@server/commands/handler";
|
||||||
import { getInventory, updateInventory } from "@server/data/inventory";
|
import { getInventory, updateInventory } from "@server/data/inventory";
|
||||||
|
import { removeItem } from "@server/items";
|
||||||
import { itemBehaviorMap, runBehavior } from "@server/items/behavior";
|
import { itemBehaviorMap, runBehavior } from "@server/items/behavior";
|
||||||
|
|
||||||
export const eat = new Command(
|
export const eat = new Command(
|
||||||
|
@ -62,45 +64,9 @@ export const eat = new Command(
|
||||||
|
|
||||||
if (shouldRemove) {
|
if (shouldRemove) {
|
||||||
if (foundObject.objtype == "fish") {
|
if (foundObject.objtype == "fish") {
|
||||||
i = 0;
|
removeItem(inventory.fishSack, foundObject);
|
||||||
|
|
||||||
for (const fish of inventory.fishSack as TFishSack) {
|
|
||||||
if (typeof fish.count !== "undefined") {
|
|
||||||
if (fish.count > 1) {
|
|
||||||
shouldRemove = false;
|
|
||||||
((inventory.fishSack as TFishSack)[i]
|
|
||||||
.count as number)--;
|
|
||||||
} else {
|
|
||||||
shouldRemove = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
shouldRemove = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldRemove)
|
|
||||||
(inventory.fishSack as TFishSack).splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (foundObject.objtype == "item") {
|
} else if (foundObject.objtype == "item") {
|
||||||
i = 0;
|
removeItem(inventory.items, foundObject);
|
||||||
|
|
||||||
for (const item of inventory.items as unknown as IItem[]) {
|
|
||||||
if (typeof item.count == "number") {
|
|
||||||
if (item.count > 1) {
|
|
||||||
shouldRemove = false;
|
|
||||||
((inventory.items as TInventoryItems)[i]
|
|
||||||
.count as number)--;
|
|
||||||
} else {
|
|
||||||
shouldRemove = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
shouldRemove = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldRemove)
|
|
||||||
(inventory.items as TInventoryItems).splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateInventory(inventory);
|
await updateInventory(inventory);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import Command from "@server/commands/Command";
|
||||||
|
import { logger } from "@server/commands/handler";
|
||||||
|
import { claimDailyPokemon } from "@server/pokemon/daily";
|
||||||
|
|
||||||
|
export const daily = new Command(
|
||||||
|
"daily",
|
||||||
|
["daily", "dailypokemon"],
|
||||||
|
"Claim your daily Pokémon reward",
|
||||||
|
"daily",
|
||||||
|
"command.inventory.daily",
|
||||||
|
async ({ id, command, args, prefix, part, user }) => {
|
||||||
|
try {
|
||||||
|
const message = await claimDailyPokemon(user.id);
|
||||||
|
return message;
|
||||||
|
} catch (err) {
|
||||||
|
logger.error("Unable to perform daily claim:", err);
|
||||||
|
return `Congratulations, you broke the bot. Your daily reward might not work now.`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
|
@ -1,15 +1,16 @@
|
||||||
|
import type { User } from "@prisma/client";
|
||||||
import prisma from "./prisma";
|
import prisma from "./prisma";
|
||||||
|
|
||||||
export async function createInventory(inventory: Partial<IInventory>) {
|
export async function createInventory(inventory: Partial<IInventory>) {
|
||||||
return await prisma.inventory.create({
|
return (await prisma.inventory.create({
|
||||||
data: inventory
|
data: inventory
|
||||||
});
|
})) as IInventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getInventory(id: IInventory["id"]) {
|
export async function getInventory(id: IInventory["id"]) {
|
||||||
return await prisma.inventory.findUnique({
|
return (await prisma.inventory.findUnique({
|
||||||
where: { id }
|
where: { id }
|
||||||
});
|
})) as IInventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateInventory(inventory: Partial<IInventory>) {
|
export async function updateInventory(inventory: Partial<IInventory>) {
|
||||||
|
|
|
@ -108,7 +108,11 @@ export function hasFishTime(
|
||||||
|
|
||||||
export function getSizeString(cm: number) {
|
export function getSizeString(cm: number) {
|
||||||
const size =
|
const size =
|
||||||
cm < 30
|
cm < 5
|
||||||
|
? "microscopic"
|
||||||
|
: cm < 10
|
||||||
|
? "tiny"
|
||||||
|
: cm < 30
|
||||||
? "small"
|
? "small"
|
||||||
: cm < 60
|
: cm < 60
|
||||||
? "medium-sized"
|
? "medium-sized"
|
||||||
|
|
|
@ -23,3 +23,26 @@ export function addItem(arr: IObject[], item: IObject) {
|
||||||
(arr[i].count as number) += inc;
|
(arr[i].count as number) += inc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function removeItem(arr: IObject[], item: IObject, count = 1) {
|
||||||
|
let found = false;
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < arr.length; i++) {
|
||||||
|
if (item.id == arr[i].id) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const foundItem = arr[i];
|
||||||
|
if (!found || !foundItem) return false;
|
||||||
|
|
||||||
|
if (typeof foundItem.count == "number" && foundItem.count > 1) {
|
||||||
|
foundItem.count -= count;
|
||||||
|
} else {
|
||||||
|
arr.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { kvGet, kvSet } from "@server/data/keyValueStore";
|
||||||
|
import { Logger } from "@util/Logger";
|
||||||
|
import { getRandomPokemon } from "./pokedex";
|
||||||
|
import { getInventory, updateInventory } from "@server/data/inventory";
|
||||||
|
import { getUser } from "@server/data/user";
|
||||||
|
import { addItem } from "@server/items";
|
||||||
|
import { getHHMMSS } from "@util/time";
|
||||||
|
|
||||||
|
const logger = new Logger("Daily Pokemon Manager");
|
||||||
|
const oneDay = 1000 * 60 * 60 * 24;
|
||||||
|
|
||||||
|
export async function claimDailyPokemon(userID: string) {
|
||||||
|
// Get the last daily timestamp
|
||||||
|
let timestampS = await kvGet(`pokedaily~${userID}`);
|
||||||
|
let timestamp = 0;
|
||||||
|
|
||||||
|
if (typeof timestampS == "string") {
|
||||||
|
try {
|
||||||
|
timestamp = parseInt(timestampS);
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn("Unable to parse JSON:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Time remaining:", Date.now() - timestamp);
|
||||||
|
|
||||||
|
// Check if it has been over a day
|
||||||
|
if (Date.now() - timestamp > oneDay) {
|
||||||
|
// Give them a random pokemon and set new timestamp
|
||||||
|
const pokemon = getRandomPokemon();
|
||||||
|
|
||||||
|
const item = {
|
||||||
|
id: pokemon.pokeID.toString(),
|
||||||
|
name: pokemon.name,
|
||||||
|
pokeID: pokemon.pokeID,
|
||||||
|
base: pokemon.base,
|
||||||
|
type: pokemon.type,
|
||||||
|
count: 1,
|
||||||
|
objtype: "pokemon"
|
||||||
|
} as IPokemon;
|
||||||
|
|
||||||
|
const user = await getUser(userID);
|
||||||
|
if (!user) throw new Error("No user found");
|
||||||
|
|
||||||
|
const inventory = await getInventory(user.inventoryId);
|
||||||
|
if (!inventory) throw new Error("No inventory found");
|
||||||
|
|
||||||
|
addItem(inventory.pokemon, pokemon);
|
||||||
|
await updateInventory(inventory);
|
||||||
|
kvSet(`pokedaily~${userID}`, Date.now().toString());
|
||||||
|
|
||||||
|
return `You claimed your daily Pokémon reward and got: ${
|
||||||
|
item.emoji || "📦"
|
||||||
|
}${item.name}${item.count ? ` (x${item.count})` : ""}`;
|
||||||
|
} else {
|
||||||
|
// or tell them no
|
||||||
|
return `You already claimed today! Time remaining: ${getHHMMSS(
|
||||||
|
oneDay - (Date.now() - timestamp),
|
||||||
|
false
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,3 +8,8 @@ const logger = new Logger("Pokédex");
|
||||||
export function getPokemonByID(id: number) {
|
export function getPokemonByID(id: number) {
|
||||||
return pokedex.find(p => p.pokeID == id);
|
return pokedex.find(p => p.pokeID == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRandomPokemon() {
|
||||||
|
const r = Math.floor(Math.random() * pokedex.length);
|
||||||
|
return pokedex[r];
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { Logger } from "@util/Logger";
|
import { Logger } from "@util/Logger";
|
||||||
import { createInterface } from "readline";
|
import { createInterface } from "readline";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "node:events";
|
||||||
import gettRPC from "@util/api/trpc";
|
import gettRPC from "@util/api/trpc";
|
||||||
import { startAutorestart } from "@util/autorestart";
|
import { startAutorestart } from "@util/autorestart";
|
||||||
|
import { CosmicColor } from "@util/CosmicColor";
|
||||||
|
|
||||||
const trpc = gettRPC(process.env.CLI_FISHING_TOKEN as string);
|
const trpc = gettRPC(process.env.CLI_FISHING_TOKEN as string);
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ const b = new EventEmitter();
|
||||||
const rl = createInterface({
|
const rl = createInterface({
|
||||||
input: process.stdin,
|
input: process.stdin,
|
||||||
output: process.stdout
|
output: process.stdout
|
||||||
});
|
} as any);
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
_id: "stdin",
|
_id: "stdin",
|
||||||
|
@ -26,6 +27,12 @@ const user = {
|
||||||
(globalThis as unknown as any).rl = rl;
|
(globalThis as unknown as any).rl = rl;
|
||||||
rl.setPrompt("> ");
|
rl.setPrompt("> ");
|
||||||
rl.prompt();
|
rl.prompt();
|
||||||
|
setPrompt();
|
||||||
|
|
||||||
|
function setPrompt() {
|
||||||
|
const color = new CosmicColor(user.color);
|
||||||
|
rl.setPrompt(`\x1b[38;2;${color.r};${color.g};${color.b}m> `);
|
||||||
|
}
|
||||||
|
|
||||||
rl.on("line", async line => {
|
rl.on("line", async line => {
|
||||||
if (line == "stop" || line == "exit") process.exit();
|
if (line == "stop" || line == "exit") process.exit();
|
||||||
|
@ -94,6 +101,7 @@ setInterval(async () => {
|
||||||
b.on("color", msg => {
|
b.on("color", msg => {
|
||||||
if (typeof msg.color !== "string" || typeof msg.id !== "string") return;
|
if (typeof msg.color !== "string" || typeof msg.id !== "string") return;
|
||||||
user.color = msg.color;
|
user.color = msg.color;
|
||||||
|
setPrompt();
|
||||||
});
|
});
|
||||||
|
|
||||||
b.on("sendchat", msg => {
|
b.on("sendchat", msg => {
|
||||||
|
|
|
@ -1,22 +1,32 @@
|
||||||
export function getHHMMSS() {
|
export function getTime(t = Date.now(), twelveHour = true) {
|
||||||
const now = Date.now();
|
const now = t;
|
||||||
|
|
||||||
const s = now / 1000;
|
const s = now / 1000;
|
||||||
const m = s / 60;
|
const m = s / 60;
|
||||||
const h = m / 60;
|
const h = m / 60;
|
||||||
|
|
||||||
const hh = Math.floor(h % 12)
|
const hours = Math.floor(h % (twelveHour ? 12 : 24))
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(2, "0");
|
.padStart(2, "0");
|
||||||
const mm = Math.floor(m % 60)
|
const minutes = Math.floor(m % 60)
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(2, "0");
|
.padStart(2, "0");
|
||||||
const ss = Math.floor(s % 60)
|
const seconds = Math.floor(s % 60)
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(2, "0");
|
.padStart(2, "0");
|
||||||
const ms = Math.floor(now % 1000)
|
const milliseconds = Math.floor(now % 1000)
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(3, "0");
|
.padStart(3, "0");
|
||||||
|
|
||||||
return `${hh}:${mm}:${ss}.${ms}`;
|
return {
|
||||||
|
hours,
|
||||||
|
minutes,
|
||||||
|
seconds,
|
||||||
|
milliseconds
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getHHMMSS(t = Date.now(), twelveHour = true) {
|
||||||
|
const { hours, minutes, seconds, milliseconds } = getTime(t, twelveHour);
|
||||||
|
return `${hours}:${minutes}:${seconds}.${milliseconds}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ interface IContextProps {
|
||||||
|
|
||||||
type TCommandCallback<User> = (props: IContextProps) => Promise<string | void>;
|
type TCommandCallback<User> = (props: IContextProps) => Promise<string | void>;
|
||||||
|
|
||||||
interface CountComponent {
|
interface ICountComponent {
|
||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ interface IFish extends IObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPokemon extends IObject {
|
interface IPokemon extends IObject {
|
||||||
id: number;
|
id: string;
|
||||||
pokeID: number;
|
pokeID: number;
|
||||||
objtype: "pokemon";
|
objtype: "pokemon";
|
||||||
emoji?: string;
|
emoji?: string;
|
||||||
|
@ -78,6 +78,7 @@ type TPokemonSack = JsonArray & IPokemon[];
|
||||||
interface IInventory {
|
interface IInventory {
|
||||||
id: number;
|
id: number;
|
||||||
balance: number;
|
balance: number;
|
||||||
|
location: string;
|
||||||
|
|
||||||
items: TInventoryItems;
|
items: TInventoryItems;
|
||||||
fishSack: TFishSack;
|
fishSack: TFishSack;
|
||||||
|
@ -90,7 +91,7 @@ interface IBack<T extends string | unknown> extends Record<string, unknown> {
|
||||||
m: T;
|
m: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Backs extends Record<string, IBack<unknown>> {
|
interface IBacks extends Record<string, IBack<unknown>> {
|
||||||
color: {
|
color: {
|
||||||
m: "color";
|
m: "color";
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue