mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-02-03 12:27:32 +01:00
Add basic get support for a hardcoded URL
This commit is contained in:
parent
78f72264fd
commit
10b24d92c5
@ -44,6 +44,7 @@
|
||||
513323082281070D00C30F19 /* AccountFeedbinSyncTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513323072281070C00C30F19 /* AccountFeedbinSyncTest.swift */; };
|
||||
5133230A2281082F00C30F19 /* subscriptions_initial.json in Resources */ = {isa = PBXBuildFile; fileRef = 513323092281082F00C30F19 /* subscriptions_initial.json */; };
|
||||
5133230C2281088A00C30F19 /* subscriptions_add.json in Resources */ = {isa = PBXBuildFile; fileRef = 5133230B2281088A00C30F19 /* subscriptions_add.json */; };
|
||||
5133BB47245FD8140001E3D0 /* RedditListing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5133BB46245FD8140001E3D0 /* RedditListing.swift */; };
|
||||
5139A6382459822D004D960C /* CloudKitArticleStatusUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5139A6372459822D004D960C /* CloudKitArticleStatusUpdate.swift */; };
|
||||
5144EA49227B497600D19003 /* FeedbinAPICaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5144EA48227B497600D19003 /* FeedbinAPICaller.swift */; };
|
||||
5144EA4E227B829A00D19003 /* FeedbinAccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5144EA4D227B829A00D19003 /* FeedbinAccountDelegate.swift */; };
|
||||
@ -300,6 +301,7 @@
|
||||
513323072281070C00C30F19 /* AccountFeedbinSyncTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountFeedbinSyncTest.swift; sourceTree = "<group>"; };
|
||||
513323092281082F00C30F19 /* subscriptions_initial.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = subscriptions_initial.json; sourceTree = "<group>"; };
|
||||
5133230B2281088A00C30F19 /* subscriptions_add.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = subscriptions_add.json; sourceTree = "<group>"; };
|
||||
5133BB46245FD8140001E3D0 /* RedditListing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedditListing.swift; sourceTree = "<group>"; };
|
||||
5139A6372459822D004D960C /* CloudKitArticleStatusUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitArticleStatusUpdate.swift; sourceTree = "<group>"; };
|
||||
5144EA48227B497600D19003 /* FeedbinAPICaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinAPICaller.swift; sourceTree = "<group>"; };
|
||||
5144EA4D227B829A00D19003 /* FeedbinAccountDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinAccountDelegate.swift; sourceTree = "<group>"; };
|
||||
@ -633,6 +635,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5193CD53245E3F7A0092735E /* RedditFeedProvider.swift */,
|
||||
5133BB46245FD8140001E3D0 /* RedditListing.swift */,
|
||||
5193CD80245F295E0092735E /* RedditUser.swift */,
|
||||
);
|
||||
path = Reddit;
|
||||
@ -1204,6 +1207,7 @@
|
||||
51F6C593245DBA8E001E41CA /* CloudKitRemoteNotificationOperation.swift in Sources */,
|
||||
846E77541F6F00E300A165E2 /* AccountManager.swift in Sources */,
|
||||
51E490362288C37100C791F0 /* FeedbinDate.swift in Sources */,
|
||||
5133BB47245FD8140001E3D0 /* RedditListing.swift in Sources */,
|
||||
9EEAE06E235D002D00E3FEE4 /* FeedlyGetCollectionsService.swift in Sources */,
|
||||
5165D72922835F7A00D9D53D /* FeedSpecifier.swift in Sources */,
|
||||
9E85C8ED2367020700D0F1F7 /* FeedlyGetEntriesService.swift in Sources */,
|
||||
|
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os.log
|
||||
import OAuthSwift
|
||||
import Secrets
|
||||
import RSParser
|
||||
@ -18,12 +19,14 @@ public enum RedditFeedProviderError: LocalizedError {
|
||||
public var localizedDescription: String {
|
||||
switch self {
|
||||
case .unknown:
|
||||
return NSLocalizedString("An Reddit Twitter Feed Provider error has occurred.", comment: "Unknown error")
|
||||
return NSLocalizedString("A Reddit Feed Provider error has occurred.", comment: "Unknown error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct RedditFeedProvider: FeedProvider {
|
||||
public final class RedditFeedProvider: FeedProvider {
|
||||
|
||||
var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "RedditFeedProvider")
|
||||
|
||||
private static let server = "www.reddit.com"
|
||||
private static let apiBase = "https://oauth.reddit.com"
|
||||
@ -42,7 +45,7 @@ public struct RedditFeedProvider: FeedProvider {
|
||||
return oauthSwift?.client
|
||||
}
|
||||
|
||||
public init?(username: String) {
|
||||
public convenience init?(username: String) {
|
||||
guard let tokenCredentials = try? CredentialsManager.retrieveCredentials(type: .oauthAccessToken, server: Self.server, username: username),
|
||||
let refreshTokenCredentials = try? CredentialsManager.retrieveCredentials(type: .oauthRefreshToken, server: Self.server, username: username) else {
|
||||
return nil
|
||||
@ -77,25 +80,20 @@ public struct RedditFeedProvider: FeedProvider {
|
||||
}
|
||||
|
||||
public func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void) {
|
||||
completion(.failure(TwitterFeedProviderError.screenNameNotFound))
|
||||
completion(.failure(RedditFeedProviderError.unknown))
|
||||
}
|
||||
|
||||
public func assignName(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void) {
|
||||
let path = urlComponents.path
|
||||
|
||||
switch path {
|
||||
case "", "/":
|
||||
|
||||
if path == "" || path == "/" {
|
||||
let name = NSLocalizedString("Reddit Timeline", comment: "Reddit Timeline")
|
||||
completion(.success(name))
|
||||
case "/r", "/u":
|
||||
let path = String(path.suffix(from: path.index(path.startIndex, offsetBy: 2)))
|
||||
completion(.success(path))
|
||||
case "/user":
|
||||
let path = String(path.suffix(from: path.index(path.startIndex, offsetBy: 5)))
|
||||
completion(.success(path))
|
||||
default:
|
||||
completion(.failure(TwitterFeedProviderError.unknown))
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: call to get the Subreddit name
|
||||
completion(.success(path))
|
||||
}
|
||||
|
||||
public func refresh(_ webFeed: WebFeed, completion: @escaping (Result<Set<ParsedItem>, Error>) -> Void) {
|
||||
@ -103,26 +101,25 @@ public struct RedditFeedProvider: FeedProvider {
|
||||
// completion(.failure(TwitterFeedProviderError.unknown))
|
||||
// return
|
||||
// }
|
||||
let api = "/r/sphynx/hot.json"
|
||||
retrieveListing(api: api, parameters: [:]) { result in
|
||||
completion(.success(Set<ParsedItem>()))
|
||||
}
|
||||
|
||||
completion(.success(Set<ParsedItem>()))
|
||||
}
|
||||
|
||||
public static func create(tokenSuccess: OAuthSwift.TokenSuccess, completion: @escaping (Result<RedditFeedProvider, Error>) -> Void) {
|
||||
let oauthToken = tokenSuccess.credential.oauthToken
|
||||
let oauthRefreshToken = tokenSuccess.credential.oauthRefreshToken
|
||||
var redditFeedProvider = RedditFeedProvider(oauthToken: oauthToken, oauthRefreshToken: oauthRefreshToken)
|
||||
let redditFeedProvider = RedditFeedProvider(oauthToken: oauthToken, oauthRefreshToken: oauthRefreshToken)
|
||||
|
||||
redditFeedProvider.retrieveUserName() { result in
|
||||
switch result {
|
||||
case .success(let username):
|
||||
|
||||
do {
|
||||
let tokenCredentials = Credentials(type: .oauthAccessToken, username: username, secret: oauthToken)
|
||||
try CredentialsManager.storeCredentials(tokenCredentials, server: Self.server)
|
||||
let tokenSecretCredentials = Credentials(type: .oauthRefreshToken, username: username, secret: oauthRefreshToken)
|
||||
try CredentialsManager.storeCredentials(tokenSecretCredentials, server: Self.server)
|
||||
|
||||
redditFeedProvider.username = username
|
||||
try storeCredentials(username: username, oauthToken: oauthToken, oauthRefreshToken: oauthRefreshToken)
|
||||
completion(.success(redditFeedProvider))
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
@ -157,7 +154,7 @@ extension RedditFeedProvider: OAuth2SwiftProvider {
|
||||
|
||||
public static var oauth2Vars: (state: String, scope: String, params: [String : String]) {
|
||||
let state = generateState(withLength: 20)
|
||||
let scope = "identity mysubreddits"
|
||||
let scope = "identity mysubreddits read"
|
||||
let params = [
|
||||
"client_id" : Secrets.redditConsumerKey,
|
||||
"response_type" : "code",
|
||||
@ -192,5 +189,125 @@ private extension RedditFeedProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func retrieveListing(api: String, parameters: [String: Any], completion: @escaping (Result<RedditListing, Error>) -> Void) {
|
||||
guard let client = client else {
|
||||
completion(.failure(RedditFeedProviderError.unknown))
|
||||
return
|
||||
}
|
||||
|
||||
let url = "\(Self.apiBase)\(api)"
|
||||
|
||||
client.get(url, parameters: parameters, headers: Self.userAgentHeaders) { result in
|
||||
switch result {
|
||||
case .success(let response):
|
||||
|
||||
let jsonString = String(data: response.data, encoding: .utf8)
|
||||
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("reddit.json")
|
||||
print("******** writing to: \(url.path)")
|
||||
try? jsonString?.write(toFile: url.path, atomically: true, encoding: .utf8)
|
||||
|
||||
// let decoder = JSONDecoder()
|
||||
// let dateFormatter = DateFormatter()
|
||||
// dateFormatter.dateFormat = Self.dateFormat
|
||||
// decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
||||
|
||||
// do {
|
||||
// let listing = try decoder.decode(RedditListing.self, from: response.data)
|
||||
// completion(.success(listing))
|
||||
// } catch {
|
||||
// completion(.failure(error))
|
||||
// }
|
||||
|
||||
let listing = RedditListing(name: "")
|
||||
completion(.success(listing))
|
||||
|
||||
case .failure(let oathError):
|
||||
self.handleFailure(error: oathError) { error in
|
||||
if let error = error {
|
||||
completion(.failure(error))
|
||||
} else {
|
||||
self.retrieveListing(api: api, parameters: parameters, completion: completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// func makeParsedItems(_ webFeedURL: String, _ statuses: [TwitterStatus]) -> Set<ParsedItem> {
|
||||
// var parsedItems = Set<ParsedItem>()
|
||||
//
|
||||
// for status in statuses {
|
||||
// guard let idStr = status.idStr, let statusURL = status.url else { continue }
|
||||
//
|
||||
// let parsedItem = ParsedItem(syncServiceID: nil,
|
||||
// uniqueID: idStr,
|
||||
// feedURL: webFeedURL,
|
||||
// url: statusURL,
|
||||
// externalURL: nil,
|
||||
// title: nil,
|
||||
// language: nil,
|
||||
// contentHTML: status.renderAsHTML(),
|
||||
// contentText: status.renderAsText(),
|
||||
// summary: nil,
|
||||
// imageURL: nil,
|
||||
// bannerImageURL: nil,
|
||||
// datePublished: status.createdAt,
|
||||
// dateModified: nil,
|
||||
// authors: makeParsedAuthors(status.user),
|
||||
// tags: nil,
|
||||
// attachments: nil)
|
||||
// parsedItems.insert(parsedItem)
|
||||
// }
|
||||
//
|
||||
// return parsedItems
|
||||
// }
|
||||
//
|
||||
// func makeUserURL(_ screenName: String) -> String {
|
||||
// return "https://twitter.com/\(screenName)"
|
||||
// }
|
||||
//
|
||||
// func makeParsedAuthors(_ user: TwitterUser?) -> Set<ParsedAuthor>? {
|
||||
// guard let user = user else { return nil }
|
||||
// return Set([ParsedAuthor(name: user.name, url: user.url, avatarURL: user.avatarURL, emailAddress: nil)])
|
||||
// }
|
||||
|
||||
func handleFailure(error: OAuthSwiftError, completion: @escaping (Error?) -> Void) {
|
||||
if case .tokenExpired = error {
|
||||
os_log(.debug, log: self.log, "Access token expired, attempting to renew...")
|
||||
|
||||
oauthSwift?.renewAccessToken(withRefreshToken: oauthRefreshToken) { [weak self] result in
|
||||
guard let self = self, let username = self.username else {
|
||||
completion(nil)
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let tokenSuccess):
|
||||
self.oauthToken = tokenSuccess.credential.oauthToken
|
||||
self.oauthRefreshToken = tokenSuccess.credential.oauthRefreshToken
|
||||
do {
|
||||
try Self.storeCredentials(username: username, oauthToken: self.oauthToken, oauthRefreshToken: self.oauthRefreshToken)
|
||||
os_log(.debug, log: self.log, "Access token renewed.")
|
||||
} catch {
|
||||
completion(error)
|
||||
return
|
||||
}
|
||||
completion(nil)
|
||||
case .failure(let oathError):
|
||||
completion(oathError)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
completion(error)
|
||||
}
|
||||
}
|
||||
|
||||
static func storeCredentials(username: String, oauthToken: String, oauthRefreshToken: String) throws {
|
||||
let tokenCredentials = Credentials(type: .oauthAccessToken, username: username, secret: oauthToken)
|
||||
try CredentialsManager.storeCredentials(tokenCredentials, server: Self.server)
|
||||
let tokenSecretCredentials = Credentials(type: .oauthRefreshToken, username: username, secret: oauthRefreshToken)
|
||||
try CredentialsManager.storeCredentials(tokenSecretCredentials, server: Self.server)
|
||||
}
|
||||
}
|
||||
|
19
Frameworks/Account/FeedProvider/Reddit/RedditListing.swift
Normal file
19
Frameworks/Account/FeedProvider/Reddit/RedditListing.swift
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// RedditListing.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Maurice Parker on 5/3/20.
|
||||
// Copyright © 2020 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct RedditListing: Codable {
|
||||
|
||||
let name: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case name = "name"
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user