-
-
-
+ {state.matches.map((m) => (
+
+
+
+
+
{m.entryTitle}
-
- {m.innerPath}
-
-
-
-
{formatBytes(m.sizeBytes)}
-
{m.md5}
-
+
+ {m.releaseYear && (
+
{m.releaseYear}
+ )}
+
+ {(m.authors.length > 0 || m.genre || m.machinetype) && (
+
+ {m.authors.length > 0 && (
+ {m.authors.join(", ")}
+ )}
+ {m.genre && (
+ {m.genre}
+ )}
+ {m.machinetype && (
+ {m.machinetype}
+ )}
+
+ )}
+
+
+
+
+ | File |
+ {m.innerPath} |
+
+
+ | Size |
+ {formatBytes(m.sizeBytes)} |
+
+
+ | MD5 |
+ {m.md5} |
+
+
+ | CRC32 |
+ {m.crc32} |
+
+
+
+
+
+ View entry
+
- ))}
-
+
+ ))}
>
) : (
diff --git a/src/server/repo/zxdb.ts b/src/server/repo/zxdb.ts
index 3c0fa79..74542c2 100644
--- a/src/server/repo/zxdb.ts
+++ b/src/server/repo/zxdb.ts
@@ -2633,6 +2633,11 @@ export type TapeMatch = {
md5: string;
crc32: string;
sizeBytes: number;
+ machinetype: string | null;
+ genre: string | null;
+ releaseYear: number | null;
+ authors: string[];
+ downloadLink: string;
};
export async function lookupByMd5(md5: string): Promise {
@@ -2645,12 +2650,46 @@ export async function lookupByMd5(md5: string): Promise {
md5: softwareHashes.md5,
crc32: softwareHashes.crc32,
sizeBytes: softwareHashes.sizeBytes,
+ machinetypeName: machinetypes.name,
+ genreName: genretypes.name,
+ releaseYear: releases.releaseYear,
+ downloadLink: downloads.fileLink,
})
.from(softwareHashes)
.innerJoin(downloads, eq(downloads.id, softwareHashes.downloadId))
.innerJoin(entries, eq(entries.id, downloads.entryId))
+ .leftJoin(machinetypes, eq(machinetypes.id, entries.machinetypeId))
+ .leftJoin(genretypes, eq(genretypes.id, entries.genretypeId))
+ .leftJoin(
+ releases,
+ and(eq(releases.entryId, downloads.entryId), eq(releases.releaseSeq, downloads.releaseSeq))
+ )
.where(eq(softwareHashes.md5, md5.toLowerCase()));
+ // Collect unique entry IDs to fetch authors
+ const entryIds = [...new Set(rows.map((r) => Number(r.entryId)))];
+ const authorMap = new Map();
+ if (entryIds.length > 0) {
+ try {
+ const authorRows = await db
+ .select({ entryId: authors.entryId, name: labels.name })
+ .from(authors)
+ .innerJoin(labels, eq(labels.id, authors.labelId))
+ .where(
+ entryIds.length === 1
+ ? eq(authors.entryId, entryIds[0])
+ : sql`${authors.entryId} in (${sql.join(entryIds.map((id) => sql`${id}`), sql`, `)})`
+ )
+ .orderBy(asc(authors.authorSeq));
+ for (const a of authorRows) {
+ const eid = Number(a.entryId);
+ const existing = authorMap.get(eid);
+ if (existing) existing.push(a.name);
+ else authorMap.set(eid, [a.name]);
+ }
+ } catch {}
+ }
+
return rows.map((r) => ({
downloadId: Number(r.downloadId),
entryId: Number(r.entryId),
@@ -2659,5 +2698,10 @@ export async function lookupByMd5(md5: string): Promise {
md5: r.md5,
crc32: r.crc32,
sizeBytes: Number(r.sizeBytes),
+ machinetype: r.machinetypeName ?? null,
+ genre: r.genreName ?? null,
+ releaseYear: r.releaseYear != null ? Number(r.releaseYear) : null,
+ authors: authorMap.get(Number(r.entryId)) ?? [],
+ downloadLink: r.downloadLink,
}));
}