Implementation

Cross-match#

This guide covers the cross-match capability used to resolve media items across providers using stable external IDs.

Overview#

Expose CrossMatchProviderApi from your ProviderPlugin when your provider can resolve exact matches from trusted IDs.

class TestProviderPlugin : ProviderPlugin() {
    private val crossMatchApi by lazy {
        TestCrossMatchApi(providerId = id)
    }
 
    override fun getCrossMatchApi(context: Context): CrossMatchProviderApi = crossMatchApi
}

CrossMatchProviderApi#

CrossMatchProviderApi lets a provider describe which external IDs it can resolve and how it can map them back to a FilmMetadata.

  • supportedIdSources declares the exact source IDs you can resolve.
  • getById(sourceIds) performs deterministic matching from trusted IDs.
  • getByFuzzy(film) can be used as a fallback when exact IDs are missing.
    • The film input is assumed to come from another provider (not the provider implementing the API).

API reference:

Example#

class TestCrossMatchApi(
    private val providerId: String,
) : CrossMatchProviderApi {
    override val supportedIdSources: Set<FilmIdSource> = setOf(
        FilmIdSource.TMDB,
        FilmIdSource.IMDB,
    )
 
    override suspend fun getById(
        sourceIds: Map<FilmIdSource, String>,
    ): FilmMetadata? {
        val tmdbId = sourceIds[FilmIdSource.TMDB]
        val imdbId = sourceIds[FilmIdSource.IMDB]
 
        return when {
            tmdbId != null -> fetchByTmdbId(tmdbId)
            imdbId != null -> fetchByImdbId(imdbId)
            else -> null
        }
    }
 
    override suspend fun getByFuzzy(
        film: FilmMetadata,
    ): FilmMetadata? {
        return null
    }
}

Prefer exact matching from known IDs whenever possible. Fuzzy matching should be a fallback, not the primary resolution path.