Clean up the URL screen name extraction

This commit is contained in:
Maurice Parker 2020-04-16 12:07:57 -05:00
parent b3afee0252
commit a59cb3b79b

View File

@ -13,6 +13,7 @@ import RSParser
// TODO: Beef up error handling... // TODO: Beef up error handling...
public enum TwitterFeedProviderError: Error { public enum TwitterFeedProviderError: Error {
case screenNameNotFound
case unknown case unknown
} }
@ -21,6 +22,9 @@ public struct TwitterFeedProvider: FeedProvider {
private static let server = "api.twitter.com" private static let server = "api.twitter.com"
private static let apiBase = "https://api.twitter.com/1.1/" private static let apiBase = "https://api.twitter.com/1.1/"
private static let userPaths = ["/home", "/notifications"]
private static let reservedPaths = ["/search", "/explore", "/messages", "/i", "/compose"]
public var userID: String public var userID: String
public var screenName: String public var screenName: String
@ -85,8 +89,11 @@ public struct TwitterFeedProvider: FeedProvider {
} }
public func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void) { public func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void) {
let screenName = extractScreenName(urlComponents) if let screenName = deriveScreenName(urlComponents) {
fetchIconURL(screenName: screenName, completion: completion) fetchIconURL(screenName: screenName, completion: completion)
} else {
completion(.failure(TwitterFeedProviderError.screenNameNotFound))
}
} }
public func provide(_ urlComponents: URLComponents, completion: @escaping (Result<ParsedFeed, Error>) -> Void) { public func provide(_ urlComponents: URLComponents, completion: @escaping (Result<ParsedFeed, Error>) -> Void) {
@ -119,24 +126,18 @@ extension TwitterFeedProvider: OAuth1SwiftProvider {
private extension TwitterFeedProvider { private extension TwitterFeedProvider {
// TODO: Full parsing routine func deriveScreenName(_ urlComponents: URLComponents) -> String? {
func extractScreenName(_ urlComponents: URLComponents) -> String {
let path = urlComponents.path let path = urlComponents.path
if let index = path.firstIndex(of: "?") { guard !Self.reservedPaths.contains(path) else { return nil }
let range = path.index(path.startIndex, offsetBy: 1)...index
return String(path[range]) if path.isEmpty || Self.userPaths.contains(path) {
return screenName
} else { } else {
return String(path.suffix(from: path.index(path.startIndex, offsetBy: 1))) 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) { func fetchIconURL(screenName: String, completion: @escaping (Result<String, Error>) -> Void) {
guard screenName != "search" else {
completion(.failure(TwitterFeedProviderError.unknown))
return
}
let url = "\(Self.apiBase)users/show.json" let url = "\(Self.apiBase)users/show.json"
let parameters = ["screen_name": screenName] let parameters = ["screen_name": screenName]