parent
6598318fc5
commit
3b16ff9b54
@ -32,6 +32,7 @@ app.use(requestLogger);
|
|||||||
app.use("/api", apiRouter);
|
app.use("/api", apiRouter);
|
||||||
app.use("/", cacheRouter);
|
app.use("/", cacheRouter);
|
||||||
app.use("/custom", customRouter);
|
app.use("/custom", customRouter);
|
||||||
|
app.use("/dynamic", dynamicController);
|
||||||
app.use("/:id/dynamic", dynamicController);
|
app.use("/:id/dynamic", dynamicController);
|
||||||
app.use("/pay", payRouter);
|
app.use("/pay", payRouter);
|
||||||
app.use("/stats", statsRouter);
|
app.use("/stats", statsRouter);
|
||||||
|
@ -297,7 +297,7 @@ const resourceGetParent = (resourceName: string): string | undefined => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// This is FNV1a-32 except operating under modulus 2^31 because JavaScript is stinky and likes producing negative integers out of nowhere.
|
// This is FNV1a-32 except operating under modulus 2^31 because JavaScript is stinky and likes producing negative integers out of nowhere.
|
||||||
const catBreadHash = (name: string): number => {
|
export const catBreadHash = (name: string): number => {
|
||||||
let hash = 2166136261;
|
let hash = 2166136261;
|
||||||
for (let i = 0; i != name.length; ++i) {
|
for (let i = 0; i != name.length; ++i) {
|
||||||
hash = (hash ^ name.charCodeAt(i)) & 0x7fffffff;
|
hash = (hash ^ name.charCodeAt(i)) & 0x7fffffff;
|
||||||
|
183
src/controllers/dynamic/getProfileViewingDataController.ts
Normal file
183
src/controllers/dynamic/getProfileViewingDataController.ts
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
|
import { Guild } from "@/src/models/guildModel";
|
||||||
|
import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
|
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||||
|
import { Account } from "@/src/models/loginModel";
|
||||||
|
import { Stats, TStatsDatabaseDocument } from "@/src/models/statsModel";
|
||||||
|
import { allDailyAffiliationKeys } from "@/src/services/inventoryService";
|
||||||
|
import { IMongoDate, IOid } from "@/src/types/commonTypes";
|
||||||
|
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
|
import {
|
||||||
|
IAffiliation,
|
||||||
|
IAlignment,
|
||||||
|
IChallengeProgress,
|
||||||
|
IDailyAffiliations,
|
||||||
|
ILoadoutConfigClient,
|
||||||
|
IMission,
|
||||||
|
IPlayerSkills,
|
||||||
|
ITypeXPItem
|
||||||
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { catBreadHash } from "../api/inventoryController";
|
||||||
|
import { ExportCustoms } from "warframe-public-export-plus";
|
||||||
|
|
||||||
|
export const getProfileViewingDataController: RequestHandler = async (req, res) => {
|
||||||
|
if (!req.query.playerId) {
|
||||||
|
res.status(400).end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const account = await Account.findOne({ _id: req.query.playerId as string }, "DisplayName");
|
||||||
|
if (!account) {
|
||||||
|
res.status(400).send("No account or guild ID specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const inventory = (await Inventory.findOne({ accountOwnerId: account._id }))!;
|
||||||
|
const loadout = (await Loadout.findOne({ _id: inventory.LoadOutPresets }, "NORMAL"))!;
|
||||||
|
|
||||||
|
const result: IPlayerProfileViewingDataResult = {
|
||||||
|
AccountId: toOid(account._id),
|
||||||
|
DisplayName: account.DisplayName,
|
||||||
|
PlayerLevel: inventory.PlayerLevel,
|
||||||
|
LoadOutInventory: {
|
||||||
|
WeaponSkins: [],
|
||||||
|
XPInfo: inventory.XPInfo
|
||||||
|
},
|
||||||
|
PlayerSkills: inventory.PlayerSkills,
|
||||||
|
ChallengeProgress: inventory.ChallengeProgress,
|
||||||
|
DeathMarks: inventory.DeathMarks,
|
||||||
|
Harvestable: inventory.Harvestable,
|
||||||
|
DeathSquadable: inventory.DeathSquadable,
|
||||||
|
Created: toMongoDate(inventory.Created),
|
||||||
|
MigratedToConsole: false,
|
||||||
|
Missions: inventory.Missions,
|
||||||
|
Affiliations: inventory.Affiliations,
|
||||||
|
DailyFocus: inventory.DailyFocus,
|
||||||
|
Wishlist: inventory.Wishlist,
|
||||||
|
Alignment: inventory.Alignment
|
||||||
|
};
|
||||||
|
if (inventory.CurrentLoadOutIds.length) {
|
||||||
|
result.LoadOutPreset = loadout.NORMAL.id(inventory.CurrentLoadOutIds[0].$oid)!.toJSON<ILoadoutConfigClient>();
|
||||||
|
result.LoadOutPreset.ItemId = undefined;
|
||||||
|
const skins = new Set<string>();
|
||||||
|
if (result.LoadOutPreset.s) {
|
||||||
|
result.LoadOutInventory.Suits = [
|
||||||
|
inventory.Suits.id(result.LoadOutPreset.s.ItemId.$oid)!.toJSON<IEquipmentClient>()
|
||||||
|
];
|
||||||
|
resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.Suits[0]);
|
||||||
|
}
|
||||||
|
if (result.LoadOutPreset.p) {
|
||||||
|
result.LoadOutInventory.Pistols = [
|
||||||
|
inventory.Pistols.id(result.LoadOutPreset.p.ItemId.$oid)!.toJSON<IEquipmentClient>()
|
||||||
|
];
|
||||||
|
resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.Pistols[0]);
|
||||||
|
}
|
||||||
|
if (result.LoadOutPreset.l) {
|
||||||
|
result.LoadOutInventory.LongGuns = [
|
||||||
|
inventory.LongGuns.id(result.LoadOutPreset.l.ItemId.$oid)!.toJSON<IEquipmentClient>()
|
||||||
|
];
|
||||||
|
resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.LongGuns[0]);
|
||||||
|
}
|
||||||
|
if (result.LoadOutPreset.m) {
|
||||||
|
result.LoadOutInventory.Melee = [
|
||||||
|
inventory.Melee.id(result.LoadOutPreset.m.ItemId.$oid)!.toJSON<IEquipmentClient>()
|
||||||
|
];
|
||||||
|
resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.Melee[0]);
|
||||||
|
}
|
||||||
|
for (const skin of skins) {
|
||||||
|
result.LoadOutInventory.WeaponSkins.push({ ItemType: skin });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inventory.GuildId) {
|
||||||
|
const guild = (await Guild.findOne({ _id: inventory.GuildId }, "Name Tier XP Class"))!;
|
||||||
|
result.GuildId = toOid(inventory.GuildId);
|
||||||
|
result.GuildName = guild.Name;
|
||||||
|
result.GuildTier = guild.Tier;
|
||||||
|
result.GuildXp = guild.XP;
|
||||||
|
result.GuildClass = guild.Class;
|
||||||
|
result.GuildEmblem = false;
|
||||||
|
}
|
||||||
|
for (const key of allDailyAffiliationKeys) {
|
||||||
|
result[key] = inventory[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
const stats = (await Stats.findOne({ accountOwnerId: account._id }))!.toJSON<Partial<TStatsDatabaseDocument>>();
|
||||||
|
delete stats._id;
|
||||||
|
delete stats.__v;
|
||||||
|
delete stats.accountOwnerId;
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
Results: [result],
|
||||||
|
TechProjects: [],
|
||||||
|
XpComponents: [],
|
||||||
|
//XpCacheExpiryDate, some IMongoDate in the future, no clue what it's for
|
||||||
|
Stats: stats
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IPlayerProfileViewingDataResult extends Partial<IDailyAffiliations> {
|
||||||
|
AccountId: IOid;
|
||||||
|
DisplayName: string;
|
||||||
|
PlayerLevel: number;
|
||||||
|
LoadOutPreset?: Omit<ILoadoutConfigClient, "ItemId"> & { ItemId?: IOid };
|
||||||
|
LoadOutInventory: {
|
||||||
|
WeaponSkins: { ItemType: string }[];
|
||||||
|
Suits?: IEquipmentClient[];
|
||||||
|
Pistols?: IEquipmentClient[];
|
||||||
|
LongGuns?: IEquipmentClient[];
|
||||||
|
Melee?: IEquipmentClient[];
|
||||||
|
XPInfo: ITypeXPItem[];
|
||||||
|
};
|
||||||
|
GuildId?: IOid;
|
||||||
|
GuildName?: string;
|
||||||
|
GuildTier?: number;
|
||||||
|
GuildXp?: number;
|
||||||
|
GuildClass?: number;
|
||||||
|
GuildEmblem?: boolean;
|
||||||
|
PlayerSkills: IPlayerSkills;
|
||||||
|
ChallengeProgress: IChallengeProgress[];
|
||||||
|
DeathMarks: string[];
|
||||||
|
Harvestable: boolean;
|
||||||
|
DeathSquadable: boolean;
|
||||||
|
Created: IMongoDate;
|
||||||
|
MigratedToConsole: boolean;
|
||||||
|
Missions: IMission[];
|
||||||
|
Affiliations: IAffiliation[];
|
||||||
|
DailyFocus: number;
|
||||||
|
Wishlist: string[];
|
||||||
|
Alignment?: IAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
let skinLookupTable: Record<number, string> | undefined;
|
||||||
|
|
||||||
|
const resolveAndCollectSkins = (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
skins: Set<string>,
|
||||||
|
item: IEquipmentClient
|
||||||
|
): void => {
|
||||||
|
for (const config of item.Configs) {
|
||||||
|
if (config.Skins) {
|
||||||
|
for (let i = 0; i != config.Skins.length; ++i) {
|
||||||
|
// Resolve oids to type names
|
||||||
|
if (config.Skins[i].length == 24) {
|
||||||
|
if (config.Skins[i].substring(0, 16) == "ca70ca70ca70ca70") {
|
||||||
|
if (!skinLookupTable) {
|
||||||
|
skinLookupTable = {};
|
||||||
|
for (const key of Object.keys(ExportCustoms)) {
|
||||||
|
skinLookupTable[catBreadHash(key)] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.Skins[i] = skinLookupTable[parseInt(config.Skins[i].substring(16), 16)];
|
||||||
|
} else {
|
||||||
|
const skinItem = inventory.WeaponSkins.id(config.Skins[i]);
|
||||||
|
config.Skins[i] = skinItem ? skinItem.ItemType : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect type names
|
||||||
|
if (config.Skins[i]) {
|
||||||
|
skins.add(config.Skins[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -153,6 +153,7 @@ const guildSchema = new Schema<IGuildDatabase>(
|
|||||||
LongMOTD: { type: longMOTDSchema, default: undefined },
|
LongMOTD: { type: longMOTDSchema, default: undefined },
|
||||||
Ranks: { type: [guildRankSchema], default: defaultRanks },
|
Ranks: { type: [guildRankSchema], default: defaultRanks },
|
||||||
TradeTax: { type: Number, default: 0 },
|
TradeTax: { type: Number, default: 0 },
|
||||||
|
Tier: { type: Number, default: 1 },
|
||||||
DojoComponents: { type: [dojoComponentSchema], default: [] },
|
DojoComponents: { type: [dojoComponentSchema], default: [] },
|
||||||
DojoCapacity: { type: Number, default: 100 },
|
DojoCapacity: { type: Number, default: 100 },
|
||||||
DojoEnergy: { type: Number, default: 5 },
|
DojoEnergy: { type: Number, default: 5 },
|
||||||
|
@ -468,7 +468,6 @@ const seasonChallengeHistorySchema = new Schema<ISeasonChallenge>(
|
|||||||
//TODO: check whether this is complete
|
//TODO: check whether this is complete
|
||||||
const playerSkillsSchema = new Schema<IPlayerSkills>(
|
const playerSkillsSchema = new Schema<IPlayerSkills>(
|
||||||
{
|
{
|
||||||
LPP_NONE: { type: Number, default: 0 },
|
|
||||||
LPP_SPACE: { type: Number, default: 0 },
|
LPP_SPACE: { type: Number, default: 0 },
|
||||||
LPS_PILOTING: { type: Number, default: 0 },
|
LPS_PILOTING: { type: Number, default: 0 },
|
||||||
LPS_GUNNERY: { type: Number, default: 0 },
|
LPS_GUNNERY: { type: Number, default: 0 },
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { aggregateSessionsController } from "@/src/controllers/dynamic/aggregateSessionsController";
|
|
||||||
import { worldStateController } from "@/src/controllers/dynamic/worldStateController";
|
|
||||||
import express from "express";
|
import express from "express";
|
||||||
|
import { aggregateSessionsController } from "@/src/controllers/dynamic/aggregateSessionsController";
|
||||||
|
import { getProfileViewingDataController } from "@/src/controllers/dynamic/getProfileViewingDataController";
|
||||||
|
import { worldStateController } from "@/src/controllers/dynamic/worldStateController";
|
||||||
|
|
||||||
const dynamicController = express.Router();
|
const dynamicController = express.Router();
|
||||||
|
|
||||||
dynamicController.get("/worldState.php", worldStateController);
|
|
||||||
dynamicController.get("/aggregateSessions.php", aggregateSessionsController);
|
dynamicController.get("/aggregateSessions.php", aggregateSessionsController);
|
||||||
|
dynamicController.get("/getProfileViewingData.php", getProfileViewingDataController);
|
||||||
|
dynamicController.get("/worldState.php", worldStateController);
|
||||||
|
|
||||||
export { dynamicController };
|
export { dynamicController };
|
||||||
|
@ -91,7 +91,7 @@ export const getGuildClient = async (guild: TGuildDatabaseDocument, accountId: s
|
|||||||
Members: members,
|
Members: members,
|
||||||
Ranks: guild.Ranks,
|
Ranks: guild.Ranks,
|
||||||
TradeTax: guild.TradeTax,
|
TradeTax: guild.TradeTax,
|
||||||
Tier: 1,
|
Tier: guild.Tier,
|
||||||
Vault: getGuildVault(guild),
|
Vault: getGuildVault(guild),
|
||||||
ActiveDojoColorResearch: guild.ActiveDojoColorResearch,
|
ActiveDojoColorResearch: guild.ActiveDojoColorResearch,
|
||||||
Class: guild.Class,
|
Class: guild.Class,
|
||||||
|
@ -27,6 +27,7 @@ export interface IGuildDatabase {
|
|||||||
LongMOTD?: ILongMOTD;
|
LongMOTD?: ILongMOTD;
|
||||||
Ranks: IGuildRank[];
|
Ranks: IGuildRank[];
|
||||||
TradeTax: number;
|
TradeTax: number;
|
||||||
|
Tier: number;
|
||||||
|
|
||||||
DojoComponents: IDojoComponentDatabase[];
|
DojoComponents: IDojoComponentDatabase[];
|
||||||
DojoCapacity: number;
|
DojoCapacity: number;
|
||||||
|
@ -928,7 +928,6 @@ export interface IPersonalTechProject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IPlayerSkills {
|
export interface IPlayerSkills {
|
||||||
LPP_NONE: number;
|
|
||||||
LPP_SPACE: number;
|
LPP_SPACE: number;
|
||||||
LPS_PILOTING: number;
|
LPS_PILOTING: number;
|
||||||
LPS_GUNNERY: number;
|
LPS_GUNNERY: number;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user