import * as Twit from 'twit' ; import log from '../log' ; import { UnderlyingClient , DummyClient , TwitClient } from './clients' ; type Status = Twit . Twitter . Status ; type User = Twit . Twitter . User ; type SearchResponse = Twit . Twitter . SearchResponse ; export class TwitterRestApi { constructor ( public client ) { } setupClient ( options ) { this . client . setupClient ( options ) ; } updateStatus ( text , in_reply_to ? ) { const params = { status : text , in_reply_to_status_id : undefined as string | undefined , trim_user : false , } ; if ( in_reply_to ) { params . in_reply_to_status_id = in_reply_to ; } return this . client . post < Status > ( 'statuses/update' , params ) ; } like ( tweet_id ) { const params = { id : tweet_id , include_entities : true , } ; return this . client . post < Status > ( 'favorites/create' , params ) ; } unlike ( tweet_id ) { const params = { id : tweet_id , include_entities : true , } ; return this . client . post < Status > ( 'favorites/destroy' , params ) ; } retweet ( tweet_id ) { return this . client . post < Status > ( 'statuses/retweet/' + tweet_id ) . then ( json => { if ( ! json . retweeted_status ) { log . error ( 'Received status is not an retweet status: ' , json ) ; return json ; } if ( ! json . retweeted_status . retweeted ) { log . warn ( 'Retweeted tweet is NOT marked as "retweeted", workaround.' , json ) ; json . retweeted_status . retweeted = true ; json . retweeted_status . retweet_count += 1 ; } return json ; } ) ; } unretweet ( tweet_id ) { return this . client . post < Status > ( 'statuses/unretweet/' + tweet_id ) . then ( json => { if ( json . retweeted ) { log . warn ( 'Unretweeted tweet is marked as "retweeted", workaround' , json ) ; json . retweeted = false ; json . retweet_count -= 1 ; } return json ; } ) ; } destroyStatus ( tweet_id ) { return this . client . post < Status > ( 'statuses/destroy/' + tweet_id ) ; } follow ( user_id ) { return this . client . post < User > ( 'friendships/create' , { user_id } ) ; } unfollow ( user_id ) { return this . client . post < User > ( 'friendships/destroy' , { user_id } ) ; } verifyCredentials ( ) { const params = { include_entities : 'true' , } ; return this . client . get < User > ( 'account/verify_credentials' , params ) ; } homeTimeline ( params = { include_entities : true } ) { return this . client . get < Status [ ] > ( 'statuses/home_timeline' , params ) ; } mentionTimeline ( params = { include_entities : true } ) { return this . client . get < Status [ ] > ( 'statuses/mentions_timeline' , params ) ; } muteIds ( params = { } ) { return this . client . get < any > ( 'mutes/users/ids' , params ) . then ( res => res . ids as number [ ] ) ; } blockIds ( params = { } ) { return this . client . get < any > ( 'blocks/ids' , params ) . then ( res => res . ids as number [ ] ) ; } noRetweetIds ( params = { } ) { return this . client . get < number [ ] > ( 'friendships/no_retweets/ids' , params ) ; } rejectedIds ( ) { return Promise . all ( [ this . muteIds ( ) , this . blockIds ( ) ] ) . then ( ( [ mute_ids , block_ids ] ) => { Array . prototype . push . apply ( mute_ids , block_ids ) ; return mute_ids ; } ) ; } userTimeline ( user_id , params = { } ) { params = Object . assign ( { user_id , include_rts : true , exclude_replies : false , count : 100 , } , params ) ; return this . client . get < Status [ ] > ( 'statuses/user_timeline' , params ) ; } searchStatuses ( query , params = { } ) { params = Object . assign ( { q : query , result_type : 'recent' , include_entities : true , count : 100 , } , params ) ; return this . client . get < SearchResponse > ( 'search/tweets' , params ) ; } conversationStatuses ( status_id , screen_name ) { const query = `@${ screen_name } OR from:${ screen_name } filter:replies -filter:retweets` ; return this . searchStatuses ( query , { since_id : status_id } ) . then ( res => { const related_ids = [ status_id ] ; return res . statuses . reduce ( ( result , status ) => { const in_reply_to = status . in_reply_to_status_id_str ! ; if ( related_ids . indexOf ( in_reply_to ) !== - 1 ) { result . push ( status ) ; related_ids . push ( status . id_str ) ; } return result ; } , [ ] as Status [ ] ) ; } ) ; } missingHomeTimeline ( max_id ? , since_id ? ) { return this . missingTimeline ( 'statuses/home_timeline' , max_id , since_id ) ; } missingMentionTimeline ( max_id ? , since_id ? ) { return this . missingTimeline ( 'statuses/mentions_timeline' , max_id , since_id ) ; } private missingTimeline ( path , max_id ? , since_id ? ) { const params = { include_entities : true , max_id , since_id , count : 200 , } ; return this . client . get < Status [ ] > ( path , params ) ; } } export default new TwitterRestApi ( process . env . YOURFUKUROU_USE_FIXTURE ? new DummyClient ( ) : new TwitClient ( ) ) ;