// ==UserScript== // @name Show Subtitle/Audio Names for Plex // @version 2.5 // @grant none // @include http://plex/* // @description Add the subtitle, video, audio track titles and media version info to the Plex Web app. // @license MIT; https://spdx.org/licenses/MIT.html#licenseText // @namespace https://greasyfork.org/users/456605 // ==/UserScript== function main () { function getMediaTitle(media) { let parts = media.Part; for (let k = 0; k < parts.length; k++) { if (!parts[k].hasOwnProperty("Stream")) continue; let filePart = ""; if (parts[k].hasOwnProperty("file")) filePart = parts[k].file + " | " let streams = parts[k].Stream; for (let l = 0; l < streams.length; l++) { if (streams[l].streamType == 1 && streams[l].hasOwnProperty("displayTitle")) { const format = streams[l].displayTitle.match(".* \\((.*)\\)$"); if (format != null) return filePart + format[1] + " " + media.container; else return filePart + media.container; } } } return "Unknown"; } function intercept(url, responseText) { if (url.indexOf("/library/metadata/") == -1 && url.indexOf("/status/sessions") == -1) return responseText; let response = JSON.parse(responseText); if (!response.hasOwnProperty("MediaContainer") || !response.MediaContainer.hasOwnProperty("Metadata")) return responseText; const meta = response.MediaContainer.Metadata; for (let i = 0; i < meta.length; i++) { if (!meta[i].hasOwnProperty("Media")) continue; let medias = meta[i].Media; for (let j = 0; j < medias.length; j++) { if (!medias[j].hasOwnProperty("Part")) continue; if (!medias[j].hasOwnProperty("title")) medias[j].title = getMediaTitle(medias[j]); let parts = medias[j].Part; for (let k = 0; k < parts.length; k++) { if (!parts[k].hasOwnProperty("Stream")) continue; let streams = parts[k].Stream; for (let l = 0; l < streams.length; l++) { if (!streams[l].hasOwnProperty("displayTitle") || !streams[l].hasOwnProperty("title")) continue; streams[l].displayTitle = streams[l].displayTitle + " (" + streams[l].title + ")"; } } } } return JSON.stringify(response); } (function() { const oldXMLHttpRequest = XMLHttpRequest; XMLHttpRequest = new Proxy(XMLHttpRequest, { construct: function(target, args) { //alert("constructor"); let made = new target(...args); let proxiedCallback = made.onreadystatechange; let _responseText = made.responseText; made.onreadystatechange = (...readyArgs) => { if (made.readyState == 4 && (made.responseType == '' || made.responseType == 'text')) { try { _responseText = intercept(made.responseURL, made.responseText); } catch (err) { console.error(err); } } if (proxiedCallback) proxiedCallback.apply(made, readyArgs); }; const processGet = function(val, target) { if (typeof val === 'function') return val.bind(target); return val; }; return new Proxy(made, { get: function(target, prop, receiver) { if (prop == "onreadystatechange") { return processGet(proxiedCallback, target); } if (prop == "responseText") { return _responseText; } return processGet(target[prop], target); }, set: function(target, prop, value, receiver) { if (prop == "onreadystatechange") { proxiedCallback = value; return true; } target[prop] = value; return true; } } ); } } ); })(); } // From https://stackoverflow.com/questions/2303147/ var script = document.createElement('script'); script.appendChild(document.createTextNode('('+ main +')();\n//# sourceURL=injectPlex.js')); (document.body || document.head || document.documentElement).appendChild(script);