// ==UserScript==
// @name Disney+ Mark Watched
// @namespace watched_disneyplus
// @version 1.5
// @description Mark Disney+ shows as watched.
// @include https://www.disneyplus.com/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_listValues
// @grant GM_deleteValue
// @license MIT
// @downloadURL https://update.greasyfork.icu/scripts/515467/Disney%2B%20Mark%20Watched.user.js
// @updateURL https://update.greasyfork.icu/scripts/515467/Disney%2B%20Mark%20Watched.meta.js
// ==/UserScript==
(function() {
// Migrate data from localStorage to GM storage
function migrateWatchedData() {
let migrated = false;
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith("watched_")) {
GM_setValue(key, localStorage.getItem(key));
console.log("Migrated:", key);
localStorage.removeItem(key);
migrated = true;
}
}
if (migrated) {
alert("Migration of watched data to new GM storage completed.");
} else {
console.log("No watched shows data found in localStorage to migrate.");
}
}
// Add the watched button to an element
function addWatchedButton(element) {
const videoId = element.attr('data-item-id');
if (!videoId) {
console.log("Video ID not found for element", element);
return;
}
const watched = GM_getValue("watched_" + videoId, 'false');
const thumbnailWrapper = $('
').append(element.children().first());
element.append(thumbnailWrapper);
if (watched === 'true') thumbnailWrapper.addClass('g_watched');
const watchedEye = $('👁
').click(function (event) {
event.preventDefault();
event.stopPropagation();
const isWatched = thumbnailWrapper.toggleClass('g_watched').hasClass('g_watched');
isWatched ? markAsWatched(videoId) : markAsUnwatched(videoId);
console.log(`Marked as ${isWatched ? 'watched' : 'unwatched'}:`, videoId);
});
element.append(watchedEye);
}
function markAsWatched(videoId) {
GM_setValue("watched_" + videoId, "true");
}
function markAsUnwatched(videoId) {
GM_setValue("watched_" + videoId, "false");
}
function backupWatchedShows() {
const watchedData = {};
GM_listValues().forEach(key => {
if (key.startsWith("watched_")) watchedData[key] = GM_getValue(key);
});
const blob = new Blob([JSON.stringify(watchedData)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "watchedShowsBackup.json";
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
function restoreWatchedShows() {
const input = document.createElement("input");
input.type = "file";
input.accept = ".json";
input.click();
input.addEventListener("change", function () {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function () {
try {
const data = JSON.parse(reader.result);
const existingKeys = GM_listValues().filter(key => key.startsWith("watched_"));
const action = prompt("Choose an action: 'overwrite' or 'merge'.", "overwrite");
if (action === "overwrite") {
for (const key in data) GM_setValue(key, data[key]);
alert("Watched data has been overwritten successfully.");
} else if (action === "merge") {
for (const key in data) {
if (!existingKeys.includes(key)) GM_setValue(key, data[key]);
}
alert("Watched data has been merged successfully.");
} else {
alert("Invalid action specified. No changes were made.");
}
} catch (e) {
alert("Error restoring data: " + e);
}
};
reader.readAsText(file);
});
}
$(document).ready(function () {
migrateWatchedData();
$('[data-item-id]').each(function () {
addWatchedButton($(this));
});
const observer = new MutationObserver(function (mutations) {
mutations.forEach(mutation => {
$(mutation.addedNodes).find('[data-item-id]').each(function () {
addWatchedButton($(this));
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
GM_registerMenuCommand("Backup Watched", backupWatchedShows);
GM_registerMenuCommand("Restore Watched", restoreWatchedShows);
$('head').append(`
`);
});
})();