Add Twitter API rate limiting
This commit is contained in:
parent
44476c5d6d
commit
2324d652cd
@ -13,11 +13,14 @@ import RSParser
|
|||||||
import RSWeb
|
import RSWeb
|
||||||
|
|
||||||
public enum TwitterFeedProviderError: LocalizedError {
|
public enum TwitterFeedProviderError: LocalizedError {
|
||||||
|
case rateLimitExceeded
|
||||||
case screenNameNotFound
|
case screenNameNotFound
|
||||||
case unknown
|
case unknown
|
||||||
|
|
||||||
public var localizedDescription: String {
|
public var localizedDescription: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .rateLimitExceeded:
|
||||||
|
return NSLocalizedString("Twitter API rate limit has been exceeded. Please wait a short time and try again.", comment: "Rate Limit")
|
||||||
case .screenNameNotFound:
|
case .screenNameNotFound:
|
||||||
return NSLocalizedString("Unable to determine screen name.", comment: "Screen name")
|
return NSLocalizedString("Unable to determine screen name.", comment: "Screen name")
|
||||||
case .unknown:
|
case .unknown:
|
||||||
@ -33,7 +36,7 @@ public enum TwitterFeedType: Int {
|
|||||||
case search = 3
|
case search = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct TwitterFeedProvider: FeedProvider {
|
public final class TwitterFeedProvider: FeedProvider {
|
||||||
|
|
||||||
private static let homeURL = "https://www.twitter.com"
|
private static let homeURL = "https://www.twitter.com"
|
||||||
private static let server = "api.twitter.com"
|
private static let server = "api.twitter.com"
|
||||||
@ -51,6 +54,9 @@ public struct TwitterFeedProvider: FeedProvider {
|
|||||||
|
|
||||||
private var client: OAuthSwiftClient
|
private var client: OAuthSwiftClient
|
||||||
|
|
||||||
|
private var rateLimitRemaining: Int?
|
||||||
|
private var rateLimitReset: Date?
|
||||||
|
|
||||||
public init?(tokenSuccess: OAuthSwift.TokenSuccess) {
|
public init?(tokenSuccess: OAuthSwift.TokenSuccess) {
|
||||||
guard let screenName = tokenSuccess.parameters["screen_name"] as? String else {
|
guard let screenName = tokenSuccess.parameters["screen_name"] as? String else {
|
||||||
return nil
|
return nil
|
||||||
@ -332,6 +338,11 @@ private extension TwitterFeedProvider {
|
|||||||
var expandedParameters = parameters
|
var expandedParameters = parameters
|
||||||
expandedParameters["tweet_mode"] = "extended"
|
expandedParameters["tweet_mode"] = "extended"
|
||||||
|
|
||||||
|
if let remaining = rateLimitRemaining, let reset = rateLimitReset, remaining < 1 && reset > Date() {
|
||||||
|
completion(.failure(TwitterFeedProviderError.rateLimitExceeded))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
client.get(url, parameters: expandedParameters, headers: Self.userAgentHeaders) { result in
|
client.get(url, parameters: expandedParameters, headers: Self.userAgentHeaders) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let response):
|
case .success(let response):
|
||||||
@ -340,7 +351,14 @@ private extension TwitterFeedProvider {
|
|||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
dateFormatter.dateFormat = Self.dateFormat
|
dateFormatter.dateFormat = Self.dateFormat
|
||||||
decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
||||||
|
|
||||||
|
if let remaining = response.response.value(forHTTPHeaderField: "x-rate-limit-remaining") {
|
||||||
|
self.rateLimitRemaining = Int(remaining) ?? 0
|
||||||
|
}
|
||||||
|
if let reset = response.response.value(forHTTPHeaderField: "x-rate-limit-reset") {
|
||||||
|
self.rateLimitReset = Date(timeIntervalSince1970: Double(reset) ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let tweets: [TwitterStatus]
|
let tweets: [TwitterStatus]
|
||||||
if isSearch {
|
if isSearch {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user