Module: Twterm::RESTClient

Includes:
Publisher
Included in:
Client
Defined in:
lib/twterm/rest_client.rb

Constant Summary collapse

CONSUMER_KEY =
'vLNSVFgXclBJQJRZ7VLMxL9lA'.freeze
CONSUMER_SECRET =
'OFLKzrepRG2p1hq0nUB9j2S9ndFQoNTPheTpmOY0GYw55jGgS5'.freeze

Instance Method Summary collapse

Methods included from Publisher

#publish

Methods included from Utils

check_type

Instance Method Details

#add_list_member(list_id, user_id) ⇒ Object



14
15
16
# File 'lib/twterm/rest_client.rb', line 14

def add_list_member(list_id, user_id)
  send_request { rest_client.add_list_member(list_id, user_id) }
end

#block(*user_ids) ⇒ Object



18
19
20
21
22
23
24
25
26
# File 'lib/twterm/rest_client.rb', line 18

def block(*user_ids)
  send_request do
    rest_client.block(*user_ids)
  end.then do |users|
    users.each do |user|
      friendship_repository.block(self.user_id, user.id)
    end
  end
end

#create_direct_message(recipient, text) ⇒ Object



28
29
30
31
32
33
34
35
36
37
# File 'lib/twterm/rest_client.rb', line 28

def create_direct_message(recipient, text)
  send_request do
    rest_client.create_direct_message(recipient.id, text)
  end.then do |message|
    msg = direct_message_repository.create(message)
    direct_message_manager.add(recipient.id, msg)
    publish(Event::DirectMessage::Fetched.new)
    publish(Event::Message::Success.new('Your message to @%s has been sent' % recipient.screen_name))
  end
end

#destroy_status(status) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/twterm/rest_client.rb', line 55

def destroy_status(status)
  send_request_without_catch do
    rest_client.destroy_status(status.id)
    publish(Event::Status::Delete.new(status.id))
    publish(Event::Message::Success.new('Your tweet has been deleted'))
  end.catch do |reason|
    case reason
    when Twitter::Error::NotFound, Twitter::Error::Forbidden
      publish(Event::Message::Error.new('You cannot destroy that status'))
    else
      raise reason
    end
  end.catch(&show_error)
end

#direct_message_conversationsObject



39
40
41
# File 'lib/twterm/rest_client.rb', line 39

def direct_message_conversations
  direct_message_manager.conversations
end

#direct_messages_receivedObject



43
44
45
46
47
# File 'lib/twterm/rest_client.rb', line 43

def direct_messages_received
  send_request do
    rest_client.direct_messages(count: 200).map { |dm| direct_message_repository.create(dm) }
  end
end

#direct_messages_sentObject



49
50
51
52
53
# File 'lib/twterm/rest_client.rb', line 49

def direct_messages_sent
  send_request do
    rest_client.direct_messages_sent(count: 200).map { |dm| direct_message_repository.create(dm) }
  end
end

#favorite(status) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/twterm/rest_client.rb', line 70

def favorite(status)
  return false unless status.is_a? Status

  send_request do
    rest_client.favorite(status.id)
  end.then do |tweet, *_|
    status_repository.create(tweet)

    publish(Event::Message::Success.new('Successfully liked: @%s "%s"' % [
      tweet.user.screen_name, status.text
    ]))
  end
end

#favorites(user_id = nil) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'lib/twterm/rest_client.rb', line 84

def favorites(user_id = nil)
  user_id ||= self.user_id

  send_request do
    rest_client.favorites(user_id, count: 200, tweet_mode: :extended)
  end.then do |tweets|
    tweets.map { |tweet| status_repository.create(tweet) }
  end
end

#fetch_muted_usersObject



94
95
96
97
98
# File 'lib/twterm/rest_client.rb', line 94

def fetch_muted_users
  send_request do
    @muted_user_ids = rest_client.muted_ids.to_a
  end
end

#follow(*user_ids) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/twterm/rest_client.rb', line 100

def follow(*user_ids)
  send_request do
    rest_client.follow(*user_ids)
  end.then do |users|
    users.each do |user|
      if user.protected?
        friendship_repository.following_requested(self.user_id, user.id)
      else
        friendship_repository.follow(self.user_id, user.id)
      end
    end
  end
end

#followers(user_id = nil) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/twterm/rest_client.rb', line 114

def followers(user_id = nil)
  user_id ||= self.user_id

  m = Mutex.new

  send_request do
    rest_client.follower_ids(user_id).each_slice(100) do |user_ids|
      m.synchronize do
        users = rest_client.users(*user_ids).map { |u| user_repository.create(u) }
        users.each do |user|
          friendship_repository.follow(user.id, self.user_id)
        end if user_id == self.user_id
        yield users
      end
    end
  end
end

#friends(user_id = nil) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/twterm/rest_client.rb', line 132

def friends(user_id = nil)
  user_id ||= self.user_id

  m = Mutex.new

  send_request do
    rest_client.friend_ids(user_id).each_slice(100) do |user_ids|
      m.synchronize do
        yield rest_client.users(*user_ids).map { |u| user_repository.create(u) }
      end
    end
  end
