Allow refreshing of Feed Wrangler subscriptions

This commit is contained in:
Jonathan Bennett 2019-10-16 08:30:11 -04:00
parent 86caa869fc
commit d80aeefdb3
6 changed files with 133 additions and 10 deletions

View File

@ -10,6 +10,8 @@
3BF610C723571CD4000EF978 /* FeedWranglerAPICaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF610C423571CD4000EF978 /* FeedWranglerAPICaller.swift */; };
3BF610C823571CD4000EF978 /* FeedWranglerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF610C523571CD4000EF978 /* FeedWranglerConfig.swift */; };
3BF610C923571CD4000EF978 /* FeedWranglerAccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF610C623571CD4000EF978 /* FeedWranglerAccountDelegate.swift */; };
3BF6112423572A62000EF978 /* FeedWranglerSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF6112323572A62000EF978 /* FeedWranglerSubscription.swift */; };
3BF6112623572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF6112523572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift */; };
5107A099227DE42E00C7C3C5 /* AccountCredentialsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A098227DE42E00C7C3C5 /* AccountCredentialsTest.swift */; };
5107A09B227DE49500C7C3C5 /* TestAccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A09A227DE49500C7C3C5 /* TestAccountManager.swift */; };
5107A09D227DE77700C7C3C5 /* TestTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A09C227DE77700C7C3C5 /* TestTransport.swift */; };
@ -191,6 +193,8 @@
3BF610C423571CD4000EF978 /* FeedWranglerAPICaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAPICaller.swift; sourceTree = "<group>"; };
3BF610C523571CD4000EF978 /* FeedWranglerConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerConfig.swift; sourceTree = "<group>"; };
3BF610C623571CD4000EF978 /* FeedWranglerAccountDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountDelegate.swift; sourceTree = "<group>"; };
3BF6112323572A62000EF978 /* FeedWranglerSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedWranglerSubscription.swift; sourceTree = "<group>"; };
3BF6112523572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedWranglerSubscriptionsRequest.swift; sourceTree = "<group>"; };
5107A098227DE42E00C7C3C5 /* AccountCredentialsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountCredentialsTest.swift; sourceTree = "<group>"; };
5107A09A227DE49500C7C3C5 /* TestAccountManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAccountManager.swift; sourceTree = "<group>"; };
5107A09C227DE77700C7C3C5 /* TestTransport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestTransport.swift; sourceTree = "<group>"; };
@ -349,6 +353,8 @@
3BF610C423571CD4000EF978 /* FeedWranglerAPICaller.swift */,
3BF610C523571CD4000EF978 /* FeedWranglerConfig.swift */,
3BF610C623571CD4000EF978 /* FeedWranglerAccountDelegate.swift */,
3BF6112323572A62000EF978 /* FeedWranglerSubscription.swift */,
3BF6112523572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift */,
);
path = FeedWrangler;
sourceTree = "<group>";
@ -892,6 +898,7 @@
9ECC9A85234DC16E009B5144 /* FeedlyAccountDelegateError.swift in Sources */,
9EA3133B231E368100268BA0 /* FeedlyAccountDelegate.swift in Sources */,
51E5959B228C781500FCC42B /* FeedbinStarredEntry.swift in Sources */,
3BF6112423572A62000EF978 /* FeedWranglerSubscription.swift in Sources */,
846E77451F6EF9B900A165E2 /* Container.swift in Sources */,
9E1D15532334304B00F4944C /* FeedlyGetStreamOperation.swift in Sources */,
9E12B0202334696A00ADE5A0 /* FeedlyCreateFeedsForCollectionFoldersOperation.swift in Sources */,
@ -950,6 +957,7 @@
84D09623217418DC00D77525 /* FeedbinTagging.swift in Sources */,
84CAD7161FDF2E22000F0755 /* FeedbinEntry.swift in Sources */,
5165D72A22835F7D00D9D53D /* HTMLFeedFinder.swift in Sources */,
3BF6112623572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift in Sources */,
841974011F6DD1EC006346C4 /* Folder.swift in Sources */,
510BD111232C3801002692E4 /* AccountMetadataFile.swift in Sources */,
846E774F1F6EF9C000A165E2 /* LocalAccountDelegate.swift in Sources */,

View File

@ -37,7 +37,13 @@ public extension URLRequest {
]
self.url = components.url
case .feedWranglerToken:
fatalError() // TODO: implement
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
return
}
components.queryItems = [
URLQueryItem(name: "access_token", value: credentials.secret),
]
self.url = components.url
case .readerBasic:
setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
httpMethod = "POST"

