Take order on the page into consideration when searching for the best feed identifier

This commit is contained in:
Maurice Parker 2020-11-01 20:31:53 -06:00
parent b504c88948
commit aa73b24291
5 changed files with 23 additions and 46 deletions

View File

@ -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 {
// Its 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)
}
}

View File

@ -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>) -> FeedSpecifier? {
@ -69,6 +71,8 @@ private extension FeedSpecifier {
score = score + 50
}
score = score - ((orderFound - 1) * 5)
if urlString.caseInsensitiveContains("comments") {
score = score - 10
}

View File

@ -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)
}
}
}
}

View File

@ -986,27 +986,22 @@ private extension FeedbinAccountDelegate {
}
func decideBestFeedChoice(account: Account, url: String, name: String?, container: Container, choices: [FeedbinSubscriptionChoice], completion: @escaping (Result<WebFeed, Error>) -> 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<WebFeed, Error>) -> Void) {

View File

@ -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<WebFeed, Error>) -> 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<WebFeed, Error>) -> Void) {