end

#home_timelineObject



146
147
148
149
150
151
152
153
154
# File 'lib/twterm/rest_client.rb', line 146

def home_timeline
  send_request do
    rest_client.home_timeline(count: 200, tweet_mode: :extended)
  end.then do |tweets|
    tweets
    .select(&@mute_filter)
    .map { |tweet| status_repository.create(tweet) }
  end
end

#list(list_id) ⇒ Object



156
157
158
159
160
161
162
# File 'lib/twterm/rest_client.rb', line 156

def list(list_id)
  send_request do
    rest_client.list(list_id)
  end.then do |list|
    list_repository.create(list)
  end
end

#list_timeline(list_id) ⇒ Object



164
165
166
167
168
169
170
171
172
# File 'lib/twterm/rest_client.rb', line 164

def list_timeline(list_id)
  send_request do
    rest_client.list_timeline(list_id, count: 200, tweet_mode: :extended)
  end.then do |statuses|
    statuses
    .select(&@mute_filter)
    .map { |tweet| status_repository.create(tweet) }
  end
end

#listsObject



174
175
176
177
178
179
180
# File 'lib/twterm/rest_client.rb', line 174

def lists
  send_request do
    rest_client.lists
  end.then do |lists|
    lists.map { |list| list_repository.create(list) }
  end
end

#lookup_friendshipsObject



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/twterm/rest_client.rb', line 182

def lookup_friendships
  repo = friendship_repository
  user_ids = user_repository.ids.reject { |id| repo.already_looked_up?(id) }
  send_request_without_catch do
    user_ids.each_slice(100) do |chunked_user_ids|
      friendships = rest_client.friendships(*chunked_user_ids)
      friendships.each do |friendship|
        id = friendship.id
        client_id = user_id

        conn = friendship.connections
        conn.include?('blocking') ? repo.block(client_id, id) : repo.unblock(client_id, id)
        conn.include?('following') ? repo.follow(client_id, id) : repo.unfollow(client_id, id)
        conn.include?('following_requested') ? repo.following_requested(client_id, id) : repo.following_not_requested(client_id, id)
        conn.include?('followed_by') ? repo.follow(id, client_id) : repo.unfollow(id, client_id)
        conn.include?('muting') ? repo.mute(client_id, id) : repo.unmute(client_id, id)

        repo.looked_up!(id)
      end
    end
  end.catch do |e|
    case e
    when Twitter::Error::TooManyRequests # rubocop:disable Lint/EmptyWhen
      # do nothing
    else
      raise e
    end
  end.catch(&show_error)
end

#memberships(user_id, options = {}) ⇒ Object



212
213
214
215
216
217
218
# File 'lib/twterm/rest_client.rb', line 212

def memberships(user_id, options = {})
  send_request do
    user_id.nil? ? rest_client.memberships(options) : rest_client.memberships(user_id, options)
  end.then do |cursor|
    cursor.map { |list| list_repository.create(list) }
  end
end

#mentionsObject



220
221
222
223
224
225
226
227
228
# File 'lib/twterm/rest_client.rb', line 220

def mentions
  send_request do
    rest_client.mentions(count: 200, tweet_mode: :extended)
  end.then do |statuses|
    statuses
    .select(&@mute_filter)
    .map { |tweet| status_repository.create(tweet) }
  end
end

#mute(user_ids) ⇒ Object



230
231
232
233
234
235
236
237
238
# File 'lib/twterm/rest_client.rb', line 230

def mute(user_ids)
  send_request do
    rest_client.mute(*user_ids)
  end.then do |users|
    users.each do |user|
      friendship_repository.mute(self.user_id, user.id)
    end
  end
end

#owned_listsObject



240
241
242
243
244
245
246
# File 'lib/twterm/rest_client.rb', line 240

def owned_lists
  send_request do
    rest_client.owned_lists
  end.then do |lists|
    lists.map { |list| list_repository.create(list) }
  end
end

#post(text, options = {}) ⇒ Object



248
249
250
251
252
253
254
255
256
257
# File 'lib/twterm/rest_client.rb', line 248

def post(text, options = {})
  send_request do
    rest_client.update(text, options)
  end
    .then do |status|
      publish(Event::Message::Success.new('Your tweet has been posted'))

      status
    end
end

#rate_limit_statusObject



259
260
261
# File 'lib/twterm/rest_client.rb', line 259

def rate_limit_status
  send_request { Twitter::REST::Request.new(rest_client, :get, '/1.1/application/rate_limit_status.json').perform }
end

#remove_list_member(list_id, user_id) ⇒ Object



263
264
265
# File 'lib/twterm/rest_client.rb', line 263

def remove_list_member(list_id, user_id)
  send_request { rest_client.remove_list_member(list_id, user_id) }
end

#rest_clientObject



408
409
410
411
412
413
414
415
# File 'lib/twterm/rest_client.rb', line 408

def rest_client
  @rest_client ||= Twitter::REST::Client.new do |config|
    config.consumer_key        = CONSUMER_KEY
    config.consumer_secret     = CONSUMER_SECRET
    config.access_token        = @access_token
    config.access_token_secret = @access_token_secret
  end
