BibleGateway: Fix bitrotted scraper, use mobile.*
[kworship.git] / kworship / bible / biblegateway / KwBibleManagerBibleGateway.cpp
blobb7089f2c92d75aec228f0c6c644a25a87f460903
1 /***************************************************************************
2 * This file is part of KWorship. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * KWorship is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * KWorship is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with KWorship. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 /**
21 * @file KwBibleManagerBibleGateway.cpp
22 * @brief A bible manager for BibleGateway.com.
23 * @author James Hogan <james@albanarts.com>
26 #include "KwBibleManagerBibleGateway.h"
27 #include "KwBibleModuleBibleGateway.h"
29 #include <KIO/NetAccess>
30 #include <KMessageBox>
31 #include <KGenericFactory>
33 #include <QFile>
34 #include <QDomDocument>
35 #include <QDomElement>
36 #include <QDomNodeList>
38 KW_REGISTER_BIBLE_MANAGER(KwBibleManagerBibleGateway)
40 K_EXPORT_COMPONENT_FACTORY( kworship_bible_biblegateway, KGenericFactory<KwBibleManagerBibleGateway>("kworship_bible_biblegateway") )
43 * Constructors + destructor
46 /// Default constructor.
47 KwBibleManagerBibleGateway::KwBibleManagerBibleGateway(QObject* parent, const QStringList& params)
48 : KwBibleManager(parent, params)
49 , m_cached(false)
50 , m_languages()
51 , m_versions()
52 , m_versionsByName()
53 , m_versionsByLanguage()
55 registerManager();
58 /// Destructor.
59 KwBibleManagerBibleGateway::~KwBibleManagerBibleGateway()
61 foreach (Version* version, m_versions)
63 delete version->module;
64 delete version;
69 * Main interface
72 QString KwBibleManagerBibleGateway::name() const
74 return "BibleGateway.com";
77 bool KwBibleManagerBibleGateway::isRemote() const
79 return true;
82 KwBibleModule* KwBibleManagerBibleGateway::module(const QString& name)
84 QHash<QString, Version*>::iterator it = m_versionsByName.find(name);
85 Version* version = 0;
86 // Does the module with this name exist?
87 if (it != m_versionsByName.end())
89 version = *it;
91 // Otherwise perhaps its a language
92 else
94 int langId = m_languages.indexOf(name);
95 if (-1 != langId)
97 // Just get the first module of this language
98 const QList<int>& moduleIds = m_versionsByLanguage[langId];
99 if (!moduleIds.isEmpty())
101 int id = moduleIds.first();
102 version = m_versions[id];
106 if (0 != version)
108 if (0 == version->module)
110 version->module = new KwBibleModuleBibleGateway(version->url);
112 return version->module;
114 else
116 return 0;
120 QStringList KwBibleManagerBibleGateway::moduleNames()
122 ensureCached();
123 return m_versionsByName.keys();
126 QStringList KwBibleManagerBibleGateway::moduleNamesInLanguage(const QString& lang)
128 ensureCached();
129 int languageId = m_languages.indexOf(lang);
130 QStringList names;
131 if (languageId >= 0)
133 const QList<int>& moduleIds = m_versionsByLanguage[languageId];
134 foreach (int id, moduleIds)
136 names << m_versions[id]->name;
139 return names;
142 QStringList KwBibleManagerBibleGateway::languages()
144 ensureCached();
145 return m_languages;
149 * Private functions
152 /// Ensure the version information is cached.
153 void KwBibleManagerBibleGateway::ensureCached()
155 if (!m_cached)
157 QString tmpFile;
158 // First get list from drop down menu on main page
159 #if 0
160 if (KIO::NetAccess::download(KUrl("http://mobile.biblegateway.com/"), tmpFile, 0))
162 QFile file(tmpFile);
163 if (file.open(QFile::ReadOnly | QFile::Text))
165 QByteArray rawPage = file.readAll();
166 file.close();
167 QString page = QString::fromUtf8(rawPage);
168 QRegExp rx("<select\\s+name=\"qs_version\">.*</select>");
169 if (-1 != rx.indexIn(page))
171 QDomDocument dom;
172 if (dom.setContent(rx.cap(), false))
174 // Go through all the options (languages and versions)
175 int langId = -1;
176 QList<int>* langMods = 0;
177 QDomNodeList options = dom.elementsByTagName("option");
178 for (int i = 0; i < options.count(); ++i)
180 QDomElement el = options.at(i).toElement();
181 if (!el.isNull())
183 // Its either a language (with class="lang") or a version
184 QString className = el.attribute("class");
185 QString text = el.text();
186 if (className == "lang")
188 m_languages << text;
189 ++langId;
190 langMods = &m_versionsByLanguage[langId];
192 else if (langId >= 0)
194 QString versionId = el.attribute("value");
195 // Ensure there is none with this shortname already
196 QHash<QString, Version*>::const_iterator it = m_versionsByShortName.constFind(versionId);
197 if (it == m_versionsByShortName.constEnd())
199 Version* version = new Version;
200 version->name = text;
201 version->shortname = versionId;
202 version->id = m_versionsById.size();
203 version->module = 0;
204 m_versionsById[version->id] = version;
205 m_versionsByName[text] = version;
206 m_versionsByShortName[versionId] = version;
207 *langMods << version->id;
216 #endif
217 if (KIO::NetAccess::download(KUrl("http://mobile.biblegateway.com/versions"), tmpFile, 0))
219 QFile file(tmpFile);
220 if (file.open(QFile::ReadOnly | QFile::Text))
222 QByteArray rawPage = file.readAll();
223 file.close();
224 QString page = QString::fromUtf8(rawPage);
225 QRegExp rx("<table[^>]*class=\"infotable\">.*</table>");
226 if (-1 != rx.indexIn(page))
228 QDomDocument dom;
229 if (dom.setContent(rx.cap(), false))
231 // Go through all the options (languages and versions)
232 int langId = -1;
233 int rowSpan = 0;
234 QList<int>* langMods = 0;
235 QDomNodeList rows = dom.elementsByTagName("tr");
236 for (int i = 0; i < rows.count(); ++i)
238 QDomElement row = rows.at(i).toElement();
239 if (!row.isNull())
241 QDomNodeList cols = row.elementsByTagName("td");
242 for (int j = 0; j < cols.count(); ++j)
244 QDomElement cell = cols.at(j).toElement();
245 if (!cell.isNull())
247 // if first columnn and rowspan, its a language
248 QString rowSpanStr = cell.attribute("rowspan");
249 bool ok;
250 int newRowSpan = rowSpanStr.toInt(&ok);
251 if (!j && ok && newRowSpan)
253 QString text = cell.text();
254 m_languages << text;
255 ++langId;
256 langMods = &m_versionsByLanguage[langId];
257 rowSpan = newRowSpan;
259 else if (langId >= 0)
261 QDomNodeList as = cell.elementsByTagName("a");
262 if (as.count())
264 QDomElement ael = as.at(0).toElement();
265 if (!ael.isNull())
267 QString href = ael.attribute("href");
268 QString text = ael.text();
269 QHash<QString, Version*>::const_iterator it = m_versionsByName.constFind(text);
270 if (it == m_versionsByName.constEnd())
272 Version* version = new Version;
273 version->name = text;
274 version->id = m_versions.size();
275 version->module = 0;
276 version->url = href;
277 m_versions.push_back(version);
278 m_versionsByName[text] = version;
279 *langMods << version->id;
283 // jump out of column loop
284 break;
288 if (rowSpan)
289 --rowSpan;
292 m_cached = true;
297 KIO::NetAccess::removeTempFile(tmpFile);
299 else
301 KMessageBox::error(0, KIO::NetAccess::lastErrorString());
306 /// Clear all modules.
307 void KwBibleManagerBibleGateway::clear()
309 if (m_cached)
311 foreach (Version* version, m_versions)
313 delete version->module;
314 delete version;
316 m_cached = false;
317 m_languages.clear();
318 m_versions.clear();
319 m_versionsByName.clear();
320 m_versionsByLanguage.clear();