diff --git a/emby2Alist/nginx/conf.d/common/util.js b/emby2Alist/nginx/conf.d/common/util.js index 6b4192e..054d1ee 100644 --- a/emby2Alist/nginx/conf.d/common/util.js +++ b/emby2Alist/nginx/conf.d/common/util.js @@ -98,11 +98,11 @@ function copyHeaders(sourceHeaders, targetHeaders, skipKeys) { skipKeys = ["Content-Length"]; } for (const key in sourceHeaders) { - if (skipKeys.includes(key)) { - continue; - } - targetHeaders[key] = sourceHeaders[key]; - } + if (skipKeys.includes(key)) { + continue; + } + targetHeaders[key] = sourceHeaders[key]; + } } /** @@ -193,7 +193,7 @@ function getRouteMode(r, filePath, isAlistRes, notLocal) { // return true; // } // } - + // // old proxy, sigle rule length is 3 or 4(group) // const oldRules = disableRedirectRule.filter(rule => rule.length <= 3); // if (oldRules.length > 0) { @@ -264,7 +264,7 @@ function getMatchedRule(r, ruleArr3D, filePath) { return flag; } const matcher = rule[2]; - if (Array.isArray(matcher) + if (Array.isArray(matcher) && matcher.some(m => strMatches(rule[1], sourceStr, m))) { flag = true; } else { @@ -299,7 +299,7 @@ function parseExpression(rootObj, expression, propertySplit, groupSplit) { if (typeof rootObj !== "object" || rootObj === null) { throw new Error("rootObj must be a non-null object"); } - + if (typeof expression !== "string" || expression.trim() === "") { return undefined; } @@ -409,7 +409,7 @@ function checkIsStrmByPath(filePath) { } function isAbsolutePath(filePath) { - return filePath && typeof filePath === "string" + return filePath && typeof filePath === "string" ? filePath.startsWith("/") || filePath.startsWith("\\") : false; } @@ -437,7 +437,7 @@ function simpleRuleFilter(r, ruleArr3D, filePath, firstSourceStr, mark) { mark = "simpleRule"; } // group current rules, old is true, new is false - const onGroupRulesObjArr = groupBy(ruleArr3D, + const onGroupRulesObjArr = groupBy(ruleArr3D, rule => Number.isInteger(rule[0]) || Object.values(MATCHER_ENUM).includes(rule[0]) ); ngx.log(ngx.INFO, `onGroupRulesObjArr: ${JSON.stringify(onGroupRulesObjArr)}`); @@ -521,9 +521,14 @@ function getItemInfo(r) { : r.args.mediaSourceId; const Etag = r.args.Tag; const api_key = urlUtil.getDefaultApiKey(r.args); + let userId = r.args["UserId"] || r.headersIn["X-Emby-UserId"]; + if (!userId) { + r.warn("⚠️ Warning: No userId found! Used default userId, if not configured, requests might fail."); + userId = config.embyDefaultUserId; + } let itemInfoUri = ""; if (r.uri.includes("JobItems")) { - itemInfoUri = `${embyHost}/Sync/JobItems?api_key=${api_key}`; + itemInfoUri = `${embyHost}/Sync/JobItems?api_key=${api_key}`; } else { if (mediaSourceId) { // before is GUID like "3c25399d9cbb41368a5abdb71cfe3dc9", V4.9.0.25 is "mediasource_447039" fomrmat @@ -532,12 +537,12 @@ function getItemInfo(r) { if (mediaSourceId.startsWith("mediasource_")) { newMediaSourceId = mediaSourceId.replace("mediasource_", ""); } - itemInfoUri = `${embyHost}/Items?Ids=${newMediaSourceId ?? mediaSourceId}&Fields=Path,MediaSources&Limit=1&api_key=${api_key}`; + itemInfoUri = `${embyHost}/Users/${userId}/Items/${newMediaSourceId ?? mediaSourceId}?&Fields=Path,MediaSources&Limit=1&api_key=${api_key}`; } else { - itemInfoUri = `${embyHost}/Items?Ids=${itemId}&Fields=Path,MediaSources&Limit=1&api_key=${api_key}`; + itemInfoUri = `${embyHost}/Users/${userId}/Items/${itemId}?&Fields=Path,MediaSources&Limit=1&api_key=${api_key}`; } } - return { itemInfoUri, itemId , Etag, mediaSourceId, api_key }; + return { itemInfoUri, itemId, Etag, mediaSourceId, api_key }; } /** @@ -559,7 +564,7 @@ function dictAdd(dictName, key, value, timeout, isSet) { const preValue = dict.get(key); if (preValue === value) return 0; } - + const msgBase = `${dictName} ${methodName}: [${key}] : [${value}]`; // simple version string compare use Unicode, better use njs.version_number if (njs.version >= "0.8.5" && timeout && timeout > 0) { @@ -623,8 +628,8 @@ function calculateHMAC(data, key) { hmac.update(data); // 计算摘要并以 GoLang 中 URLEncoding 方式返回 return hmac.digest('base64') - .replaceAll("+", "-") - .replaceAll("/", "_"); + .replaceAll("+", "-") + .replaceAll("/", "_"); } function addAlistSign(url, alistToken, alistSignExpireTime) { @@ -644,7 +649,7 @@ function addAlistSign(url, alistToken, alistSignExpireTime) { if (expiredHour !== 0) { time = Math.floor(Date.now() / 1000 + expiredHour * 3600) } - path = decodeURIComponent(path.substring(startIndex + 2).replaceAll('//','/')) + path = decodeURIComponent(path.substring(startIndex + 2).replaceAll('//', '/')) const signData = `${path}:${time}` ngx.log(ngx.WARN, `sign data: ${signData}`) const signPrefix = calculateHMAC(signData, alistToken) diff --git a/emby2Alist/nginx/conf.d/constant.js b/emby2Alist/nginx/conf.d/constant.js index 3b53ade..6714718 100644 --- a/emby2Alist/nginx/conf.d/constant.js +++ b/emby2Alist/nginx/conf.d/constant.js @@ -17,6 +17,9 @@ const embyHost = "http://172.17.0.1:8096"; // emby/jellyfin api key, 在 emby/jellyfin 后台设置 const embyApiKey = "f839390f50a648fd92108bc11ca6730a"; +// 用于无法获取到用户的情况下,默认使用的用户 id +const embyDefaultUserId = "xxxxxxxx"; + // 挂载工具 rclone/CD2 多出来的挂载目录, 例如将 od,gd 挂载到 /mnt 目录下: /mnt/onedrive /mnt/gd ,那么这里就填写 /mnt // 通常配置一个远程挂载根路径就够了,默认非此路径开头文件将转给原始 emby 处理 // 如果没有挂载,全部使用 strm 文件,此项填[""],必须要是数组 @@ -43,6 +46,7 @@ function getUsersItemsLatestFilterEnable(r) { export default { embyHost, embyApiKey, + embyDefaultUserId, mediaMountPath, strHead: commonConfig.strHead, diff --git a/emby2Alist/nginx/conf.d/emby.js b/emby2Alist/nginx/conf.d/emby.js index 09fb169..72a07bd 100644 --- a/emby2Alist/nginx/conf.d/emby.js +++ b/emby2Alist/nginx/conf.d/emby.js @@ -603,7 +603,7 @@ async function fetchEmbyFilePath(itemInfoUri, itemId, Etag, mediaSourceId) { return rvt; } } else { - const item = result.Items[0]; + const item = result if (!item) { rvt.message = `error: emby_api /Items response is null`; return rvt; diff --git a/emby2Alist/nginx/conf.d/exampleConfig/constant-all.js b/emby2Alist/nginx/conf.d/exampleConfig/constant-all.js index 79210ba..613b686 100644 --- a/emby2Alist/nginx/conf.d/exampleConfig/constant-all.js +++ b/emby2Alist/nginx/conf.d/exampleConfig/constant-all.js @@ -12,6 +12,9 @@ const embyHost = "http://172.17.0.1:8096"; // emby/jellyfin api key, 在 emby/jellyfin 后台设置 const embyApiKey = "f839390f50a648fd92108bc11ca6730a"; +// 用于无法获取到用户的情况下,默认使用的用户 id +const embyDefaultUserId = "xxxxxxxx"; + // 挂载工具 rclone/CD2 多出来的挂载目录, 例如将 od,gd 挂载到 /mnt 目录下: /mnt/onedrive /mnt/gd ,那么这里就填写 /mnt // 通常配置一个远程挂载根路径就够了,默认非此路径开头文件将转给原始 emby 处理 // 如果没有挂载,全部使用 strm 文件,此项填[""],必须要是数组 @@ -434,6 +437,7 @@ function getUsersItemsLatestFilterEnable(r) { export default { embyHost, embyApiKey, + embyDefaultUserId, mediaMountPath, alistAddr, alistToken, diff --git a/emby2Alist/nginx/conf.d/exampleConfig/constant-main.js b/emby2Alist/nginx/conf.d/exampleConfig/constant-main.js index 8a45867..cd2fba2 100644 --- a/emby2Alist/nginx/conf.d/exampleConfig/constant-main.js +++ b/emby2Alist/nginx/conf.d/exampleConfig/constant-main.js @@ -18,6 +18,9 @@ const embyHost = "http://172.17.0.1:8096"; // emby/jellyfin api key, 在 emby/jellyfin 后台设置 const embyApiKey = "f839390f50a648fd92108bc11ca6730a"; +// 用于无法获取到用户的情况下,默认使用的用户 id +const embyDefaultUserId = "xxxxxxxx"; + // 挂载工具 rclone/CD2 多出来的挂载目录, 例如将 od,gd 挂载到 /mnt 目录下: /mnt/onedrive /mnt/gd ,那么这里就填写 /mnt // 通常配置一个远程挂载根路径就够了,默认非此路径开头文件将转给原始 emby 处理 // 如果没有挂载,全部使用 strm 文件,此项填[""],必须要是数组 @@ -44,6 +47,7 @@ function getUsersItemsLatestFilterEnable(r) { export default { embyHost, embyApiKey, + embyDefaultUserId, mediaMountPath, strHead: commonConfig.strHead, diff --git a/embyWebAddExternalUrl/README.md b/embyWebAddExternalUrl/README.md index 70194dd..7c1c341 100644 --- a/embyWebAddExternalUrl/README.md +++ b/embyWebAddExternalUrl/README.md @@ -71,6 +71,9 @@ Emby Web, iconOnly: true ### CHANGELOG +#### 1.1.21 +1. fix(embyLaunchPotplayer): 修复上个版本引入的 jellyfin 下的误改,并修复图标 + #### 1.1.20 1. fix(embyLaunchPotplayer): 适配 4.9.0.40 2. refactor(embyLaunchPotplayer): 抽取 selectors diff --git a/embyWebAddExternalUrl/embyLaunchPotplayer.js b/embyWebAddExternalUrl/embyLaunchPotplayer.js index ac58556..dfae54d 100644 --- a/embyWebAddExternalUrl/embyLaunchPotplayer.js +++ b/embyWebAddExternalUrl/embyLaunchPotplayer.js @@ -4,7 +4,7 @@ // @name:zh embyLaunchPotplayer // @name:zh-CN embyLaunchPotplayer // @namespace http://tampermonkey.net/ -// @version 1.1.20 +// @version 1.1.21 // @description emby/jellfin launch extetnal player // @description:zh-cn emby/jellfin 调用外部播放器 // @description:en emby/jellfin to external player @@ -82,12 +82,14 @@ , onClick: embySenPlayer, osCheck: [OS.isIOS], }, { id: "embyCopyUrl", title: "复制串流地址", iconId: "icon-Copy", onClick: embyCopyUrl, }, ]; + // Jellyfin Icons: https://marella.github.io/material-icons/demo + // Emby Icons: https://fonts.google.com/icons const customBtns = [ { id: "hideByOS", title: "异构播放器", iconName: "more", onClick: hideByOSHandler, }, { id: "iconOnly", title: "显示模式", iconName: "open_in_full", onClick: iconOnlyHandler, }, - { id: "notCurrentPot", title: "多开Potplayer", iconName: "select_window", onClick: notCurrentPotHandler, }, + { id: "notCurrentPot", title: "多开Potplayer", iconName: "window", onClick: notCurrentPotHandler, }, { id: "strmDirect", title: "STRM直通", desc: "AList注意关sign,否则不要开启此选项,任然由服务端处理sign" - , iconName: "media_link", onClick: strmDirectHandler, + , iconName: "link", onClick: strmDirectHandler, }, ]; if (!iconConfig.removeCustomBtns) { @@ -118,6 +120,7 @@ } let mainDetailButtons = document.querySelector(selectors.embyMainDetailButtons); function generateButtonHTML({ id, title, desc, iconId, iconName }) { + // jellyfin icon class: material-icons return `