aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/db/schema.ts2
-rw-r--r--packages/open-api/hoarder-openapi-spec.json9
-rw-r--r--packages/shared/assetdb.ts16
-rw-r--r--packages/shared/config.ts6
-rw-r--r--packages/shared/queues.ts23
-rw-r--r--packages/shared/types/bookmarks.ts2
-rw-r--r--packages/trpc/lib/attachments.ts5
-rw-r--r--packages/trpc/routers/bookmarks.ts5
8 files changed, 68 insertions, 0 deletions
diff --git a/packages/db/schema.ts b/packages/db/schema.ts
index 033295bf..10c69d9d 100644
--- a/packages/db/schema.ts
+++ b/packages/db/schema.ts
@@ -165,6 +165,7 @@ export const enum AssetTypes {
LINK_BANNER_IMAGE = "linkBannerImage",
LINK_SCREENSHOT = "linkScreenshot",
LINK_FULL_PAGE_ARCHIVE = "linkFullPageArchive",
+ LINK_VIDEO = "linkVideo",
BOOKMARK_ASSET = "bookmarkAsset",
UNKNOWN = "unknown",
}
@@ -179,6 +180,7 @@ export const assets = sqliteTable(
AssetTypes.LINK_BANNER_IMAGE,
AssetTypes.LINK_SCREENSHOT,
AssetTypes.LINK_FULL_PAGE_ARCHIVE,
+ AssetTypes.LINK_VIDEO,
AssetTypes.BOOKMARK_ASSET,
AssetTypes.UNKNOWN,
],
diff --git a/packages/open-api/hoarder-openapi-spec.json b/packages/open-api/hoarder-openapi-spec.json
index a93a0b9c..eac98326 100644
--- a/packages/open-api/hoarder-openapi-spec.json
+++ b/packages/open-api/hoarder-openapi-spec.json
@@ -140,6 +140,10 @@
"type": "string",
"nullable": true
},
+ "videoAssetId": {
+ "type": "string",
+ "nullable": true
+ },
"favicon": {
"type": "string",
"nullable": true,
@@ -245,6 +249,7 @@
"screenshot",
"bannerImage",
"fullPageArchive",
+ "video",
"bookmarkAsset",
"unknown"
]
@@ -488,6 +493,10 @@
"type": "string",
"nullable": true
},
+ "videoAssetId": {
+ "type": "string",
+ "nullable": true
+ },
"favicon": {
"type": "string",
"nullable": true,
diff --git a/packages/shared/assetdb.ts b/packages/shared/assetdb.ts
index 64413e9f..fb7d2461 100644
--- a/packages/shared/assetdb.ts
+++ b/packages/shared/assetdb.ts
@@ -13,6 +13,7 @@ export const enum ASSET_TYPES {
IMAGE_WEBP = "image/webp",
APPLICATION_PDF = "application/pdf",
TEXT_HTML = "text/html",
+ VIDEO_MP4 = "video/mp4",
}
export const IMAGE_ASSET_TYPES: Set<string> = new Set<string>([
@@ -31,6 +32,7 @@ export const SUPPORTED_UPLOAD_ASSET_TYPES: Set<string> = new Set<string>([
export const SUPPORTED_ASSET_TYPES: Set<string> = new Set<string>([
...SUPPORTED_UPLOAD_ASSET_TYPES,
ASSET_TYPES.TEXT_HTML,
+ ASSET_TYPES.VIDEO_MP4,
]);
function getAssetDir(userId: string, assetId: string) {
@@ -152,6 +154,20 @@ export async function getAssetSize({
return stat.size;
}
+/**
+ * Deletes the passed in asset if it exists and ignores any errors
+ * @param userId the id of the user the asset belongs to
+ * @param assetId the id of the asset to delete
+ */
+export async function silentDeleteAsset(
+ userId: string,
+ assetId: string | undefined,
+) {
+ if (assetId) {
+ await deleteAsset({ userId, assetId }).catch(() => ({}));
+ }
+}
+
export async function deleteAsset({
userId,
assetId,
diff --git a/packages/shared/config.ts b/packages/shared/config.ts
index 4b51d15d..35d3df54 100644
--- a/packages/shared/config.ts
+++ b/packages/shared/config.ts
@@ -42,6 +42,9 @@ const allEnv = z.object({
CRAWLER_STORE_SCREENSHOT: stringBool("true"),
CRAWLER_FULL_PAGE_SCREENSHOT: stringBool("false"),
CRAWLER_FULL_PAGE_ARCHIVE: stringBool("false"),
+ CRAWLER_VIDEO_DOWNLOAD: stringBool("false"),
+ CRAWLER_VIDEO_DOWNLOAD_MAX_SIZE: z.coerce.number().default(50),
+ CRAWLER_VIDEO_DOWNLOAD_TIMEOUT_SEC: z.coerce.number().default(10 * 60),
MEILI_ADDR: z.string().optional(),
MEILI_MASTER_KEY: z.string().default(""),
LOG_LEVEL: z.string().default("debug"),
@@ -98,6 +101,9 @@ const serverConfigSchema = allEnv.transform((val) => {
storeScreenshot: val.CRAWLER_STORE_SCREENSHOT,
fullPageScreenshot: val.CRAWLER_FULL_PAGE_SCREENSHOT,
fullPageArchive: val.CRAWLER_FULL_PAGE_ARCHIVE,
+ downloadVideo: val.CRAWLER_VIDEO_DOWNLOAD,
+ maxVideoDownloadSize: val.CRAWLER_VIDEO_DOWNLOAD_MAX_SIZE,
+ downloadVideoTimeout: val.CRAWLER_VIDEO_DOWNLOAD_TIMEOUT_SEC,
},
ocr: {
langs: val.OCR_LANGS,
diff --git a/packages/shared/queues.ts b/packages/shared/queues.ts
index 0cb30aae..6189a633 100644
--- a/packages/shared/queues.ts
+++ b/packages/shared/queues.ts
@@ -93,3 +93,26 @@ export async function triggerSearchDeletion(bookmarkId: string) {
type: "delete",
});
}
+
+export const zvideoRequestSchema = z.object({
+ bookmarkId: z.string(),
+ url: z.string(),
+});
+export type ZVideoRequest = z.infer<typeof zvideoRequestSchema>;
+
+export const VideoWorkerQueue = new SqliteQueue<ZVideoRequest>(
+ "video_queue",
+ queueDB,
+ {
+ defaultJobArgs: {
+ numRetries: 5,
+ },
+ },
+);
+
+export async function triggerVideoWorker(bookmarkId: string, url: string) {
+ await VideoWorkerQueue.enqueue({
+ bookmarkId,
+ url,
+ });
+}
diff --git a/packages/shared/types/bookmarks.ts b/packages/shared/types/bookmarks.ts
index c731cb32..2d46684e 100644
--- a/packages/shared/types/bookmarks.ts
+++ b/packages/shared/types/bookmarks.ts
@@ -15,6 +15,7 @@ export const zAssetTypesSchema = z.enum([
"screenshot",
"bannerImage",
"fullPageArchive",
+ "video",
"bookmarkAsset",
"unknown",
]);
@@ -34,6 +35,7 @@ export const zBookmarkedLinkSchema = z.object({
imageAssetId: z.string().nullish(),
screenshotAssetId: z.string().nullish(),
fullPageArchiveAssetId: z.string().nullish(),
+ videoAssetId: z.string().nullish(),
favicon: z.string().url().nullish(),
htmlContent: z.string().nullish(),
crawledAt: z.date().nullish(),
diff --git a/packages/trpc/lib/attachments.ts b/packages/trpc/lib/attachments.ts
index 175947f8..0fd41d1b 100644
--- a/packages/trpc/lib/attachments.ts
+++ b/packages/trpc/lib/attachments.ts
@@ -8,6 +8,7 @@ export function mapDBAssetTypeToUserType(assetType: AssetTypes): ZAssetType {
[AssetTypes.LINK_SCREENSHOT]: "screenshot",
[AssetTypes.LINK_FULL_PAGE_ARCHIVE]: "fullPageArchive",
[AssetTypes.LINK_BANNER_IMAGE]: "bannerImage",
+ [AssetTypes.LINK_VIDEO]: "video",
[AssetTypes.BOOKMARK_ASSET]: "bookmarkAsset",
[AssetTypes.UNKNOWN]: "bannerImage",
};
@@ -21,6 +22,7 @@ export function mapSchemaAssetTypeToDB(
screenshot: AssetTypes.LINK_SCREENSHOT,
fullPageArchive: AssetTypes.LINK_FULL_PAGE_ARCHIVE,
bannerImage: AssetTypes.LINK_BANNER_IMAGE,
+ video: AssetTypes.LINK_VIDEO,
bookmarkAsset: AssetTypes.BOOKMARK_ASSET,
unknown: AssetTypes.UNKNOWN,
};
@@ -32,6 +34,7 @@ export function humanFriendlyNameForAssertType(type: ZAssetType) {
screenshot: "Screenshot",
fullPageArchive: "Full Page Archive",
bannerImage: "Banner Image",
+ video: "Video",
bookmarkAsset: "Bookmark Asset",
unknown: "Unknown",
};
@@ -43,6 +46,7 @@ export function isAllowedToAttachAsset(type: ZAssetType) {
screenshot: true,
fullPageArchive: false,
bannerImage: true,
+ video: false,
bookmarkAsset: false,
unknown: false,
};
@@ -54,6 +58,7 @@ export function isAllowedToDetachAsset(type: ZAssetType) {
screenshot: true,
fullPageArchive: true,
bannerImage: true,
+ video: true,
bookmarkAsset: false,
unknown: false,
};
diff --git a/packages/trpc/routers/bookmarks.ts b/packages/trpc/routers/bookmarks.ts
index 80dd4bec..9a27c25a 100644
--- a/packages/trpc/routers/bookmarks.ts
+++ b/packages/trpc/routers/bookmarks.ts
@@ -215,6 +215,8 @@ function toZodSchema(bookmark: BookmarkQueryReturnType): ZBookmark {
imageAssetId: assets.find(
(a) => a.assetType == AssetTypes.LINK_BANNER_IMAGE,
)?.id,
+ videoAssetId: assets.find((a) => a.assetType == AssetTypes.LINK_VIDEO)
+ ?.id,
...link,
};
break;
@@ -698,6 +700,9 @@ export const bookmarksAppRouter = router({
if (row.assets.assetType == AssetTypes.LINK_BANNER_IMAGE) {
content.imageAssetId = row.assets.id;
}
+ if (row.assets.assetType == AssetTypes.LINK_VIDEO) {
+ content.videoAssetId = row.assets.id;
+ }
acc[bookmarkId].content = content;
}
acc[bookmarkId].assets.push({