Skip to content

Commit 6daf466

Browse files
committed
chore: dont sort / filter aiostreams at all
1 parent d5ae1f9 commit 6daf466

1 file changed

Lines changed: 45 additions & 18 deletions

File tree

pkg/server/stremio/handlers.go

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ func (s *Server) handleStream(w http.ResponseWriter, r *http.Request, device *au
293293
var streams []Stream
294294
streamsList := s.streamConfigsForStreamRequest()
295295
for _, str := range streamsList {
296-
list, err := s.buildOrderedPlayList(ctx, str.ID, contentType, id)
296+
list, err := s.buildOrderedPlayList(ctx, str.ID, contentType, id, isAIOStreams)
297297
if err != nil {
298298
logger.Error("Error building play list", "streamId", str.ID, "err", err)
299299
continue
@@ -493,7 +493,7 @@ func (s *Server) GetStreams(ctx context.Context, contentType, id string, device
493493
var streams []Stream
494494
streamsList := s.streamConfigsForStreamRequest()
495495
for _, str := range streamsList {
496-
list, err := s.buildOrderedPlayList(ctx, str.ID, contentType, id)
496+
list, err := s.buildOrderedPlayList(ctx, str.ID, contentType, id, false)
497497
if err != nil || list == nil {
498498
continue
499499
}
@@ -725,21 +725,24 @@ type rawSearchCacheEntry struct {
725725
until time.Time
726726
}
727727

728-
func (s *Server) buildOrderedPlayList(ctx context.Context, streamId, contentType, id string) (*orderedPlayListResult, error) {
728+
func (s *Server) buildOrderedPlayList(ctx context.Context, streamId, contentType, id string, skipFilterSort bool) (*orderedPlayListResult, error) {
729729
if streamId == "" {
730730
streamId = s.getDefaultStreamID()
731731
}
732-
list, err := s.buildOrderedPlayListUncached(ctx, streamId, contentType, id)
732+
list, err := s.buildOrderedPlayListUncached(ctx, streamId, contentType, id, skipFilterSort)
733733
if err != nil || list == nil {
734734
return list, err
735735
}
736736
// Cache so play/next resolve the same list order.
737737
cacheKey := streamId + ":" + contentType + ":" + id
738+
if skipFilterSort {
739+
cacheKey += "|noFilter"
740+
}
738741
s.playListCache.Store(cacheKey, &playListCacheEntry{result: list, until: time.Now().Add(playListCacheTTL)})
739742
return list, nil
740743
}
741744

742-
func (s *Server) buildOrderedPlayListUncached(ctx context.Context, streamId, contentType, id string) (*orderedPlayListResult, error) {
745+
func (s *Server) buildOrderedPlayListUncached(ctx context.Context, streamId, contentType, id string, skipFilterSort bool) (*orderedPlayListResult, error) {
743746
raw, err := s.getOrBuildRawSearchResult(ctx, contentType, id)
744747
if err != nil || raw == nil {
745748
return nil, err
@@ -754,7 +757,7 @@ func (s *Server) buildOrderedPlayListUncached(ctx context.Context, streamId, con
754757
if str == nil {
755758
str = s.getGlobalStream()
756759
}
757-
return s.buildOrderedPlayListFromRaw(raw, str)
760+
return s.buildOrderedPlayListFromRaw(raw, str, skipFilterSort)
758761
}
759762

760763
// getOrBuildRawSearchResult runs TMDB + AvailNZB + indexer search once per (contentType, id); result is shared by all streams.
@@ -1009,8 +1012,21 @@ func (s *Server) GetSearchReleases(ctx context.Context, contentType, id string)
10091012
return &SearchReleasesResponse{Streams: streamInfos, Releases: releasesOut}, nil
10101013
}
10111014

1015+
// releasesToCandidates converts releases to candidates with no stream filtering (score 0, preserve order).
1016+
func releasesToCandidates(releases []*release.Release) []triage.Candidate {
1017+
var out []triage.Candidate
1018+
for _, rel := range releases {
1019+
if rel == nil {
1020+
continue
1021+
}
1022+
out = append(out, triage.Candidate{Release: rel, Score: 0})
1023+
}
1024+
return out
1025+
}
1026+
10121027
// buildOrderedPlayListFromRaw applies one stream's filters/sorting to raw results (triage, merge, filter, sort).
1013-
func (s *Server) buildOrderedPlayListFromRaw(raw *rawSearchResult, str *stream.Stream) (*orderedPlayListResult, error) {
1028+
// When skipFilterSort is true (e.g. AIOStreams), stream triage and sort are skipped; only merge, dedupe, and safety filters apply.
1029+
func (s *Server) buildOrderedPlayListFromRaw(raw *rawSearchResult, str *stream.Stream, skipFilterSort bool) (*orderedPlayListResult, error) {
10141030
// Set of DetailsURLs that AvailNZB reports as unavailable — exclude these from Stremio play list.
10151031
unavailableDetailsURLs := make(map[string]bool)
10161032
if raw.AvailResult != nil {
@@ -1024,8 +1040,14 @@ func (s *Server) buildOrderedPlayListFromRaw(raw *rawSearchResult, str *stream.S
10241040
}
10251041
}
10261042

1027-
availCandidates := s.triageCandidates(str, raw.AvailReleases)
1028-
indexerCandidates := s.triageCandidates(str, raw.IndexerReleases)
1043+
var availCandidates, indexerCandidates []triage.Candidate
1044+
if skipFilterSort {
1045+
availCandidates = releasesToCandidates(raw.AvailReleases)
1046+
indexerCandidates = releasesToCandidates(raw.IndexerReleases)
1047+
} else {
1048+
availCandidates = s.triageCandidates(str, raw.AvailReleases)
1049+
indexerCandidates = s.triageCandidates(str, raw.IndexerReleases)
1050+
}
10291051

10301052
seenURL := make(map[string]bool)
10311053
var merged []triage.Candidate
@@ -1110,11 +1132,13 @@ func (s *Server) buildOrderedPlayListFromRaw(raw *rawSearchResult, str *stream.S
11101132
merged = filtered
11111133
}
11121134
}
1113-
// Sort by stream's score only. AvailNZB does not override the stream's priority: we only badge/serve
1114-
// [availNZB] when the stream's #1 choice happens to be AvailNZB-good.
1115-
sort.Slice(merged, func(i, j int) bool {
1116-
return streamScoreFromCandidate(merged[i]) > streamScoreFromCandidate(merged[j])
1117-
})
1135+
if !skipFilterSort {
1136+
// Sort by stream's score only. AvailNZB does not override the stream's priority: we only badge/serve
1137+
// [availNZB] when the stream's #1 choice happens to be AvailNZB-good.
1138+
sort.Slice(merged, func(i, j int) bool {
1139+
return streamScoreFromCandidate(merged[i]) > streamScoreFromCandidate(merged[j])
1140+
})
1141+
}
11181142

11191143
firstIsAvailGood := false
11201144
if len(merged) > 0 && merged[0].Release != nil && merged[0].Release.DetailsURL != "" {
@@ -1401,11 +1425,12 @@ func (s *Server) GetAvailNZBStreams(ctx context.Context, contentType, id string,
14011425

14021426
// resolveStreamSlot builds the ordered play list for the given stream, creates a deferred session for the release at index, and sets fallback URLs.
14031427
// streamId empty means default stream; it is normalized to the actual id for sessionID and URLs.
1404-
func (s *Server) resolveStreamSlot(ctx context.Context, streamId, contentType, id string, index int, device *auth.Device) (*session.Session, error) {
1428+
// skipFilterSort when true (e.g. AIOStreams) uses raw order without stream filtering/sorting.
1429+
func (s *Server) resolveStreamSlot(ctx context.Context, streamId, contentType, id string, index int, device *auth.Device, skipFilterSort bool) (*session.Session, error) {
14051430
if streamId == "" {
14061431
streamId = s.getDefaultStreamID()
14071432
}
1408-
list, err := s.buildOrderedPlayList(ctx, streamId, contentType, id)
1433+
list, err := s.buildOrderedPlayList(ctx, streamId, contentType, id, skipFilterSort)
14091434
if err != nil || list == nil {
14101435
return nil, fmt.Errorf("build play list: %w", err)
14111436
}
@@ -1516,7 +1541,8 @@ func (s *Server) handleNextRelease(w http.ResponseWriter, r *http.Request, devic
15161541
}
15171542
return ":" + streamId + ":" + contentType + ":" + id
15181543
})()
1519-
list, err := s.buildOrderedPlayList(r.Context(), streamId, contentType, id)
1544+
isAIOStreams := strings.Contains(r.Header.Get("User-Agent"), "AIOStreams")
1545+
list, err := s.buildOrderedPlayList(r.Context(), streamId, contentType, id, isAIOStreams)
15201546
maxIdx := 0
15211547
if err == nil && list != nil && len(list.Candidates) > 1 {
15221548
maxIdx = len(list.Candidates) - 1
@@ -1625,7 +1651,8 @@ func (s *Server) handlePlay(w http.ResponseWriter, r *http.Request, device *auth
16251651
if err != nil {
16261652
// Phase 3: resolve stream slot to a real session (create deferred for this index, set fallbacks)
16271653
if streamId, contentType, id, index, ok := parseStreamSlotID(sessionID); ok {
1628-
sess, err = s.resolveStreamSlot(r.Context(), streamId, contentType, id, index, device)
1654+
isAIOStreams := strings.Contains(r.Header.Get("User-Agent"), "AIOStreams")
1655+
sess, err = s.resolveStreamSlot(r.Context(), streamId, contentType, id, index, device, isAIOStreams)
16291656
if err != nil {
16301657
logger.Debug("Resolve stream slot failed", "slot", sessionID, "err", err)
16311658
http.Error(w, "Stream slot not found or invalid", http.StatusNotFound)

0 commit comments

Comments
 (0)