File indexing completed on 2024-05-12 05:10:11
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 "goodreadsimporter.h" 0026 #include "xslthandler.h" 0027 #include "tellicoimporter.h" 0028 #include "../core/filehandler.h" 0029 #include "../utils/datafileregistry.h" 0030 #include "../utils/string_utils.h" 0031 #include "../tellico_debug.h" 0032 0033 #include <KConfigGroup> 0034 #include <KLocalizedString> 0035 0036 #include <QLineEdit> 0037 #include <QVBoxLayout> 0038 #include <QFormLayout> 0039 #include <QGroupBox> 0040 #include <QDomDocument> 0041 #include <QRegularExpression> 0042 #include <QUrlQuery> 0043 #include <QFile> 0044 0045 namespace { 0046 static const char* GOODREADS_LIST_URL = "https://www.goodreads.com/review/list.xml"; 0047 static const char* GOODREADS_USER_URL = "https://www.goodreads.com/user/show.xml"; 0048 static const char* GOODREADS_API_KEY = "23626735f5a498f2f2c003300549c0b73f5caa9e87e9faca81eac394eaa5a0d66b3a6d0f563182f29efa"; 0049 } 0050 0051 using Tellico::Import::GoodreadsImporter; 0052 0053 GoodreadsImporter::GoodreadsImporter() : Import::Importer(), m_widget(nullptr), m_userEdit(nullptr) { 0054 QString xsltFile = DataFileRegistry::self()->locate(QStringLiteral("goodreads2tellico.xsl")); 0055 if(!xsltFile.isEmpty()) { 0056 m_xsltURL = QUrl::fromLocalFile(xsltFile); 0057 } else { 0058 myWarning() << "unable to find goodreads2tellico.xsl!"; 0059 } 0060 } 0061 0062 void GoodreadsImporter::setConfig(KSharedConfig::Ptr config_) { 0063 m_config = config_; 0064 } 0065 0066 bool GoodreadsImporter::canImport(int type) const { 0067 return type == Data::Collection::Book; 0068 } 0069 0070 Tellico::Data::CollPtr GoodreadsImporter::collection() { 0071 if(m_coll) { 0072 return m_coll; 0073 } 0074 0075 if(!m_config) { 0076 m_config = KSharedConfig::openConfig(); 0077 } 0078 0079 KConfigGroup cg(m_config, QStringLiteral("ImportOptions - Goodreads")); 0080 m_user = cg.readEntry("User ID"); 0081 m_key = cg.readEntry("Developer Key"); 0082 if(m_key.isEmpty()) { 0083 m_key = Tellico::reverseObfuscate(GOODREADS_API_KEY); 0084 } 0085 0086 if(m_xsltURL.isEmpty() || !m_xsltURL.isValid()) { 0087 setStatusMessage(i18n("A valid XSLT file is needed to import the file.")); 0088 return Data::CollPtr(); 0089 } 0090 0091 if(m_widget) { 0092 m_user = m_userEdit->text().trimmed(); 0093 } else if(m_user.isEmpty()) { 0094 myWarning() << "no widget and no user!"; 0095 return Data::CollPtr(); 0096 } 0097 0098 // if the user is not all digits, assume it's a user name and 0099 // convert it to a user id 0100 static const QRegularExpression digitsRx(QLatin1String("^\\d+$")); 0101 if(!digitsRx.match(m_user).hasMatch()) { 0102 m_user = idFromName(m_user); 0103 } 0104 if(m_user.isEmpty()) { 0105 setStatusMessage(i18n("A valid user ID must be entered.")); 0106 return Data::CollPtr(); 0107 } 0108 0109 XSLTHandler handler(m_xsltURL); 0110 if(!handler.isValid()) { 0111 setStatusMessage(i18n("Tellico encountered an error in XSLT processing.")); 0112 return Data::CollPtr(); 0113 } 0114 0115 const QString text = this->text(); 0116 #if 0 0117 myWarning() << "Remove output debug from goodreadsimporter.cpp"; 0118 QFile f(QLatin1String("/tmp/goodreads.xml")); 0119 if(f.open(QIODevice::WriteOnly)) { 0120 QTextStream t(&f); 0121 t.setCodec("UTF-8"); 0122 t << text; 0123 } 0124 f.close(); 0125 #endif 0126 0127 QString str = handler.applyStylesheet(text); 0128 // myDebug() << str; 0129 0130 Import::TellicoImporter imp(str); 0131 imp.setOptions(imp.options() ^ Import::ImportShowImageErrors); 0132 m_coll = imp.collection(); 0133 setStatusMessage(imp.statusMessage()); 0134 0135 cg.writeEntry("User ID", m_user); 0136 cg.writeEntry("Developer Key", m_key); 0137 0138 return m_coll; 0139 } 0140 0141 QWidget* GoodreadsImporter::widget(QWidget* parent_) { 0142 if(m_widget) { 0143 return m_widget; 0144 } 0145 m_widget = new QWidget(parent_); 0146 QVBoxLayout* l = new QVBoxLayout(m_widget); 0147 0148 QGroupBox* gbox = new QGroupBox(i18n("Goodreads Options"), m_widget); 0149 QFormLayout* lay = new QFormLayout(gbox); 0150 0151 m_userEdit = new QLineEdit(gbox); 0152 m_userEdit->setText(m_user); 0153 0154 lay->addRow(i18n("User ID:"), m_userEdit); 0155 0156 l->addWidget(gbox); 0157 l->addStretch(1); 0158 0159 return m_widget; 0160 } 0161 0162 QString GoodreadsImporter::text() const { 0163 QUrl u(QString::fromLatin1(GOODREADS_LIST_URL)); 0164 QUrlQuery q; 0165 q.addQueryItem(QStringLiteral("v"), QStringLiteral("2")); 0166 q.addQueryItem(QStringLiteral("id"), m_user); 0167 q.addQueryItem(QStringLiteral("key"), m_key); 0168 u.setQuery(q); 0169 // myDebug() << u; 0170 return FileHandler::readTextFile(u, true /* quiet */, true); 0171 } 0172 0173 QString GoodreadsImporter::idFromName(const QString& name_) const { 0174 QUrl u(QString::fromLatin1(GOODREADS_USER_URL)); 0175 QUrlQuery q; 0176 q.addQueryItem(QStringLiteral("username"), name_); 0177 q.addQueryItem(QStringLiteral("key"), m_key); 0178 u.setQuery(q); 0179 // myDebug() << u; 0180 0181 QDomDocument dom = FileHandler::readXMLDocument(u, false /* process namespace */, true /* quiet */); 0182 return dom.documentElement().namedItem(QStringLiteral("user")) 0183 .namedItem(QStringLiteral("id")) 0184 .toElement() 0185 .text() 0186 .trimmed(); 0187 }