File indexing completed on 2024-05-12 05:09:28

0001 /***************************************************************************
0002     Copyright (C) 2011 Robby Stephenson <robby@periapsis.org>
0003  ***************************************************************************/
0004 
0005 /***************************************************************************
0006  *                                                                         *
0007  *   This program is free software; you can redistribute it and/or         *
0008  *   modify it under the terms of the GNU General Public License as        *
0009  *   published by the Free Software Foundation; either version 2 of        *
0010  *   the License or (at your option) version 3 or any later version        *
0011  *   accepted by the membership of KDE e.V. (or its successor approved     *
0012  *   by the membership of KDE e.V.), which shall act as a proxy            *
0013  *   defined in Section 14 of version 3 of the license.                    *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful,       *
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0018  *   GNU General Public License for more details.                          *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0022  *                                                                         *
0023  ***************************************************************************/
0024 
0025 #include "bibliosharefetcher.h"
0026 #include "../utils/isbnvalidator.h"
0027 #include "../entry.h"
0028 #include "../images/imagefactory.h"
0029 #include "../images/imageinfo.h"
0030 #include "../core/tellico_strings.h"
0031 #include "../tellico_debug.h"
0032 
0033 #include <KLocalizedString>
0034 #include <KConfigGroup>
0035 
0036 #include <QLineEdit>
0037 #include <QLabel>
0038 #include <QVBoxLayout>
0039 #include <QUrlQuery>
0040 
0041 namespace {
0042   static const char* BIBLIOSHARE_BASE_URL = "https://www.biblioshare.org/BNCServices/BNCServices.asmx/";
0043   static const char* BIBLIOSHARE_TOKEN = "nsnqwebh87kstlty";
0044 }
0045 
0046 using namespace Tellico;
0047 using Tellico::Fetch::BiblioShareFetcher;
0048 
0049 BiblioShareFetcher::BiblioShareFetcher(QObject* parent_)
0050     : XMLFetcher(parent_)
0051     , m_token(QLatin1String(BIBLIOSHARE_TOKEN)) {
0052   setLimit(1);
0053   setXSLTFilename(QStringLiteral("biblioshare2tellico.xsl"));
0054 }
0055 
0056 BiblioShareFetcher::~BiblioShareFetcher() {
0057 }
0058 
0059 QString BiblioShareFetcher::source() const {
0060   return m_name.isEmpty() ? defaultName() : m_name;
0061 }
0062 
0063 // https://www.booknetcanada.ca/get-a-token
0064 QString BiblioShareFetcher::attribution() const {
0065   return i18n(providedBy, QLatin1String("https://www.booknetcanada.ca/biblioshare"), QLatin1String("BNC BiblioShare"));
0066 }
0067 
0068 bool BiblioShareFetcher::canFetch(int type) const {
0069   return type == Data::Collection::Book || type == Data::Collection::Bibtex;
0070 }
0071 
0072 void BiblioShareFetcher::readConfigHook(const KConfigGroup& config_) {
0073   QString k = config_.readEntry("Token", BIBLIOSHARE_TOKEN);
0074   if(!k.isEmpty()) {
0075     m_token = k;
0076   }
0077 }
0078 
0079 QUrl BiblioShareFetcher::searchUrl() {
0080   QUrl u(QString::fromLatin1(BIBLIOSHARE_BASE_URL));
0081   u.setPath(u.path() + QStringLiteral("BiblioSimple"));
0082 
0083   QUrlQuery q;
0084   q.addQueryItem(QStringLiteral("Token"), m_token);
0085 
0086   switch(request().key()) {
0087     case ISBN:
0088       {
0089         // only grab first value
0090         QString v = request().value().section(QLatin1Char(';'), 0);
0091         v = ISBNValidator::isbn13(v);
0092         v.remove(QLatin1Char('-'));
0093         q.addQueryItem(QStringLiteral("EAN"), v);
0094       }
0095       break;
0096 
0097     default:
0098       return QUrl();
0099   }
0100   u.setQuery(q);
0101 //  myDebug() << "url:" << u.url();
0102   return u;
0103 }
0104 
0105 Tellico::Data::EntryPtr BiblioShareFetcher::fetchEntryHookData(Data::EntryPtr entry_) {
0106   Q_ASSERT(entry_);
0107 
0108   if(!entry_) {
0109     myWarning() << "no entry";
0110     return entry_;
0111   }
0112 
0113   // if the entry cover is not set, go ahead and try to fetch it
0114   if(entry_->field(QStringLiteral("cover")).isEmpty()) {
0115     QString isbn = ISBNValidator::cleanValue(entry_->field(QStringLiteral("isbn")));
0116     if(!isbn.isEmpty()) {
0117       isbn = ISBNValidator::isbn13(isbn);
0118       isbn.remove(QLatin1Char('-'));
0119 
0120       QUrl imageUrl(QString::fromLatin1(BIBLIOSHARE_BASE_URL));
0121       imageUrl.setPath(imageUrl.path() + QStringLiteral("Images"));
0122       QUrlQuery q;
0123       q.addQueryItem(QStringLiteral("Token"), m_token);
0124       q.addQueryItem(QStringLiteral("EAN"), isbn);
0125       // the actual values for SAN Thumbnail don't seem to matter, they just can't be empty
0126       q.addQueryItem(QStringLiteral("SAN"), QStringLiteral("string"));
0127       q.addQueryItem(QStringLiteral("Thumbnail"), QStringLiteral("cover"));
0128       imageUrl.setQuery(q);
0129       const QString id = ImageFactory::addImage(imageUrl, true);
0130       if(!id.isEmpty()) {
0131         // placeholder images are 120x120 or 1x1
0132         Data::ImageInfo info = ImageFactory::imageInfo(id);
0133         if((info.width() != 120 || info.height() != 120) &&
0134            (info.width() != 1 || info.height() != 1)) {
0135           entry_->setField(QStringLiteral("cover"), id);
0136         }
0137       }
0138     }
0139   }
0140 
0141   return entry_;
0142 }
0143 
0144 Tellico::Fetch::FetchRequest BiblioShareFetcher::updateRequest(Data::EntryPtr entry_) {
0145   const QString isbn = entry_->field(QStringLiteral("isbn"));
0146   if(!isbn.isEmpty()) {
0147     return FetchRequest(Fetch::ISBN, isbn);
0148   }
0149 
0150   return FetchRequest();
0151 }
0152 
0153 Tellico::Fetch::ConfigWidget* BiblioShareFetcher::configWidget(QWidget* parent_) const {
0154   return new BiblioShareFetcher::ConfigWidget(parent_, this);
0155 }
0156 
0157 QString BiblioShareFetcher::defaultName() {
0158   return QStringLiteral("BiblioShare");
0159 }
0160 
0161 QString BiblioShareFetcher::defaultIcon() {
0162   return favIcon(QUrl(QLatin1String("https://www.booknetcanada.ca")),
0163                  QUrl(QLatin1String("https://images.squarespace-cdn.com/content/v1/550334cbe4b0e08b6885e88f/1443713102643-G58N3NF6V7EWOGZ0I4A8/favicon.ico?format=100w")));
0164 }
0165 
0166 BiblioShareFetcher::ConfigWidget::ConfigWidget(QWidget* parent_, const BiblioShareFetcher* fetcher_)
0167     : Fetch::ConfigWidget(parent_) {
0168   QGridLayout* l = new QGridLayout(optionsWidget());
0169   l->setSpacing(4);
0170   l->setColumnStretch(1, 10);
0171 
0172   int row = -1;
0173   QLabel* al = new QLabel(i18n("Registration is required for accessing this data source. "
0174                                "If you agree to the terms and conditions, <a href='%1'>sign "
0175                                "up for an account</a>, and enter your information below.",
0176                                 QStringLiteral("https://www.booknetcanada.ca/get-a-token")),
0177                           optionsWidget());
0178   al->setOpenExternalLinks(true);
0179   al->setWordWrap(true);
0180   ++row;
0181   l->addWidget(al, row, 0, 1, 2);
0182   // richtext gets weird with size
0183   al->setMinimumWidth(al->sizeHint().width());
0184 
0185   QLabel* label = new QLabel(i18n("Access key: "), optionsWidget());
0186   l->addWidget(label, ++row, 0);
0187 
0188   m_tokenEdit = new QLineEdit(optionsWidget());
0189   connect(m_tokenEdit, &QLineEdit::textChanged, this, &ConfigWidget::slotSetModified);
0190   l->addWidget(m_tokenEdit, row, 1);
0191   QString w = i18n("The default Tellico key may be used, but searching may fail due to reaching access limits.");
0192   label->setWhatsThis(w);
0193   m_tokenEdit->setWhatsThis(w);
0194   label->setBuddy(m_tokenEdit);
0195 
0196   l->setRowStretch(++row, 10);
0197 
0198   if(fetcher_) {
0199     // only show the key if it is not the default Tellico one...
0200     // that way the user is prompted to apply for their own
0201     if(fetcher_->m_token != QLatin1String(BIBLIOSHARE_TOKEN)) {
0202       m_tokenEdit->setText(fetcher_->m_token);
0203     }
0204   }
0205 }
0206 
0207 void BiblioShareFetcher::ConfigWidget::saveConfigHook(KConfigGroup& config_) {
0208   QString token = m_tokenEdit->text().trimmed();
0209   if(!token.isEmpty()) {
0210     config_.writeEntry("Token", token);
0211   }
0212 }
0213 
0214 QString BiblioShareFetcher::ConfigWidget::preferredName() const {
0215   return BiblioShareFetcher::defaultName();
0216 }