Add links-mode embed thumbnails, item metadata, and media filters
This commit is contained in:
@@ -93,6 +93,12 @@ export interface MediaItemResult {
|
||||
channelId: string;
|
||||
kind: MediaKind;
|
||||
source: string | null;
|
||||
authorId: string | null;
|
||||
authorName: string | null;
|
||||
postedAt: string | null;
|
||||
width: number | null;
|
||||
height: number | null;
|
||||
aspectRatio: number | null;
|
||||
url: string;
|
||||
localUrl: string | null;
|
||||
thumbUrl: string | null;
|
||||
@@ -337,6 +343,29 @@ export class MediaService {
|
||||
};
|
||||
}
|
||||
|
||||
/** Distinct posters across every scrape, biggest first. */
|
||||
listAuthors(): Array<{ id: string | null; name: string | null; count: number }> {
|
||||
const totals = new Map<string, { id: string | null; name: string | null; count: number }>();
|
||||
|
||||
for (const meta of this.engine.list()) {
|
||||
if (meta.state === "deleted") continue;
|
||||
|
||||
const store = new ScrapeStore(scrapeDir(this.rootDir, meta.id));
|
||||
try {
|
||||
for (const author of store.authors()) {
|
||||
const key = author.id ?? author.name ?? "unknown";
|
||||
const current = totals.get(key);
|
||||
if (current) current.count += author.count;
|
||||
else totals.set(key, { ...author });
|
||||
}
|
||||
} finally {
|
||||
store.close();
|
||||
}
|
||||
}
|
||||
|
||||
return [...totals.values()].sort((a, b) => b.count - a.count);
|
||||
}
|
||||
|
||||
/** One media row inside a scrape, with its scrape and channel for context. */
|
||||
getMediaItem(scrapeId: string, itemId: number): (MediaRow & { scrapeId: string; channelId: string }) | null {
|
||||
const meta = this.engine.get(scrapeId);
|
||||
@@ -358,6 +387,11 @@ export class MediaService {
|
||||
source?: string;
|
||||
scrapeId?: string;
|
||||
channelId?: string;
|
||||
authorId?: string;
|
||||
aspect?: string;
|
||||
resolution?: string;
|
||||
after?: string;
|
||||
before?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
} = {}
|
||||
@@ -377,6 +411,11 @@ export class MediaService {
|
||||
const rows = store.queryMedia({
|
||||
kind: options.kind,
|
||||
source: options.source,
|
||||
authorId: options.authorId,
|
||||
aspect: options.aspect,
|
||||
resolution: options.resolution,
|
||||
after: options.after,
|
||||
before: options.before,
|
||||
limit: limit + offset
|
||||
});
|
||||
for (const row of rows) {
|
||||
@@ -388,6 +427,12 @@ export class MediaService {
|
||||
channelId: meta.channelId,
|
||||
kind: row.kind,
|
||||
source: row.source,
|
||||
authorId: row.author_id,
|
||||
authorName: row.author_name,
|
||||
postedAt: row.posted_at,
|
||||
width: row.width,
|
||||
height: row.height,
|
||||
aspectRatio: row.aspect_ratio,
|
||||
url: row.url,
|
||||
localUrl: row.file_path ? `/api/media/${meta.id}/${row.id}/file` : null,
|
||||
thumbUrl: row.preview_hash ? `/api/media/${meta.id}/${row.id}/thumb` : null,
|
||||
|
||||
Reference in New Issue
Block a user