aboutsummaryrefslogtreecommitdiffstats
path: root/packages/trpc/models/bookmarks.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/trpc/models/bookmarks.ts')
-rw-r--r--packages/trpc/models/bookmarks.ts80
1 files changed, 79 insertions, 1 deletions
diff --git a/packages/trpc/models/bookmarks.ts b/packages/trpc/models/bookmarks.ts
index 986fca58..07b3832d 100644
--- a/packages/trpc/models/bookmarks.ts
+++ b/packages/trpc/models/bookmarks.ts
@@ -27,6 +27,7 @@ import {
rssFeedImportsTable,
tagsOnBookmarks,
} from "@karakeep/db/schema";
+import { readAsset } from "@karakeep/shared/assetdb";
import serverConfig from "@karakeep/shared/config";
import {
createSignedToken,
@@ -46,6 +47,7 @@ import {
getBookmarkLinkAssetIdOrUrl,
getBookmarkTitle,
} from "@karakeep/shared/utils/bookmarkUtils";
+import { htmlToPlainText } from "@karakeep/shared/utils/htmlUtils";
import { AuthedContext } from "..";
import { mapDBAssetTypeToUserType } from "../lib/attachments";
@@ -202,8 +204,11 @@ export class Bookmark implements PrivacyAware {
imageUrl: row.bookmarkLinks.imageUrl,
favicon: row.bookmarkLinks.favicon,
htmlContent: input.includeContent
- ? row.bookmarkLinks.htmlContent
+ ? row.bookmarkLinks.contentAssetId
+ ? null // Will be populated later from asset
+ : row.bookmarkLinks.htmlContent
: null,
+ contentAssetId: row.bookmarkLinks.contentAssetId,
crawledAt: row.bookmarkLinks.crawledAt,
author: row.bookmarkLinks.author,
publisher: row.bookmarkLinks.publisher,
@@ -300,6 +305,33 @@ export class Bookmark implements PrivacyAware {
const bookmarksArr = Object.values(bookmarksRes);
+ // Fetch HTML content from assets for bookmarks that have contentAssetId (large content)
+ if (input.includeContent) {
+ await Promise.all(
+ bookmarksArr.map(async (bookmark) => {
+ if (
+ bookmark.content.type === BookmarkTypes.LINK &&
+ bookmark.content.contentAssetId &&
+ !bookmark.content.htmlContent // Only fetch if not already inline
+ ) {
+ try {
+ const asset = await readAsset({
+ userId: ctx.user.id,
+ assetId: bookmark.content.contentAssetId,
+ });
+ bookmark.content.htmlContent = asset.asset.toString("utf8");
+ } catch (error) {
+ // If asset reading fails, keep htmlContent as null
+ console.warn(
+ `Failed to read HTML content asset ${bookmark.content.contentAssetId}:`,
+ error,
+ );
+ }
+ }
+ }),
+ );
+ }
+
bookmarksArr.sort((a, b) => {
if (a.createdAt != b.createdAt) {
return input.sortOrder === "asc"
@@ -427,4 +459,50 @@ export class Bookmark implements PrivacyAware {
bannerImageUrl: getBannerImageUrl(this.bookmark.content),
};
}
+
+ static async getBookmarkHtmlContent(
+ {
+ contentAssetId,
+ htmlContent,
+ }: {
+ contentAssetId: string | null;
+ htmlContent: string | null;
+ },
+ userId: string,
+ ): Promise<string | null> {
+ if (contentAssetId) {
+ // Read large HTML content from asset
+ const asset = await readAsset({
+ userId,
+ assetId: contentAssetId,
+ });
+ return asset.asset.toString("utf8");
+ } else if (htmlContent) {
+ return htmlContent;
+ }
+ return null;
+ }
+
+ static async getBookmarkPlainTextContent(
+ {
+ contentAssetId,
+ htmlContent,
+ }: {
+ contentAssetId: string | null;
+ htmlContent: string | null;
+ },
+ userId: string,
+ ): Promise<string | null> {
+ const content = await this.getBookmarkHtmlContent(
+ {
+ contentAssetId,
+ htmlContent,
+ },
+ userId,
+ );
+ if (!content) {
+ return null;
+ }
+ return htmlToPlainText(content);
+ }
}