Skip to content

Commit 28d2b7b

Browse files
committed
user bookmarks list page
1 parent 8fa663b commit 28d2b7b

6 files changed

Lines changed: 104 additions & 3 deletions

File tree

api/src/controllers/torrent.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ export const deleteTorrent = async (req, res, next) => {
450450
export const getTorrentsPage = async ({
451451
skip = 0,
452452
limit = 25,
453+
ids,
453454
query,
454455
category,
455456
source,
@@ -473,6 +474,13 @@ export const getTorrentsPage = async ({
473474
tags: 1,
474475
},
475476
},
477+
...(Array.isArray(ids)
478+
? [
479+
{
480+
$match: { $expr: { $in: ["$_id", ids] } },
481+
},
482+
]
483+
: []),
476484
...(query
477485
? [
478486
{
@@ -581,6 +589,13 @@ export const getTorrentsPage = async ({
581589
]);
582590

583591
const [count] = await Torrent.aggregate([
592+
...(Array.isArray(ids)
593+
? [
594+
{
595+
$match: { expr: { $in: ["$_id", ids] } },
596+
},
597+
]
598+
: []),
584599
...(query
585600
? [
586601
{
@@ -636,7 +651,7 @@ export const getTorrentsPage = async ({
636651

637652
return {
638653
torrents: await embellishTorrentsWithTrackerScrape(tracker, torrents),
639-
...count,
654+
total: count?.total ?? torrents.length,
640655
};
641656
};
642657

api/src/controllers/user.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Progress from "../schema/progress";
99
import { getTorrentsPage } from "./torrent";
1010
import { getUserRatio } from "../utils/ratio";
1111
import { BYTES_GB } from "../tracker/announce";
12+
import Torrent from "../schema/torrent";
1213

1314
export const sendVerificationEmail = async (mail, address, token) => {
1415
await mail.sendMail({
@@ -1044,3 +1045,17 @@ export const deleteAccount = async (req, res, next) => {
10441045
res.status(400).send("Request must include password");
10451046
}
10461047
};
1048+
1049+
export const getUserBookmarks = (tracker) => async (req, res, next) => {
1050+
try {
1051+
const user = await User.findOne({ _id: req.userId }).lean();
1052+
const bookmarks = await getTorrentsPage({
1053+
ids: user.bookmarks,
1054+
userId: req.userId,
1055+
tracker,
1056+
});
1057+
res.json(bookmarks);
1058+
} catch (e) {
1059+
next(e);
1060+
}
1061+
};

api/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ validateConfig(config).then(() => {
164164
// everything from here on requires user auth
165165
app.use(auth);
166166

167-
app.use("/account", accountRoutes(mail));
167+
app.use("/account", accountRoutes(tracker, mail));
168168
app.use("/user", userRoutes(tracker));
169169
app.use("/torrent", torrentRoutes(tracker));
170170
app.use("/announcements", announcementRoutes());

api/src/routes/account.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import {
1111
enableTotp,
1212
disableTotp,
1313
deleteAccount,
14+
getUserBookmarks,
1415
} from "../controllers/user";
1516

1617
const router = express.Router();
1718

18-
export default (mail) => {
19+
export default (tracker, mail) => {
1920
router.get("/invites", fetchInvites);
2021
router.post("/generate-invite", generateInvite(mail));
2122
router.post("/change-password", changePassword(mail));
@@ -27,5 +28,6 @@ export default (mail) => {
2728
router.post("/totp/enable", enableTotp);
2829
router.post("/totp/disable", disableTotp);
2930
router.post("/delete", deleteAccount);
31+
router.get("/bookmarks", getUserBookmarks(tracker));
3032
return router;
3133
};

client/components/Navigation.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { MessageAdd } from "@styled-icons/boxicons-regular/MessageAdd";
1414
import { News } from "@styled-icons/boxicons-regular/News";
1515
import { BookOpen } from "@styled-icons/boxicons-regular/BookOpen";
1616
import { Rss } from "@styled-icons/boxicons-regular/Rss";
17+
import { Bookmark } from "@styled-icons/boxicons-regular/Bookmark";
1718
import { User } from "@styled-icons/boxicons-regular/User";
1819
import { Error } from "@styled-icons/boxicons-regular/Error";
1920
import { TrendingUp } from "@styled-icons/boxicons-regular/TrendingUp";
@@ -196,6 +197,12 @@ const Navigation = ({ isMobile, menuIsOpen, setMenuIsOpen }) => {
196197
<Rss size={24} />
197198
</NavLink>
198199
</Link>
200+
<Link href="/bookmarks" passHref>
201+
<NavLink>
202+
<Text>Bookmarks</Text>
203+
<Bookmark size={24} />
204+
</NavLink>
205+
</Link>
199206
<Link href={`/user/${username}`} passHref>
200207
<NavLink highlights={["/account"]}>
201208
<Text>{username}</Text>

client/pages/bookmarks.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from "react";
2+
import getConfig from "next/config";
3+
import { useRouter } from "next/router";
4+
import qs from "qs";
5+
import { withAuthServerSideProps } from "../utils/withAuth";
6+
import SEO from "../components/SEO";
7+
import Text from "../components/Text";
8+
import TorrentList from "../components/TorrentList";
9+
10+
const Bookmarks = ({ results }) => {
11+
const {
12+
publicRuntimeConfig: { SQ_TORRENT_CATEGORIES },
13+
} = getConfig();
14+
15+
return (
16+
<>
17+
<SEO title="Your bookmarks" />
18+
<Text as="h1" mb={5}>
19+
Your bookmarks
20+
</Text>
21+
{results.torrents.length ? (
22+
<TorrentList
23+
torrents={results.torrents}
24+
categories={SQ_TORRENT_CATEGORIES}
25+
total={results.total}
26+
/>
27+
) : (
28+
<Text color="grey">You do not have any bookmarks.</Text>
29+
)}
30+
</>
31+
);
32+
};
33+
34+
export const getServerSideProps = withAuthServerSideProps(
35+
async ({ token, fetchHeaders }) => {
36+
if (!token) return { props: {} };
37+
38+
const {
39+
publicRuntimeConfig: { SQ_API_URL },
40+
} = getConfig();
41+
42+
try {
43+
const bookmarksRes = await fetch(`${SQ_API_URL}/account/bookmarks`, {
44+
headers: fetchHeaders,
45+
});
46+
if (
47+
bookmarksRes.status === 403 &&
48+
(await bookmarksRes.text()) === "User is banned"
49+
) {
50+
throw "banned";
51+
} else {
52+
const results = await bookmarksRes.json();
53+
return { props: { results } };
54+
}
55+
} catch (e) {
56+
if (e === "banned") throw "banned";
57+
return { props: { results: { torrents: [] } } };
58+
}
59+
}
60+
);
61+
62+
export default Bookmarks;

0 commit comments

Comments
 (0)