end

#retweet(status) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/twterm/rest_client.rb', line 267

def retweet(status)
  fail ArgumentError,
    'argument must be an instance of Status class' unless status.is_a? Status

  send_request_without_catch do
    rest_client.retweet!(status.id)
  end.then do |tweet, *_|
    status_repository.create(tweet)

    publish(Event::Message::Success.new('Successfully retweeted: @%s "%s"' % [
      tweet.user.screen_name, status.text
    ]))
  end.catch do |reason|
    message =
      case reason
      when Twitter::Error::AlreadyRetweeted
        'The status is already retweeted'
      when Twitter::Error::NotFound
        'The status is not found'
      when Twitter::Error::Forbidden
        'The status is protected'
      else
        raise e
      end
    publish(Event::Message::Error.new("Retweet attempt failed: #{message}"))
  end.catch(&show_error)
end

#saved_searchObject



295
296
297
298
299
# File 'lib/twterm/rest_client.rb', line 295

def saved_search
  send_request do
    rest_client.saved_searches
  end
end

#search(query) ⇒ Object



301
302
303
304
305
306
307
308
309
# File 'lib/twterm/rest_client.rb', line 301

def search(query)
  send_request do
    rest_client.search(query, count: 100, tweet_mode: :extended).attrs[:statuses]
  end.then do |statuses|
    statuses
    .map(&Twitter::Tweet.method(:new))
    .map { |tweet| status_repository.create(tweet) }
  end
end

#send_request(&block) ⇒ Object



417
418
419
# File 'lib/twterm/rest_client.rb', line 417

def send_request(&block)
  send_request_without_catch(&block).catch(&show_error)
end

#send_request_without_catch(&block) ⇒ Object



421
422
423
# File 'lib/twterm/rest_client.rb', line 421

def send_request_without_catch(&block)
  Concurrent::Promise.execute { block.call }
end

#show_status(status_id) ⇒ Object



311
312
313
314
315
316
317
# File 'lib/twterm/rest_client.rb', line 311

def show_status(status_id)
  send_request do
    rest_client.status(status_id)
  end.then do |status|
    status_repository.create(status)
  end
end

#show_user(query) ⇒ Object



319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/twterm/rest_client.rb', line 319

def show_user(query)
  send_request_without_catch do
    rest_client.user(query)
  end.catch do |reason|
    case reason
    when Twitter::Error::NotFound
      nil
    else
      raise reason
    end
  end.catch(&show_error).then do |user|
    user.nil? ? nil : user_repository.create(user)
  end
end

#unblock(*user_ids) ⇒ Object



334
335
336
337
338
339
340
341
342
# File 'lib/twterm/rest_client.rb', line 334

def unblock(*user_ids)
  send_request do
    rest_client.unblock(*user_ids)
  end.then do |users|
    users.each do |user|
      friendship_repository.unblock(self.user_id, user.id)
    end
  end
end

#unfavorite(status) ⇒ Object



344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/twterm/rest_client.rb', line 344

def unfavorite(status)
  fail ArgumentError,
    'argument must be an instance of Status class' unless status.is_a? Status

  send_request do
    rest_client.unfavorite(status.id)
  end.then do |tweet, *_|
    status_repository.create(tweet)

    publish(Event::Message::Success.new("Successfully unliked @#{tweet.user.screen_name}'s tweet", sutatus.text))
  end
end

#unfollow(*user_ids) ⇒ Object



357
358
359
360
361
362
363
364
365
# File 'lib/twterm/rest_client.rb', line 357

def unfollow(*user_ids)
  send_request do
    rest_client.unfollow(*user_ids)
  end.then do |users|
    users.each do |user|
      friendship_repository.unfollow(self.user_id, user.id)
    end
  end
end

#unmute(user_ids) ⇒ Object



367
368
369
370
371
372
373
374
375
# File 'lib/twterm/rest_client.rb', line 367

def unmute(user_ids)
  send_request do
    rest_client.unmute(*user_ids)
  end.then do |users|
    users.each do |user|
      friendship_repository.unmute(self.user_id, user.id)
    end
  end
end

#unretweet(status) ⇒ Object



377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/twterm/rest_client.rb', line 377

def unretweet(status)
  send_request do
    Twitter::REST::Request.new(rest_client, :post, "/1.1/statuses/unretweet/#{status.id}.json").perform
  end
    .then do |json, *_|
      json[:retweet_count] -= 1
      json[:retweeted] = false

      Twitter::Tweet.new(json)
    end
    .then do |tweet|
      status = status_repository.create(tweet)

      publish(Event::Message::Success.new('Successfully unretweeted: @%s "%s"' % [
        tweet.user.screen_name, status.text
      ]))

      status
    end
end

#user_timeline(user_id) ⇒ Object



398
399
400
401
402
403
404
405
406
# File 'lib/twterm/rest_client.rb', line 398

def user_timeline(user_id)
  send_request do
    rest_client.user_timeline(user_id, count: 200)
  end.then do |statuses|
    statuses
    .select(&@mute_filter)
    .map { |tweet| status_repository.create(tweet) }
  end
end