Homelabtoolkit v2
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { DatabaseSync } from 'node:sqlite';
|
||||
|
||||
function getCacheDbPath() {
|
||||
return process.env.EMBY_USER_CACHE_DB_PATH || resolve('.cache', 'emby-users.db');
|
||||
}
|
||||
|
||||
function ensureCacheDir() {
|
||||
const dir = dirname(getCacheDbPath());
|
||||
if (!existsSync(dir)) {
|
||||
mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
function openCacheDb() {
|
||||
ensureCacheDir();
|
||||
const db = new DatabaseSync(getCacheDbPath());
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS EmbyUsers (
|
||||
embyGuid TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
fetchedAt TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS CacheMeta (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
`);
|
||||
return db;
|
||||
}
|
||||
|
||||
function normalizeGuid(value) {
|
||||
return typeof value === 'string' ? value.replace(/-/g, '').trim().toLowerCase() : '';
|
||||
}
|
||||
|
||||
export function normalizeEmbyUsers(users) {
|
||||
if (!Array.isArray(users)) return [];
|
||||
|
||||
return users
|
||||
.map((user) => ({
|
||||
embyGuid: normalizeGuid(user?.embyGuid ?? user?.Id),
|
||||
name: String(user?.name ?? user?.Name ?? '').trim()
|
||||
}))
|
||||
.filter((user) => user.embyGuid && user.name);
|
||||
}
|
||||
|
||||
export function writeCachedEmbyUsers(users) {
|
||||
const normalizedUsers = normalizeEmbyUsers(users);
|
||||
const fetchedAt = new Date().toISOString();
|
||||
const db = openCacheDb();
|
||||
|
||||
try {
|
||||
const clearStmt = db.prepare('DELETE FROM EmbyUsers');
|
||||
const insertStmt = db.prepare(
|
||||
'INSERT INTO EmbyUsers (embyGuid, name, fetchedAt) VALUES (?, ?, ?)'
|
||||
);
|
||||
const metaStmt = db.prepare(
|
||||
'INSERT INTO CacheMeta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value'
|
||||
);
|
||||
|
||||
db.exec('BEGIN');
|
||||
try {
|
||||
clearStmt.run();
|
||||
for (const user of normalizedUsers) {
|
||||
insertStmt.run(user.embyGuid, user.name, fetchedAt);
|
||||
}
|
||||
metaStmt.run('lastSyncedAt', fetchedAt);
|
||||
db.exec('COMMIT');
|
||||
} catch (error) {
|
||||
db.exec('ROLLBACK');
|
||||
throw error;
|
||||
}
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
|
||||
return { users: normalizedUsers, lastSyncedAt: fetchedAt };
|
||||
}
|
||||
|
||||
export function readCachedEmbyUsers() {
|
||||
if (!existsSync(getCacheDbPath())) {
|
||||
return { users: [], lastSyncedAt: null };
|
||||
}
|
||||
|
||||
const db = openCacheDb();
|
||||
try {
|
||||
const users = db
|
||||
.prepare('SELECT embyGuid, name, fetchedAt FROM EmbyUsers ORDER BY lower(name), embyGuid')
|
||||
.all()
|
||||
.map((row) => ({
|
||||
embyGuid: normalizeGuid(row.embyGuid),
|
||||
name: row.name
|
||||
}));
|
||||
const meta = db.prepare("SELECT value FROM CacheMeta WHERE key = 'lastSyncedAt'").get();
|
||||
|
||||
return {
|
||||
users,
|
||||
lastSyncedAt: meta?.value || users[0]?.fetchedAt || null
|
||||
};
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
export function getCachedEmbyUserMap() {
|
||||
return new Map(readCachedEmbyUsers().users.map((user) => [user.embyGuid, user]));
|
||||
}
|
||||
|
||||
export function applyCachedEmbyNames(users) {
|
||||
const cached = readCachedEmbyUsers();
|
||||
const lookup = new Map(cached.users.map((user) => [user.embyGuid, user]));
|
||||
let matchedCount = 0;
|
||||
|
||||
const hydratedUsers = (users || []).map((user) => {
|
||||
const embyGuid = normalizeGuid(user?.embyGuid);
|
||||
const cachedUser = lookup.get(embyGuid);
|
||||
if (!cachedUser) {
|
||||
return user;
|
||||
}
|
||||
|
||||
matchedCount++;
|
||||
return {
|
||||
...user,
|
||||
dbName: user.dbName || user.name,
|
||||
embyName: cachedUser.name,
|
||||
name: cachedUser.name
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
users: hydratedUsers,
|
||||
cache: {
|
||||
matchedCount,
|
||||
totalCachedUsers: lookup.size,
|
||||
lastSyncedAt: cached.lastSyncedAt
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user