From becf67a286eacd311e1adce1118a6bf8b9fec2eb Mon Sep 17 00:00:00 2001 From: Yuta Koshizawa Date: Sat, 30 Dec 2017 01:41:48 +0900 Subject: [PATCH] Implement tweet chains by replies --- Sources/TweetupKit/Async.swift | 18 ++++++++++++------ Sources/TweetupKit/Speaker.swift | 6 +++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Sources/TweetupKit/Async.swift b/Sources/TweetupKit/Async.swift index 70fc351..bacac33 100644 --- a/Sources/TweetupKit/Async.swift +++ b/Sources/TweetupKit/Async.swift @@ -28,27 +28,33 @@ public func sync(operation: (@escaping (T, @escaping (() throws -> R) -> ( } } +internal func repeated(operation: @escaping (T, R1?) -> Promise<() throws -> R2>, convert: @escaping (R2) -> R1, interval: TimeInterval? = nil) -> ([T]) -> Promise<() throws -> [R2]> { + return { values in + _repeat(operation: operation, for: values[...], convert: convert, interval: interval) + } +} + internal func repeated(operation: @escaping (T) -> Promise<() throws -> R>, interval: TimeInterval? = nil) -> ([T]) -> Promise<() throws -> [R]> { return { values in - _repeat(operation: operation, for: values[...], interval: interval) + _repeat(operation: { r, _ in operation(r) }, for: values[...], convert: { $0 }, interval: interval) } } -private func _repeat(operation: @escaping (T) -> Promise<() throws -> R>, for values: ArraySlice, interval: TimeInterval?, results: [R] = []) -> Promise<() throws -> [R]> { +private func _repeat(operation: @escaping (T, R1?) -> Promise<() throws -> R2>, for values: ArraySlice, convert: @escaping (R2) -> R1, interval: TimeInterval?, results: [R2] = []) -> Promise<() throws -> [R2]> { let (headOrNil, tail) = values.headAndTail guard let head = headOrNil else { return Promise { results } } - let resultPromise: Promise<() throws -> R> + let resultPromise: Promise<() throws -> R2> if let interval = interval, !tail.isEmpty { - resultPromise = wait(operation(head), for: interval) + resultPromise = wait(operation(head, results.last.map(convert)), for: interval) } else { - resultPromise = operation(head) + resultPromise = operation(head, results.last.map(convert)) } return resultPromise.flatMap { getResult in - _repeat(operation: operation, for: tail, interval: interval, results: results + [try getResult()]) + _repeat(operation: operation, for: tail, convert: convert, interval: interval, results: results + [try getResult()]) } } diff --git a/Sources/TweetupKit/Speaker.swift b/Sources/TweetupKit/Speaker.swift index 110817b..97bc9fd 100644 --- a/Sources/TweetupKit/Speaker.swift +++ b/Sources/TweetupKit/Speaker.swift @@ -43,10 +43,10 @@ public struct Speaker { } public func post(tweets: [Tweet], interval: TimeInterval?) -> Promise<() throws -> [PostResponse]> { - return repeated(operation: post, interval: interval)(tweets) + return repeated(operation: post, convert: { $0.statusId }, interval: interval)(tweets) } - public func post(tweet: Tweet) -> Promise<() throws -> PostResponse> { + public func post(tweet: Tweet, replyingTo statusId: String?) -> Promise<() throws -> PostResponse> { guard let twitterCredential = twitterCredential else { return Promise { throw SpeakerError.noTwitterCredential } } @@ -76,7 +76,7 @@ public struct Speaker { } else { mediaId = nil } - return Twitter.update(status: status, mediaId: mediaId, credential: twitterCredential).map { PostResponse(try $0()) } + return Twitter.update(status: status, mediaId: mediaId, inReplyToStatusId: statusId, credential: twitterCredential).map { PostResponse(try $0()) } }.map { getResponse in try getResponse() }