From aa73b242912b25f881dd2e61d73290fd276ab509 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sun, 1 Nov 2020 20:31:53 -0600 Subject: [PATCH] Take order on the page into consideration when searching for the best feed identifier --- .../Account/FeedFinder/FeedFinder.swift | 8 +++---- .../Account/FeedFinder/FeedSpecifier.swift | 6 ++++- .../Account/FeedFinder/HTMLFeedFinder.swift | 18 +++++++------- .../Feedbin/FeedbinAccountDelegate.swift | 13 ++++------ .../ReaderAPI/ReaderAPIAccountDelegate.swift | 24 ------------------- 5 files changed, 23 insertions(+), 46 deletions(-) diff --git a/Account/Sources/Account/FeedFinder/FeedFinder.swift b/Account/Sources/Account/FeedFinder/FeedFinder.swift index d743b629a..e81c5160c 100644 --- a/Account/Sources/Account/FeedFinder/FeedFinder.swift +++ b/Account/Sources/Account/FeedFinder/FeedFinder.swift @@ -20,7 +20,7 @@ class FeedFinder { if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), urlComponents.host == "micro.blog" { urlComponents.path = "\(urlComponents.path).json" if let newURLString = urlComponents.url?.absoluteString { - let microblogFeedSpecifier = FeedSpecifier(title: nil, urlString: newURLString, source: .HTMLLink) + let microblogFeedSpecifier = FeedSpecifier(title: nil, urlString: newURLString, source: .HTMLLink, orderFound: 1) completion(.success(Set([microblogFeedSpecifier]))) } } else { @@ -45,7 +45,7 @@ class FeedFinder { } if FeedFinder.isFeed(data, url.absoluteString) { - let feedSpecifier = FeedSpecifier(title: nil, urlString: url.absoluteString, source: .UserEntered) + let feedSpecifier = FeedSpecifier(title: nil, urlString: url.absoluteString, source: .UserEntered, orderFound: 1) completion(.success(Set([feedSpecifier]))) return } @@ -120,11 +120,11 @@ private extension FeedFinder { // It’s also fairly common for /index.xml to work. if let url = URL(string: urlString) { let feedURL = url.appendingPathComponent("feed", isDirectory: true) - let wordpressFeedSpecifier = FeedSpecifier(title: nil, urlString: feedURL.absoluteString, source: .HTMLLink) + let wordpressFeedSpecifier = FeedSpecifier(title: nil, urlString: feedURL.absoluteString, source: .HTMLLink, orderFound: 1) feedSpecifiers.insert(wordpressFeedSpecifier) let indexXMLURL = url.appendingPathComponent("index.xml", isDirectory: false) - let indexXMLFeedSpecifier = FeedSpecifier(title: nil, urlString: indexXMLURL.absoluteString, source: .HTMLLink) + let indexXMLFeedSpecifier = FeedSpecifier(title: nil, urlString: indexXMLURL.absoluteString, source: .HTMLLink, orderFound: 1) feedSpecifiers.insert(indexXMLFeedSpecifier) } } diff --git a/Account/Sources/Account/FeedFinder/FeedSpecifier.swift b/Account/Sources/Account/FeedFinder/FeedSpecifier.swift index 5b48b1b98..2957b011f 100644 --- a/Account/Sources/Account/FeedFinder/FeedSpecifier.swift +++ b/Account/Sources/Account/FeedFinder/FeedSpecifier.swift @@ -21,6 +21,7 @@ struct FeedSpecifier: Hashable { public let title: String? public let urlString: String public let source: Source + public let orderFound: Int public var score: Int { return calculatedScore() } @@ -30,8 +31,9 @@ struct FeedSpecifier: Hashable { let mergedTitle = title ?? feedSpecifier.title let mergedSource = source.equalToOrBetterThan(feedSpecifier.source) ? source : feedSpecifier.source + let mergedOrderFound = orderFound >= feedSpecifier.orderFound ? orderFound : feedSpecifier.orderFound - return FeedSpecifier(title: mergedTitle, urlString: urlString, source: mergedSource) + return FeedSpecifier(title: mergedTitle, urlString: urlString, source: mergedSource, orderFound: mergedOrderFound) } public static func bestFeed(in feedSpecifiers: Set) -> FeedSpecifier? { @@ -69,6 +71,8 @@ private extension FeedSpecifier { score = score + 50 } + score = score - ((orderFound - 1) * 5) + if urlString.caseInsensitiveContains("comments") { score = score - 10 } diff --git a/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift b/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift index 1592afa66..7e776f6c0 100644 --- a/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift +++ b/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift @@ -21,22 +21,24 @@ class HTMLFeedFinder { init(parserData: ParserData) { let metadata = RSHTMLMetadataParser.htmlMetadata(with: parserData) - + var orderFound = 0 + for oneFeedLink in metadata.feedLinks { if let oneURLString = oneFeedLink.urlString?.normalizedURL { - let oneFeedSpecifier = FeedSpecifier(title: oneFeedLink.title, urlString: oneURLString, source: .HTMLHead) + orderFound = orderFound + 1 + let oneFeedSpecifier = FeedSpecifier(title: oneFeedLink.title, urlString: oneURLString, source: .HTMLHead, orderFound: orderFound) addFeedSpecifier(oneFeedSpecifier) } } let bodyLinks = RSHTMLLinkParser.htmlLinks(with: parserData) - for oneBodyLink in bodyLinks { - - if linkMightBeFeed(oneBodyLink), let normalizedURL = oneBodyLink.urlString?.normalizedURL { - let oneFeedSpecifier = FeedSpecifier(title: oneBodyLink.text, urlString: normalizedURL, source: .HTMLLink) - addFeedSpecifier(oneFeedSpecifier) - } + for oneBodyLink in bodyLinks { + if linkMightBeFeed(oneBodyLink), let normalizedURL = oneBodyLink.urlString?.normalizedURL { + orderFound = orderFound + 1 + let oneFeedSpecifier = FeedSpecifier(title: oneBodyLink.text, urlString: normalizedURL, source: .HTMLLink, orderFound: orderFound) + addFeedSpecifier(oneFeedSpecifier) } + } } } diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index d934b0162..4b51cc5c6 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -986,27 +986,22 @@ private extension FeedbinAccountDelegate { } func decideBestFeedChoice(account: Account, url: String, name: String?, container: Container, choices: [FeedbinSubscriptionChoice], completion: @escaping (Result) -> Void) { + var orderFound = 0 let feedSpecifiers: [FeedSpecifier] = choices.map { choice in let source = url == choice.url ? FeedSpecifier.Source.UserEntered : FeedSpecifier.Source.HTMLLink - let specifier = FeedSpecifier(title: choice.name, urlString: choice.url, source: source) + orderFound = orderFound + 1 + let specifier = FeedSpecifier(title: choice.name, urlString: choice.url, source: source, orderFound: orderFound) return specifier } if let bestSpecifier = FeedSpecifier.bestFeed(in: Set(feedSpecifiers)) { - if let bestSubscription = choices.filter({ bestSpecifier.urlString == $0.url }).first { - createWebFeed(for: account, url: bestSubscription.url, name: name, container: container, completion: completion) - } else { - DispatchQueue.main.async { - completion(.failure(FeedbinAccountDelegateError.invalidParameter)) - } - } + createWebFeed(for: account, url: bestSpecifier.urlString, name: name, container: container, completion: completion) } else { DispatchQueue.main.async { completion(.failure(FeedbinAccountDelegateError.invalidParameter)) } } - } func createFeed( account: Account, subscription sub: FeedbinSubscription, name: String?, container: Container, completion: @escaping (Result) -> Void) { diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index 1602469a0..b2164481a 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -827,30 +827,6 @@ private extension ReaderAPIAccountDelegate { feed.folderRelationship = [folderExternalID: feedExternalID] } } - - func decideBestFeedChoice(account: Account, url: String, name: String?, container: Container, choices: [ReaderAPISubscriptionChoice], completion: @escaping (Result) -> Void) { - - let feedSpecifiers: [FeedSpecifier] = choices.map { choice in - let source = url == choice.url ? FeedSpecifier.Source.UserEntered : FeedSpecifier.Source.HTMLLink - let specifier = FeedSpecifier(title: choice.name, urlString: choice.url, source: source) - return specifier - } - - if let bestSpecifier = FeedSpecifier.bestFeed(in: Set(feedSpecifiers)) { - if let bestSubscription = choices.filter({ bestSpecifier.urlString == $0.url }).first { - createWebFeed(for: account, url: bestSubscription.url, name: name, container: container, completion: completion) - } else { - DispatchQueue.main.async { - completion(.failure(ReaderAPIAccountDelegateError.invalidParameter)) - } - } - } else { - DispatchQueue.main.async { - completion(.failure(ReaderAPIAccountDelegateError.invalidParameter)) - } - } - - } func createFeed( account: Account, subscription sub: ReaderAPISubscription, name: String?, container: Container, completion: @escaping (Result) -> Void) {