Merge pull request #801 from jbeker/freshrss_use_feedfinder_GH-744

FreshRSS: Use Feed Finder to get proper feed URL before adding
This commit is contained in:
Maurice Parker 2019-07-16 15:09:11 -05:00 committed by GitHub
commit bf76956616
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 108 additions and 100 deletions

View File

@ -454,8 +454,8 @@ private extension ReaderAPIAccountDelegate {
}
func syncFolders(_ account: Account, _ tags: [ReaderAPITag]?) {
guard let tags = tags else { return }
assert(Thread.isMainThread)
os_log(.debug, log: log, "Syncing folders with %ld tags.", tags.count)
@ -465,13 +465,11 @@ private extension ReaderAPIAccountDelegate {
if let folders = account.folders {
folders.forEach { folder in
if !tagNames.contains(folder.name ?? "") {
DispatchQueue.main.sync {
for feed in folder.topLevelFeeds {
account.addFeed(feed)
clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
}
account.removeFolder(folder)
for feed in folder.topLevelFeeds {
account.addFeed(feed)
clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
}
account.removeFolder(folder)
}
}
}
@ -487,9 +485,7 @@ private extension ReaderAPIAccountDelegate {
// Make any folders Reader has, but we don't
tagNames.forEach { tagName in
if !folderNames.contains(tagName) {
DispatchQueue.main.sync {
_ = account.ensureFolder(with: tagName)
}
_ = account.ensureFolder(with: tagName)
}
}
@ -523,7 +519,8 @@ private extension ReaderAPIAccountDelegate {
func syncFeeds(_ account: Account, _ subscriptions: [ReaderAPISubscription]?) {
guard let subscriptions = subscriptions else { return }
assert(Thread.isMainThread)
os_log(.debug, log: log, "Syncing feeds with %ld subscriptions.", subscriptions.count)
let subFeedIds = subscriptions.map { String($0.feedID) }
@ -533,9 +530,7 @@ private extension ReaderAPIAccountDelegate {
for folder in folders {
for feed in folder.topLevelFeeds {
if !subFeedIds.contains(feed.feedID) {
DispatchQueue.main.sync {
folder.removeFeed(feed)
}
folder.removeFeed(feed)
}
}
}
@ -543,9 +538,7 @@ private extension ReaderAPIAccountDelegate {
for feed in account.topLevelFeeds {
if !subFeedIds.contains(feed.feedID) {
DispatchQueue.main.sync {
account.removeFeed(feed)
}
account.removeFeed(feed)
}
}
@ -553,17 +546,14 @@ private extension ReaderAPIAccountDelegate {
subscriptions.forEach { subscription in
let subFeedId = String(subscription.feedID)
DispatchQueue.main.sync {
if let feed = account.idToFeedDictionary[subFeedId] {
feed.name = subscription.name
feed.homePageURL = subscription.homePageURL
} else {
let feed = account.createFeed(with: subscription.name, url: subscription.url, feedID: subFeedId, homePageURL: subscription.homePageURL)
feed.iconURL = subscription.iconURL
feed.subscriptionID = String(subscription.feedID)
account.addFeed(feed)
}
if let feed = account.idToFeedDictionary[subFeedId] {
feed.name = subscription.name
feed.homePageURL = subscription.homePageURL
} else {
let feed = account.createFeed(with: subscription.name, url: subscription.url, feedID: subFeedId, homePageURL: subscription.homePageURL)
feed.iconURL = subscription.iconURL
feed.subscriptionID = String(subscription.feedID)
account.addFeed(feed)
}
}
@ -573,6 +563,7 @@ private extension ReaderAPIAccountDelegate {
func syncTaggings(_ account: Account, _ subscriptions: [ReaderAPISubscription]?) {
guard let subscriptions = subscriptions else { return }
assert(Thread.isMainThread)
os_log(.debug, log: log, "Syncing taggings with %ld subscriptions.", subscriptions.count)
@ -613,11 +604,9 @@ private extension ReaderAPIAccountDelegate {
// Move any feeds not in the folder to the account
for feed in folder.topLevelFeeds {
if !taggingFeedIDs.contains(feed.feedID) {
DispatchQueue.main.sync {
folder.removeFeed(feed)
clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
account.addFeed(feed)
}
folder.removeFeed(feed)
clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
account.addFeed(feed)
}
}
@ -631,10 +620,8 @@ private extension ReaderAPIAccountDelegate {
guard let feed = idDictionary[taggingFeedID] else {
continue
}
DispatchQueue.main.sync {
saveFolderRelationship(for: feed, withFolderName: folderName, id: String(subscription.feedID))
folder.addFeed(feed)
}
saveFolderRelationship(for: feed, withFolderName: folderName, id: String(subscription.feedID))
folder.addFeed(feed)
}
}
@ -643,11 +630,9 @@ private extension ReaderAPIAccountDelegate {
let taggedFeedIDs = Set(subscriptions.map { String($0.feedID) })
// Remove all feeds from the account container that have a tag
DispatchQueue.main.sync {
for feed in account.topLevelFeeds {
if taggedFeedIDs.contains(feed.feedID) {
account.removeFeed(feed)
}
for feed in account.topLevelFeeds {
if taggedFeedIDs.contains(feed.feedID) {
account.removeFeed(feed)
}
}

View File

@ -321,79 +321,102 @@ final class ReaderAPICaller: NSObject {
return
}
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
guard let url = URL(string: url) else {
completion(.failure(LocalAccountDelegateError.invalidParameter))
return
}
FeedFinder.find(url: url) { result in
switch result {
case .success(let token):
guard var components = URLComponents(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.subscriptionAdd.rawValue), resolvingAgainstBaseURL: false) else {
completion(.failure(TransportError.noURL))
return
case .success(let feedSpecifiers):
guard let bestFeedSpecifier = FeedSpecifier.bestFeed(in: feedSpecifiers),
let url = URL(string: bestFeedSpecifier.urlString) else {
completion(.failure(AccountError.createErrorNotFound))
return
}
components.queryItems = [
URLQueryItem(name: "quickadd", value: url)
]
guard let callURL = components.url else {
completion(.failure(TransportError.noURL))
return
}
var request = URLRequest(url: callURL, credentials: self.credentials)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postData = "T=\(token)".data(using: String.Encoding.utf8)
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIQuickAddResult.self, completion: { (result) in
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
switch result {
case .success(let (_, subResult)):
switch subResult?.numResults {
case 0:
completion(.success(.alreadySubscribed))
default:
// We have a feed ID but need to get feed information
guard let streamId = subResult?.streamId else {
completion(.failure(AccountError.createErrorNotFound))
return
}
// There is no call to get a single subscription entry, so we get them all,
// look up the one we just subscribed to and return that
self.retrieveSubscriptions(completion: { (result) in
switch result {
case .success(let subscriptions):
guard let subscriptions = subscriptions else {
case .success(let token):
guard var components = URLComponents(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.subscriptionAdd.rawValue), resolvingAgainstBaseURL: false) else {
completion(.failure(TransportError.noURL))
return
}
components.queryItems = [
URLQueryItem(name: "quickadd", value: url.absoluteString)
]
guard let callURL = components.url else {
completion(.failure(TransportError.noURL))
return
}
var request = URLRequest(url: callURL, credentials: self.credentials)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postData = "T=\(token)".data(using: String.Encoding.utf8)
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIQuickAddResult.self, completion: { (result) in
switch result {
case .success(let (_, subResult)):
switch subResult?.numResults {
case 0:
completion(.success(.alreadySubscribed))
default:
// We have a feed ID but need to get feed information
guard let streamId = subResult?.streamId else {
completion(.failure(AccountError.createErrorNotFound))
return
}
let newStreamId = "feed/\(streamId)"
guard let subscription = subscriptions.first(where: { (sub) -> Bool in
sub.feedID == newStreamId
}) else {
completion(.failure(AccountError.createErrorNotFound))
return
// There is no call to get a single subscription entry, so we get them all,
// look up the one we just subscribed to and return that
self.retrieveSubscriptions(completion: { (result) in
switch result {
case .success(let subscriptions):
guard let subscriptions = subscriptions else {
completion(.failure(AccountError.createErrorNotFound))
return
}
let newStreamId = "feed/\(streamId)"
guard let subscription = subscriptions.first(where: { (sub) -> Bool in
sub.feedID == newStreamId
}) else {
completion(.failure(AccountError.createErrorNotFound))
return
}
completion(.success(.created(subscription)))
case .failure(let error):
completion(.failure(error))
}
})
}
completion(.success(.created(subscription)))
case .failure(let error):
completion(.failure(error))
}
})
case .failure(let error):
completion(.failure(error))
}
})
case .failure(let error):
completion(.failure(error))
}
})
}
case .failure(let error):
completion(.failure(error))
case .failure:
completion(.failure(AccountError.createErrorNotFound))
}
}
//
}
func renameSubscription(subscriptionID: String, newName: String, completion: @escaping (Result<Void, Error>) -> Void) {