mirror of
https://github.com/YuzuZensai/VRC-Circle.git
synced 2026-09-13 10:58:59 +00:00
✨ feat: Initial commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import type { UserProfile } from "../../shared/types/user";
|
||||
import { requireActiveClient } from "./client";
|
||||
import { toUserProfile } from "./mappers";
|
||||
import { TtlCache } from "../cache/cache";
|
||||
import { cacheKeys, policies } from "../cache/policies";
|
||||
import { entityStore } from "../store/entityStore";
|
||||
|
||||
export const userCache = new TtlCache();
|
||||
|
||||
async function selfId(): Promise<string> {
|
||||
return (await currentUser()).id;
|
||||
}
|
||||
|
||||
function dropPresence(p: UserProfile): Partial<UserProfile> & { id: string } {
|
||||
const { state: _s, location: _l, status: _st, ...rest } = p;
|
||||
return rest;
|
||||
}
|
||||
|
||||
function refreshStore(p: UserProfile, key: string): void {
|
||||
const known = !p.isSelf && entityStore.get(p.id)?.isFriend;
|
||||
const stamped = p.isSelf || known ? dropPresence(p) : p;
|
||||
entityStore.upsertFrom(stamped, "rest:detail", userCache.createdAt(key) ?? Date.now());
|
||||
}
|
||||
|
||||
export async function currentUser(): Promise<UserProfile> {
|
||||
const vrc = requireActiveClient();
|
||||
const key = cacheKeys.currentUser();
|
||||
const profile = await userCache.get(key, policies.currentUser, async () => {
|
||||
const { data } = await vrc.getCurrentUser({ throwOnError: true });
|
||||
if (!("id" in data)) throw { status: 401, message: "Not authenticated" };
|
||||
return toUserProfile(data, data.id);
|
||||
});
|
||||
refreshStore(profile, key);
|
||||
return profile;
|
||||
}
|
||||
|
||||
export async function getUser(userId: string): Promise<UserProfile> {
|
||||
const vrc = requireActiveClient();
|
||||
const self = await selfId();
|
||||
const key = cacheKeys.user(userId);
|
||||
const profile = await userCache.get(key, policies.user, async () => {
|
||||
const { data } = await vrc.getUser({ path: { userId }, throwOnError: true });
|
||||
return toUserProfile(data, self);
|
||||
});
|
||||
refreshStore(profile, key);
|
||||
return profile;
|
||||
}
|
||||
|
||||
export async function getUserByName(username: string): Promise<UserProfile> {
|
||||
const vrc = requireActiveClient();
|
||||
const self = await selfId();
|
||||
return userCache.get(cacheKeys.userByName(username), policies.user, async () => {
|
||||
const { data } = await vrc.getUserByName({ path: { username }, throwOnError: true });
|
||||
return toUserProfile(data, self);
|
||||
});
|
||||
}
|
||||
|
||||
export async function searchUsers(query: string): Promise<UserProfile[]> {
|
||||
const vrc = requireActiveClient();
|
||||
const self = await selfId();
|
||||
return userCache.get(cacheKeys.userSearch(query), policies.userSearch, async () => {
|
||||
const { data } = await vrc.searchUsers({ query: { search: query, n: 25 }, throwOnError: true });
|
||||
return data.map((u) => toUserProfile(u, self));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user