View File

@ -56,4 +56,19 @@ final class FeedWranglerAPICaller: NSObject {
}
}
func retrieveSubscriptions(completion: @escaping (Result<[FeedWranglerSubscription], Error>) -> Void) {
let url = FeedWranglerConfig.clientURL.appendingPathComponent("subscriptions/list")
let request = URLRequest(url: url, credentials: credentials)
transport.send(request: request, resultType: FeedWranglerSubscriptionsRequest.self) { result in
switch result {
case .success(let (_, results)):
completion(.success(results?.feeds ?? []))
case .failure(let error):
completion(.failure(error))
}
}
}
}

View File

@ -19,7 +19,12 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
var isOPMLImportInProgress = false
var server: String? = FeedWranglerConfig.clientPath
var credentials: Credentials?
var credentials: Credentials? {
didSet {
caller.credentials = credentials
}
}
var accountMetadata: AccountMetadata?
var refreshProgress = DownloadProgress(numberOfTasks: 0)
@ -54,13 +59,17 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
func refreshAll(for account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
refreshProgress.addToNumberOfTasksAndRemaining(6)
self.sendArticleStatus(for: account) {
self.refreshArticleStatus(for: account) {
self.refreshArticles(for: account) {
self.refreshMissingArticles(for: account) {
self.refreshProgress.clear()
DispatchQueue.main.async {
completion(.success(()))
self.refreshCredentials(for: account) {
self.refreshSubscriptions(for: account) { _ in
self.sendArticleStatus(for: account) {
self.refreshArticleStatus(for: account) {
self.refreshArticles(for: account) {
self.refreshMissingArticles(for: account) {
self.refreshProgress.clear()
DispatchQueue.main.async {
completion(.success(()))
}
}
}
}
}
@ -68,8 +77,31 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
}
}
func refreshCredentials(for account: Account, completion: @escaping (() -> Void)) {
os_log(.debug, log: log, "Refreshing credentials...")
// MARK: TODO
credentials = try? account.retrieveCredentials(type: .feedWranglerToken)
completion()
}
func refreshSubscriptions(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
os_log(.debug, log: log, "Refreshing subscriptions...")
caller.retrieveSubscriptions { result in
switch result {
case .success(let subscriptions):
self.syncFeeds(account, subscriptions)
completion(.success(()))
case .failure(let error):
completion(.failure(error))
}
}
}
func refreshArticles(for account: Account, completion: @escaping (() -> Void)) {
os_log(.debug, log: log, "Refreshing articles...")
completion()
}
func refreshMissingArticles(for account: Account, completion: @escaping (() -> Void)) {
@ -153,4 +185,31 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
// MARK: Private
private extension FeedWranglerAccountDelegate {
func syncFeeds(_ account: Account, _ subscriptions: [FeedWranglerSubscription]) {
assert(Thread.isMainThread)
let feedIds = subscriptions.map { String($0.feed_id) }
let feedsToRemove = account.topLevelFeeds.filter { !feedIds.contains($0.feedID) }
account.removeFeeds(feedsToRemove)
var subscriptionsToAdd = Set<FeedWranglerSubscription>()
subscriptions.forEach { subscription in
let subscriptionId = String(subscription.feed_id)
if let feed = account.existingFeed(withFeedID: subscriptionId) {
feed.name = subscription.title
feed.homePageURL = subscription.site_url
feed.subscriptionID = nil // MARK: TODO What should this be?
} else {
subscriptionsToAdd.insert(subscription)
}
}
subscriptionsToAdd.forEach { subscription in
let feedId = String(subscription.feed_id)
let feed = account.createFeed(with: subscription.title, url: subscription.feed_url, feedID: feedId, homePageURL: subscription.site_url)
feed.subscriptionID = nil
account.addFeed(feed)
}
}
}

View File

@ -0,0 +1,18 @@
//
// FeedWranglerSubscription.swift
// Account
//
// Created by Jonathan Bennett on 2019-10-16.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSCore
import RSParser
struct FeedWranglerSubscription: Hashable, Codable {
let title: String
let feed_id: Int
let feed_url: String
let site_url: String?
}

View File

@ -0,0 +1,17 @@
//
// FeedWranglerSubscriptionsRequest.swift
// Account
//
// Created by Jonathan Bennett on 2019-10-16.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
//
import Foundation
struct FeedWranglerSubscriptionsRequest: Hashable, Codable {
let feeds: [FeedWranglerSubscription]
let error: String?
let result: String
}