Skip to content

Discover extension to support imdb_id as search_term #5050

Description

@Grantys

Summary

Problem: FlexGet's discover builds search queries in the INPUT phase and hands each
query entry to the search plugin (e.g. search_rss). search_rss substitutes
only {{search_term}} into the URL, and that term comes from
entry['search_strings'] (falling back to entry['title']).

Gap: The stock movie_list input emits imdb_id but NOT search_strings, and the
set: plugin runs in the METAINFO phase — too late for discover. So there is no
config-only way to search Prowlarr/Torznab by imdbid= from a movie_list.

A potential plugin closes that gap: it could wrap any input plugin (typically movie_list),
runs it during the input phase, and sets search_strings = [imdb_id] on each
produced entry. Discover then receives query entries whose {{search_term}} is
the IMDb id, so ...&t=movie&imdbid={{search_term}} renders to
...&imdbid=tt6857112.

Something like this (what I use as a custom plugin to overcome this gap)

from loguru import logger
 
from flexget import plugin
from flexget.event import event
 
logger = logger.bind(name='imdb_search_input')
 
RESERVED = ('field', 'require')
 
 
class ImdbSearchInput:
    # Permissive schema: one wrapped-input mapping plus optional field/require.
    # additionalProperties allows the wrapped input key (e.g. movie_list).
    schema = {
        'type': 'object',
        'properties': {
            'field': {'type': 'string'},
            'require': {'type': 'boolean'},
        },
        'additionalProperties': True,
    }
 
    def _resolve(self, config):
        """Return (input_name, input_config, field, require)."""
        field = config.get('field', 'imdb_id')
        require = config.get('require', True)
        items = {k: v for k, v in config.items() if k not in RESERVED}
        if len(items) != 1:
            raise plugin.PluginError(
                'imdb_search_input: expected exactly one wrapped input plugin '
                f'(plus optional {RESERVED}), got keys: {list(config.keys())}'
            )
        input_name, input_config = next(iter(items.items()))
        return input_name, input_config, field, require
 
    def on_task_input(self, task, config):
        input_name, input_config, field, require = self._resolve(config)
 
        try:
            wrapped = plugin.get_plugin_by_name(input_name)
        except plugin.DependencyError:
            raise plugin.PluginError(
                f'imdb_search_input: unknown input plugin "{input_name}"'
            )
 
        input_handler = wrapped.phase_handlers.get('input')
        if input_handler is None:
            raise plugin.PluginError(
                f'imdb_search_input: plugin "{input_name}" is not an input plugin'
            )
 
        produced = input_handler(task, input_config) or []
 
        out = []
        missing = 0
        for entry in produced:
            value = entry.get(field)
            if not value:
                missing += 1
                if require:
                    logger.debug(
                        'Dropping "{}" — no {} to search by', entry.get('title'), field
                    )
                    continue
                out.append(entry)  # keep; search_rss falls back to title
                continue
            entry['search_strings'] = [str(value)]
            out.append(entry)
 
        if missing:
            logger.verbose(
                '{} of {} entries had no {} ({})',
                missing,
                len(produced),
                field,
                'dropped' if require else 'kept, search by title',
            )
        logger.verbose('Produced {} search entries via {}', len(out), input_name)
        return out
 
 
@event('plugin.register')
def register_plugin():
    plugin.register(ImdbSearchInput, 'imdb_search_input', api_ver=2, interfaces=['task'])

Activity

  1. added theissue type on Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions