Merge pull request #24470 from fuzzard/release_20.3
[xbmc.git] / xbmc / NfoFile.cpp
blob98a49b5091bf7ac2df187dbdc376fb557ed4828d
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8 // NfoFile.cpp: implementation of the CNfoFile class.
9 //
10 //////////////////////////////////////////////////////////////////////
12 #include "NfoFile.h"
14 #include "FileItem.h"
15 #include "ServiceBroker.h"
16 #include "addons/AddonManager.h"
17 #include "addons/AddonSystemSettings.h"
18 #include "addons/addoninfo/AddonType.h"
19 #include "filesystem/File.h"
20 #include "music/Album.h"
21 #include "music/Artist.h"
22 #include "video/VideoInfoDownloader.h"
24 #include <string>
25 #include <vector>
27 using namespace XFILE;
28 using namespace ADDON;
30 CInfoScanner::INFO_TYPE CNfoFile::Create(const std::string& strPath,
31 const ScraperPtr& info, int episode)
33 m_info = info; // assume we can use these settings
34 m_type = ScraperTypeFromContent(info->Content());
35 if (Load(strPath) != 0)
36 return CInfoScanner::NO_NFO;
38 CFileItemList items;
39 bool bNfo=false;
41 if (m_type == AddonType::SCRAPER_ALBUMS)
43 CAlbum album;
44 bNfo = GetDetails(album);
46 else if (m_type == AddonType::SCRAPER_ARTISTS)
48 CArtist artist;
49 bNfo = GetDetails(artist);
51 else if (m_type == AddonType::SCRAPER_TVSHOWS || m_type == AddonType::SCRAPER_MOVIES ||
52 m_type == AddonType::SCRAPER_MUSICVIDEOS)
54 // first check if it's an XML file with the info we need
55 CVideoInfoTag details;
56 bNfo = GetDetails(details);
57 if (episode > -1 && bNfo && m_type == AddonType::SCRAPER_TVSHOWS)
59 int infos=0;
60 while (m_headPos != std::string::npos && details.m_iEpisode != episode)
62 m_headPos = m_doc.find("<episodedetails", m_headPos + 1);
63 if (m_headPos == std::string::npos)
64 break;
66 bNfo = GetDetails(details);
67 infos++;
69 if (details.m_iEpisode != episode)
71 bNfo = false;
72 details.Reset();
73 m_headPos = 0;
74 if (infos == 1) // still allow differing nfo/file numbers for single ep nfo's
75 bNfo = GetDetails(details);
80 std::vector<ScraperPtr> vecScrapers = GetScrapers(m_type, m_info);
82 // search ..
83 int res = -1;
84 for (unsigned int i=0; i<vecScrapers.size(); ++i)
85 if ((res = Scrape(vecScrapers[i], m_scurl, m_doc)) == 0 || res == 2)
86 break;
88 if (res == 2)
89 return CInfoScanner::ERROR_NFO;
90 if (bNfo)
92 if (!m_scurl.HasUrls())
94 if (m_doc.find("[scrape url]") != std::string::npos)
95 return CInfoScanner::OVERRIDE_NFO;
96 else
97 return CInfoScanner::FULL_NFO;
99 else
100 return CInfoScanner::COMBINED_NFO;
102 return m_scurl.HasUrls() ? CInfoScanner::URL_NFO : CInfoScanner::NO_NFO;
105 // return value: 0 - success; 1 - no result; skip; 2 - error
106 int CNfoFile::Scrape(ScraperPtr& scraper, CScraperUrl& url,
107 const std::string& content)
109 if (scraper->IsNoop())
111 url = CScraperUrl();
112 return 0;
115 scraper->ClearCache();
119 url = scraper->NfoUrl(content);
121 catch (const CScraperError &sce)
123 CVideoInfoDownloader::ShowErrorDialog(sce);
124 if (!sce.FAborted())
125 return 2;
128 return url.HasUrls() ? 0 : 1;
131 int CNfoFile::Load(const std::string& strFile)
133 Close();
134 XFILE::CFile file;
135 std::vector<uint8_t> buf;
136 if (file.LoadFile(strFile, buf) > 0)
138 m_doc.assign(reinterpret_cast<char*>(buf.data()), buf.size());
139 m_headPos = 0;
140 return 0;
142 m_doc.clear();
143 return 1;
146 void CNfoFile::Close()
148 m_doc.clear();
149 m_headPos = 0;
150 m_scurl.Clear();
153 std::vector<ScraperPtr> CNfoFile::GetScrapers(AddonType type, const ScraperPtr& selectedScraper)
155 AddonPtr addon;
156 ScraperPtr defaultScraper;
157 if (CAddonSystemSettings::GetInstance().GetActive(type, addon))
158 defaultScraper = std::dynamic_pointer_cast<CScraper>(addon);
160 std::vector<ScraperPtr> vecScrapers;
162 // add selected scraper - first priority
163 if (selectedScraper)
164 vecScrapers.push_back(selectedScraper);
166 // Add all scrapers except selected and default
167 VECADDONS addons;
168 CServiceBroker::GetAddonMgr().GetAddons(addons, type);
170 for (auto& addon : addons)
172 ScraperPtr scraper = std::dynamic_pointer_cast<CScraper>(addon);
174 // skip if scraper requires settings and there's nothing set yet
175 if (scraper->RequiresSettings() && !scraper->HasUserSettings())
176 continue;
178 if ((!selectedScraper || selectedScraper->ID() != scraper->ID()) &&
179 (!defaultScraper || defaultScraper->ID() != scraper->ID()))
180 vecScrapers.push_back(scraper);
183 // add default scraper - not user selectable so it's last priority
184 if (defaultScraper && (!selectedScraper ||
185 selectedScraper->ID() != defaultScraper->ID()) &&
186 (!defaultScraper->RequiresSettings() || defaultScraper->HasUserSettings()))
187 vecScrapers.push_back(defaultScraper);
189 return vecScrapers;