2019-05-03 01:17:52 +02:00
|
|
|
//
|
|
|
|
// FeedbinAccountDelegate.swift
|
|
|
|
// Account
|
|
|
|
//
|
|
|
|
// Created by Maurice Parker on 5/2/19.
|
|
|
|
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2019-05-05 22:41:20 +02:00
|
|
|
#if os(macOS)
|
|
|
|
import AppKit
|
|
|
|
#else
|
|
|
|
import UIKit
|
|
|
|
import RSCore
|
|
|
|
#endif
|
2019-05-03 01:17:52 +02:00
|
|
|
import RSWeb
|
|
|
|
|
|
|
|
final class FeedbinAccountDelegate: AccountDelegate {
|
|
|
|
|
|
|
|
let supportsSubFolders = false
|
2019-05-04 18:48:48 +02:00
|
|
|
let server: String? = "api.feedbin.com"
|
2019-05-03 01:17:52 +02:00
|
|
|
|
2019-05-04 15:54:07 +02:00
|
|
|
private let caller: FeedbinAPICaller
|
2019-05-05 10:25:21 +02:00
|
|
|
var credentials: Credentials? {
|
|
|
|
didSet {
|
|
|
|
caller.credentials = credentials
|
|
|
|
}
|
|
|
|
}
|
2019-05-03 01:17:52 +02:00
|
|
|
|
2019-05-05 14:49:59 +02:00
|
|
|
var accountMetadata: AccountMetadata? {
|
|
|
|
didSet {
|
|
|
|
caller.accountMetadata = accountMetadata
|
|
|
|
}
|
|
|
|
}
|
2019-05-05 14:21:26 +02:00
|
|
|
|
2019-05-04 15:54:07 +02:00
|
|
|
init(transport: Transport) {
|
2019-05-05 10:25:21 +02:00
|
|
|
caller = FeedbinAPICaller(transport: transport)
|
2019-05-03 01:17:52 +02:00
|
|
|
}
|
|
|
|
|
2019-05-04 15:54:07 +02:00
|
|
|
var refreshProgress = DownloadProgress(numberOfTasks: 0)
|
|
|
|
|
2019-05-05 22:41:20 +02:00
|
|
|
static func validateCredentials(transport: Transport, credentials: Credentials, completionHandler completion: @escaping (Result<Bool, Error>) -> Void) {
|
2019-05-03 01:17:52 +02:00
|
|
|
|
2019-05-05 10:25:21 +02:00
|
|
|
let caller = FeedbinAPICaller(transport: transport)
|
|
|
|
caller.credentials = credentials
|
|
|
|
caller.validateCredentials() { result in
|
2019-05-05 22:41:20 +02:00
|
|
|
completion(result)
|
2019-05-03 01:17:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-05-05 22:41:20 +02:00
|
|
|
func refreshAll(for account: Account, completionHandler completion: (() -> Void)? = nil) {
|
|
|
|
refreshAll(account) { result in
|
|
|
|
switch result {
|
|
|
|
case .success():
|
|
|
|
completion?()
|
|
|
|
case .failure(let error):
|
|
|
|
// TODO: We should do a better job of error handling here.
|
|
|
|
// We need to prompt for credentials and provide user friendly
|
|
|
|
// errors.
|
|
|
|
#if os(macOS)
|
|
|
|
NSApplication.shared.presentError(error)
|
|
|
|
#else
|
|
|
|
UIApplication.shared.presentError(error)
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2019-05-03 01:17:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func accountDidInitialize(_ account: Account) {
|
2019-05-05 14:21:26 +02:00
|
|
|
credentials = try? account.retrieveBasicCredentials()
|
2019-05-03 01:17:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2019-05-05 22:41:20 +02:00
|
|
|
|
|
|
|
// MARK: Private
|
|
|
|
|
|
|
|
private extension FeedbinAccountDelegate {
|
|
|
|
|
|
|
|
func refreshAll(_ account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
|
|
|
|
|
|
|
|
caller.retrieveTags { [weak self] result in
|
|
|
|
switch result {
|
|
|
|
case .success(let tags):
|
|
|
|
self?.syncFolders(account, tags)
|
|
|
|
completion(.success(()))
|
|
|
|
case .failure(let error):
|
|
|
|
self?.checkErrorOrNotModified(error, completion: completion)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func syncFolders(_ account: Account, _ tags: [FeedbinTag]) {
|
|
|
|
|
|
|
|
let tagNames = tags.map { $0.name }
|
|
|
|
|
|
|
|
// Delete any folders not at Feedbin
|
|
|
|
if let folders = account.folders {
|
|
|
|
folders.forEach { folder in
|
|
|
|
if !tagNames.contains(folder.name ?? "") {
|
|
|
|
account.deleteFolder(folder)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let folderNames: [String] = {
|
|
|
|
if let folders = account.folders {
|
|
|
|
return folders.map { $0.name ?? "" }
|
|
|
|
} else {
|
|
|
|
return [String]()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Make any folders Feedbin has, but we don't
|
|
|
|
tagNames.forEach { tagName in
|
|
|
|
if !folderNames.contains(tagName) {
|
|
|
|
account.ensureFolder(with: tagName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkErrorOrNotModified(_ error: Error, completion: @escaping (Result<Void, Error>) -> Void) {
|
|
|
|
switch error {
|
|
|
|
case TransportError.httpError(let status):
|
|
|
|
if status == HTTPResponseCode.notModified {
|
|
|
|
completion(.success(()))
|
|
|
|
} else {
|
|
|
|
completion(.failure(error))
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
completion(.failure(error))
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|