v3: added site-wide categories, added admin category management, various visual fixes
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 2m52s
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 2m52s
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
playlistRowToApi,
|
||||
userRowToApi,
|
||||
} from "../model/db.ts";
|
||||
import { attachCategoryIds } from "./category-service.ts";
|
||||
|
||||
// ── Follow / unfollow a user ──────────────────────────────────────────────────
|
||||
|
||||
@@ -139,26 +140,35 @@ export function getFollowedUsersDumpFeed(
|
||||
followerId: string,
|
||||
page: number,
|
||||
limit: number,
|
||||
categoryId?: string,
|
||||
): { items: Dump[]; total: number } {
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
// Optional category filter: join the membership table and constrain to it.
|
||||
const catJoin = categoryId
|
||||
? "INNER JOIN dump_categories dc ON dc.dump_id = d.id AND dc.category_id = ?"
|
||||
: "";
|
||||
const catParams = categoryId ? [categoryId] : [];
|
||||
|
||||
const rawRows = db.prepare(
|
||||
`SELECT ${SELECT_COLS_ALIASED}
|
||||
FROM dumps d
|
||||
INNER JOIN follows f ON f.followed_user_id = d.user_id
|
||||
${catJoin}
|
||||
WHERE f.follower_id = ?
|
||||
AND d.is_private = 0
|
||||
ORDER BY d.created_at DESC
|
||||
LIMIT ? OFFSET ?;`,
|
||||
).all(followerId, limit, offset);
|
||||
).all(...catParams, followerId, limit, offset);
|
||||
|
||||
const totalRow = db.prepare(
|
||||
`SELECT COUNT(*) as count
|
||||
FROM dumps d
|
||||
INNER JOIN follows f ON f.followed_user_id = d.user_id
|
||||
${catJoin}
|
||||
WHERE f.follower_id = ?
|
||||
AND d.is_private = 0;`,
|
||||
).get(followerId) as { count: number } | undefined;
|
||||
).get(...catParams, followerId) as { count: number } | undefined;
|
||||
|
||||
const userFeedRows = rawRows as Parameters<typeof isDumpRow>[0][];
|
||||
if (!userFeedRows.every(isDumpRow)) {
|
||||
@@ -168,7 +178,9 @@ export function getFollowedUsersDumpFeed(
|
||||
"Malformed dump data",
|
||||
);
|
||||
}
|
||||
return { items: userFeedRows.map(dumpRowToApi), total: totalRow?.count ?? 0 };
|
||||
const items = userFeedRows.map(dumpRowToApi);
|
||||
attachCategoryIds(items);
|
||||
return { items, total: totalRow?.count ?? 0 };
|
||||
}
|
||||
|
||||
// ── Followed-playlists dump feed ──────────────────────────────────────────────
|
||||
@@ -177,22 +189,29 @@ export function getFollowedPlaylistsDumpFeed(
|
||||
followerId: string,
|
||||
page: number,
|
||||
limit: number,
|
||||
categoryId?: string,
|
||||
): { items: Dump[]; total: number } {
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
const catJoin = categoryId
|
||||
? "INNER JOIN dump_categories dc ON dc.dump_id = d.id AND dc.category_id = ?"
|
||||
: "";
|
||||
const catParams = categoryId ? [categoryId] : [];
|
||||
|
||||
const rawRows = db.prepare(
|
||||
`SELECT ${SELECT_COLS_ALIASED}
|
||||
FROM dumps d
|
||||
INNER JOIN playlist_dumps pd ON pd.dump_id = d.id
|
||||
INNER JOIN playlists p ON p.id = pd.playlist_id
|
||||
INNER JOIN follows f ON f.followed_playlist_id = p.id
|
||||
${catJoin}
|
||||
WHERE f.follower_id = ?
|
||||
AND p.is_public = 1
|
||||
AND d.is_private = 0
|
||||
GROUP BY d.id
|
||||
ORDER BY MAX(pd.added_at) DESC
|
||||
LIMIT ? OFFSET ?;`,
|
||||
).all(followerId, limit, offset);
|
||||
).all(...catParams, followerId, limit, offset);
|
||||
|
||||
const totalRow = db.prepare(
|
||||
`SELECT COUNT(DISTINCT d.id) as count
|
||||
@@ -200,10 +219,11 @@ export function getFollowedPlaylistsDumpFeed(
|
||||
INNER JOIN playlist_dumps pd ON pd.dump_id = d.id
|
||||
INNER JOIN playlists p ON p.id = pd.playlist_id
|
||||
INNER JOIN follows f ON f.followed_playlist_id = p.id
|
||||
${catJoin}
|
||||
WHERE f.follower_id = ?
|
||||
AND p.is_public = 1
|
||||
AND d.is_private = 0;`,
|
||||
).get(followerId) as { count: number } | undefined;
|
||||
).get(...catParams, followerId) as { count: number } | undefined;
|
||||
|
||||
if (!rawRows.every(isDumpRow)) {
|
||||
throw new APIException(
|
||||
@@ -212,10 +232,9 @@ export function getFollowedPlaylistsDumpFeed(
|
||||
"Malformed dump data",
|
||||
);
|
||||
}
|
||||
return {
|
||||
items: rawRows.map(dumpRowToApi),
|
||||
total: totalRow?.count ?? 0,
|
||||
};
|
||||
const items = rawRows.map(dumpRowToApi);
|
||||
attachCategoryIds(items);
|
||||
return { items, total: totalRow?.count ?? 0 };
|
||||
}
|
||||
|
||||
// ── Followed playlists (as playlist objects) ──────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user