File indexing completed on 2024-12-22 04:28:22

0001 /*
0002   SPDX-FileCopyrightText: 2023-2024 Laurent Montel <montel.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "voskdownloadlanguagejob.h"
0008 #include "generateinstalledlanguageinfojob.h"
0009 #include "libvoskspeechtotext_debug.h"
0010 #include "speechtotext/speechtotextengineaccessmanager.h"
0011 #include "voskextractlanguagejob.h"
0012 #include <KLocalizedString>
0013 #include <QFileInfo>
0014 #include <QNetworkReply>
0015 #include <QNetworkRequest>
0016 #include <QTemporaryFile>
0017 
0018 VoskDownloadLanguageJob::VoskDownloadLanguageJob(QObject *parent)
0019     : QObject{parent}
0020 {
0021 }
0022 
0023 VoskDownloadLanguageJob::~VoskDownloadLanguageJob()
0024 {
0025     delete mHash;
0026 }
0027 
0028 void VoskDownloadLanguageJob::start()
0029 {
0030     if (!canStart()) {
0031         qCWarning(LIBVOSKSPEECHTOTEXT_LOG) << "Impossible to start DownloadLanguageJob";
0032         deleteLater();
0033         return;
0034     }
0035     mDestination = new QTemporaryFile(this);
0036     if (!mDestination->open()) {
0037         Q_EMIT errorText(i18n("Cannot open file for downloading."));
0038         deleteLater();
0039         return;
0040     }
0041 
0042     mHash = new QCryptographicHash(QCryptographicHash::Md5);
0043 
0044     QNetworkRequest request(mInfo.url);
0045     // qDebug() << " mInfo.url " << mInfo.url;
0046     QNetworkReply *reply = TextSpeechToText::SpeechToTextEngineAccessManager::self()->networkManager()->get(request);
0047     connect(reply, &QNetworkReply::errorOccurred, this, [this](QNetworkReply::NetworkError error) {
0048         if (error == QNetworkReply::ServiceUnavailableError) {
0049             Q_EMIT errorText(i18n("Error: Engine systems have detected suspicious traffic from your computer network. Please try your request again later."));
0050         } else {
0051             Q_EMIT errorText(i18n("Impossible to access to url: %1", mInfo.url.toString()));
0052         }
0053     });
0054 
0055     connect(reply, &QNetworkReply::downloadProgress, this, &VoskDownloadLanguageJob::downloadProgress);
0056     connect(reply, &QNetworkReply::finished, this, [this, reply]() {
0057         mDestination->flush();
0058         mDestination->seek(0);
0059         reply->deleteLater();
0060         if (!mInfo.checksum.isEmpty() && mHash->result().toHex() != mInfo.checksum.toLatin1()) {
0061             // qDebug() << " mHash->result() " << mHash->result().toHex() << " mCheckSum " << mCheckSum;
0062             Q_EMIT errorText(i18n("CheckSum is not correct."));
0063             deleteLater();
0064             return;
0065         } else {
0066             extractLanguage();
0067         }
0068     });
0069     connect(reply, &QIODevice::readyRead, this, [this, reply] {
0070         const QByteArray buffer = reply->readAll();
0071         if (mDestination->write(buffer) == -1) {
0072             Q_EMIT errorText(i18n("Error during writing on disk: %1", mDestination->errorString()));
0073             reply->abort();
0074         }
0075         mHash->addData(buffer);
0076     });
0077 }
0078 
0079 bool VoskDownloadLanguageJob::canStart() const
0080 {
0081     return mInfo.isValid();
0082 }
0083 
0084 void VoskDownloadLanguageJob::extractLanguage()
0085 {
0086     auto extraJob = new VoskExtractLanguageJob(this);
0087     extraJob->setSource(mDestination->fileName());
0088     connect(extraJob, &VoskExtractLanguageJob::errorText, this, &VoskDownloadLanguageJob::errorText);
0089     connect(extraJob, &VoskExtractLanguageJob::finished, this, &VoskDownloadLanguageJob::generateInstalledLanguageInfo);
0090 
0091     extraJob->start();
0092 }
0093 
0094 void VoskDownloadLanguageJob::generateInstalledLanguageInfo()
0095 {
0096     auto generateInstalledLanguageJob = new GenerateInstalledLanguageInfoJob(this);
0097     GenerateInstalledLanguageInfoJob::LanguageInfo info;
0098     info.pathToStore = VoskEngineUtils::storageLanguagePath() + QLatin1Char('/') + mInfo.name;
0099     info.info.absoluteLanguageModelPath = VoskEngineUtils::storageLanguagePath() + QLatin1Char('/') + mInfo.name;
0100     info.info.name = mInfo.name;
0101     info.info.url = mInfo.url.toString();
0102     info.info.versionStr = mInfo.version;
0103     generateInstalledLanguageJob->setInfo(info);
0104 
0105     connect(generateInstalledLanguageJob, &GenerateInstalledLanguageInfoJob::errorText, this, &VoskDownloadLanguageJob::errorText);
0106     connect(generateInstalledLanguageJob,
0107             &GenerateInstalledLanguageInfoJob::generatedDone,
0108             this,
0109             &VoskDownloadLanguageJob::slotGenerateInstalledLanguageInfoDone);
0110     generateInstalledLanguageJob->start();
0111 }
0112 
0113 void VoskDownloadLanguageJob::slotGenerateInstalledLanguageInfoDone()
0114 {
0115     Q_EMIT extractDone();
0116     deleteLater();
0117 }
0118 
0119 VoskDownloadLanguageJob::DownloadLanguageInfo VoskDownloadLanguageJob::info() const
0120 {
0121     return mInfo;
0122 }
0123 
0124 void VoskDownloadLanguageJob::setInfo(const DownloadLanguageInfo &newInfo)
0125 {
0126     mInfo = newInfo;
0127 }
0128 
0129 QDebug operator<<(QDebug d, const VoskDownloadLanguageJob::DownloadLanguageInfo &t)
0130 {
0131     d << "url " << t.url;
0132     d << "checksum " << t.checksum;
0133     d << "name " << t.name;
0134     d << "version " << t.version;
0135     return d;
0136 }
0137 
0138 bool VoskDownloadLanguageJob::DownloadLanguageInfo::isValid() const
0139 {
0140     return !url.isEmpty() && !name.isEmpty();
0141 }
0142 
0143 #include "moc_voskdownloadlanguagejob.cpp"