Repository: xbmc/xbmc
File: xbmc/addons/Scraper.cpp (C++)

Code before:
                          const std::string &action,
                          const std::string &pathSettings,
                          T &result)
{
  std::stringstream str;
  str << "plugin://" << ID << "?action=" << action << "&" << key << "=" << CURL::Encode(url);
  str << "&pathSettings=" << CURL::Encode(pathSettings);

  CFileItem item(url, false);

  if (!XFILE::CPluginDirectory::GetPluginResult(str.str(), item, false))
    return false;

  DetailsFromFileItem(item, result);
  return true;
}

// fetch list of matching movies sorted by relevance (may be empty);
// throws CScraperError on error; first called with fFirst set, then unset if first try fails
std::vector<CScraperUrl> CScraper::FindMovie(XFILE::CCurlFile &fcurl,
                                             const std::string &movieTitle, int movieYear,
                                             bool fFirst)
{
  // prepare parameters for URL creation
  std::string sTitle, sYear;
  std::string database;
  std::string identifier;
  if (movieYear < 0)
  {
    std::string sTitleYear;
    CUtil::CleanString(movieTitle, sTitle, sTitleYear, sYear, database, identifier,
                       true /*fRemoveExt*/, fFirst);
  }
  else
  {
    sTitle = movieTitle;
    sYear = std::to_string( movieYear );
  }

  CLog::Log(LOGDEBUG,
            "{}: Searching for '{}' using {} scraper "
            "(path: '{}', content: '{}', version: '{}')",
            __FUNCTION__, sTitle, Name(), Path(), ADDON::TranslateContent(Content()),
            Version().asString());

  std::vector<CScraperUrl> vcscurl;
  if (IsNoop())
    return vcscurl;

  if (!fFirst)
    StringUtils::Replace(sTitle, '-', ' ');

Review comment (suggestion):
Use a different term than "database". Maybe `idType` or `identifierType`, to somewhat match the term "type" used for unique IDs in NFOs.

Code after:
  return false;
}

template<class T>
static bool PythonDetails(const std::string& ID,
                          const std::string& key,
                          const std::string& url,
                          const std::string& action,
                          const std::string& pathSettings,
                          const std::unordered_map<std::string, std::string>& uniqueIDs,
                          T& result)
{
  CVariant ids;
  for (const auto& [identifierType, identifier] : uniqueIDs)
    ids[identifierType] = identifier;
  std::string uids;
  CJSONVariantWriter::Write(ids, uids, true);
  std::stringstream str;
  str << "plugin://" << ID << "?action=" << action << "&" << key << "=" << CURL::Encode(url);
  str << "&pathSettings=" << CURL::Encode(pathSettings);
  if (!uniqueIDs.empty())
    str << "&uniqueIDs=" << CURL::Encode(uids);

  CFileItem item(url, false);

  if (!XFILE::CPluginDirectory::GetPluginResult(str.str(), item, false))
    return false;

  return DetailsFromFileItem(item, result);
}

template<class T>
static bool PythonDetails(const std::string& ID,
                          const std::string& key,
                          const std::string& url,
                          const std::string& action,
                          const std::string& pathSettings,
                          T& result)
{
  const std::unordered_map<std::string, std::string> ids;
  return PythonDetails(ID, key, url, action, pathSettings, ids, result);
}

// fetch list of matching movies sorted by relevance (may be empty);
// throws CScraperError on error; first called with fFirst set, then unset if first try fails
std::vector<CScraperUrl> CScraper::FindMovie(XFILE::CCurlFile &fcurl,
                                             const std::string &movieTitle, int movieYear,
                                             bool fFirst)
{
  // prepare parameters for URL creation
  std::string sTitle, sYear;