From 265962c94f786421d4997f8680964ca9be87c431 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 15 Jun 2025 09:23:24 +0000 Subject: [PATCH 1/2] Add Crop action type and crop parameters for chapter and windowbox categories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Crop to ActionType enum - Add windowbox category with full and crop action support - Extend segment interfaces with optional crop parameters (cropLeft, cropRight, cropTop, cropBottom) - Add database migration to add crop fields to sponsorTimes table - Add validation for crop parameters (0-255 range, left+right ≤ 256, top+bottom ≤ 256) - Update database insertion and retrieval logic for crop fields Co-Authored-By: Erkin Alp Güney --- databases/_upgrade_sponsorTimes_45.sql | 10 ++++++++ src/config.ts | 5 ++-- src/routes/getSkipSegments.ts | 4 +-- src/routes/postSkipSegments.ts | 34 +++++++++++++++++++++++--- src/types/segments.model.ts | 19 +++++++++++--- 5 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 databases/_upgrade_sponsorTimes_45.sql diff --git a/databases/_upgrade_sponsorTimes_45.sql b/databases/_upgrade_sponsorTimes_45.sql new file mode 100644 index 000000000..63d7e804f --- /dev/null +++ b/databases/_upgrade_sponsorTimes_45.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +ALTER TABLE "sponsorTimes" ADD "cropLeft" INTEGER; +ALTER TABLE "sponsorTimes" ADD "cropRight" INTEGER; +ALTER TABLE "sponsorTimes" ADD "cropTop" INTEGER; +ALTER TABLE "sponsorTimes" ADD "cropBottom" INTEGER; + +UPDATE "config" SET value = 45 WHERE key = 'version'; + +COMMIT; diff --git a/src/config.ts b/src/config.ts index c290a6f41..090127e60 100644 --- a/src/config.ts +++ b/src/config.ts @@ -19,7 +19,7 @@ addDefaults(config, { privateDBSchema: "./databases/_private.db.sql", readOnly: false, webhooks: [], - categoryList: ["sponsor", "selfpromo", "exclusive_access", "interaction", "intro", "outro", "preview", "music_offtopic", "filler", "poi_highlight", "chapter"], + categoryList: ["sponsor", "selfpromo", "exclusive_access", "interaction", "intro", "outro", "preview", "music_offtopic", "filler", "poi_highlight", "chapter", "windowbox"], casualCategoryList: ["funny", "creative", "clever", "descriptive", "other"], categorySupport: { sponsor: ["skip", "mute", "full"], @@ -32,7 +32,8 @@ addDefaults(config, { filler: ["skip", "mute"], music_offtopic: ["skip"], poi_highlight: ["poi"], - chapter: ["chapter"] + chapter: ["chapter", "crop"], + windowbox: ["full", "crop"] }, deArrowTypes: ["title", "thumbnail"], maxTitleLength: 110, diff --git a/src/routes/getSkipSegments.ts b/src/routes/getSkipSegments.ts index e21305cf4..7ec26cce1 100644 --- a/src/routes/getSkipSegments.ts +++ b/src/routes/getSkipSegments.ts @@ -218,7 +218,7 @@ async function getSegmentsFromDBByHash(hashedVideoIDPrefix: VideoIDHash, service const fetchFromDB = () => db .prepare( "all", - `SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "hidden", "reputation", "shadowHidden", "hashedVideoID", "timeSubmitted", "description" FROM "sponsorTimes" + `SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "hidden", "reputation", "shadowHidden", "hashedVideoID", "timeSubmitted", "description", "cropLeft", "cropRight", "cropTop", "cropBottom" FROM "sponsorTimes" WHERE "hashedVideoID" LIKE ? AND "service" = ? ORDER BY "startTime"`, [`${hashedVideoIDPrefix}%`, service], { useReplica: true } @@ -237,7 +237,7 @@ async function getSegmentsFromDBByVideoID(videoID: VideoID, service: Service): P const fetchFromDB = () => db .prepare( "all", - `SELECT "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "hidden", "reputation", "shadowHidden", "timeSubmitted", "description" FROM "sponsorTimes" + `SELECT "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "hidden", "reputation", "shadowHidden", "timeSubmitted", "description", "cropLeft", "cropRight", "cropTop", "cropBottom" FROM "sponsorTimes" WHERE "videoID" = ? AND "service" = ? ORDER BY "startTime"`, [videoID, service], { useReplica: true } diff --git a/src/routes/postSkipSegments.ts b/src/routes/postSkipSegments.ts index 8759b1e04..2e6551412 100644 --- a/src/routes/postSkipSegments.ts +++ b/src/routes/postSkipSegments.ts @@ -302,6 +302,34 @@ async function checkEachSegmentValid(rawIP: IPAddress, paramUserID: UserID, user return { pass: false, errorMessage: "ActionType is not supported with this category.", errorCode: 400 }; } + if (segments[i].actionType === ActionType.Crop) { + const cropFields = [ + { name: 'cropLeft', value: segments[i].cropLeft }, + { name: 'cropRight', value: segments[i].cropRight }, + { name: 'cropTop', value: segments[i].cropTop }, + { name: 'cropBottom', value: segments[i].cropBottom } + ]; + for (const field of cropFields) { + if (field.value !== undefined) { + if (!Number.isInteger(field.value) || field.value < 0 || field.value > 255) { + return { pass: false, errorMessage: `${field.name} must be an integer between 0 and 255.`, errorCode: 400 }; + } + } + } + + const leftValue = segments[i].cropLeft || 0; + const rightValue = segments[i].cropRight || 0; + const topValue = segments[i].cropTop || 0; + const bottomValue = segments[i].cropBottom || 0; + + if (leftValue + rightValue > 256) { + return { pass: false, errorMessage: "cropLeft + cropRight must not exceed 256.", errorCode: 400 }; + } + if (topValue + bottomValue > 256) { + return { pass: false, errorMessage: "cropTop + cropBottom must not exceed 256.", errorCode: 400 }; + } + } + const startTime = parseFloat(segments[i].segment[0]); const endTime = parseFloat(segments[i].segment[1]); @@ -612,10 +640,10 @@ export async function postSkipSegments(req: Request, res: Response): Promise Date: Sun, 15 Jun 2025 09:29:40 +0000 Subject: [PATCH 2/2] Fix segment archive jobs by adding crop fields to archivedSponsorTimes table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update migration to add crop fields to both sponsorTimes and archivedSponsorTimes - Ensures archive job SELECT * operations work correctly with new crop parameters - Maintains transaction consistency as requested Co-Authored-By: Erkin Alp Güney --- databases/_upgrade_sponsorTimes_45.sql | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/databases/_upgrade_sponsorTimes_45.sql b/databases/_upgrade_sponsorTimes_45.sql index 63d7e804f..d50e2d9ae 100644 --- a/databases/_upgrade_sponsorTimes_45.sql +++ b/databases/_upgrade_sponsorTimes_45.sql @@ -5,6 +5,11 @@ ALTER TABLE "sponsorTimes" ADD "cropRight" INTEGER; ALTER TABLE "sponsorTimes" ADD "cropTop" INTEGER; ALTER TABLE "sponsorTimes" ADD "cropBottom" INTEGER; +ALTER TABLE "archivedSponsorTimes" ADD "cropLeft" INTEGER; +ALTER TABLE "archivedSponsorTimes" ADD "cropRight" INTEGER; +ALTER TABLE "archivedSponsorTimes" ADD "cropTop" INTEGER; +ALTER TABLE "archivedSponsorTimes" ADD "cropBottom" INTEGER; + UPDATE "config" SET value = 45 WHERE key = 'version'; COMMIT;