// ==UserScript== // @name embyLaunchPotplayer // @namespace http://tampermonkey.net/ // @version 0.7 // @description try to take over the world! // @author @bpking // @include *emby* // @include *:8* // @downloadURL none // ==/UserScript== const domain = window.location.href; const api_key = "?api_key=1b52b02396894aa5a162233f0ef61681"; const reg = /\/[a-z]{2,}\/\S*?id=/; const regResult = domain.match(reg)[0]; var timer = setInterval(function() { var potplayer = document.querySelectorAll("div[is='emby-scroller']:not(.hide) .potplayer")[0]; if(!potplayer){ var mainDetailButtons = document.querySelectorAll("div[is='emby-scroller']:not(.hide) .mainDetailButtons")[0]; if(mainDetailButtons){ var html = mainDetailButtons.innerHTML; mainDetailButtons.innerHTML = html +'' +''; document.querySelector("div[is='emby-scroller']:not(.hide) #potPlayer").onclick = potPlayer; document.querySelector('#iina').onclick = iina; } } }, 1000) function getItemInfo(){ let domain = window.location.href; const itemInfoUrl = domain.replace(regResult, "/emby/Items/").split('&')[0] + "/PlaybackInfo" + api_key; console.log("itemInfo:" + itemInfoUrl); return new Promise((resolve, reject) => { fetch(itemInfoUrl).then(resp => resp.json().then(data => resolve(data)).catch(e => {alert("网络错误,检查api_key是否设置正确 "+e.message)}) ) }) } function getSeek(){ const resumeButton = document.querySelector("div[is='emby-scroller']:not(.hide) div.resumeButtonText"); let seek = ''; if (resumeButton) { if (resumeButton.innerText.includes('恢复播放于')) { seek = resumeButton.innerText.replace('恢复播放于', ''); } } return seek; } function getSubUrl(itemInfo, MediaSourceIndex){ var selectSubtitles = document.querySelector("div[is='emby-scroller']:not(.hide) select.selectSubtitles"); let subTitleUrl = ''; if (selectSubtitles) { if (selectSubtitles.value > 0) { console.log(selectSubtitles.value); if (itemInfo.MediaSources[MediaSourceIndex].MediaStreams[selectSubtitles.value].IsExternal) { let domain = window.location.href; const subtitleCodec = itemInfo.MediaSources[MediaSourceIndex].MediaStreams[selectSubtitles.value].Codec; subTitleUrl = domain.replace(regResult, "/emby/videos/").split('&')[0] + "/" + itemInfo.MediaSources[MediaSourceIndex].Id + "/Subtitles/" + selectSubtitles.value + "/" + MediaSourceIndex + "/Stream." + subtitleCodec + api_key; console.log(subTitleUrl); } } } return subTitleUrl; } var getVideoUrl = async function () { var selectSource = document.querySelector("div[is='emby-scroller']:not(.hide) select.selectSource"); var selectAudio = document.querySelector("div[is='emby-scroller']:not(.hide) select.selectAudio"); const itemInfo = await getItemInfo(); let MediaSourceIndex = 0; for(let i = 0; i< itemInfo.MediaSources.length; i++){ if(itemInfo.MediaSources[i].Id == selectSource.value){ MediaSourceIndex = i; }; } const container = itemInfo.MediaSources[MediaSourceIndex].Container; const MediaSourceId = selectSource.value; const PlaySessionId = itemInfo.PlaySessionId; const subUrl = await getSubUrl(itemInfo, MediaSourceIndex); let domain = window.location.href; const streamUrl = domain.replace(regResult, "/emby/videos/").split('&')[0] + "/stream." + container + api_key + "&Static=true" + "&MediaSourceId=" + MediaSourceId + "&PlaySessionId=" + PlaySessionId; return new Array(streamUrl, subUrl); } function potPlayer(){ const seek = getSeek(); getVideoUrl().then((videoUrl) => { console.log("videoUrl :"+videoUrl); const poturl = "potplayer://"+ encodeURI(videoUrl[0]) + " /sub=" + encodeURI(videoUrl[1])+" /current" + " /seek=" + seek; console.log("potUrl= " + poturl); window.open(poturl, "_blank"); }); } function iina(){ const seek = getSeek(); getVideoUrl().then((videoUrl) => { console.log("videoUrl :"+videoUrl); var iinaurl = "iina://weblink?url=" +escape(videoUrl[0])+"&new_window=1"; console.log("iinaUrl= " + iinaurl); window.open(iinaurl, "_blank"); }); }