From 50d436ce64b941c546e5a57441d7a0274b1370f4 Mon Sep 17 00:00:00 2001 From: Noah <60208472+Noahh16@users.noreply.github.com> Date: Mon, 9 Feb 2026 18:31:27 -0500 Subject: [PATCH 1/2] Fix playback reporting procedure --- ..._playback_plugin_data_to_activity_table.js | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js diff --git a/backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js b/backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js new file mode 100644 index 0000000..05ddeeb --- /dev/null +++ b/backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js @@ -0,0 +1,151 @@ +exports.up = async function (knex) { + try { + // Update the procedure to use SeriesId for shows + await knex.schema.raw(` + CREATE OR REPLACE PROCEDURE public.ji_insert_playback_plugin_data_to_activity_table( + ) + LANGUAGE 'plpgsql' + AS $BODY$ + BEGIN + insert into jf_playback_activity + SELECT + rowid, + false "IsPaused", + pb."UserId", + u."Name", + pb."ClientName", + pb."DeviceName", + null "DeviceId", + null "ApplicationVersion", + CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."SeriesId" ELSE "ItemId" END "NowPlayingItemId", + "ItemName" "NowPlayingItemName", + CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."SeasonId" ELSE null END "SeasonId", + CASE WHEN i."Id"=e."SeriesId" THEN i."Name" ELSE null END "SeriesName", + CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."EpisodeId" ELSE null END "EpisodeId", + "PlayDuration" "PlaybackDuration", + pb."DateCreated" "ActivityDateInserted", + "PlaybackMethod" "PlayMethod", + null "MediaStreams", + null "TranscodingInfo", + null "PlayState", + null "OriginalContainer", + null "RemoteEndPoint", + null "ServerId", + true "imported" + FROM public.jf_playback_reporting_plugin_data pb + LEFT JOIN public.jf_users u + on u."Id"=pb."UserId" + + LEFT JOIN public.jf_library_episodes e + on e."EpisodeId"=pb."ItemId" + + LEFT JOIN public.jf_library_items i + on i."Id"=pb."ItemId" + or i."Id"=e."SeriesId" + + WHERE NOT EXISTS + ( + SELECT "Id" "rowid" + FROM jf_playback_activity + WHERE imported=true + ) + AND + (i."Type" is not null OR (i."Type"='Series' and e."SeasonId" is not null and e."Id" is not null )); + END; + + + $BODY$; + ALTER PROCEDURE public.ji_insert_playback_plugin_data_to_activity_table() + OWNER TO "${process.env.POSTGRES_ROLE}"; + `); + + // Update all existing playback plugin data to have the correct NowPlayingItemId=SeriesId + await knex.raw(` + MERGE INTO jf_playback_activity a + USING jf_library_episodes e + ON a."NowPlayingItemId" = e."EpisodeId" + WHEN MATCHED + AND a."NowPlayingItemId" = a."EpisodeId" + AND a."imported" = true + AND position('-' in a."Id") = 0 + THEN UPDATE SET "NowPlayingItemId" = e."SeriesId"; + `); + } catch (error) { + console.error(error); + } +}; + +exports.down = async function (knex) { + try { + // Revert the procedure to the previous state + await knex.schema.raw(` + CREATE OR REPLACE PROCEDURE public.ji_insert_playback_plugin_data_to_activity_table( + ) + LANGUAGE 'plpgsql' + AS $BODY$ + BEGIN + insert into jf_playback_activity + SELECT + rowid, + false "IsPaused", + pb."UserId", + u."Name", + pb."ClientName", + pb."DeviceName", + null "DeviceId", + null "ApplicationVersion", + "ItemId" "NowPlayingItemId", + "ItemName" "NowPlayingItemName", + CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."SeasonId" ELSE null END "SeasonId", + CASE WHEN i."Id"=e."SeriesId" THEN i."Name" ELSE null END "SeriesName", + CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."EpisodeId" ELSE null END "EpisodeId", + "PlayDuration" "PlaybackDuration", + pb."DateCreated" "ActivityDateInserted", + "PlaybackMethod" "PlayMethod", + null "MediaStreams", + null "TranscodingInfo", + null "PlayState", + null "OriginalContainer", + null "RemoteEndPoint", + null "ServerId", + true "imported" + FROM public.jf_playback_reporting_plugin_data pb + LEFT JOIN public.jf_users u + on u."Id"=pb."UserId" + + LEFT JOIN public.jf_library_episodes e + on e."EpisodeId"=pb."ItemId" + + LEFT JOIN public.jf_library_items i + on i."Id"=pb."ItemId" + or i."Id"=e."SeriesId" + + WHERE NOT EXISTS + ( + SELECT "Id" "rowid" + FROM jf_playback_activity + WHERE imported=true + ) + AND + (i."Type" is not null OR (i."Type"='Series' and e."SeasonId" is not null and e."Id" is not null )); + END; + + + $BODY$; + ALTER PROCEDURE public.ji_insert_playback_plugin_data_to_activity_table() + OWNER TO "${process.env.POSTGRES_ROLE}"; + `); + + // revert only the Playback plugin records back to the old NowPlayingId=EpisodeId + await knex.raw(` + UPDATE jf_playback_activity + SET "NowPlayingItemId" = "EpisodeId" + WHERE "EpisodeId" IS NOT NULL + AND "NowPlayingItemId" != "EpisodeId" + AND position('-' in "Id") = 0 + AND "imported" = true; + `); + } catch (error) { + console.error(error); + } +}; From b5589e90c847e731893d3062eac47f3b42bd3716 Mon Sep 17 00:00:00 2001 From: Noah <60208472+Noahh16@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:27:41 -0500 Subject: [PATCH 2/2] Fix for NowPlayingItemName as well --- ..._playback_plugin_data_to_activity_table.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js b/backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js index 05ddeeb..833ccde 100644 --- a/backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js +++ b/backend/migrations/100_ji_insert_playback_plugin_data_to_activity_table.js @@ -18,7 +18,7 @@ exports.up = async function (knex) { null "DeviceId", null "ApplicationVersion", CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."SeriesId" ELSE "ItemId" END "NowPlayingItemId", - "ItemName" "NowPlayingItemName", + CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."Name" ELSE "ItemName" END "NowPlayingItemName", CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."SeasonId" ELSE null END "SeasonId", CASE WHEN i."Id"=e."SeriesId" THEN i."Name" ELSE null END "SeriesName", CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."EpisodeId" ELSE null END "EpisodeId", @@ -60,6 +60,7 @@ exports.up = async function (knex) { `); // Update all existing playback plugin data to have the correct NowPlayingItemId=SeriesId + // and set the NowPlayingItemName to the jf_library_episode."Name" await knex.raw(` MERGE INTO jf_playback_activity a USING jf_library_episodes e @@ -68,7 +69,7 @@ exports.up = async function (knex) { AND a."NowPlayingItemId" = a."EpisodeId" AND a."imported" = true AND position('-' in a."Id") = 0 - THEN UPDATE SET "NowPlayingItemId" = e."SeriesId"; + THEN UPDATE SET "NowPlayingItemId" = e."SeriesId", "NowPlayingItemName" = e."Name"; `); } catch (error) { console.error(error); @@ -96,7 +97,7 @@ exports.down = async function (knex) { null "ApplicationVersion", "ItemId" "NowPlayingItemId", "ItemName" "NowPlayingItemName", - CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."SeasonId" ELSE null END "SeasonId", + CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."SeasonId" ELSE null END "SeasonId", CASE WHEN i."Id"=e."SeriesId" THEN i."Name" ELSE null END "SeriesName", CASE WHEN e."EpisodeId"=pb."ItemId" THEN e."EpisodeId" ELSE null END "EpisodeId", "PlayDuration" "PlaybackDuration", @@ -137,13 +138,17 @@ exports.down = async function (knex) { `); // revert only the Playback plugin records back to the old NowPlayingId=EpisodeId + // and reset the NowPlayingItemName to the original playback reporting name await knex.raw(` - UPDATE jf_playback_activity - SET "NowPlayingItemId" = "EpisodeId" - WHERE "EpisodeId" IS NOT NULL - AND "NowPlayingItemId" != "EpisodeId" - AND position('-' in "Id") = 0 - AND "imported" = true; + MERGE INTO jf_playback_activity a + USING jf_playback_reporting_plugin_data p + ON a."Id"=p."rowid"::TEXT + WHEN MATCHED + AND a."EpisodeId" IS NOT NULL + AND a."NowPlayingItemId" != a."EpisodeId" + AND position('-' in a."Id") = 0 + AND "imported" = true + THEN UPDATE SET "NowPlayingItemId" = a."EpisodeId", "NowPlayingItemName" = p."ItemName"; `); } catch (error) { console.error(error);