diff --git a/Account/Package.swift b/Account/Package.swift index 051f75ad4..e520a8bd4 100644 --- a/Account/Package.swift +++ b/Account/Package.swift @@ -14,6 +14,7 @@ dependencies.append(contentsOf: [ .package(path: "../ArticlesDatabase"), .package(path: "../Secrets"), .package(path: "../SyncDatabase"), + .package(path: "../SyncClients/NewsBlur"), ]) #else dependencies.append(contentsOf: [ @@ -47,6 +48,7 @@ let package = Package( "ArticlesDatabase", "Secrets", "SyncDatabase", + "NewsBlur" ], linkerSettings: [ .unsafeFlags(["-Xlinker", "-no_application_extension"]) diff --git a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift index 0614dcb1f..6ba4c88fd 100644 --- a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift +++ b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift @@ -13,6 +13,7 @@ import RSDatabase import RSParser import RSWeb import SyncDatabase +import NewsBlur extension NewsBlurAccountDelegate { diff --git a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift index 11aac5837..ce86c05bf 100644 --- a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift +++ b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift @@ -13,6 +13,7 @@ import RSParser import RSWeb import SyncDatabase import Secrets +import NewsBlur final class NewsBlurAccountDelegate: AccountDelegate, Logging { @@ -34,7 +35,9 @@ final class NewsBlurAccountDelegate: AccountDelegate, Logging { init(dataFolder: String, transport: Transport?) { if let transport = transport { - caller = NewsBlurAPICaller(transport: transport) + caller = NewsBlurAPICaller(transport: transport) { url, credentials in + URLRequest(url: url, credentials: credentials) + } } else { let sessionConfiguration = URLSessionConfiguration.default sessionConfiguration.requestCachePolicy = .reloadIgnoringLocalCacheData @@ -50,7 +53,9 @@ final class NewsBlurAccountDelegate: AccountDelegate, Logging { } let session = URLSession(configuration: sessionConfiguration) - caller = NewsBlurAPICaller(transport: session) + caller = NewsBlurAPICaller(transport: session) { url, credentials in + URLRequest(url: url, credentials: credentials) + } } database = SyncDatabase(databaseFilePath: dataFolder.appending("/DB.sqlite3")) @@ -644,7 +649,9 @@ final class NewsBlurAccountDelegate: AccountDelegate, Logging { } class func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result) -> ()) { - let caller = NewsBlurAPICaller(transport: transport) + let caller = NewsBlurAPICaller(transport: transport) { url, credentials in + URLRequest(url: url, credentials: credentials) + } caller.credentials = credentials caller.validateCredentials() { result in DispatchQueue.main.async { diff --git a/Account/Sources/Account/URLRequest+Account.swift b/Account/Sources/Account/URLRequest+Account.swift index 035106a7c..be394f9a3 100755 --- a/Account/Sources/Account/URLRequest+Account.swift +++ b/Account/Sources/Account/URLRequest+Account.swift @@ -9,6 +9,7 @@ import Foundation import RSWeb import Secrets +import NewsBlur public extension URLRequest { diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index c03436173..25fdcc6e5 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -1379,6 +1379,7 @@ 848363072262A3DD00DA1D35 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 8483630A2262A3F000DA1D35 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Mac/Base.lproj/RenameSheet.xib; sourceTree = SOURCE_ROOT; }; 8483630D2262A3FE00DA1D35 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Mac/Base.lproj/MainWindow.storyboard; sourceTree = SOURCE_ROOT; }; + 8486EC3E2A9BE083007EF90D /* NewsBlur */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = NewsBlur; path = SyncClients/NewsBlur; sourceTree = ""; }; 848B937121C8C5540038DC0D /* CrashReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrashReporter.swift; sourceTree = ""; }; 848D578D21543519005FFAD5 /* PasteboardFeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteboardFeed.swift; sourceTree = ""; }; 848F6AE41FC29CFA002D422E /* FaviconDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FaviconDownloader.swift; sourceTree = ""; }; @@ -2501,6 +2502,7 @@ 849C64611ED37A5D003D8FC0 /* Products */, 51C452B22265141B00C03939 /* Frameworks */, 51CD32C624D2DEF9009ABAEF /* Account */, + 8486EC3E2A9BE083007EF90D /* NewsBlur */, 51CD32C424D2CF1D009ABAEF /* Articles */, 51CD32C324D2CD57009ABAEF /* ArticlesDatabase */, 51CD32C724D2E06C009ABAEF /* Secrets */, diff --git a/SyncClients/NewsBlur/.gitignore b/SyncClients/NewsBlur/.gitignore new file mode 100644 index 000000000..3b2981208 --- /dev/null +++ b/SyncClients/NewsBlur/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/config/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/SyncClients/NewsBlur/Package.swift b/SyncClients/NewsBlur/Package.swift new file mode 100644 index 000000000..fabf19ef1 --- /dev/null +++ b/SyncClients/NewsBlur/Package.swift @@ -0,0 +1,36 @@ +// swift-tools-version: 5.8 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "NewsBlur", + platforms: [.macOS(.v13), .iOS(.v16)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "NewsBlur", + targets: ["NewsBlur"]), + ], + dependencies: [ + .package(path: "../Secrets"), + .package(url: "https://github.com/Ranchero-Software/RSWeb.git", .upToNextMajor(from: "1.0.0")), + .package(url: "https://github.com/Ranchero-Software/RSCore.git", .upToNextMajor(from: "2.0.1")), + .package(url: "https://github.com/Ranchero-Software/RSParser.git", .upToNextMajor(from: "2.0.2")) + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "NewsBlur", + dependencies: [ + "Secrets", + "RSWeb", + "RSParser", + "RSCore" + ]), + .testTarget( + name: "NewsBlurTests", + dependencies: ["NewsBlur"]), + ] +) diff --git a/SyncClients/NewsBlur/README.md b/SyncClients/NewsBlur/README.md new file mode 100644 index 000000000..19fc8b51f --- /dev/null +++ b/SyncClients/NewsBlur/README.md @@ -0,0 +1,3 @@ +# NewsBlur + +A description of this package. diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurFeed.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurFeed.swift similarity index 76% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurFeed.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurFeed.swift index f0b0300bb..34d26859e 100644 --- a/Account/Sources/Account/NewsBlur/Models/NewsBlurFeed.swift +++ b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurFeed.swift @@ -10,23 +10,23 @@ import Foundation import RSCore import RSParser -typealias NewsBlurFolder = NewsBlurFeedsResponse.Folder +public typealias NewsBlurFolder = NewsBlurFeedsResponse.Folder -struct NewsBlurFeed: Hashable, Codable { - let name: String - let feedID: Int - let feedURL: String - let homePageURL: String? - let faviconURL: String? +public struct NewsBlurFeed: Hashable, Codable { + public let name: String + public let feedID: Int + public let feedURL: String + public let homePageURL: String? + public let faviconURL: String? } -struct NewsBlurFeedsResponse: Decodable { +public struct NewsBlurFeedsResponse: Decodable { let feeds: [NewsBlurFeed] let folders: [Folder] - struct Folder: Hashable, Codable { - let name: String - let feedIDs: [Int] + public struct Folder: Hashable, Codable { + public let name: String + public let feedIDs: [Int] } } @@ -34,9 +34,9 @@ struct NewsBlurAddURLResponse: Decodable { let feed: NewsBlurFeed? } -struct NewsBlurFolderRelationship { - let folderName: String - let feedID: Int +public struct NewsBlurFolderRelationship { + public let folderName: String + public let feedID: Int } extension NewsBlurFeed { @@ -56,7 +56,7 @@ extension NewsBlurFeedsResponse { // TODO: flat_folders_with_inactive } - init(from decoder: Decoder) throws { + public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // Tricky part: Some feeds listed in `feeds` don't exist in `folders` for some reason @@ -89,7 +89,7 @@ extension NewsBlurFeedsResponse { } extension NewsBlurFeedsResponse.Folder { - var asRelationships: [NewsBlurFolderRelationship] { + public var asRelationships: [NewsBlurFolderRelationship] { return feedIDs.map { NewsBlurFolderRelationship(folderName: name, feedID: $0) } } } diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurFeedChange.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurFeedChange.swift similarity index 100% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurFeedChange.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurFeedChange.swift diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurFolderChange.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurFolderChange.swift similarity index 100% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurFolderChange.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurFolderChange.swift diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurGenericCodingKeys.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurGenericCodingKeys.swift similarity index 100% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurGenericCodingKeys.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurGenericCodingKeys.swift diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurLoginResponse.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurLoginResponse.swift similarity index 100% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurLoginResponse.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurLoginResponse.swift diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurStory.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStory.swift similarity index 70% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurStory.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStory.swift index e4878b287..5961a973b 100644 --- a/Account/Sources/Account/NewsBlur/Models/NewsBlurStory.swift +++ b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStory.swift @@ -10,23 +10,23 @@ import Foundation import RSCore import RSParser -typealias NewsBlurStory = NewsBlurStoriesResponse.Story +public typealias NewsBlurStory = NewsBlurStoriesResponse.Story -struct NewsBlurStoriesResponse: Decodable { +public struct NewsBlurStoriesResponse: Decodable { let stories: [Story] - struct Story: Decodable { - let storyID: String - let feedID: Int - let title: String? - let url: String? - let authorName: String? - let contentHTML: String? - var imageURL: String? { + public struct Story: Decodable { + public let storyID: String + public let feedID: Int + public let title: String? + public let url: String? + public let authorName: String? + public let contentHTML: String? + public var imageURL: String? { return imageURLs?.first?.value } - var tags: [String]? - var datePublished: Date? { + public var tags: [String]? + public var datePublished: Date? { let interval = (publishedTimestamp as NSString).doubleValue return Date(timeIntervalSince1970: interval) } diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurStoryHash.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStoryHash.swift similarity index 85% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurStoryHash.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStoryHash.swift index 48286df00..7a4a694be 100644 --- a/Account/Sources/Account/NewsBlur/Models/NewsBlurStoryHash.swift +++ b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStoryHash.swift @@ -10,17 +10,22 @@ import Foundation import RSCore import RSParser -typealias NewsBlurStoryHash = NewsBlurStoryHashesResponse.StoryHash +public typealias NewsBlurStoryHash = NewsBlurStoryHashesResponse.StoryHash -struct NewsBlurStoryHashesResponse: Decodable { +public struct NewsBlurStoryHashesResponse: Decodable { typealias StoryHashDictionary = [String: [StoryHash]] var unread: [StoryHash]? var starred: [StoryHash]? - struct StoryHash: Hashable, Codable { - var hash: String - var timestamp: Date + public struct StoryHash: Hashable, Codable { + public var hash: String + public var timestamp: Date + + public init(hash: String, timestamp: Date) { + self.hash = hash + self.timestamp = timestamp + } } } @@ -30,7 +35,7 @@ extension NewsBlurStoryHashesResponse { case starred = "starred_story_hashes" } - init(from decoder: Decoder) throws { + public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // Parse unread diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurStoryStatusChange.swift b/SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStoryStatusChange.swift similarity index 100% rename from Account/Sources/Account/NewsBlur/Models/NewsBlurStoryStatusChange.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/Models/NewsBlurStoryStatusChange.swift diff --git a/SyncClients/NewsBlur/Sources/NewsBlur/NewsBlur.swift b/SyncClients/NewsBlur/Sources/NewsBlur/NewsBlur.swift new file mode 100644 index 000000000..45e7c5f24 --- /dev/null +++ b/SyncClients/NewsBlur/Sources/NewsBlur/NewsBlur.swift @@ -0,0 +1,6 @@ +public struct NewsBlur { + public private(set) var text = "Hello, World!" + + public init() { + } +} diff --git a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAPICaller+Internal.swift b/SyncClients/NewsBlur/Sources/NewsBlur/NewsBlurAPICaller+Internal.swift similarity index 94% rename from Account/Sources/Account/NewsBlur/Internals/NewsBlurAPICaller+Internal.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/NewsBlurAPICaller+Internal.swift index 078bb1d36..b5117ab0a 100644 --- a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAPICaller+Internal.swift +++ b/SyncClients/NewsBlur/Sources/NewsBlur/NewsBlurAPICaller+Internal.swift @@ -13,12 +13,12 @@ protocol NewsBlurDataConvertible { var asData: Data? { get } } -enum NewsBlurError: LocalizedError { +public enum NewsBlurError: LocalizedError { case general(message: String) case invalidParameter case unknown - var errorDescription: String? { + public var errorDescription: String? { switch self { case .general(let message): return message @@ -108,7 +108,7 @@ extension NewsBlurAPICaller { return } - let request = URLRequest(url: callURL, credentials: credentials) + let request = createURLRequest(callURL, credentials) transport.send(request: request) { result in if self.suspended { @@ -138,7 +138,7 @@ extension NewsBlurAPICaller { return } - let request = URLRequest(url: callURL, credentials: credentials) + let request = createURLRequest(callURL, credentials) transport.send( request: request, @@ -171,7 +171,7 @@ extension NewsBlurAPICaller { return } - var request = URLRequest(url: callURL, credentials: credentials) + var request = createURLRequest(callURL, credentials) request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: HTTPRequestHeader.contentType) request.httpBody = payload.asData @@ -209,7 +209,7 @@ extension NewsBlurAPICaller { return } - var request = URLRequest(url: callURL, credentials: credentials) + var request = createURLRequest(callURL, credentials) request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: HTTPRequestHeader.contentType) transport.send( diff --git a/Account/Sources/Account/NewsBlur/NewsBlurAPICaller.swift b/SyncClients/NewsBlur/Sources/NewsBlur/NewsBlurAPICaller.swift similarity index 74% rename from Account/Sources/Account/NewsBlur/NewsBlurAPICaller.swift rename to SyncClients/NewsBlur/Sources/NewsBlur/NewsBlurAPICaller.swift index 58849c6cd..ceb103555 100644 --- a/Account/Sources/Account/NewsBlur/NewsBlurAPICaller.swift +++ b/SyncClients/NewsBlur/Sources/NewsBlur/NewsBlurAPICaller.swift @@ -10,32 +10,32 @@ import Foundation import RSWeb import Secrets -final class NewsBlurAPICaller: NSObject { - static let SessionIdCookie = "newsblur_sessionid" +public final class NewsBlurAPICaller { + public static let SessionIdCookie = "newsblur_sessionid" let baseURL = URL(string: "https://www.newsblur.com/")! var transport: Transport! + let createURLRequest: ((URL, Credentials?) -> URLRequest) var suspended = false - var credentials: Credentials? - weak var accountMetadata: AccountMetadata? + public var credentials: Credentials? - init(transport: Transport!) { - super.init() + public init(transport: Transport!, createURLRequest: @escaping (URL, Credentials?) -> URLRequest) { self.transport = transport + self.createURLRequest = createURLRequest } /// Cancels all pending requests rejects any that come in later - func suspend() { + public func suspend() { transport.cancelAll() suspended = true } - func resume() { + public func resume() { suspended = false } - func validateCredentials(completion: @escaping (Result) -> Void) { + public func validateCredentials(completion: @escaping (Result) -> Void) { requestData(endpoint: "api/login", resultType: NewsBlurLoginResponse.self) { result in switch result { case .success((let response, let payload)): @@ -68,11 +68,11 @@ final class NewsBlurAPICaller: NSObject { } } - func logout(completion: @escaping (Result) -> Void) { + public func logout(completion: @escaping (Result) -> Void) { requestData(endpoint: "api/logout", completion: completion) } - func retrieveFeeds(completion: @escaping (Result<([NewsBlurFeed]?, [NewsBlurFolder]?), Error>) -> Void) { + public func retrieveFeeds(completion: @escaping (Result<([NewsBlurFeed]?, [NewsBlurFolder]?), Error>) -> Void) { let url = baseURL .appendingPathComponent("reader/feeds") .appendingQueryItems([ @@ -112,21 +112,21 @@ final class NewsBlurAPICaller: NSObject { } } - func retrieveUnreadStoryHashes(completion: @escaping (Result<[NewsBlurStoryHash]?, Error>) -> Void) { + public func retrieveUnreadStoryHashes(completion: @escaping (Result<[NewsBlurStoryHash]?, Error>) -> Void) { retrieveStoryHashes( endpoint: "reader/unread_story_hashes", completion: completion ) } - func retrieveStarredStoryHashes(completion: @escaping (Result<[NewsBlurStoryHash]?, Error>) -> Void) { + public func retrieveStarredStoryHashes(completion: @escaping (Result<[NewsBlurStoryHash]?, Error>) -> Void) { retrieveStoryHashes( endpoint: "reader/starred_story_hashes", completion: completion ) } - func retrieveStories(feedID: String, page: Int, completion: @escaping (Result<([NewsBlurStory]?, Date?), Error>) -> Void) { + public func retrieveStories(feedID: String, page: Int, completion: @escaping (Result<([NewsBlurStory]?, Date?), Error>) -> Void) { let url = baseURL .appendingPathComponent("reader/feed/\(feedID)") .appendingQueryItems([ @@ -147,7 +147,7 @@ final class NewsBlurAPICaller: NSObject { } } - func retrieveStories(hashes: [NewsBlurStoryHash], completion: @escaping (Result<([NewsBlurStory]?, Date?), Error>) -> Void) { + public func retrieveStories(hashes: [NewsBlurStoryHash], completion: @escaping (Result<([NewsBlurStory]?, Date?), Error>) -> Void) { let url = baseURL .appendingPathComponent("reader/river_stories") .appendingQueryItem(.init(name: "include_hidden", value: "false"))? @@ -165,7 +165,7 @@ final class NewsBlurAPICaller: NSObject { } } - func markAsUnread(hashes: [String], completion: @escaping (Result) -> Void) { + public func markAsUnread(hashes: [String], completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/mark_story_hash_as_unread", payload: NewsBlurStoryStatusChange(hashes: hashes), @@ -173,7 +173,7 @@ final class NewsBlurAPICaller: NSObject { ) } - func markAsRead(hashes: [String], completion: @escaping (Result) -> Void) { + public func markAsRead(hashes: [String], completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/mark_story_hashes_as_read", payload: NewsBlurStoryStatusChange(hashes: hashes), @@ -181,7 +181,7 @@ final class NewsBlurAPICaller: NSObject { ) } - func star(hashes: [String], completion: @escaping (Result) -> Void) { + public func star(hashes: [String], completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/mark_story_hash_as_starred", payload: NewsBlurStoryStatusChange(hashes: hashes), @@ -189,7 +189,7 @@ final class NewsBlurAPICaller: NSObject { ) } - func unstar(hashes: [String], completion: @escaping (Result) -> Void) { + public func unstar(hashes: [String], completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/mark_story_hash_as_unstarred", payload: NewsBlurStoryStatusChange(hashes: hashes), @@ -197,7 +197,7 @@ final class NewsBlurAPICaller: NSObject { ) } - func addFolder(named name: String, completion: @escaping (Result) -> Void) { + public func addFolder(named name: String, completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/add_folder", payload: NewsBlurFolderChange.add(name), @@ -205,7 +205,7 @@ final class NewsBlurAPICaller: NSObject { ) } - func renameFolder(with folder: String, to name: String, completion: @escaping (Result) -> Void) { + public func renameFolder(with folder: String, to name: String, completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/rename_folder", payload: NewsBlurFolderChange.rename(folder, name), @@ -213,7 +213,7 @@ final class NewsBlurAPICaller: NSObject { ) } - func removeFolder(named name: String, feedIDs: [String], completion: @escaping (Result) -> Void) { + public func removeFolder(named name: String, feedIDs: [String], completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/delete_folder", payload: NewsBlurFolderChange.delete(name, feedIDs), @@ -221,7 +221,7 @@ final class NewsBlurAPICaller: NSObject { ) } - func addURL(_ url: String, folder: String?, completion: @escaping (Result) -> Void) { + public func addURL(_ url: String, folder: String?, completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/add_url", payload: NewsBlurFeedChange.add(url, folder), @@ -236,7 +236,7 @@ final class NewsBlurAPICaller: NSObject { } } - func renameFeed(feedID: String, newName: String, completion: @escaping (Result) -> Void) { + public func renameFeed(feedID: String, newName: String, completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/rename_feed", payload: NewsBlurFeedChange.rename(feedID, newName) @@ -250,7 +250,7 @@ final class NewsBlurAPICaller: NSObject { } } - func deleteFeed(feedID: String, folder: String? = nil, completion: @escaping (Result) -> Void) { + public func deleteFeed(feedID: String, folder: String? = nil, completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/delete_feed", payload: NewsBlurFeedChange.delete(feedID, folder) @@ -264,7 +264,7 @@ final class NewsBlurAPICaller: NSObject { } } - func moveFeed(feedID: String, from: String?, to: String?, completion: @escaping (Result) -> Void) { + public func moveFeed(feedID: String, from: String?, to: String?, completion: @escaping (Result) -> Void) { sendUpdates( endpoint: "reader/move_feed_to_folder", payload: NewsBlurFeedChange.move(feedID, from, to) diff --git a/SyncClients/NewsBlur/Tests/NewsBlurTests/NewsBlurTests.swift b/SyncClients/NewsBlur/Tests/NewsBlurTests/NewsBlurTests.swift new file mode 100644 index 000000000..84cd6e935 --- /dev/null +++ b/SyncClients/NewsBlur/Tests/NewsBlurTests/NewsBlurTests.swift @@ -0,0 +1,11 @@ +import XCTest +@testable import NewsBlur + +final class NewsBlurTests: XCTestCase { + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + XCTAssertEqual(NewsBlur().text, "Hello, World!") + } +}