mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2024-12-18 12:28:37 +01:00
Add web feed icon downloader support for Feed Providers.
This commit is contained in:
parent
ca28faa8b5
commit
c44759fdb2
@ -11,9 +11,15 @@ import Secrets
|
||||
import OAuthSwift
|
||||
import RSParser
|
||||
|
||||
// TODO: Beef up error handling...
|
||||
public enum TwitterFeedProviderError: Error {
|
||||
case unknown
|
||||
}
|
||||
|
||||
public struct TwitterFeedProvider: FeedProvider {
|
||||
|
||||
private static let server = "api.twitter.com"
|
||||
private static let apiBase = "https://api.twitter.com/1.1/"
|
||||
|
||||
public var userID: String
|
||||
public var screenName: String
|
||||
@ -21,6 +27,8 @@ public struct TwitterFeedProvider: FeedProvider {
|
||||
private var oauthToken: String
|
||||
private var oauthTokenSecret: String
|
||||
|
||||
private var client: OAuthSwiftClient
|
||||
|
||||
public init?(tokenSuccess: OAuthSwift.TokenSuccess) {
|
||||
guard let userID = tokenSuccess.parameters["user_id"] as? String,
|
||||
let screenName = tokenSuccess.parameters["screen_name"] as? String else {
|
||||
@ -37,6 +45,12 @@ public struct TwitterFeedProvider: FeedProvider {
|
||||
|
||||
let tokenSecretCredentials = Credentials(type: .oauthAccessTokenSecret, username: userID, secret: oauthTokenSecret)
|
||||
try? CredentialsManager.storeCredentials(tokenSecretCredentials, server: Self.server)
|
||||
|
||||
client = OAuthSwiftClient(consumerKey: Secrets.twitterConsumerKey,
|
||||
consumerSecret: Secrets.twitterConsumerSecret,
|
||||
oauthToken: oauthToken,
|
||||
oauthTokenSecret: oauthTokenSecret,
|
||||
version: .oauth1)
|
||||
}
|
||||
|
||||
public init?(userID: String, screenName: String) {
|
||||
@ -50,6 +64,12 @@ public struct TwitterFeedProvider: FeedProvider {
|
||||
|
||||
self.oauthToken = tokenCredentials.secret
|
||||
self.oauthTokenSecret = tokenSecretCredentials.secret
|
||||
|
||||
client = OAuthSwiftClient(consumerKey: Secrets.twitterConsumerKey,
|
||||
consumerSecret: Secrets.twitterConsumerSecret,
|
||||
oauthToken: oauthToken,
|
||||
oauthTokenSecret: oauthTokenSecret,
|
||||
version: .oauth1)
|
||||
}
|
||||
|
||||
public func ability(_ urlComponents: URLComponents, forUsername username: String?) -> FeedProviderAbility {
|
||||
@ -65,7 +85,8 @@ public struct TwitterFeedProvider: FeedProvider {
|
||||
}
|
||||
|
||||
public func iconURL(_ url: URLComponents, completion: @escaping (Result<String, Error>) -> Void) {
|
||||
// TODO: Finish implementation
|
||||
let screenName = extractScreenName(url)
|
||||
fetchIconURL(screenName: screenName, completion: completion)
|
||||
}
|
||||
|
||||
public func provide(_ url: URLComponents, completion: @escaping (Result<ParsedFeed, Error>) -> Void) {
|
||||
@ -93,3 +114,39 @@ extension TwitterFeedProvider: OAuth1SwiftProvider {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private extension TwitterFeedProvider {
|
||||
|
||||
// TODO: Full parsing routine
|
||||
func extractScreenName(_ urlComponents: URLComponents) -> String {
|
||||
let path = urlComponents.path
|
||||
if let index = path.firstIndex(of: "?") {
|
||||
let range = path.index(path.startIndex, offsetBy: 1)...index
|
||||
return String(path[range])
|
||||
} else {
|
||||
return String(path.suffix(from: path.index(path.startIndex, offsetBy: 1)))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Update to retrieve the full user
|
||||
func fetchIconURL(screenName: String, completion: @escaping (Result<String, Error>) -> Void) {
|
||||
let url = "\(Self.apiBase)users/show.json"
|
||||
let parameters = ["screen_name": screenName]
|
||||
|
||||
client.get(url, parameters: parameters) { result in
|
||||
switch result {
|
||||
case .success(let response):
|
||||
if let json = try? response.jsonObject() as? [String: Any], let url = json["profile_image_url_https"] as? String {
|
||||
completion(.success(url))
|
||||
} else {
|
||||
completion(.failure(TwitterFeedProviderError.unknown))
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -82,22 +82,38 @@ public final class WebFeedIconDownloader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let iconURL = feed.iconURL {
|
||||
icon(forURL: iconURL, feed: feed) { (image) in
|
||||
if let image = image {
|
||||
self.postFeedIconDidBecomeAvailableNotification(feed)
|
||||
self.cache[feed] = IconImage(image)
|
||||
}
|
||||
else {
|
||||
checkHomePageURL()
|
||||
|
||||
func checkFeedIconURL() {
|
||||
if let iconURL = feed.iconURL {
|
||||
icon(forURL: iconURL, feed: feed) { (image) in
|
||||
if let image = image {
|
||||
self.postFeedIconDidBecomeAvailableNotification(feed)
|
||||
self.cache[feed] = IconImage(image)
|
||||
} else {
|
||||
checkHomePageURL()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
checkHomePageURL()
|
||||
}
|
||||
}
|
||||
else {
|
||||
checkHomePageURL()
|
||||
}
|
||||
|
||||
if let components = URLComponents(string: feed.url), let feedProvider = ExtensionPointManager.shared.bestFeedProvider(for: components, with: nil) {
|
||||
feedProvider.iconURL(components) { result in
|
||||
if case .success(let url) = result {
|
||||
self.icon(forURL: url, feed: feed) { (image) in
|
||||
if let image = image {
|
||||
self.postFeedIconDidBecomeAvailableNotification(feed)
|
||||
self.cache[feed] = IconImage(image)
|
||||
} else {
|
||||
checkFeedIconURL()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
checkFeedIconURL()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user