forked from OpenWF/SpaceNinjaServer
Compare commits
1 Commits
main
...
unique-pee
Author | SHA1 | Date | |
---|---|---|---|
9a20c1259e |
8
package-lock.json
generated
8
package-lock.json
generated
@ -18,7 +18,7 @@
|
|||||||
"mongoose": "^8.11.0",
|
"mongoose": "^8.11.0",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"typescript": ">=5.5 <5.6.0",
|
"typescript": ">=5.5 <5.6.0",
|
||||||
"warframe-public-export-plus": "^0.5.47",
|
"warframe-public-export-plus": "^0.5.48",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
@ -4013,9 +4013,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.47",
|
"version": "0.5.48",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.47.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.48.tgz",
|
||||||
"integrity": "sha512-ZJK3VT1PdSPwZlhIzUVBlydwK4DM0sOmeCiixVMgOM8XuOPJ8OHfQUoLKydtw5rxCsowzFPbx5b3KBke5C4akQ=="
|
"integrity": "sha512-vJitVYnaViQo43xAkL/h3MJ/6wS7YknKEYhYs+N/GrsspYLMPGf9KSuR19tprB2g9KVGS5o67t0v5K8p0RTQCQ=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"mongoose": "^8.11.0",
|
"mongoose": "^8.11.0",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"typescript": ">=5.5 <5.6.0",
|
"typescript": ">=5.5 <5.6.0",
|
||||||
"warframe-public-export-plus": "^0.5.47",
|
"warframe-public-export-plus": "^0.5.48",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { updateTheme } from "@/src/services/inventoryService";
|
||||||
|
import { IThemeUpdateRequest } from "@/src/types/requestTypes";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getInventory } from "@/src/services/inventoryService";
|
|
||||||
|
|
||||||
export const updateThemeController: RequestHandler = async (request, response) => {
|
const updateThemeController: RequestHandler = async (request, response) => {
|
||||||
const accountId = await getAccountIdForRequest(request);
|
const accountId = await getAccountIdForRequest(request);
|
||||||
const data = getJSONfromString<IThemeUpdateRequest>(String(request.body));
|
const body = String(request.body);
|
||||||
|
|
||||||
const inventory = await getInventory(accountId, "ThemeStyle ThemeBackground ThemeSounds");
|
try {
|
||||||
if (data.Style) inventory.ThemeStyle = data.Style;
|
const json = getJSONfromString<IThemeUpdateRequest>(body);
|
||||||
if (data.Background) inventory.ThemeBackground = data.Background;
|
if (typeof json !== "object") {
|
||||||
if (data.Sounds) inventory.ThemeSounds = data.Sounds;
|
throw new Error("Invalid data format");
|
||||||
await inventory.save();
|
}
|
||||||
|
|
||||||
|
await updateTheme(json, accountId);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error parsing JSON data:", err);
|
||||||
|
}
|
||||||
|
|
||||||
response.json({});
|
response.json({});
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IThemeUpdateRequest {
|
export { updateThemeController };
|
||||||
Style?: string;
|
|
||||||
Background?: string;
|
|
||||||
Sounds?: string;
|
|
||||||
}
|
|
||||||
|
@ -1,24 +1,9 @@
|
|||||||
import { Account } from "@/src/models/loginModel";
|
import { getAccountForRequest } from "@/src/services/loginService";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
export const ircDroppedController: RequestHandler = async (req, res) => {
|
export const ircDroppedController: RequestHandler = async (req, res) => {
|
||||||
if (!req.query.accountId) {
|
const account = await getAccountForRequest(req);
|
||||||
throw new Error("Request is missing accountId parameter");
|
account.Dropped = true;
|
||||||
}
|
await account.save();
|
||||||
const nonce: number = parseInt(req.query.nonce as string);
|
|
||||||
if (!nonce) {
|
|
||||||
throw new Error("Request is missing nonce parameter");
|
|
||||||
}
|
|
||||||
|
|
||||||
await Account.updateOne(
|
|
||||||
{
|
|
||||||
_id: req.query.accountId,
|
|
||||||
Nonce: nonce
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Dropped: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
res.end();
|
res.end();
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getAccountForRequest, isAdministrator, isNameTaken } from "@/src/services/loginService";
|
import { getAccountForRequest, isNameTaken } from "@/src/services/loginService";
|
||||||
import { config, saveConfig } from "@/src/services/configService";
|
|
||||||
|
|
||||||
export const renameAccountController: RequestHandler = async (req, res) => {
|
export const renameAccountController: RequestHandler = async (req, res) => {
|
||||||
const account = await getAccountForRequest(req);
|
const account = await getAccountForRequest(req);
|
||||||
@ -8,18 +7,8 @@ export const renameAccountController: RequestHandler = async (req, res) => {
|
|||||||
if (await isNameTaken(req.query.newname)) {
|
if (await isNameTaken(req.query.newname)) {
|
||||||
res.status(409).json("Name already in use");
|
res.status(409).json("Name already in use");
|
||||||
} else {
|
} else {
|
||||||
if (isAdministrator(account)) {
|
|
||||||
for (let i = 0; i != config.administratorNames!.length; ++i) {
|
|
||||||
if (config.administratorNames![i] == account.DisplayName) {
|
|
||||||
config.administratorNames![i] = req.query.newname;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await saveConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
account.DisplayName = req.query.newname;
|
account.DisplayName = req.query.newname;
|
||||||
await account.save();
|
await account.save();
|
||||||
|
|
||||||
res.end();
|
res.end();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
10
src/index.ts
10
src/index.ts
@ -19,13 +19,9 @@ import mongoose from "mongoose";
|
|||||||
return "<BIGINT>" + this.toString() + "</BIGINT>";
|
return "<BIGINT>" + this.toString() + "</BIGINT>";
|
||||||
};
|
};
|
||||||
const og_stringify = JSON.stringify;
|
const og_stringify = JSON.stringify;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
||||||
JSON.stringify = (obj: any, replacer?: any, space?: string | number): string => {
|
(JSON as any).stringify = (obj: any): string => {
|
||||||
return og_stringify(obj, replacer as string[], space)
|
return og_stringify(obj).split(`"<BIGINT>`).join(``).split(`</BIGINT>"`).join(``);
|
||||||
.split(`"<BIGINT>`)
|
|
||||||
.join(``)
|
|
||||||
.split(`</BIGINT>"`)
|
|
||||||
.join(``);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ interface IConfig {
|
|||||||
httpsPort?: number;
|
httpsPort?: number;
|
||||||
myIrcAddresses?: string[];
|
myIrcAddresses?: string[];
|
||||||
NRS?: string[];
|
NRS?: string[];
|
||||||
administratorNames?: string[];
|
administratorNames?: string[] | string;
|
||||||
autoCreateAccount?: boolean;
|
autoCreateAccount?: boolean;
|
||||||
skipTutorial?: boolean;
|
skipTutorial?: boolean;
|
||||||
skipAllDialogue?: boolean;
|
skipAllDialogue?: boolean;
|
||||||
@ -83,15 +83,10 @@ export const updateConfig = async (data: string): Promise<void> => {
|
|||||||
Object.assign(config, JSON.parse(data));
|
Object.assign(config, JSON.parse(data));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const saveConfig = async (): Promise<void> => {
|
|
||||||
amnesia = true;
|
|
||||||
await fsPromises.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const validateConfig = (): void => {
|
export const validateConfig = (): void => {
|
||||||
if (typeof config.administratorNames == "string") {
|
if (typeof config.administratorNames == "string") {
|
||||||
logger.info(`Updating config.json to make administratorNames an array.`);
|
logger.warn(
|
||||||
config.administratorNames = [config.administratorNames];
|
`"administratorNames" should be an array; please add square brackets: ["${config.administratorNames}"]`
|
||||||
void saveConfig();
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,11 @@ import {
|
|||||||
ICrewShipWeaponClient
|
ICrewShipWeaponClient
|
||||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
|
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
|
||||||
import { IMissionInventoryUpdateRequest, IUpdateChallengeProgressRequest } from "../types/requestTypes";
|
import {
|
||||||
|
IMissionInventoryUpdateRequest,
|
||||||
|
IThemeUpdateRequest,
|
||||||
|
IUpdateChallengeProgressRequest
|
||||||
|
} from "../types/requestTypes";
|
||||||
import { logger } from "@/src/utils/logger";
|
import { logger } from "@/src/utils/logger";
|
||||||
import { convertInboxMessage, fromStoreItem, getExalted, getKeyChainItems } from "@/src/services/itemDataService";
|
import { convertInboxMessage, fromStoreItem, getExalted, getKeyChainItems } from "@/src/services/itemDataService";
|
||||||
import {
|
import {
|
||||||
@ -887,6 +891,15 @@ export const updateGeneric = async (data: IGenericUpdate, accountId: string): Pr
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateTheme = async (data: IThemeUpdateRequest, accountId: string): Promise<void> => {
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
if (data.Style) inventory.ThemeStyle = data.Style;
|
||||||
|
if (data.Background) inventory.ThemeBackground = data.Background;
|
||||||
|
if (data.Sounds) inventory.ThemeSounds = data.Sounds;
|
||||||
|
|
||||||
|
await inventory.save();
|
||||||
|
};
|
||||||
|
|
||||||
export const addEquipment = (
|
export const addEquipment = (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
category: TEquipmentKey,
|
category: TEquipmentKey,
|
||||||
|
@ -69,31 +69,36 @@ export const getAccountForRequest = async (req: Request): Promise<TAccountDocume
|
|||||||
if (!req.query.accountId) {
|
if (!req.query.accountId) {
|
||||||
throw new Error("Request is missing accountId parameter");
|
throw new Error("Request is missing accountId parameter");
|
||||||
}
|
}
|
||||||
const nonce: number = parseInt(req.query.nonce as string);
|
if (!req.query.nonce || parseInt(req.query.nonce as string) === 0) {
|
||||||
if (!nonce) {
|
|
||||||
throw new Error("Request is missing nonce parameter");
|
throw new Error("Request is missing nonce parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = await Account.findOne({
|
const account = await Account.findOne({
|
||||||
_id: req.query.accountId,
|
_id: req.query.accountId,
|
||||||
Nonce: nonce
|
Nonce: req.query.nonce
|
||||||
});
|
});
|
||||||
if (!account) {
|
if (!account) {
|
||||||
throw new Error("Invalid accountId-nonce pair");
|
throw new Error("Invalid accountId-nonce pair");
|
||||||
}
|
}
|
||||||
if (account.Dropped && req.query.ct) {
|
|
||||||
account.Dropped = undefined;
|
|
||||||
await account.save();
|
|
||||||
}
|
|
||||||
return account;
|
return account;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAccountIdForRequest = async (req: Request): Promise<string> => {
|
export const getAccountIdForRequest = async (req: Request): Promise<string> => {
|
||||||
return (await getAccountForRequest(req))._id.toString();
|
const account = await getAccountForRequest(req);
|
||||||
|
if (account.Dropped && req.query.ct) {
|
||||||
|
account.Dropped = undefined;
|
||||||
|
await account.save();
|
||||||
|
}
|
||||||
|
return account._id.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isAdministrator = (account: TAccountDocument): boolean => {
|
export const isAdministrator = (account: TAccountDocument): boolean => {
|
||||||
return !!config.administratorNames?.find(x => x == account.DisplayName);
|
if (!config.administratorNames) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof config.administratorNames == "string") {
|
||||||
|
return config.administratorNames == account.DisplayName;
|
||||||
|
}
|
||||||
|
return !!config.administratorNames.find(x => x == account.DisplayName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const platform_magics = [753, 639, 247, 37, 60];
|
const platform_magics = [753, 639, 247, 37, 60];
|
||||||
|
@ -415,24 +415,24 @@ const handleBoosterPackPurchase = async (
|
|||||||
"attempt to roll over 100 booster packs in a single go. possible but unlikely to be desirable for the user or the server."
|
"attempt to roll over 100 booster packs in a single go. possible but unlikely to be desirable for the user or the server."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (typeName == "/Lotus/Types/BoosterPacks/1999StickersPackEchoesArchimedeaFixed") {
|
for (let i = 0; i != quantity; ++i) {
|
||||||
for (const result of pack.components) {
|
const disallowedItems = new Set();
|
||||||
purchaseResponse.BoosterPackItems += toStoreItem(result.Item) + ',{"lvl":0};';
|
for (let roll = 0; roll != pack.rarityWeightsPerRoll.length; ) {
|
||||||
combineInventoryChanges(purchaseResponse.InventoryChanges, await addItem(inventory, result.Item, 1));
|
const weights = pack.rarityWeightsPerRoll[roll];
|
||||||
}
|
const result = getRandomWeightedRewardUc(pack.components, weights);
|
||||||
} else {
|
if (result) {
|
||||||
for (let i = 0; i != quantity; ++i) {
|
logger.debug(`booster pack rolled`, result);
|
||||||
for (const weights of pack.rarityWeightsPerRoll) {
|
if (disallowedItems.has(result.Item)) {
|
||||||
const result = getRandomWeightedRewardUc(pack.components, weights);
|
logger.debug(`oops, can't use that one; trying again`);
|
||||||
if (result) {
|
continue;
|
||||||
logger.debug(`booster pack rolled`, result);
|
|
||||||
purchaseResponse.BoosterPackItems += toStoreItem(result.Item) + ',{"lvl":0};';
|
|
||||||
combineInventoryChanges(
|
|
||||||
purchaseResponse.InventoryChanges,
|
|
||||||
await addItem(inventory, result.Item, 1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
if (!pack.canGiveDuplicates) {
|
||||||
|
disallowedItems.add(result.Item);
|
||||||
|
}
|
||||||
|
purchaseResponse.BoosterPackItems += toStoreItem(result.Item) + ',{"lvl":0};';
|
||||||
|
combineInventoryChanges(purchaseResponse.InventoryChanges, await addItem(inventory, result.Item, 1));
|
||||||
}
|
}
|
||||||
|
++roll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return purchaseResponse;
|
return purchaseResponse;
|
||||||
|
@ -19,6 +19,12 @@ import {
|
|||||||
ICollectibleEntry
|
ICollectibleEntry
|
||||||
} from "./inventoryTypes/inventoryTypes";
|
} from "./inventoryTypes/inventoryTypes";
|
||||||
|
|
||||||
|
export interface IThemeUpdateRequest {
|
||||||
|
Style?: string;
|
||||||
|
Background?: string;
|
||||||
|
Sounds?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IAffiliationChange {
|
export interface IAffiliationChange {
|
||||||
Tag: string;
|
Tag: string;
|
||||||
Standing: number;
|
Standing: number;
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user