guessing feed now exception based
This commit is contained in:
		
							parent
							
								
									7446d7323b
								
							
						
					
					
						commit
						9f929fb787
					
				
					 4 changed files with 122 additions and 147 deletions
				
			
		|  | @ -2,6 +2,9 @@ | |||
| 
 | ||||
| #include "services/standard/gui/standardfeeddetails.h" | ||||
| 
 | ||||
| #include "exceptions/applicationexception.h" | ||||
| #include "exceptions/networkexception.h" | ||||
| #include "exceptions/scriptexception.h" | ||||
| #include "gui/guiutilities.h" | ||||
| #include "miscellaneous/iconfactory.h" | ||||
| #include "network-web/networkfactory.h" | ||||
|  | @ -115,37 +118,36 @@ StandardFeedDetails::StandardFeedDetails(QWidget* parent) : QWidget(parent) { | |||
| void StandardFeedDetails::guessIconOnly(StandardFeed::SourceType source_type, const QString& source, | ||||
|                                         const QString& post_process_script, const QString& username, | ||||
|                                         const QString& password, const QNetworkProxy& custom_proxy) { | ||||
|   bool result; | ||||
|   try { | ||||
|     StandardFeed* metadata = StandardFeed::guessFeed(source_type, | ||||
|                                                      source, | ||||
|                                                      post_process_script, | ||||
|                                                    &result, | ||||
|                                                      username, | ||||
|                                                      password, | ||||
|                                                      custom_proxy); | ||||
| 
 | ||||
|   if (metadata != nullptr) { | ||||
|     // Icon or whole feed was guessed.
 | ||||
|     m_ui.m_btnIcon->setIcon(metadata->icon()); | ||||
| 
 | ||||
|     if (result) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Ok, | ||||
|                                        tr("Icon fetched successfully."), | ||||
|                                        tr("Icon metadata fetched.")); | ||||
|     } | ||||
|     else { | ||||
|       m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Warning, | ||||
|                                          tr("Icon metadata not fetched."), | ||||
|                                          tr("Icon metadata not fetched.")); | ||||
|     } | ||||
| 
 | ||||
|     // Remove temporary feed object.
 | ||||
|     delete metadata; | ||||
|     metadata->deleteLater(); | ||||
|   } | ||||
|   else { | ||||
|     // No feed guessed, even no icon available.
 | ||||
|   catch (const ScriptException& ex) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Error, | ||||
|                                        tr("No icon fetched."), | ||||
|                                        tr("Script failed: %1").arg(ex.message()), | ||||
|                                        tr("No icon fetched.")); | ||||
|   } | ||||
|   catch (const NetworkException& ex) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Error, | ||||
|                                        tr("Network error: %1").arg(ex.message()), | ||||
|                                        tr("No icon fetched.")); | ||||
|   } | ||||
|   catch (const ApplicationException& ex) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Error, | ||||
|                                        tr("Error: %1").arg(ex.message()), | ||||
|                                        tr("No icon fetched.")); | ||||
|   } | ||||
| } | ||||
|  | @ -153,16 +155,14 @@ void StandardFeedDetails::guessIconOnly(StandardFeed::SourceType source_type, co | |||
| void StandardFeedDetails::guessFeed(StandardFeed::SourceType source_type, const QString& source, | ||||
|                                     const QString& post_process_script, const QString& username, | ||||
|                                     const QString& password, const QNetworkProxy& custom_proxy) { | ||||
|   bool result; | ||||
|   try { | ||||
|     StandardFeed* metadata = StandardFeed::guessFeed(source_type, | ||||
|                                                      source, | ||||
|                                                      post_process_script, | ||||
|                                                    &result, | ||||
|                                                      username, | ||||
|                                                      password, | ||||
|                                                      custom_proxy); | ||||
| 
 | ||||
|   if (metadata != nullptr) { | ||||
|     // Icon or whole feed was guessed.
 | ||||
|     m_ui.m_btnIcon->setIcon(metadata->icon()); | ||||
|     m_ui.m_txtTitle->lineEdit()->setText(metadata->title()); | ||||
|  | @ -177,24 +177,26 @@ void StandardFeedDetails::guessFeed(StandardFeed::SourceType source_type, const | |||
|       m_ui.m_cmbEncoding->setCurrentIndex(m_ui.m_cmbEncoding->findText(DEFAULT_FEED_ENCODING, Qt::MatchFixedString)); | ||||
|     } | ||||
| 
 | ||||
|     if (result) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Ok, | ||||
|                                        tr("All metadata fetched successfully."), | ||||
|                                        tr("Feed and icon metadata fetched.")); | ||||
|     } | ||||
|     else { | ||||
|       m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Warning, | ||||
|                                          tr("Feed or icon metadata not fetched."), | ||||
|                                          tr("Feed or icon metadata not fetched.")); | ||||
|     } | ||||
| 
 | ||||
|     // Remove temporary feed object.
 | ||||
|     delete metadata; | ||||
|     metadata->deleteLater(); | ||||
|   } | ||||
|   else { | ||||
|     // No feed guessed, even no icon available.
 | ||||
|   catch (const ScriptException& ex) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Error, | ||||
|                                        tr("No metadata fetched."), | ||||
|                                        tr("Script failed: %1").arg(ex.message()), | ||||
|                                        tr("No metadata fetched.")); | ||||
|   } | ||||
|   catch (const NetworkException& ex) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Error, | ||||
|                                        tr("Network error: %1").arg(ex.message()), | ||||
|                                        tr("No metadata fetched.")); | ||||
|   } | ||||
|   catch (const ApplicationException& ex) { | ||||
|     m_ui.m_lblFetchMetadata->setStatus(WidgetWithStatus::StatusType::Error, | ||||
|                                        tr("Error: %1").arg(ex.message()), | ||||
|                                        tr("No metadata fetched.")); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,8 @@ | |||
| #include "database/databasequeries.h" | ||||
| #include "definitions/definitions.h" | ||||
| #include "exceptions/applicationexception.h" | ||||
| #include "exceptions/networkexception.h" | ||||
| #include "exceptions/scriptexception.h" | ||||
| #include "exceptions/scriptexception.h" | ||||
| #include "gui/feedmessageviewer.h" | ||||
| #include "gui/feedsview.h" | ||||
|  | @ -184,27 +186,24 @@ QString StandardFeed::sourceTypeToString(StandardFeed::SourceType type) { | |||
| } | ||||
| 
 | ||||
| void StandardFeed::fetchMetadataForItself() { | ||||
|   bool result; | ||||
|   try { | ||||
|     StandardFeed* metadata = guessFeed(sourceType(), | ||||
|                                        source(), | ||||
|                                        postProcessScript(), | ||||
|                                      &result, | ||||
|                                        username(), | ||||
|                                        password(), | ||||
|                                        getParentServiceRoot()->networkProxy()); | ||||
| 
 | ||||
|   if (metadata != nullptr && result) { | ||||
|     // Copy metadata to our object.
 | ||||
|     setTitle(metadata->title()); | ||||
|     setDescription(metadata->description()); | ||||
|     setType(metadata->type()); | ||||
|     setEncoding(metadata->encoding()); | ||||
|     setIcon(metadata->icon()); | ||||
|     delete metadata; | ||||
|     metadata->deleteLater(); | ||||
| 
 | ||||
|     QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); | ||||
| 
 | ||||
|     try { | ||||
|     DatabaseQueries::createOverwriteFeed(database, this, getParentServiceRoot()->accountId(), parent()->id()); | ||||
|     serviceRoot()->itemChanged({ this }); | ||||
|   } | ||||
|  | @ -213,18 +212,11 @@ void StandardFeed::fetchMetadataForItself() { | |||
|                 << "Cannot overwrite feed:" | ||||
|                 << QUOTE_W_SPACE_DOT(ex.message()); | ||||
|     qApp->showGuiMessage(tr("Error"), | ||||
|                            tr("Cannot save data for feed, detailed information was logged via debug log."), | ||||
|                          tr("Cannot save data for feed: %1").arg(ex.message()), | ||||
|                          QSystemTrayIcon::MessageIcon::Critical, | ||||
|                          nullptr, | ||||
|                          true); | ||||
|   } | ||||
| 
 | ||||
|   } | ||||
|   else { | ||||
|     qApp->showGuiMessage(tr("Metadata not fetched"), | ||||
|                          tr("Metadata was not fetched."), | ||||
|                          QSystemTrayIcon::MessageIcon::Critical); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| QString StandardFeed::postProcessScript() const { | ||||
|  | @ -246,7 +238,6 @@ void StandardFeed::setSourceType(SourceType source_type) { | |||
| StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | ||||
|                                       const QString& source, | ||||
|                                       const QString& post_process_script, | ||||
|                                       bool* result, | ||||
|                                       const QString& username, | ||||
|                                       const QString& password, | ||||
|                                       const QNetworkProxy& custom_proxy) { | ||||
|  | @ -271,8 +262,7 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | |||
|     content_type = network_result.second.toString(); | ||||
| 
 | ||||
|     if (network_result.first != QNetworkReply::NetworkError::NoError) { | ||||
|       *result = false; | ||||
|       return nullptr; | ||||
|       throw NetworkException(network_result.first); | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|  | @ -282,37 +272,14 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | |||
|              << "to obtain feed data."; | ||||
| 
 | ||||
|     // Use script to generate feed file.
 | ||||
|     try { | ||||
|     feed_contents = generateFeedFileWithScript(source, timeout).toUtf8(); | ||||
|   } | ||||
|     catch (const ScriptException& ex) { | ||||
|       qCriticalNN << LOGSEC_CORE | ||||
|                   << "Custom script for generating feed file failed during guessing:" | ||||
|                   << QUOTE_W_SPACE_DOT(ex.message()); | ||||
| 
 | ||||
|       *result = false; | ||||
|       return nullptr; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (!post_process_script.simplified().isEmpty()) { | ||||
|     qDebugNN << LOGSEC_CORE | ||||
|              << "Post-processing obtained feed data with custom script for guessing" | ||||
|              << QUOTE_W_SPACE_DOT(post_process_script); | ||||
| 
 | ||||
|     try { | ||||
|       feed_contents = postProcessFeedFileWithScript(post_process_script, | ||||
|                                                     feed_contents, | ||||
|                                                     timeout).toUtf8(); | ||||
|     } | ||||
|     catch (const ScriptException& ex) { | ||||
|       qCriticalNN << LOGSEC_CORE | ||||
|                   << "Post-processing script for feed file for guessing failed:" | ||||
|                   << QUOTE_W_SPACE_DOT(ex.message()); | ||||
| 
 | ||||
|       *result = false; | ||||
|       return nullptr; | ||||
|     } | ||||
|     feed_contents = postProcessFeedFileWithScript(post_process_script, feed_contents, timeout).toUtf8(); | ||||
|   } | ||||
| 
 | ||||
|   StandardFeed* feed = nullptr; | ||||
|  | @ -326,8 +293,7 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | |||
|   // only use its domain and download via DuckDuckGo.
 | ||||
|   QList<QPair<QString, bool>> icon_possible_locations; | ||||
| 
 | ||||
|   if (content_type.contains(QSL("json"), Qt::CaseSensitivity::CaseInsensitive) || | ||||
|       feed_contents.startsWith('{')) { | ||||
|   if (content_type.contains(QSL("json"), Qt::CaseSensitivity::CaseInsensitive) || feed_contents.startsWith('{')) { | ||||
|     feed = new StandardFeed(); | ||||
| 
 | ||||
|     // We have JSON feed.
 | ||||
|  | @ -362,9 +328,7 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | |||
|     QString xml_schema_encoding; | ||||
|     QString xml_contents_encoded; | ||||
|     QString enc = QRegularExpression(QSL("encoding=\"([A-Z0-9\\-]+)\""), | ||||
|                                      QRegularExpression::PatternOption::CaseInsensitiveOption) | ||||
|                   .match(feed_contents) | ||||
|                   .captured(1); | ||||
|                                      QRegularExpression::PatternOption::CaseInsensitiveOption).match(feed_contents).captured(1); | ||||
| 
 | ||||
|     if (!enc.isEmpty()) { | ||||
|       // Some "encoding" attribute was found get the encoding
 | ||||
|  | @ -396,13 +360,7 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | |||
|                                  &error_msg, | ||||
|                                  &error_line, | ||||
|                                  &error_column)) { | ||||
|       qDebugNN << LOGSEC_CORE | ||||
|                << "XML of feed" << QUOTE_W_SPACE(source) << "is not valid and cannot be loaded. " | ||||
|                << "Error:" << QUOTE_W_SPACE(error_msg) << "(line " << error_line | ||||
|                << ", column " << error_column << ")."; | ||||
| 
 | ||||
|       *result = false; | ||||
|       return nullptr; | ||||
|       throw ApplicationException(tr("XML is not well-formed, %1").arg(error_msg)); | ||||
|     } | ||||
| 
 | ||||
|     feed = new StandardFeed(); | ||||
|  | @ -479,9 +437,7 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | |||
|       // File was downloaded and it really was XML file
 | ||||
|       // but feed format was NOT recognized.
 | ||||
|       feed->deleteLater(); | ||||
| 
 | ||||
|       *result = false; | ||||
|       return nullptr; | ||||
|       throw ApplicationException(tr("XML feed file format unrecognized")); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -501,7 +457,6 @@ StandardFeed* StandardFeed::guessFeed(StandardFeed::SourceType source_type, | |||
|     feed->setIcon(icon_data); | ||||
|   } | ||||
| 
 | ||||
|   *result = true; | ||||
|   return feed; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -87,7 +87,6 @@ class StandardFeed : public Feed { | |||
|     static StandardFeed* guessFeed(SourceType source_type, | ||||
|                                    const QString& url, | ||||
|                                    const QString& post_process_script, | ||||
|                                    bool* result, | ||||
|                                    const QString& username = QString(), | ||||
|                                    const QString& password = QString(), | ||||
|                                    const QNetworkProxy& custom_proxy = QNetworkProxy::ProxyType::DefaultProxy); | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| #include "services/standard/standardfeedsimportexportmodel.h" | ||||
| 
 | ||||
| #include "definitions/definitions.h" | ||||
| #include "exceptions/applicationexception.h" | ||||
| #include "miscellaneous/application.h" | ||||
| #include "miscellaneous/iconfactory.h" | ||||
| #include "services/standard/definitions.h" | ||||
|  | @ -193,23 +194,31 @@ void FeedsImportExportModel::importAsOPML20(const QByteArray& data, bool fetch_m | |||
|           // This is FEED.
 | ||||
|           // Add feed and end this iteration.
 | ||||
|           QString feed_url = child_element.attribute(QSL("xmlUrl")); | ||||
|           bool add_offline_anyway = true; | ||||
| 
 | ||||
|           if (!feed_url.isEmpty()) { | ||||
|             StandardFeed* guessed = nullptr; | ||||
|             bool result = false; | ||||
| 
 | ||||
|             if (fetch_metadata_online && | ||||
|                 (guessed = StandardFeed::guessFeed(StandardFeed::SourceType::Url, | ||||
|             try { | ||||
|               if (fetch_metadata_online) { | ||||
|                 StandardFeed* guessed = StandardFeed::guessFeed(StandardFeed::SourceType::Url, | ||||
|                                                                 feed_url, | ||||
|                                                    {}, &result, {}, {}, | ||||
|                                                    custom_proxy)) != nullptr && | ||||
|                 result) { | ||||
|               // We should obtain fresh metadata from online feed source.
 | ||||
|                                                                 {}, {}, {}, | ||||
|                                                                 custom_proxy); | ||||
| 
 | ||||
|                 guessed->setSource(feed_url); | ||||
|                 active_model_item->appendChild(guessed); | ||||
|                 succeded++; | ||||
|                 add_offline_anyway = false; | ||||
|               } | ||||
|             else { | ||||
|             } | ||||
|             catch (const ApplicationException& ex) { | ||||
|               qCriticalNN << LOGSEC_CORE | ||||
|                           << "Cannot fetch medatada for feed:" | ||||
|                           << QUOTE_W_SPACE(feed_url) | ||||
|                           << "with error:" | ||||
|                           << QUOTE_W_SPACE_DOT(ex.message()); | ||||
|             } | ||||
| 
 | ||||
|             if (add_offline_anyway) { | ||||
|               QString feed_title = child_element.attribute(QSL("text")); | ||||
|               QString feed_encoding = child_element.attribute(QSL("encoding"), DEFAULT_FEED_ENCODING); | ||||
|               QString feed_type = child_element.attribute(QSL("version"), DEFAULT_FEED_TYPE).toUpper(); | ||||
|  | @ -246,7 +255,7 @@ void FeedsImportExportModel::importAsOPML20(const QByteArray& data, bool fetch_m | |||
| 
 | ||||
|               active_model_item->appendChild(new_feed); | ||||
| 
 | ||||
|               if (fetch_metadata_online && result) { | ||||
|               if (fetch_metadata_online) { | ||||
|                 failed++; | ||||
|               } | ||||
|               else { | ||||
|  | @ -330,19 +339,29 @@ void FeedsImportExportModel::importAsTxtURLPerLine(const QByteArray& data, bool | |||
| 
 | ||||
|   for (const QByteArray& url : urls) { | ||||
|     if (!url.isEmpty()) { | ||||
|       StandardFeed* guessed = nullptr; | ||||
|       bool result = false; | ||||
|       bool add_offline_anyway = true; | ||||
| 
 | ||||
|       try { | ||||
|         if (fetch_metadata_online) { | ||||
|           StandardFeed* guessed = StandardFeed::guessFeed(StandardFeed::SourceType::Url, | ||||
|                                                           url, {}, {}, {}, | ||||
|                                                           custom_proxy); | ||||
| 
 | ||||
|       if (fetch_metadata_online && | ||||
|           (guessed = StandardFeed::guessFeed(StandardFeed::SourceType::Url, | ||||
|                                              url, {}, &result, {}, {}, | ||||
|                                              custom_proxy)) != nullptr && | ||||
|           result) { | ||||
|           guessed->setSource(url); | ||||
|           root_item->appendChild(guessed); | ||||
|           succeded++; | ||||
|           add_offline_anyway = false; | ||||
|         } | ||||
|       else { | ||||
|       } | ||||
|       catch (const ApplicationException& ex) { | ||||
|         qCriticalNN << LOGSEC_CORE | ||||
|                     << "Cannot fetch medatada for feed:" | ||||
|                     << QUOTE_W_SPACE(url) | ||||
|                     << "with error:" | ||||
|                     << QUOTE_W_SPACE_DOT(ex.message()); | ||||
|       } | ||||
| 
 | ||||
|       if (add_offline_anyway) { | ||||
|         auto* feed = new StandardFeed(); | ||||
| 
 | ||||
|         feed->setSource(url); | ||||
|  | @ -352,7 +371,7 @@ void FeedsImportExportModel::importAsTxtURLPerLine(const QByteArray& data, bool | |||
|         feed->setEncoding(DEFAULT_FEED_ENCODING); | ||||
|         root_item->appendChild(feed); | ||||
| 
 | ||||
|         if (fetch_metadata_online && result) { | ||||
|         if (fetch_metadata_online) { | ||||
|           failed++; | ||||
|         } | ||||
|         else { | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue