Merge pull request #3227 from dave-atx/greader
ReaderAPI Account Changes
This commit is contained in:
commit
185b4cd28e
|
@ -473,10 +473,23 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
||||||
if from is Account {
|
if from is Account {
|
||||||
addWebFeed(for: account, with: feed, to: to, completion: completion)
|
addWebFeed(for: account, with: feed, to: to, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
deleteTagging(for: account, with: feed, from: from) { result in
|
guard
|
||||||
|
let subscriptionId = feed.externalID,
|
||||||
|
let fromTag = (from as? Folder)?.name,
|
||||||
|
let toTag = (to as? Folder)?.name
|
||||||
|
else {
|
||||||
|
completion(.failure(ReaderAPIAccountDelegateError.invalidParameter))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
|
caller.moveSubscription(subscriptionID: subscriptionId, fromTag: fromTag, toTag: toTag) { result in
|
||||||
|
self.refreshProgress.completeTask()
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
self.addWebFeed(for: account, with: feed, to: to, completion: completion)
|
from.removeWebFeed(feed)
|
||||||
|
to.addWebFeed(feed)
|
||||||
|
completion(.success(()))
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
@ -1008,8 +1021,13 @@ private extension ReaderAPIAccountDelegate {
|
||||||
guard let streamID = entry.origin.streamId else {
|
guard let streamID = entry.origin.streamId else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// let authors = Set([ParsedAuthor(name: entry.authorName, url: entry.jsonFeed?.jsonFeedAuthor?.url, avatarURL: entry.jsonFeed?.jsonFeedAuthor?.avatarURL, emailAddress: nil)])
|
|
||||||
// let feed = account.idToFeedDictionary[entry.origin.streamId!]! // TODO clean this up
|
var authors: Set<ParsedAuthor>? {
|
||||||
|
guard let name = entry.author else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return Set([ParsedAuthor(name: name, url: nil, avatarURL: nil, emailAddress: nil)])
|
||||||
|
}
|
||||||
|
|
||||||
return ParsedItem(syncServiceID: entry.uniqueID(variant: variant),
|
return ParsedItem(syncServiceID: entry.uniqueID(variant: variant),
|
||||||
uniqueID: entry.uniqueID(variant: variant),
|
uniqueID: entry.uniqueID(variant: variant),
|
||||||
|
@ -1025,7 +1043,7 @@ private extension ReaderAPIAccountDelegate {
|
||||||
bannerImageURL: nil,
|
bannerImageURL: nil,
|
||||||
datePublished: entry.parseDatePublished(),
|
datePublished: entry.parseDatePublished(),
|
||||||
dateModified: nil,
|
dateModified: nil,
|
||||||
authors: nil,
|
authors: authors,
|
||||||
tags: nil,
|
tags: nil,
|
||||||
attachments: nil)
|
attachments: nil)
|
||||||
}
|
}
|
||||||
|
@ -1132,32 +1150,4 @@ private extension ReaderAPIAccountDelegate {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteTagging(for account: Account, with feed: WebFeed, from container: Container?, completion: @escaping (Result<Void, Error>) -> Void) {
|
|
||||||
|
|
||||||
if let folder = container as? Folder, let feedName = feed.externalID {
|
|
||||||
caller.deleteTagging(subscriptionID: feedName, tagName: folder.name ?? "") { result in
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.clearFolderRelationship(for: feed, folderExternalID: folder.externalID)
|
|
||||||
folder.removeWebFeed(feed)
|
|
||||||
account.addFeedIfNotInAnyFolder(feed)
|
|
||||||
completion(.success(()))
|
|
||||||
}
|
|
||||||
case .failure(let error):
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
let wrappedError = AccountError.wrappedError(error: error, account: account)
|
|
||||||
completion(.failure(wrappedError))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let account = container as? Account {
|
|
||||||
account.removeWebFeed(feed)
|
|
||||||
}
|
|
||||||
completion(.success(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,21 +358,19 @@ final class ReaderAPICaller: NSObject {
|
||||||
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let token):
|
case .success(let token):
|
||||||
let url = baseURL
|
let callURL = baseURL
|
||||||
.appendingPathComponent(ReaderAPIEndpoints.subscriptionAdd.rawValue)
|
.appendingPathComponent(ReaderAPIEndpoints.subscriptionAdd.rawValue)
|
||||||
.appendingQueryItem(URLQueryItem(name: "quickadd", value: url))
|
|
||||||
|
|
||||||
guard let callURL = url else {
|
|
||||||
completion(.failure(TransportError.noURL))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var request = URLRequest(url: callURL, credentials: self.credentials)
|
var request = URLRequest(url: callURL, credentials: self.credentials)
|
||||||
self.addVariantHeaders(&request)
|
self.addVariantHeaders(&request)
|
||||||
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
||||||
request.httpMethod = "POST"
|
request.httpMethod = "POST"
|
||||||
|
|
||||||
let postData = "T=\(token)".data(using: String.Encoding.utf8)
|
guard let encodedFeedURL = self.encodeForURLPath(url) else {
|
||||||
|
completion(.failure(ReaderAPIAccountDelegateError.invalidParameter))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let postData = "T=\(token)&quickadd=\(encodedFeedURL)".data(using: String.Encoding.utf8)
|
||||||
|
|
||||||
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIQuickAddResult.self, completion: { (result) in
|
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIQuickAddResult.self, completion: { (result) in
|
||||||
switch result {
|
switch result {
|
||||||
|
@ -387,34 +385,7 @@ final class ReaderAPICaller: NSObject {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == nil && folder == nil {
|
|
||||||
findSubscription(streamID: streamId, completion: completion)
|
findSubscription(streamID: streamId, completion: completion)
|
||||||
} else {
|
|
||||||
let callURL = baseURL.appendingPathComponent(ReaderAPIEndpoints.subscriptionEdit.rawValue)
|
|
||||||
var request = URLRequest(url: callURL, credentials: self.credentials)
|
|
||||||
self.addVariantHeaders(&request)
|
|
||||||
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
|
||||||
request.httpMethod = "POST"
|
|
||||||
|
|
||||||
var postString = "T=\(token)&ac=subscribe&s=\(streamId)"
|
|
||||||
if let folderName = self.encodeForURLPath(folder?.nameForDisplay) {
|
|
||||||
postString += "&a=user/-/label/\(folderName)"
|
|
||||||
}
|
|
||||||
if let name = self.encodeForURLPath(name) {
|
|
||||||
postString += "&t=\(name)"
|
|
||||||
}
|
|
||||||
|
|
||||||
let postData = postString.data(using: String.Encoding.utf8)
|
|
||||||
self.transport.send(request: request, method: HTTPMethod.post, payload: postData!, completion: { (result) in
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
findSubscription(streamID: streamId, completion: completion)
|
|
||||||
case .failure:
|
|
||||||
completion(.failure(AccountError.createErrorAlreadySubscribed))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
@ -432,42 +403,7 @@ final class ReaderAPICaller: NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func renameSubscription(subscriptionID: String, newName: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
func renameSubscription(subscriptionID: String, newName: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
guard let baseURL = apiBaseURL else {
|
changeSubscription(subscriptionID: subscriptionID, title: newName, completion: completion)
|
||||||
completion(.failure(CredentialsError.incompleteCredentials))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
|
||||||
switch result {
|
|
||||||
case .success(let token):
|
|
||||||
var request = URLRequest(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.subscriptionEdit.rawValue), credentials: self.credentials)
|
|
||||||
self.addVariantHeaders(&request)
|
|
||||||
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
|
||||||
request.httpMethod = "POST"
|
|
||||||
|
|
||||||
guard let encodedNewName = self.encodeForURLPath(newName) else {
|
|
||||||
completion(.failure(ReaderAPIAccountDelegateError.invalidParameter))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let postData = "T=\(token)&s=\(subscriptionID)&ac=edit&t=\(encodedNewName)".data(using: String.Encoding.utf8)
|
|
||||||
|
|
||||||
self.transport.send(request: request, method: HTTPMethod.post, payload: postData!, completion: { (result) in
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
completion(.success(()))
|
|
||||||
break
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteSubscription(subscriptionID: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
func deleteSubscription(subscriptionID: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
@ -504,46 +440,23 @@ final class ReaderAPICaller: NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTagging(subscriptionID: String, tagName: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
func createTagging(subscriptionID: String, tagName: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
changeSubscription(subscriptionID: subscriptionID, addTagName: tagName, completion: completion)
|
||||||
guard let baseURL = apiBaseURL else {
|
|
||||||
completion(.failure(CredentialsError.incompleteCredentials))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
func deleteTagging(subscriptionID: String, tagName: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
switch result {
|
changeSubscription(subscriptionID: subscriptionID, removeTagName: tagName, completion: completion)
|
||||||
case .success(let token):
|
}
|
||||||
var request = URLRequest(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.subscriptionEdit.rawValue), credentials: self.credentials)
|
|
||||||
self.addVariantHeaders(&request)
|
|
||||||
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
|
||||||
request.httpMethod = "POST"
|
|
||||||
|
|
||||||
guard let tagName = self.encodeForURLPath(tagName) else {
|
func moveSubscription(subscriptionID: String, fromTag: String, toTag: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
changeSubscription(subscriptionID: subscriptionID, removeTagName: fromTag, addTagName: toTag, completion: completion)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func changeSubscription(subscriptionID: String, removeTagName: String? = nil, addTagName: String? = nil, title: String? = nil, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
guard removeTagName != nil || addTagName != nil || title != nil else {
|
||||||
completion(.failure(ReaderAPIAccountDelegateError.invalidParameter))
|
completion(.failure(ReaderAPIAccountDelegateError.invalidParameter))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let postData = "T=\(token)&s=\(subscriptionID)&ac=edit&a=user/-/label/\(tagName)".data(using: String.Encoding.utf8)
|
|
||||||
|
|
||||||
self.transport.send(request: request, method: HTTPMethod.post, payload: postData!, completion: { (result) in
|
|
||||||
switch result {
|
|
||||||
case .success:
|
|
||||||
completion(.success(()))
|
|
||||||
break
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteTagging(subscriptionID: String, tagName: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
|
||||||
guard let baseURL = apiBaseURL else {
|
guard let baseURL = apiBaseURL else {
|
||||||
completion(.failure(CredentialsError.incompleteCredentials))
|
completion(.failure(CredentialsError.incompleteCredentials))
|
||||||
return
|
return
|
||||||
|
@ -557,8 +470,17 @@ final class ReaderAPICaller: NSObject {
|
||||||
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
||||||
request.httpMethod = "POST"
|
request.httpMethod = "POST"
|
||||||
|
|
||||||
let tagName = "user/-/label/\(tagName)"
|
var postString = "T=\(token)&s=\(subscriptionID)&ac=edit"
|
||||||
let postData = "T=\(token)&s=\(subscriptionID)&ac=edit&r=\(tagName)".data(using: String.Encoding.utf8)
|
if let fromLabel = self.encodeForURLPath(removeTagName) {
|
||||||
|
postString += "&r=user/-/label/\(fromLabel)"
|
||||||
|
}
|
||||||
|
if let toLabel = self.encodeForURLPath(addTagName) {
|
||||||
|
postString += "&a=user/-/label/\(toLabel)"
|
||||||
|
}
|
||||||
|
if let encodedTitle = self.encodeForURLPath(title) {
|
||||||
|
postString += "&t=\(encodedTitle)"
|
||||||
|
}
|
||||||
|
let postData = postString.data(using: String.Encoding.utf8)
|
||||||
|
|
||||||
self.transport.send(request: request, method: HTTPMethod.post, payload: postData!, completion: { (result) in
|
self.transport.send(request: request, method: HTTPMethod.post, payload: postData!, completion: { (result) in
|
||||||
switch result {
|
switch result {
|
||||||
|
|
|
@ -51,6 +51,7 @@ struct ReaderAPIEntry: Codable {
|
||||||
|
|
||||||
let articleID: String
|
let articleID: String
|
||||||
let title: String?
|
let title: String?
|
||||||
|
let author: String?
|
||||||
|
|
||||||
let publishedTimestamp: Double?
|
let publishedTimestamp: Double?
|
||||||
let crawledTimestamp: String?
|
let crawledTimestamp: String?
|
||||||
|
@ -64,6 +65,7 @@ struct ReaderAPIEntry: Codable {
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case articleID = "id"
|
case articleID = "id"
|
||||||
case title = "title"
|
case title = "title"
|
||||||
|
case author = "author"
|
||||||
case summary = "summary"
|
case summary = "summary"
|
||||||
case alternates = "alternate"
|
case alternates = "alternate"
|
||||||
case categories = "categories"
|
case categories = "categories"
|
||||||
|
|
Loading…
Reference in New Issue