Show SCUM player identifiers and login IP
This commit is contained in:
@@ -205,6 +205,9 @@ describe("plugin manifest validation", () => {
|
||||
const compile = (pattern: string) => new RegExp(pattern.replaceAll("(?P<", "(?<"));
|
||||
expect(compile(projection.steps[0].pattern).exec('LogBattlEye: Display: Player "love_fitting" reported as player 0')?.groups).toMatchObject({ displayName: "love_fitting", slot: "0" });
|
||||
expect(compile(projection.steps[1].pattern).exec("LogBattlEye: Display: Player 0 SteamID (assumed): 76561199510658111")?.groups).toMatchObject({ slot: "0", steamId: "76561199510658111" });
|
||||
const loginLogProjection = manifest.gameClientBridge.logProjections.find((candidate: { key: string }) => candidate.key === "scum.login-log.login");
|
||||
expect(loginLogProjection.target.captureMappings).toMatchObject({ steamId: "steamId", displayName: "displayName", lastLoginIp: "ip" });
|
||||
expect(loginLogProjection.presence.activityTarget.captureMappings).toMatchObject({ steamId: "steamId", displayName: "displayName", lastLoginIp: "ip" });
|
||||
});
|
||||
|
||||
it("declares SCUM install/update and start lifecycle through plugin assets", () => {
|
||||
@@ -648,6 +651,7 @@ describe("plugin manifest validation", () => {
|
||||
pollIntervalSeconds: number;
|
||||
maxRows: number;
|
||||
timeoutSeconds: number;
|
||||
projections?: Array<{ collection: string; rowPath: string; upsertKeys: string[]; observedAtField?: string; mergeExisting?: boolean }>;
|
||||
}>;
|
||||
pages: Array<{ pageKey: string; commandTypes?: string[]; queryTemplateKeys?: string[] }>;
|
||||
};
|
||||
@@ -669,6 +673,7 @@ describe("plugin manifest validation", () => {
|
||||
const fastTemplates = new Set(["scum.player.profile", "scum.vehicles", "scum.positions"]);
|
||||
const templatesByKey = new Map(manifest.gameClientBridge.queryTemplates.map((template) => [template.key, template]));
|
||||
expect([...templatesByKey.keys()]).toEqual(expect.arrayContaining(expectedKeys));
|
||||
expect(templatesByKey.get("scum.player.profile")?.projections).toEqual([expect.objectContaining({ collection: "scum_users", rowPath: "rows", upsertKeys: ["steamId"], observedAtField: "profileSampledAt", mergeExisting: true })]);
|
||||
expect(manifest.capabilities).toContain("remote.run.db.sqlite.query");
|
||||
expect(manifest.capabilities).toContain("remote.run.db.sqlite.execute");
|
||||
expect(manifest.remoteAccess?.runCapabilities).toContain("remote.run.db.sqlite.query");
|
||||
|
||||
@@ -15,7 +15,7 @@ const pageSource = readFileSync(resolve(featureRoot, "page.ts"), "utf8");
|
||||
const dataClientSource = readFileSync(resolve(featureRoot, "page-data.ts"), "utf8");
|
||||
|
||||
const surfaceData: SCUMSurfaceData = {
|
||||
players: [{ gamePlayerId: "steam-1", steamId: "76561198000000001", userProfileId: "profile-1", displayName: "Mira", squadName: "Wolves", squadId: "squad-1", online: true, famePoints: 42, normalBalance: 1000, goldBalance: 3, position: { x: 10, y: 20, z: 3 }, freshness: { status: "fresh" } }],
|
||||
players: [{ gamePlayerId: "steam-1", steamId: "76561198000000001", userProfileId: "profile-1", displayName: "Mira", squadName: "Wolves", squadId: "squad-1", online: true, famePoints: 42, normalBalance: 1000, goldBalance: 3, lastLoginIp: "203.0.113.7", position: { x: 10, y: 20, z: 3 }, freshness: { status: "fresh" } }],
|
||||
squads: [{ squadId: "squad-1", name: "Wolves", memberCount: 1, memberLimit: 12, leaderProfileId: "profile-1", score: 88, message: "Hold the north", freshness: { status: "fresh" } }],
|
||||
members: [{ gamePlayerId: "steam-1", steamId: "76561198000000001", displayName: "Mira", squadId: "squad-1", rank: "Leader", score: 42, lastLoginAt: "2026-08-10T00:00:00Z", freshness: { status: "fresh" } }],
|
||||
events: [{ id: "event-1", name: "Friday Range", eventType: "range", class: 1, corn: "0 20 * * 5", placard: "Event starting", percent: 75, npc: 1, item: 3, zombie: 12, animal: 2, status: "enabled" }],
|
||||
@@ -186,8 +186,7 @@ describe("SCUM plugin feature module", () => {
|
||||
expect(view.nodes).toContain("section:用户管理");
|
||||
expect(view.texts).not.toContain("SCUM 用户真实记录");
|
||||
expect(view.texts).toEqual(expect.arrayContaining(["在线用户 ", "1 / 1"]));
|
||||
expect(view.texts).toEqual(expect.arrayContaining(["用户名", "队伍", "状态", "最后活动", "操作"]));
|
||||
expect(view.texts).not.toEqual(expect.arrayContaining(["Steam", "上次登录", "登录 IP", "概况"]));
|
||||
expect(view.texts).toEqual(expect.arrayContaining(["用户名", "UUID / Steam", "渣币", "登录 IP", "队伍", "状态", "最后活动", "操作"]));
|
||||
expect(view.texts).not.toContain("筛选结果");
|
||||
expect(view.texts).not.toContain("通用数据/机器动作可用");
|
||||
expect(view.buttons.map((button) => button.label)).not.toEqual(expect.arrayContaining(["同步 SCUM.db", "重新读取"]));
|
||||
@@ -197,8 +196,11 @@ describe("SCUM plugin feature module", () => {
|
||||
expect(pageSource).toContain("resource-filter-bar scum-filter-bar");
|
||||
expect(pageSource).toContain("provider-table-wrap scum-table-wrap");
|
||||
expect(view.texts).toContain("Mira");
|
||||
expect(view.texts).not.toContain("76561198000000001");
|
||||
expect(view.texts.join("\n")).not.toContain("Fame 42");
|
||||
expect(view.texts).toEqual(expect.arrayContaining(["steam-1", "Steam 76561198000000001", "1000", "Gold 3", "203.0.113.7"]));
|
||||
const ipSearch = renderAndCollect({ playerSearch: "203.0.113.7" });
|
||||
expect(ipSearch.texts).toContain("Mira");
|
||||
const uuidSearch = renderAndCollect({ playerSearch: "profile-1" });
|
||||
expect(uuidSearch.texts).toContain("Mira");
|
||||
});
|
||||
|
||||
it("expires online users after five minutes without activity", () => {
|
||||
@@ -325,7 +327,7 @@ function gameClientActions() {
|
||||
};
|
||||
}
|
||||
|
||||
function renderAndCollect(options: { data?: SCUMSurfaceData; permissions?: string[]; pageKey?: string; pageTitle?: string; giftTab?: "definitions" | "claims" | "deliveries" | "timed" } = {}) {
|
||||
function renderAndCollect(options: { data?: SCUMSurfaceData; permissions?: string[]; pageKey?: string; pageTitle?: string; giftTab?: "definitions" | "claims" | "deliveries" | "timed"; playerSearch?: string } = {}) {
|
||||
const nodes: string[] = [];
|
||||
const texts: string[] = [];
|
||||
const buttons: Array<{ label: string; disabled: boolean; onClick?: () => void }> = [];
|
||||
@@ -346,6 +348,7 @@ function renderAndCollect(options: { data?: SCUMSurfaceData; permissions?: strin
|
||||
useState: <T,>(initial: T | (() => T)): [T, (next: T | ((previous: T) => T)) => void] => {
|
||||
stateCall += 1;
|
||||
if (stateCall === 1) return [{ status: "ready", data: options.data ?? surfaceData } as T, () => undefined];
|
||||
if (stateCall === 3 && options.playerSearch !== undefined) return [options.playerSearch as T, () => undefined];
|
||||
const value = typeof initial === "function" ? (initial as () => T)() : initial;
|
||||
if (options.giftTab && value === "definitions") return [options.giftTab as T, () => undefined];
|
||||
return [value, () => undefined];
|
||||
|
||||
Reference in New Issue
Block a user