fix some problems, also rssguard now automatically detects youtube atom feeds from youtube video URLs more properly

This commit is contained in:
Martin Rotter 2024-07-03 10:24:00 +02:00
parent a82972352b
commit 0d4b7e6583
3 changed files with 55 additions and 13 deletions

View File

@ -44,6 +44,7 @@ QList<StandardFeed*> AtomParser::discoverFeeds(ServiceRoot* root, const QUrl& ur
// https://github.com/:owner/:repo/releases.atom // https://github.com/:owner/:repo/releases.atom
// https://github.com/:owner/:repo/commits.atom // https://github.com/:owner/:repo/commits.atom
// https://github.com/:user/:repo/tags.atom // https://github.com/:user/:repo/tags.atom
// 6. If URL if Youtube, find channel ID.
// Download URL. // Download URL.
int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
@ -58,6 +59,7 @@ QList<StandardFeed*> AtomParser::discoverFeeds(ServiceRoot* root, const QUrl& ur
{}, {},
{}, {},
root->networkProxy()); root->networkProxy());
QString direct_html_data = QString::fromUtf8(data);
if (res.m_networkError == QNetworkReply::NetworkError::NoError) { if (res.m_networkError == QNetworkReply::NetworkError::NoError) {
try { try {
@ -77,9 +79,10 @@ QList<StandardFeed*> AtomParser::discoverFeeds(ServiceRoot* root, const QUrl& ur
static QRegularExpression rx_href(QSL(ATOM_HREF_REGEX_MATCHER), static QRegularExpression rx_href(QSL(ATOM_HREF_REGEX_MATCHER),
QRegularExpression::PatternOption::CaseInsensitiveOption); QRegularExpression::PatternOption::CaseInsensitiveOption);
rx.optimize();
rx_href.optimize(); rx_href.optimize();
QRegularExpressionMatchIterator it_rx = rx.globalMatch(QString::fromUtf8(data)); QRegularExpressionMatchIterator it_rx = rx.globalMatch(direct_html_data);
while (it_rx.hasNext()) { while (it_rx.hasNext()) {
QRegularExpressionMatch mat_tx = it_rx.next(); QRegularExpressionMatch mat_tx = it_rx.next();
@ -175,12 +178,12 @@ QList<StandardFeed*> AtomParser::discoverFeeds(ServiceRoot* root, const QUrl& ur
// 5. // 5.
my_url = url.toString(QUrl::UrlFormattingOption::StripTrailingSlash); my_url = url.toString(QUrl::UrlFormattingOption::StripTrailingSlash);
auto mtch = QRegularExpression(QSL(GITHUB_URL_REGEX)).match(my_url); auto mtch_github = QRegularExpression(QSL(GITHUB_URL_REGEX)).match(my_url);
if (mtch.isValid() && mtch.hasMatch()) { if (mtch_github.isValid() && mtch_github.hasMatch()) {
QStringList github_feeds = {QSL("releases.atom"), QSL("commits.atom"), QSL("tags.atom")}; QStringList github_feeds = {QSL("releases.atom"), QSL("commits.atom"), QSL("tags.atom")};
QString gh_username = mtch.captured(1); QString gh_username = mtch_github.captured(1);
QString gh_repo = mtch.captured(2); QString gh_repo = mtch_github.captured(2);
for (const QString& github_feed : github_feeds) { for (const QString& github_feed : github_feeds) {
my_url = QSL("https://github.com/%1/%2/%3").arg(gh_username, gh_repo, github_feed); my_url = QSL("https://github.com/%1/%2/%3").arg(gh_username, gh_repo, github_feed);
@ -209,6 +212,40 @@ QList<StandardFeed*> AtomParser::discoverFeeds(ServiceRoot* root, const QUrl& ur
} }
} }
// 6.
my_url = url.toString(QUrl::UrlFormattingOption::StripTrailingSlash);
if (!direct_html_data.isEmpty() && my_url.contains(QSL("youtube"))) {
QString youtube_channel_id =
QRegularExpression(QSL("\"externalChannelId\": ?\"([^\"]+)\"")).match(direct_html_data).captured(1);
if (!youtube_channel_id.isEmpty()) {
my_url = QSL("https://www.youtube.com/feeds/videos.xml?channel_id=%1").arg(youtube_channel_id);
res = NetworkFactory::performNetworkOperation(my_url,
timeout,
{},
data,
QNetworkAccessManager::Operation::GetOperation,
{},
{},
{},
{},
root->networkProxy());
if (res.m_networkError == QNetworkReply::NetworkError::NoError) {
try {
auto guessed_feed = guessFeed(data, res.m_contentType);
guessed_feed.first->setSource(my_url);
feeds.append(guessed_feed.first);
}
catch (...) {
qDebugNN << LOGSEC_CORE << QUOTE_W_SPACE(my_url) << "is not a direct feed file.";
}
}
}
}
return feeds; return feeds;
} }

View File

@ -62,13 +62,13 @@ void OAuthHttpHandler::answerClient(QTcpSocket* socket, const HttpRequest& reque
const QString html = QSL("<html><head><title>") + qApp->applicationName() + QSL("</title></head><body>") + const QString html = QSL("<html><head><title>") + qApp->applicationName() + QSL("</title></head><body>") +
m_successText + QSL("</body></html>"); m_successText + QSL("</body></html>");
const QByteArray html_utf = html.toUtf8(); const QByteArray html_utf = html.toUtf8();
const QByteArray reply_message = QSL("HTTP/1.0 200 OK \r\n" const QByteArray reply_message = QSL("HTTP/1.1 200 OK \r\n"
"Content-Type: text/html; charset=\"utf-8\"\r\n" "Content-Type: text/html; charset=utf-8\r\n"
"Content-Length: %1" "Content-Length: %1\r\n"
"\r\n\r\n" "\r\n")
"%2") .arg(QString::number(html_utf.size()))
.arg(QString::number(html_utf.size()), html_utf) .toLocal8Bit()
.toLocal8Bit(); .append(html_utf);
socket->write(reply_message); socket->write(reply_message);
} }

View File

@ -207,7 +207,12 @@ QVariant RootItem::data(int column, int role) const {
} }
Qt::ItemFlags RootItem::additionalFlags() const { Qt::ItemFlags RootItem::additionalFlags() const {
return Qt::ItemFlag::NoItemFlags; if (m_kind == RootItem::Kind::Root) {
return Qt::ItemFlag::ItemIsDropEnabled;
}
else {
return Qt::ItemFlag::NoItemFlags;
}
} }
bool RootItem::performDragDropChange(RootItem* target_item) { bool RootItem::performDragDropChange(RootItem* target_item) {