From 9727219b09b80059ee522b50d29e7f259ed57403 Mon Sep 17 00:00:00 2001 From: Anh Do Date: Mon, 9 Mar 2020 23:26:48 -0400 Subject: [PATCH] Add feed list query --- .../Account/Account.xcodeproj/project.pbxproj | 4 + .../Models/NewsBlurSubscription.swift | 90 +++++++++++++++++++ .../Account/NewsBlur/NewsBlurAPICaller.swift | 24 +++++ .../NewsBlur/NewsBlurAccountDelegate.swift | 26 +++++- 4 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 Frameworks/Account/NewsBlur/Models/NewsBlurSubscription.swift diff --git a/Frameworks/Account/Account.xcodeproj/project.pbxproj b/Frameworks/Account/Account.xcodeproj/project.pbxproj index abd406985..9b18a5cfa 100644 --- a/Frameworks/Account/Account.xcodeproj/project.pbxproj +++ b/Frameworks/Account/Account.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 179DB28CF49F73A945EBF5DB /* NewsBlurLoginResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DB088236E3236010462E8 /* NewsBlurLoginResponse.swift */; }; + 179DBF4DE2562D4C532F6008 /* NewsBlurSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DB1B909672E0E807B5E8C /* NewsBlurSubscription.swift */; }; 3B3A33E7238D3D6800314204 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A33E6238D3D6800314204 /* Secrets.swift */; }; 3B826DA72385C81C00FC1ADB /* FeedWranglerAuthorizationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826D9E2385C81C00FC1ADB /* FeedWranglerAuthorizationResult.swift */; }; 3B826DA82385C81C00FC1ADB /* FeedWranglerFeedItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826D9F2385C81C00FC1ADB /* FeedWranglerFeedItem.swift */; }; @@ -224,6 +225,7 @@ /* Begin PBXFileReference section */ 179DB088236E3236010462E8 /* NewsBlurLoginResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewsBlurLoginResponse.swift; sourceTree = ""; }; + 179DB1B909672E0E807B5E8C /* NewsBlurSubscription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewsBlurSubscription.swift; sourceTree = ""; }; 3B3A33E6238D3D6800314204 /* Secrets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Secrets.swift; path = ../../Shared/Secrets.swift; sourceTree = ""; }; 3B826D9E2385C81C00FC1ADB /* FeedWranglerAuthorizationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAuthorizationResult.swift; sourceTree = ""; }; 3B826D9F2385C81C00FC1ADB /* FeedWranglerFeedItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerFeedItem.swift; sourceTree = ""; }; @@ -445,6 +447,7 @@ isa = PBXGroup; children = ( 179DB088236E3236010462E8 /* NewsBlurLoginResponse.swift */, + 179DB1B909672E0E807B5E8C /* NewsBlurSubscription.swift */, ); path = Models; sourceTree = ""; @@ -1135,6 +1138,7 @@ 769F295938E5A30D03DFF88F /* NewsBlurAccountDelegate.swift in Sources */, 769F2BA02EF5F329CDE45F5A /* NewsBlurAPICaller.swift in Sources */, 179DB28CF49F73A945EBF5DB /* NewsBlurLoginResponse.swift in Sources */, + 179DBF4DE2562D4C532F6008 /* NewsBlurSubscription.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Frameworks/Account/NewsBlur/Models/NewsBlurSubscription.swift b/Frameworks/Account/NewsBlur/Models/NewsBlurSubscription.swift new file mode 100644 index 000000000..e10ba0099 --- /dev/null +++ b/Frameworks/Account/NewsBlur/Models/NewsBlurSubscription.swift @@ -0,0 +1,90 @@ +// +// NewsBlurSubscription.swift +// Account +// +// Created by Anh Quang Do on 2020-03-09. +// Copyright (c) 2020 Ranchero Software, LLC. All rights reserved. +// + +import Foundation +import RSCore +import RSParser + +typealias NewsBlurSubscription = NewsBlurFeedsResponse.Subscription + +struct NewsBlurFeedsResponse: Decodable { + let subscriptions: [Subscription] + let folders: [Folder] + + struct Subscription: Hashable, Codable { + let title: String + let feedId: Int + let feedURL: String + let siteURL: String? + let favicon: String? + } + + struct Folder: Hashable, Codable { + let name: String + let subscriptionIds: [Int] + } +} + +extension NewsBlurFeedsResponse { + private enum CodingKeys: String, CodingKey { + case feeds = "feeds" + case folders = "flat_folders" + // TODO: flat_folders_with_inactive + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + // Parse subscriptions + var subscriptions: [Subscription] = [] + let subscriptionContainer = try container.nestedContainer(keyedBy: GenericCodingKeys.self, forKey: .feeds) + try subscriptionContainer.allKeys.forEach { key in + let subscription = try subscriptionContainer.decode(Subscription.self, forKey: key) + subscriptions.append(subscription) + } + + // Parse folders + var folders: [Folder] = [] + let folderContainer = try container.nestedContainer(keyedBy: GenericCodingKeys.self, forKey: .folders) + try folderContainer.allKeys.forEach { key in + let subscriptionIds = try folderContainer.decode([Int].self, forKey: key) + let folder = Folder(name: key.stringValue, subscriptionIds: subscriptionIds) + + folders.append(folder) + } + + self.subscriptions = subscriptions + self.folders = folders + } +} + +extension NewsBlurFeedsResponse.Subscription { + private enum CodingKeys: String, CodingKey { + case title = "feed_title" + case feedId = "id" + case feedURL = "feed_address" + case siteURL = "feed_link" + case favicon = "favicon_url" + } +} + +fileprivate struct GenericCodingKeys: CodingKey { + var stringValue: String + + init?(stringValue: String) { + self.stringValue = stringValue + } + + var intValue: Int? { + return nil + } + + init?(intValue: Int) { + return nil + } +} diff --git a/Frameworks/Account/NewsBlur/NewsBlurAPICaller.swift b/Frameworks/Account/NewsBlur/NewsBlurAPICaller.swift index ca63b9404..5039e5f0e 100644 --- a/Frameworks/Account/NewsBlur/NewsBlurAPICaller.swift +++ b/Frameworks/Account/NewsBlur/NewsBlurAPICaller.swift @@ -83,4 +83,28 @@ final class NewsBlurAPICaller: NSObject { } } } + + func retrieveSubscriptions(completion: @escaping (Result<[NewsBlurSubscription]?, Error>) -> Void) { + let url = baseURL + .appendingPathComponent("reader/feeds") + .appendingQueryItems([ + URLQueryItem(name: "flat", value: "true"), + URLQueryItem(name: "update_counts", value: "false"), + ]) + + guard let callURL = url else { + completion(.failure(TransportError.noURL)) + return + } + + let request = URLRequest(url: callURL, credentials: credentials) + transport.send(request: request, resultType: NewsBlurFeedsResponse.self) { result in + switch result { + case .success(let (response, payload)): + print(payload) + case .failure(let error): + completion(.failure(error)) + } + } + } } diff --git a/Frameworks/Account/NewsBlur/NewsBlurAccountDelegate.swift b/Frameworks/Account/NewsBlur/NewsBlurAccountDelegate.swift index 7ddad1867..991f55ab6 100644 --- a/Frameworks/Account/NewsBlur/NewsBlurAccountDelegate.swift +++ b/Frameworks/Account/NewsBlur/NewsBlurAccountDelegate.swift @@ -58,7 +58,15 @@ final class NewsBlurAccountDelegate: AccountDelegate { } func refreshAll(for account: Account, completion: @escaping (Result) -> ()) { - completion(.success(())) + self.refreshProgress.addToNumberOfTasks(1) + refreshSubscriptions(for: account) { result in + switch result { + case .success: + completion(.success(())) + case .failure(let error): + completion(.failure(error)) + } + } } func sendArticleStatus(for account: Account, completion: @escaping (Result) -> ()) { @@ -144,3 +152,19 @@ final class NewsBlurAccountDelegate: AccountDelegate { database.resume() } } + +extension NewsBlurAccountDelegate { + private func refreshSubscriptions(for account: Account, completion: @escaping (Result) -> Void) { + os_log(.debug, log: log, "Refreshing subscriptions...") + caller.retrieveSubscriptions { result in + switch result { + case .success(let subscriptions): + print(subscriptions) + self.refreshProgress.completeTask() + completion(.success(())) + case .failure(let error): + completion(.failure(error)) + } + } + } +}