mirror of
https://github.com/YuzuZensai/VRC-Circle.git
synced 2026-09-13 10:58:59 +00:00
✨ feat: Instance grouping and user count
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { app } from "electron";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { KeyvFile } from "keyv-file";
|
||||
import { VRChat } from "vrchat";
|
||||
import { activeId, pendingFile, sessionFile } from "../accounts/store";
|
||||
@@ -59,10 +60,33 @@ export function closeClients(): void {
|
||||
loginClient?.pipeline.close();
|
||||
}
|
||||
|
||||
interface SessionCookie {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
function readAuthCookieFromSession(filename: string): string | null {
|
||||
try {
|
||||
const raw = JSON.parse(readFileSync(filename, "utf8")) as {
|
||||
cache?: [string, { value?: string }][];
|
||||
};
|
||||
const entry = raw.cache?.find(([k]) => k === "keyv:cookies")?.[1];
|
||||
if (!entry?.value) return null;
|
||||
const outer = JSON.parse(entry.value) as { value?: SessionCookie[] };
|
||||
const auth = outer.value?.find((c) => c.name === "auth");
|
||||
return auth?.value ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPipelineAuthToken(vrc: VRChat): Promise<string | null> {
|
||||
const getCookies = (
|
||||
vrc as unknown as { getCookies?: () => Promise<{ name: string; value: string }[]> }
|
||||
).getCookies;
|
||||
const id = activeId();
|
||||
if (id) {
|
||||
const fromDisk = readAuthCookieFromSession(sessionFile(id));
|
||||
if (fromDisk) return fromDisk;
|
||||
}
|
||||
const getCookies = (vrc as unknown as { getCookies?: () => Promise<SessionCookie[]> }).getCookies;
|
||||
const cookies = (await getCookies?.()) ?? [];
|
||||
return cookies.find((c) => c.name === "auth")?.value ?? null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { Instance } from "../../shared/types/instance";
|
||||
import { toInstance } from "./mappers";
|
||||
import { cachedRead } from "./cachedRead";
|
||||
import { cacheKeys, policies } from "../cache/policies";
|
||||
|
||||
export async function getInstance(worldId: string, instanceId: string): Promise<Instance> {
|
||||
return cachedRead(
|
||||
cacheKeys.instance(`${worldId}:${instanceId}`),
|
||||
policies.instance,
|
||||
async (vrc) => {
|
||||
const { data } = await vrc.getInstance({ path: { worldId, instanceId }, throwOnError: true });
|
||||
return toInstance(data);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -8,12 +8,14 @@ import type {
|
||||
User,
|
||||
CurrentUser,
|
||||
LimitedUserFriend,
|
||||
Instance as SdkInstance,
|
||||
} from "vrchat";
|
||||
import type { TrustRank, UserProfile, UserStatus } from "../../shared/types/user";
|
||||
import type { CurrentUserSummary } from "../../shared/types/auth";
|
||||
import type { ReleaseStatus, World, WorldPlatforms } from "../../shared/types/world";
|
||||
import type { Avatar } from "../../shared/types/avatar";
|
||||
import type { Group } from "../../shared/types/group";
|
||||
import type { Instance } from "../../shared/types/instance";
|
||||
|
||||
interface RawUser {
|
||||
id: string;
|
||||
@@ -194,6 +196,24 @@ export function toWorld(raw: RawWorld): World {
|
||||
};
|
||||
}
|
||||
|
||||
export function toInstance(raw: SdkInstance): Instance {
|
||||
return {
|
||||
id: raw.id,
|
||||
location: raw.location,
|
||||
worldId: raw.worldId,
|
||||
instanceId: raw.instanceId,
|
||||
type: raw.type,
|
||||
region: raw.region ?? undefined,
|
||||
ownerId: raw.ownerId ?? undefined,
|
||||
userCount: raw.userCount ?? 0,
|
||||
capacity: raw.capacity ?? raw.recommendedCapacity ?? 0,
|
||||
recommendedCapacity: raw.recommendedCapacity,
|
||||
full: raw.full ?? false,
|
||||
queueEnabled: raw.queueEnabled ?? false,
|
||||
queueSize: raw.queueSize ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
export function toGroup(raw: LimitedUserGroups | RepresentedGroup): Group {
|
||||
return {
|
||||
id: raw.groupId ?? "",
|
||||
|
||||
Reference in New Issue
Block a user