From a09a03c1ef7ff022a04510088d3ccefb52b5cfa0 Mon Sep 17 00:00:00 2001 From: Viren070 Date: Sun, 28 Sep 2025 14:43:22 +0100 Subject: [PATCH] feat: add `queriedAddons` and `queryType` to exit conditions and improve descriptions --- packages/core/src/streams/fetcher.ts | 39 +++++++++++++++-- .../frontend/src/components/menu/addons.tsx | 43 ++++++++++++++++--- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/packages/core/src/streams/fetcher.ts b/packages/core/src/streams/fetcher.ts index ade27e79..809acc0d 100644 --- a/packages/core/src/streams/fetcher.ts +++ b/packages/core/src/streams/fetcher.ts @@ -201,6 +201,20 @@ class StreamFetcher { } await new Promise((resolve) => { + const queriedAddons: string[] = []; + const presetProgress = addons.reduce( + (acc, addon) => { + const id = addon.preset.id; + const name = addon.name; + if (!acc[id]) { + acc[id] = { name, remaining: 0 }; + } + acc[id].remaining++; + return acc; + }, + {} as Record + ); + let activePromises = addons.length; if (activePromises === 0) { resolve(); @@ -209,12 +223,22 @@ class StreamFetcher { const checkExit = async () => { const timeTaken = Date.now() - start; - const evaluator = new ExitConditionEvaluator(allStreams, timeTaken); - const shouldExit = await evaluator.evaluate(condition); + const evaluator = new ExitConditionEvaluator( + allStreams, + timeTaken, + queryType, + queriedAddons + ); + const shouldExit = await evaluator.evaluate(condition); + logger.debug(`Evaluated exit condition`, { + shouldExit, + queriedAddons, + }); if (shouldExit) { logger.info( - `Exit condition met with results from ${addons.length - activePromises} addons. (${activePromises} addons still fetching) Returning results.` + // subtract 1 because this function is awaited before activePromises is decremented + `Exit condition met with results from ${queriedAddons.length} addons. (${activePromises - 1} addons still fetching) Returning results.` ); resolve(); } @@ -223,6 +247,15 @@ class StreamFetcher { addons.forEach((addon) => { fetchAndProcessAddons([addon]) .then(async (result) => { + const progress = presetProgress[addon.preset.id]; + progress.remaining--; + if (progress.remaining === 0) { + logger.debug( + `All addons from preset ${progress.name} (${addon.preset.id}) have been queried. Pushing addon name to queriedAddons.` + ); + queriedAddons.push(addon.name); + } + allStreams.push(...result.streams); allErrors.push(...result.errors); if (result.statistics) { diff --git a/packages/frontend/src/components/menu/addons.tsx b/packages/frontend/src/components/menu/addons.tsx index d1ed3dfa..036aba1c 100644 --- a/packages/frontend/src/components/menu/addons.tsx +++ b/packages/frontend/src/components/menu/addons.tsx @@ -1256,9 +1256,9 @@ function AddonFetchingBehaviorCard() { default: 'Fetch from all addons simultaneously and wait for all addons to finish fetching before returning results.', groups: - 'Organize addons into groups. Streams are fetched based on group conditions, either sequentially or in parallel.', + 'Organise addons into groups with conditions. Each group can be evaluated based on results from previous groups. Read the [Wiki](https://github.com/Viren070/AIOStreams/wiki/Groups) for more information.', dynamic: - 'Fetch from all addons at once, and exit once a specified condition is met.', + 'All addons start fetching at the same time. As soon as any addon returns results, the exit condition is evaluated. If the condition is met, results are returned immediately and any remaining addon results are ignored.', }; return ( @@ -1272,8 +1272,8 @@ function AddonFetchingBehaviorCard() { onValueChange={handleModeChange} options={[ { label: 'Default', value: 'default' }, - { label: 'Groups', value: 'groups' }, { label: 'Dynamic', value: 'dynamic' }, + { label: 'Groups', value: 'groups' }, ]} /> @@ -1301,8 +1301,8 @@ function AddonFetchingBehaviorCard() { ]} help={ userData.groups?.behaviour === 'sequential' - ? 'Streams are fetched from the first group only to begin with. If the condition for the next group is met, streams are fetched from the next group, and so on.' - : 'Streams are fetched from all groups at the same time. When a condition is not met, results from its group onwards are simply not shown.' + ? 'Sequential: Start with group 1. Only fetch from group 2 if its condition evaluates to true based on group 1\'s results (e.g., "count(totalStreams) < 4"). Continue this pattern for subsequent groups.' + : "Parallel: Begin fetching from all groups simultaneously. When group 1's results arrive, evaluate group 2's condition. If true, wait for group 2's results; if false, return results without waiting." } /> @@ -1392,7 +1392,38 @@ function AddonFetchingBehaviorCard() { }, })); }} - help="When this condition is met, no more addons will be fetched from" + help={ +

+ Write the condition using{' '} + + Stream Expression Language (SEL) + + . The following variables are available: +

    +
  • + totalStreams: The total number of streams +
  • +
  • + totalTimeTaken: The total time taken to fetch the + streams +
  • +
  • + queryType: The type of query e.g. 'movie', + 'series', or 'anime' +
  • +
  • + queriedAddons: The addons that have been queried. + Tip: use the in operator to check if a specific + addon has been queried. +
  • +
+

+ } /> )}