File indexing completed on 2024-05-19 05:57:22

0001 // SPDX-FileCopyrightText: 2022 Plata Hill <plata.hill@kdemail.net>
0002 // SPDX-License-Identifier: LGPL-2.1-or-later
0003 
0004 #include "fetcher.h"
0005 
0006 #include "TellySkoutSettings.h"
0007 #include "database.h"
0008 #include "tvspielfilmfetcher.h"
0009 #include "xmltvfetcher.h"
0010 
0011 #include <KLocalizedString>
0012 
0013 #include <QAtomicInteger>
0014 #include <QCryptographicHash>
0015 #include <QDebug>
0016 #include <QFile>
0017 
0018 Fetcher::Fetcher()
0019 {
0020     const TellySkoutSettings::EnumFetcher::type fetcherType = static_cast<TellySkoutSettings::EnumFetcher::type>(TellySkoutSettings::fetcher());
0021 
0022     switch (fetcherType) {
0023     case TellySkoutSettings::EnumFetcher::TVSpielfilm:
0024         m_fetcherImpl.reset(new TvSpielfilmFetcher);
0025         break;
0026     case TellySkoutSettings::EnumFetcher::XMLTV:
0027         m_fetcherImpl.reset(new XmltvFetcher);
0028         break;
0029     case TellySkoutSettings::EnumFetcher::COUNT:
0030         qDebug() << "Invalid Fetcher type!";
0031         assert(false);
0032     }
0033 }
0034 
0035 void Fetcher::fetchFavorites()
0036 {
0037     static QAtomicInteger<qsizetype> channelCounter = 0; // reference counter to determine when all channels have been fetched
0038 
0039     qDebug() << "Starting to fetch favorites";
0040 
0041     const QVector<ChannelId> favoriteChannels = Database::instance().favorites();
0042 
0043     // do nothing if favorites are already being fetched (e.g. triggered from main() and from QML)
0044     if (!channelCounter.testAndSetOrdered(0, favoriteChannels.size())) {
0045         qDebug() << "Favorites are already being fetched, do nothing";
0046         return;
0047     }
0048 
0049     for (const ChannelId &channelId : favoriteChannels) {
0050         Q_EMIT startedFetchingChannel(channelId);
0051         m_fetcherImpl->fetchProgram(
0052             channelId,
0053             [this, channelId](const QVector<ProgramData> &programs) {
0054                 Database::instance().addPrograms(programs);
0055                 Q_EMIT channelUpdated(channelId);
0056 
0057                 channelCounter.deref();
0058             },
0059             [this, channelId](const Error &error) {
0060                 Q_EMIT errorFetchingChannel(channelId, error);
0061 
0062                 channelCounter.deref();
0063             });
0064     }
0065 }
0066 
0067 void Fetcher::fetchGroups()
0068 {
0069     m_fetcherImpl->fetchGroups([](const QVector<GroupData> &groups) {
0070         Database::instance().addGroups(groups);
0071     });
0072 }
0073 
0074 void Fetcher::fetchGroup(const QString &url, const QString &groupId)
0075 {
0076     fetchGroup(url, GroupId(groupId));
0077 }
0078 
0079 void Fetcher::fetchGroup(const QString &url, const GroupId &groupId)
0080 {
0081     Q_EMIT startedFetchingGroup(groupId);
0082     m_fetcherImpl->fetchGroup(
0083         url,
0084         groupId,
0085         [this, groupId](const QList<ChannelData> &channels) {
0086             Database::instance().addChannels(channels, groupId);
0087             Q_EMIT groupUpdated(groupId);
0088         },
0089         [this, groupId](const Error &error) {
0090             Q_EMIT errorFetchingGroup(groupId, error);
0091         });
0092 }
0093 
0094 void Fetcher::fetchProgramDescription(const QString &channelId, const QString &programId, const QString &url)
0095 {
0096     fetchProgramDescription(ChannelId(channelId), ProgramId(programId), url);
0097 }
0098 
0099 void Fetcher::fetchProgramDescription(const ChannelId &channelId, const ProgramId &programId, const QString &url)
0100 {
0101     m_fetcherImpl->fetchProgramDescription(ChannelId(channelId), ProgramId(programId), url, [this, channelId, programId](const QString &description) {
0102         Database::instance().updateProgramDescription(programId, description);
0103         Q_EMIT channelUpdated(channelId);
0104     }); // TODO: separate signal
0105 }
0106 
0107 QString Fetcher::image(const QString &url)
0108 {
0109     return m_fetcherImpl->image(
0110         url,
0111         [this, url]() {
0112             Q_EMIT imageDownloadFinished(url);
0113         },
0114         [this, url](const Error &error) {
0115             Q_EMIT errorDownloadingImage(url, error);
0116         });
0117 }
0118 
0119 void Fetcher::setImpl(std::unique_ptr<FetcherImpl> fetcherImpl)
0120 {
0121     m_fetcherImpl = std::move(fetcherImpl);
0122 }
0123 
0124 void Fetcher::removeImage(const QString &url)
0125 {
0126     qDebug() << "Remove image: " << m_fetcherImpl->imagePath(url);
0127     QFile(m_fetcherImpl->imagePath(url)).remove();
0128 }