(feat) Discord build share
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import { avatarUrl } from '$lib/avatar';
|
||||
import { parseLoadoutDraft } from '$lib/builder/loadout';
|
||||
import { summarizeLoadout } from '$lib/builder/loadout-summary';
|
||||
import { getDatabase } from '$lib/server/database';
|
||||
import { loadSharedBuildSummaryCatalog } from '$lib/server/shared-build-summary';
|
||||
|
||||
export type SharedBuildAccessPolicy =
|
||||
{ kind: 'viewer-page'; viewerId: string | null } | { kind: 'public-preview' };
|
||||
type BuildVisibility = 'public' | 'unlisted' | 'private';
|
||||
|
||||
export async function loadSharedBuildProjection(
|
||||
slug: string,
|
||||
access: SharedBuildAccessPolicy,
|
||||
) {
|
||||
const database = await getDatabase();
|
||||
const build = await (
|
||||
await database.prepare(`
|
||||
SELECT builds.*,COALESCE(user_profiles.display_name,users.username,'Deleted Agent') AS author,
|
||||
user_profiles.public_slug,
|
||||
COALESCE(user_profiles.is_public,1) AS profile_is_public,deleted_accounts.user_id AS deleted_user_id,
|
||||
user_avatars.source AS avatar_source,user_avatars.value AS avatar_value,
|
||||
user_avatars.updated_at AS avatar_updated_at
|
||||
FROM builds
|
||||
JOIN users ON users.id=builds.owner_id
|
||||
LEFT JOIN user_profiles ON user_profiles.user_id=users.id
|
||||
LEFT JOIN deleted_accounts ON deleted_accounts.user_id=users.id
|
||||
LEFT JOIN user_avatars ON user_avatars.user_id=users.id
|
||||
WHERE builds.slug=?
|
||||
`)
|
||||
).get(slug);
|
||||
|
||||
if (!build) return null;
|
||||
|
||||
const ownerId = String(build.owner_id);
|
||||
const visibility = String(build.visibility) as BuildVisibility;
|
||||
const viewerId = access.kind === 'viewer-page' ? access.viewerId : null;
|
||||
const accessible =
|
||||
access.kind === 'public-preview'
|
||||
? visibility === 'public' || visibility === 'unlisted'
|
||||
: visibility === 'public' ||
|
||||
visibility === 'unlisted' ||
|
||||
(visibility === 'private' && ownerId === viewerId);
|
||||
if (!accessible) return null;
|
||||
|
||||
let loadout;
|
||||
try {
|
||||
loadout = parseLoadoutDraft(JSON.parse(String(build.loadout_json)));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
if (!loadout) return null;
|
||||
|
||||
const [gear, weapons, chips, protocols, brands, summaryCatalog] =
|
||||
await Promise.all([
|
||||
(
|
||||
await database.prepare(
|
||||
'SELECT id,name,slot,tier,base_armor_min FROM gear',
|
||||
)
|
||||
).all(),
|
||||
(
|
||||
await database.prepare(
|
||||
'SELECT id,name,category,is_exotic,rpm,magazine,reload_speed,damage_type FROM weapons',
|
||||
)
|
||||
).all(),
|
||||
(await database.prepare('SELECT id,name FROM skill_chip_sets')).all(),
|
||||
(
|
||||
await database.prepare('SELECT id,name,quality FROM os_protocols')
|
||||
).all(),
|
||||
(await database.prepare('SELECT id,name FROM brand_sets')).all(),
|
||||
loadSharedBuildSummaryCatalog(database),
|
||||
]);
|
||||
const summary = summarizeLoadout(loadout, summaryCatalog);
|
||||
|
||||
return {
|
||||
build: {
|
||||
id: String(build.id),
|
||||
title: String(build.title),
|
||||
slug: String(build.slug),
|
||||
visibility,
|
||||
author: String(build.author),
|
||||
ownerId,
|
||||
authorPublicSlug: build.public_slug ? String(build.public_slug) : null,
|
||||
profileAvailable:
|
||||
Boolean(build.profile_is_public) && !build.deleted_user_id,
|
||||
authorAvatarUrl: avatarUrl(
|
||||
build.avatar_source,
|
||||
build.avatar_value,
|
||||
ownerId,
|
||||
build.avatar_updated_at,
|
||||
),
|
||||
owner: ownerId === viewerId,
|
||||
updatedAt: String(build.updated_at),
|
||||
},
|
||||
loadout,
|
||||
gear,
|
||||
weapons,
|
||||
chips,
|
||||
protocols,
|
||||
brands,
|
||||
summary,
|
||||
attributes: summaryCatalog.attributes,
|
||||
talents: summaryCatalog.talents,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user