Improve ISAC libraries, roles, and public profiles
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import type { Database } from '@tursodatabase/database';
|
||||
import {
|
||||
displayNameKey,
|
||||
newAgentDisplayName,
|
||||
publicProfileSlugBase
|
||||
} from '$lib/agents';
|
||||
|
||||
export async function displayNameIsAvailable(
|
||||
database: Database,
|
||||
displayName: string,
|
||||
exceptUserId = ''
|
||||
): Promise<boolean> {
|
||||
const row = await (await database.prepare(
|
||||
'SELECT user_id FROM user_profiles WHERE display_name_key=? AND user_id<>?'
|
||||
)).get(displayNameKey(displayName), exceptUserId);
|
||||
return !row;
|
||||
}
|
||||
|
||||
export async function createAvailableDisplayName(
|
||||
database: Database,
|
||||
preferredName: string,
|
||||
userId: string,
|
||||
placeholder = false
|
||||
): Promise<string> {
|
||||
if (!placeholder && await displayNameIsAvailable(database, preferredName)) return preferredName;
|
||||
if (placeholder) {
|
||||
const names = await (await database.prepare(
|
||||
"SELECT display_name FROM user_profiles WHERE display_name LIKE 'Agent %'"
|
||||
)).all();
|
||||
let sequence = names.reduce((highest, row) => {
|
||||
const match = /^Agent ([1-9]\d*)$/.exec(String(row.display_name));
|
||||
return match ? Math.max(highest, Number(match[1])) : highest;
|
||||
}, 0) + 1;
|
||||
while (!(await displayNameIsAvailable(database, newAgentDisplayName(sequence)))) sequence += 1;
|
||||
return newAgentDisplayName(sequence);
|
||||
}
|
||||
for (let suffixLength = 5; suffixLength <= 12; suffixLength += 1) {
|
||||
const candidate = `${preferredName} ${userId.replaceAll('-', '').slice(0, suffixLength).toLowerCase()}`;
|
||||
if (await displayNameIsAvailable(database, candidate)) return candidate;
|
||||
}
|
||||
throw new Error('Unable to allocate a unique display name.');
|
||||
}
|
||||
|
||||
export async function createPublicProfileSlug(
|
||||
database: Database,
|
||||
displayName: string,
|
||||
userId: string
|
||||
): Promise<string> {
|
||||
const base = publicProfileSlugBase(displayName, userId);
|
||||
const existing = await (await database.prepare(
|
||||
'SELECT user_id FROM user_profiles WHERE public_slug=?'
|
||||
)).get(base);
|
||||
if (!existing || String(existing.user_id) === userId) return base;
|
||||
return `${base.slice(0, 55).replace(/-+$/g, '')}~${userId.replaceAll('-', '').slice(0, 8).toLowerCase()}`;
|
||||
}
|
||||
|
||||
export async function insertUserProfile(
|
||||
database: Database,
|
||||
userId: string,
|
||||
preferredName: string,
|
||||
updatedAt: string,
|
||||
options: { placeholder?: boolean; resolveCollision?: boolean } = {}
|
||||
): Promise<{ displayName: string; publicSlug: string }> {
|
||||
const displayName = options.placeholder || options.resolveCollision
|
||||
? await createAvailableDisplayName(database, preferredName, userId, Boolean(options.placeholder))
|
||||
: preferredName;
|
||||
const publicSlug = await createPublicProfileSlug(database, displayName, userId);
|
||||
await (await database.prepare(`INSERT INTO user_profiles
|
||||
(user_id,display_name,display_name_key,public_slug,updated_at) VALUES(?,?,?,?,?)`))
|
||||
.run(userId, displayName, displayNameKey(displayName), publicSlug, updatedAt);
|
||||
return { displayName, publicSlug };
|
||||
}
|
||||
|
||||
export async function resolveAgentProfile(
|
||||
database: Database,
|
||||
identifier: string
|
||||
): Promise<{ id: string; publicSlug: string; displayName: string } | null> {
|
||||
const row = await (await database.prepare(`SELECT users.id,
|
||||
COALESCE(profile.public_slug,users.id) AS public_slug,
|
||||
COALESCE(profile.display_name,users.username) AS display_name
|
||||
FROM users LEFT JOIN user_profiles profile ON profile.user_id=users.id
|
||||
WHERE users.id=? OR profile.public_slug=?
|
||||
ORDER BY CASE WHEN profile.public_slug=? THEN 0 ELSE 1 END
|
||||
LIMIT 1`)).get(identifier, identifier, identifier);
|
||||
return row ? {
|
||||
id: String(row.id),
|
||||
publicSlug: String(row.public_slug),
|
||||
displayName: String(row.display_name)
|
||||
} : null;
|
||||
}
|
||||
Reference in New Issue
Block a user