Prefer longest scan root for shelf assignment and refresh Stremio shelf manifests.
This commit is contained in:
parent
788cfa1255
commit
8200b908e1
4 changed files with 45 additions and 11 deletions
|
|
@ -45,7 +45,7 @@ async function buildShelfCatalogs() {
|
||||||
orderBy: [{ sortOrder: "asc" }, { name: "asc" }],
|
orderBy: [{ sortOrder: "asc" }, { name: "asc" }],
|
||||||
});
|
});
|
||||||
// Skip default Films/Series — already in BASE_CATALOGS as movies/series
|
// Skip default Films/Series — already in BASE_CATALOGS as movies/series
|
||||||
return shelves
|
const catalogs = shelves
|
||||||
.filter((s) => s.slug !== "films" && s.slug !== "series")
|
.filter((s) => s.slug !== "films" && s.slug !== "series")
|
||||||
.map((s) => ({
|
.map((s) => ({
|
||||||
type: s.kind === "SERIES" ? "series" : "movie",
|
type: s.kind === "SERIES" ? "series" : "movie",
|
||||||
|
|
@ -53,18 +53,31 @@ async function buildShelfCatalogs() {
|
||||||
name: s.name,
|
name: s.name,
|
||||||
extra: SEARCH_SKIP_EXTRAS,
|
extra: SEARCH_SKIP_EXTRAS,
|
||||||
}));
|
}));
|
||||||
|
// Fingerprint so Stremio refreshes when shelves are added/renamed (version cache).
|
||||||
|
const stamp = shelves
|
||||||
|
.filter((s) => s.slug !== "films" && s.slug !== "series")
|
||||||
|
.map((s) => `${s.slug}:${s.kind}:${s.updatedAt.getTime()}`)
|
||||||
|
.join("|");
|
||||||
|
return { catalogs, stamp };
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
return { catalogs: [] as Array<{ type: string; id: string; name: string; extra: typeof SEARCH_SKIP_EXTRAS }>, stamp: "" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildManifest(tokenId: string | null, config: Config) {
|
async function buildManifest(tokenId: string | null, config: Config) {
|
||||||
const iptv = tokenId ? await buildIptvCatalogs(tokenId, config) : { catalogs: [], types: [] };
|
const iptv = tokenId ? await buildIptvCatalogs(tokenId, config) : { catalogs: [], types: [] };
|
||||||
const shelfCatalogs = await buildShelfCatalogs();
|
const { catalogs: shelfCatalogs, stamp } = await buildShelfCatalogs();
|
||||||
const types = new Set(["movie", "series", ...iptv.types]);
|
const types = new Set(["movie", "series", ...iptv.types]);
|
||||||
|
// Patch version when shelves change so clients drop cached catalogs.
|
||||||
|
const shelfPatch =
|
||||||
|
stamp.length === 0
|
||||||
|
? "0"
|
||||||
|
: String(
|
||||||
|
[...stamp].reduce((h, c) => ((h << 5) - h + c.charCodeAt(0)) | 0, 0) >>> 0
|
||||||
|
).slice(-4);
|
||||||
return {
|
return {
|
||||||
id: "com.mediacluster.library",
|
id: "com.mediacluster.library",
|
||||||
version: "1.6.1",
|
version: `1.7.${shelfPatch}`,
|
||||||
name: "Media Cluster",
|
name: "Media Cluster",
|
||||||
description: "Privé bibliotheek + Live TV / IPTV (Xtream) met EPG",
|
description: "Privé bibliotheek + Live TV / IPTV (Xtream) met EPG",
|
||||||
catalogs: [...BASE_CATALOGS, ...shelfCatalogs, ...iptv.catalogs],
|
catalogs: [...BASE_CATALOGS, ...shelfCatalogs, ...iptv.catalogs],
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ WORKDIR /src
|
||||||
RUN apk add --no-cache git ca-certificates
|
RUN apk add --no-cache git ca-certificates
|
||||||
COPY node/media-node/ ./
|
COPY node/media-node/ ./
|
||||||
RUN go mod tidy \
|
RUN go mod tidy \
|
||||||
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=1.2.1" -o /media-node-linux-amd64 ./cmd/media-node \
|
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=1.2.2" -o /media-node-linux-amd64 ./cmd/media-node \
|
||||||
&& CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w -X main.version=1.2.1" -o /media-node-linux-arm64 ./cmd/media-node
|
&& CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w -X main.version=1.2.2" -o /media-node-linux-arm64 ./cmd/media-node
|
||||||
|
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
COPY package.json pnpm-workspace.yaml ./
|
COPY package.json pnpm-workspace.yaml ./
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"github.com/sthmedia/media-node/internal/streaming"
|
"github.com/sthmedia/media-node/internal/streaming"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "1.2.1"
|
var version = "1.2.2"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
|
|
|
||||||
|
|
@ -406,21 +406,37 @@ func (s *Scanner) runWatchSession() {
|
||||||
|
|
||||||
func (s *Scanner) detectRootMeta(path string, rootType, rootShelf map[string]string) (kind, shelfID string) {
|
func (s *Scanner) detectRootMeta(path string, rootType, rootShelf map[string]string) (kind, shelfID string) {
|
||||||
clean := filepath.Clean(path)
|
clean := filepath.Clean(path)
|
||||||
|
bestRoot := ""
|
||||||
|
bestKind := ""
|
||||||
for root, k := range rootType {
|
for root, k := range rootType {
|
||||||
if clean == root || strings.HasPrefix(clean, root+string(filepath.Separator)) {
|
if clean == root || strings.HasPrefix(clean, root+string(filepath.Separator)) {
|
||||||
return k, rootShelf[root]
|
if len(root) >= len(bestRoot) {
|
||||||
|
bestRoot = root
|
||||||
|
bestKind = k
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if bestRoot != "" {
|
||||||
|
return bestKind, rootShelf[bestRoot]
|
||||||
|
}
|
||||||
return detectMediaType(path), ""
|
return detectMediaType(path), ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) detectRootType(path string, rootType map[string]string) string {
|
func (s *Scanner) detectRootType(path string, rootType map[string]string) string {
|
||||||
clean := filepath.Clean(path)
|
clean := filepath.Clean(path)
|
||||||
|
bestRoot := ""
|
||||||
|
bestKind := ""
|
||||||
for root, kind := range rootType {
|
for root, kind := range rootType {
|
||||||
if clean == root || strings.HasPrefix(clean, root+string(filepath.Separator)) {
|
if clean == root || strings.HasPrefix(clean, root+string(filepath.Separator)) {
|
||||||
return kind
|
if len(root) >= len(bestRoot) {
|
||||||
|
bestRoot = root
|
||||||
|
bestKind = kind
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if bestRoot != "" {
|
||||||
|
return bestKind
|
||||||
|
}
|
||||||
return detectMediaType(path)
|
return detectMediaType(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -503,13 +519,18 @@ func (s *Scanner) AllMediaFiles() []MediaFileInfo {
|
||||||
|
|
||||||
func shelfForPath(path string, roots []config.MediaRoot) string {
|
func shelfForPath(path string, roots []config.MediaRoot) string {
|
||||||
clean := filepath.Clean(path)
|
clean := filepath.Clean(path)
|
||||||
|
best := ""
|
||||||
|
bestLen := -1
|
||||||
for _, r := range roots {
|
for _, r := range roots {
|
||||||
root := filepath.Clean(r.Path)
|
root := filepath.Clean(r.Path)
|
||||||
if clean == root || strings.HasPrefix(clean, root+string(filepath.Separator)) {
|
if clean == root || strings.HasPrefix(clean, root+string(filepath.Separator)) {
|
||||||
return r.ShelfID
|
if len(root) > bestLen {
|
||||||
|
bestLen = len(root)
|
||||||
|
best = r.ShelfID
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return best
|
||||||
}
|
}
|
||||||
|
|
||||||
func isVideo(path string) bool {
|
func isVideo(path string) bool {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue