Continue work on Feedbin sync data types.

This commit is contained in:
Brent Simmons 2018-10-14 18:10:07 -07:00
parent 5cc4373f99
commit cd6e6daf31
9 changed files with 197 additions and 170 deletions

View File

@ -13,10 +13,7 @@
841974251F6DDCE4006346C4 /* AccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841974241F6DDCE4006346C4 /* AccountDelegate.swift */; };
841D4D702106B40400DD04E6 /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 841D4D6F2106B40400DD04E6 /* ArticlesDatabase.framework */; };
841D4D722106B40A00DD04E6 /* Articles.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 841D4D712106B40A00DD04E6 /* Articles.framework */; };
84245C7F1FDDD2580074AFBB /* FeedbinAccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C7E1FDDD2580074AFBB /* FeedbinAccountDelegate.swift */; };
84245C811FDDD42A0074AFBB /* Feedbin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C801FDDD42A0074AFBB /* Feedbin.swift */; };
84245C831FDDD8160074AFBB /* FeedbinGetSubscriptionsDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C821FDDD8160074AFBB /* FeedbinGetSubscriptionsDelegate.swift */; };
84245C851FDDD8CB0074AFBB /* FeedbinSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C841FDDD8CB0074AFBB /* FeedbinSubscription.swift */; };
84245C851FDDD8CB0074AFBB /* FeedbinFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C841FDDD8CB0074AFBB /* FeedbinFeed.swift */; };
844B297D2106C7EC004020B3 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B297C2106C7EC004020B3 /* Feed.swift */; };
844B297F210CE37E004020B3 /* UnreadCountProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B297E210CE37E004020B3 /* UnreadCountProvider.swift */; };
844B2981210CE3BF004020B3 /* RSWeb.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844B2980210CE3BF004020B3 /* RSWeb.framework */; };
@ -31,6 +28,9 @@
84C3654A1F899F3B001EC85C /* CombinedRefreshProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C365491F899F3B001EC85C /* CombinedRefreshProgress.swift */; };
84C8B3F41F89DE430053CCA6 /* DataExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C8B3F31F89DE430053CCA6 /* DataExtensions.swift */; };
84CAD7161FDF2E22000F0755 /* FeedbinArticle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CAD7151FDF2E22000F0755 /* FeedbinArticle.swift */; };
84D096212174169100D77525 /* FeedbinArticleIDArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D096202174169100D77525 /* FeedbinArticleIDArray.swift */; };
84D09623217418DC00D77525 /* FeedbinTagging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D09622217418DC00D77525 /* FeedbinTagging.swift */; };
84D0962521741B8500D77525 /* FeedbinSavedSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D0962421741B8500D77525 /* FeedbinSavedSearch.swift */; };
84EAC4822148CC6300F154AB /* RSDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EAC4812148CC6300F154AB /* RSDatabase.framework */; };
84F73CF1202788D90000BCEF /* ArticleFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F73CF0202788D80000BCEF /* ArticleFetcher.swift */; };
/* End PBXBuildFile section */
@ -90,10 +90,7 @@
8419742D1F6DDE96006346C4 /* LocalAccountRefresher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAccountRefresher.swift; sourceTree = "<group>"; };
841D4D6F2106B40400DD04E6 /* ArticlesDatabase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ArticlesDatabase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
841D4D712106B40A00DD04E6 /* Articles.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Articles.framework; sourceTree = BUILT_PRODUCTS_DIR; };
84245C7E1FDDD2580074AFBB /* FeedbinAccountDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbinAccountDelegate.swift; sourceTree = "<group>"; };
84245C801FDDD42A0074AFBB /* Feedbin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feedbin.swift; sourceTree = "<group>"; };
84245C821FDDD8160074AFBB /* FeedbinGetSubscriptionsDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinGetSubscriptionsDelegate.swift; sourceTree = "<group>"; };
84245C841FDDD8CB0074AFBB /* FeedbinSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinSubscription.swift; sourceTree = "<group>"; };
84245C841FDDD8CB0074AFBB /* FeedbinFeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinFeed.swift; sourceTree = "<group>"; };
844B297C2106C7EC004020B3 /* Feed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = "<group>"; };
844B297E210CE37E004020B3 /* UnreadCountProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnreadCountProvider.swift; sourceTree = "<group>"; };
844B2980210CE3BF004020B3 /* RSWeb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RSWeb.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -108,6 +105,9 @@
84C365491F899F3B001EC85C /* CombinedRefreshProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombinedRefreshProgress.swift; sourceTree = "<group>"; };
84C8B3F31F89DE430053CCA6 /* DataExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataExtensions.swift; sourceTree = "<group>"; };
84CAD7151FDF2E22000F0755 /* FeedbinArticle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinArticle.swift; sourceTree = "<group>"; };
84D096202174169100D77525 /* FeedbinArticleIDArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinArticleIDArray.swift; sourceTree = "<group>"; };
84D09622217418DC00D77525 /* FeedbinTagging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinTagging.swift; sourceTree = "<group>"; };
84D0962421741B8500D77525 /* FeedbinSavedSearch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinSavedSearch.swift; sourceTree = "<group>"; };
84EAC4812148CC6300F154AB /* RSDatabase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RSDatabase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
84F73CF0202788D80000BCEF /* ArticleFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleFetcher.swift; sourceTree = "<group>"; };
D511EEB5202422BB00712EC3 /* Account_project_debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Account_project_debug.xcconfig; sourceTree = "<group>"; };
@ -173,11 +173,11 @@
84245C7D1FDDD2580074AFBB /* Feedbin */ = {
isa = PBXGroup;
children = (
84245C7E1FDDD2580074AFBB /* FeedbinAccountDelegate.swift */,
84245C801FDDD42A0074AFBB /* Feedbin.swift */,
84245C821FDDD8160074AFBB /* FeedbinGetSubscriptionsDelegate.swift */,
84245C841FDDD8CB0074AFBB /* FeedbinSubscription.swift */,
84245C841FDDD8CB0074AFBB /* FeedbinFeed.swift */,
84CAD7151FDF2E22000F0755 /* FeedbinArticle.swift */,
84D096202174169100D77525 /* FeedbinArticleIDArray.swift */,
84D09622217418DC00D77525 /* FeedbinTagging.swift */,
84D0962421741B8500D77525 /* FeedbinSavedSearch.swift */,
);
path = Feedbin;
sourceTree = "<group>";
@ -411,21 +411,21 @@
84C8B3F41F89DE430053CCA6 /* DataExtensions.swift in Sources */,
84C3654A1F899F3B001EC85C /* CombinedRefreshProgress.swift in Sources */,
8469F81C1F6DD15E0084783E /* Account.swift in Sources */,
84D096212174169100D77525 /* FeedbinArticleIDArray.swift in Sources */,
846E77451F6EF9B900A165E2 /* Container.swift in Sources */,
84F73CF1202788D90000BCEF /* ArticleFetcher.swift in Sources */,
84245C7F1FDDD2580074AFBB /* FeedbinAccountDelegate.swift in Sources */,
841974251F6DDCE4006346C4 /* AccountDelegate.swift in Sources */,
846E77541F6F00E300A165E2 /* AccountManager.swift in Sources */,
844B297D2106C7EC004020B3 /* Feed.swift in Sources */,
84B99C9F1FAE8D3200ECDEDB /* ContainerPath.swift in Sources */,
846E77501F6EF9C400A165E2 /* LocalAccountRefresher.swift in Sources */,
84245C811FDDD42A0074AFBB /* Feedbin.swift in Sources */,
84D09623217418DC00D77525 /* FeedbinTagging.swift in Sources */,
84CAD7161FDF2E22000F0755 /* FeedbinArticle.swift in Sources */,
84D0962521741B8500D77525 /* FeedbinSavedSearch.swift in Sources */,
841974011F6DD1EC006346C4 /* Folder.swift in Sources */,
846E774F1F6EF9C000A165E2 /* LocalAccountDelegate.swift in Sources */,
844B297F210CE37E004020B3 /* UnreadCountProvider.swift in Sources */,
84245C851FDDD8CB0074AFBB /* FeedbinSubscription.swift in Sources */,
84245C831FDDD8160074AFBB /* FeedbinGetSubscriptionsDelegate.swift in Sources */,
84245C851FDDD8CB0074AFBB /* FeedbinFeed.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -1,46 +0,0 @@
//
// Feedbin.swift
// Account
//
// Created by Brent Simmons on 12/10/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSWeb
final class Feedbin: WebServiceProvider {
let account: Account
struct MethodName {
static let getSubscriptions = "getSubscriptions"
}
init(account: Account) {
self.account = account
}
// MARK: - Feedbin API
func getSubscriptions() {
let delegate = FeedbinGetSubscriptionsDelegate(provider: self)
callAPI(MethodName.getSubscriptions, delegate)
}
}
private extension Feedbin {
func callAPI(_ methodName: String, _ delegate: APICallDelegate) {
let call = APICall(provider: self, methodName: methodName, delegate: delegate)
run(call)
}
func run(_ apiCall: APICall) {
// TODO: add to url session
}
}

View File

@ -1,43 +0,0 @@
//
// FeedbinAccountDelegate.swift
// Account
//
// Created by Brent Simmons on 12/10/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSWeb
final class FeedbinAccountDelegate: AccountDelegate {
let supportsSubFolders = false
var refreshProgress: DownloadProgress {
return DownloadProgress(numberOfTasks: 0) // TODO
}
func refreshAll(for: Account) {
// TODO
}
// MARK: Disk
func accountDidInitialize(_ account: Account) {
// TODO: add username to account name
account.nameForDisplay = NSLocalizedString("Feedbin", comment: "Feedbin Account Name")
}
func update(account: Account, withUserInfo: NSDictionary?) {
}
func userInfo(for: Account) -> NSDictionary? {
// TODO: save username
return nil
}
}

View File

@ -12,6 +12,8 @@ import RSCore
struct FeedbinArticle {
// https://github.com/feedbin/feedbin-api/blob/master/content/entries.md
//
// "id": 2077,
// "feed_id": 135,
// "title": "Objective-C Runtime Releases",
@ -22,6 +24,16 @@ struct FeedbinArticle {
// "published": "2013-02-03T01:00:19.000000Z",
// "created_at": "2013-02-04T01:00:19.127893Z"
let syncID: String
let feedID: String
let title: String?
let url: String?
let authorName: String?
let contentHTML: String?
let summary: String?
let datePublished: Date?
let dateArrived: Date?
struct Key {
static let syncID = "id"
static let feedID = "feed_id"
@ -34,16 +46,6 @@ struct FeedbinArticle {
static let dateArrived = "created_at"
}
let syncID: String
let feedID: String
let title: String?
let url: String?
let authorName: String?
let contentHTML: String?
let summary: String?
let datePublished: Date?
let dateArrived: Date?
init?(jsonDictionary: JSONDictionary) {
guard let syncIDInt = jsonDictionary[Key.syncID] as? Int else {

View File

@ -0,0 +1,22 @@
//
// FeedbinArticleIDArray.swift
// Account
//
// Created by Brent Simmons on 10/14/18.
// Copyright © 2018 Ranchero Software, LLC. All rights reserved.
//
import Foundation
struct FeedbinArticleIDArray {
// https://github.com/feedbin/feedbin-api/blob/master/content/unread-entries.md
//
// [4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097]
let articleIDs: [Int]
init(jsonArray: [Any]) {
self.articleIDs = jsonArray.compactMap { $0 as? Int }
}
}

View File

@ -1,5 +1,5 @@
//
// FeedbinSubscription.swift
// FeedbinFeed.swift
// Account
//
// Created by Brent Simmons on 12/10/17.
@ -10,7 +10,16 @@ import Foundation
import RSCore
import RSParser
struct FeedbinSubscription {
struct FeedbinFeed {
// https://github.com/feedbin/feedbin-api/blob/master/content/feeds.md
//
// "id": 525,
// "created_at": "2013-03-12T11:30:25.209432Z",
// "feed_id": 47,
// "title": "Daring Fireball",
// "feed_url": "http://daringfireball.net/index.xml",
// "site_url": "http://daringfireball.net/"
let subscriptionID: String
let feedID: String
@ -19,13 +28,6 @@ struct FeedbinSubscription {
let url: String
let homePageURL: String?
// "id": 525,
// "created_at": "2013-03-12T11:30:25.209432Z",
// "feed_id": 47,
// "title": "Daring Fireball",
// "feed_url": "http://daringfireball.net/index.xml",
// "site_url": "http://daringfireball.net/"
struct Key {
static let subscriptionID = "id"
static let feedID = "feed_id"
@ -47,8 +49,8 @@ struct FeedbinSubscription {
return nil
}
self.subscriptionID = "\(subscriptionIDInt)"
self.feedID = "\(feedIDInt)"
self.subscriptionID = String(subscriptionIDInt)
self.feedID = String(feedIDInt)
self.url = url
if let creationDateString = dictionary[Key.creationDate] as? String {
@ -62,9 +64,9 @@ struct FeedbinSubscription {
self.homePageURL = dictionary[Key.homePageURL] as? String
}
static func subscriptions(with array: JSONArray) -> [FeedbinSubscription]? {
static func feeds(with array: JSONArray) -> [FeedbinFeed]? {
let subs = array.compactMap { FeedbinSubscription(dictionary: $0) }
let subs = array.compactMap { FeedbinFeed(dictionary: $0) }
return subs.isEmpty ? nil : subs
}
}

View File

@ -1,42 +0,0 @@
//
// FeedbinGetSubscriptionsDelegate.swift
// Account
//
// Created by Brent Simmons on 12/10/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSWeb
import RSParser
struct FeedbinGetSubscriptionsDelegate: APICallDelegate {
let provider: Feedbin
func apiCallURLRequest(_ call: APICall) -> URLRequest? {
return nil // TODO
}
func apiCall(_ call: APICall, parseReturnedObjectWith result: HTTPResult) -> Any? {
guard let data = result.data, let jsonArray = JSONUtilities.array(with: data) else {
return nil
}
return FeedbinSubscription.subscriptions(with: jsonArray)
}
func apiCall(_ call: APICall, handleErrorWith: HTTPResult, returnedObject: Any?) {
// TODO
}
func apiCall(_ call: APICall, performActionWith: HTTPResult, returnedObject: Any?) {
// TODO
}
}

View File

@ -0,0 +1,57 @@
//
// FeedbinSavedSearch.swift
// Account
//
// Created by Brent Simmons on 10/14/18.
// Copyright © 2018 Ranchero Software, LLC. All rights reserved.
//
import Foundation
struct FeedbinSavedSearch: Hashable {
// https://github.com/feedbin/feedbin-api/blob/master/content/saved-searches.md
//
// [
// {
// "id": 1,
// "name": "JavaScript",
// "query": "javascript is:unread"
// }
// ]
let uniqueID: Int
let name: String
let query: String
private struct Key {
static let uniqueID = "id"
static let name = "name"
static let query = "query"
}
init?(jsonDictionary: [String: Any]) {
guard let uniqueID = jsonDictionary[Key.uniqueID] as? Int else {
return nil
}
guard let name = jsonDictionary[Key.name] as? String else {
return nil
}
guard let query = jsonDictionary[Key.query] as? String else {
return nil
}
self.uniqueID = uniqueID
self.name = name
self.query = query
}
static func savedSearches(with jsonArray: [Any]) -> Set<FeedbinSavedSearch> {
let searches = jsonArray.compactMap { (oneSearch) -> FeedbinSavedSearch? in
if let oneSearch = oneSearch as? [String: Any] {
return FeedbinSavedSearch(jsonDictionary: oneSearch)
}
return nil
}
return Set(searches)
}
}

View File

@ -0,0 +1,75 @@
//
// FeedbinTagging.swift
// Account
//
// Created by Brent Simmons on 10/14/18.
// Copyright © 2018 Ranchero Software, LLC. All rights reserved.
//
import Foundation
struct FeedbinTagging: Hashable {
// https://github.com/feedbin/feedbin-api/blob/master/content/taggings.md
//
// [
// {
// "id": 4,
// "feed_id": 1,
// "name": "Tech"
// },
// {
// "id": 5,
// "feed_id": 2,
// "name": "News"
// }
// ]
let taggingID: Int
let feedID: Int
let name: String
private struct Key {
static let taggingID = "id"
static let feedID = "feed_id"
static let name = "name"
}
init?(jsonDictionary: [String: Any]) {
guard let taggingID = jsonDictionary[Key.taggingID] as? Int else {
return nil
}
guard let feedID = jsonDictionary[Key.feedID] as? Int else {
return nil
}
guard let name = jsonDictionary[Key.name] as? String else {
return nil
}
self.taggingID = taggingID
self.feedID = feedID
self.name = name
}
// MARK: - Hashable
public func hash(into hasher: inout Hasher) {
hasher.combine(taggingID)
}
// MARK: - Equatable
public static func ==(lhs: FeedbinTagging, rhs: FeedbinTagging) -> Bool {
return lhs.taggingID == rhs.taggingID && lhs.feedID == rhs.feedID && lhs.name == rhs.name
}
static func taggings(with jsonArray: [Any]) -> Set<FeedbinTagging> {
let taggingsArray = jsonArray.compactMap { (item) -> FeedbinTagging? in
if let oneDictionary = item as? [String: Any] {
return FeedbinTagging(jsonDictionary: oneDictionary)
}
return nil
}
return Set(taggingsArray)
}
}