twterm 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/bin/twterm +4 -4
  3. data/lib/twterm/app.rb +19 -4
  4. data/lib/twterm/client.rb +8 -470
  5. data/lib/twterm/direct_message.rb +82 -0
  6. data/lib/twterm/direct_message_composer.rb +74 -0
  7. data/lib/twterm/direct_message_manager.rb +52 -0
  8. data/lib/twterm/event/base.rb +22 -0
  9. data/lib/twterm/event/direct_message/fetched.rb +10 -0
  10. data/lib/twterm/event/favorite.rb +18 -0
  11. data/lib/twterm/event/follow.rb +17 -0
  12. data/lib/twterm/event/notification.rb +33 -0
  13. data/lib/twterm/event/open_uri.rb +11 -0
  14. data/lib/twterm/event/screen/resize.rb +13 -0
  15. data/lib/twterm/event/status/base.rb +14 -0
  16. data/lib/twterm/event/status/delete.rb +13 -0
  17. data/lib/twterm/event/status/mention.rb +10 -0
  18. data/lib/twterm/event/status/timeline.rb +10 -0
  19. data/lib/twterm/event_dispatcher.rb +59 -0
  20. data/lib/twterm/filter_query_window.rb +11 -5
  21. data/lib/twterm/filterable_list.rb +6 -1
  22. data/lib/twterm/notifier.rb +39 -15
  23. data/lib/twterm/promise.rb +2 -2
  24. data/lib/twterm/publisher.rb +16 -0
  25. data/lib/twterm/rest_client.rb +401 -0
  26. data/lib/twterm/screen.rb +16 -13
  27. data/lib/twterm/status.rb +12 -1
  28. data/lib/twterm/streaming_client.rb +103 -0
  29. data/lib/twterm/subscriber.rb +33 -0
  30. data/lib/twterm/tab/base.rb +13 -6
  31. data/lib/twterm/tab/direct_message/conversation.rb +103 -0
  32. data/lib/twterm/tab/direct_message/conversation_list.rb +99 -0
  33. data/lib/twterm/tab/key_assignments_cheatsheet.rb +3 -2
  34. data/lib/twterm/tab/new/list.rb +5 -3
  35. data/lib/twterm/tab/new/search.rb +3 -2
  36. data/lib/twterm/tab/new/start.rb +17 -2
  37. data/lib/twterm/tab/new/user.rb +6 -3
  38. data/lib/twterm/tab/statuses/base.rb +18 -11
  39. data/lib/twterm/tab/statuses/conversation.rb +3 -2
  40. data/lib/twterm/tab/statuses/favorites.rb +3 -2
  41. data/lib/twterm/tab/statuses/home.rb +10 -4
  42. data/lib/twterm/tab/statuses/list_timeline.rb +3 -2
  43. data/lib/twterm/tab/statuses/mentions.rb +6 -6
  44. data/lib/twterm/tab/statuses/search.rb +4 -3
  45. data/lib/twterm/tab/statuses/user_timeline.rb +3 -2
  46. data/lib/twterm/tab/user_tab.rb +26 -16
  47. data/lib/twterm/tab/users/base.rb +3 -2
  48. data/lib/twterm/tab/users/followers.rb +3 -2
  49. data/lib/twterm/tab/users/friends.rb +3 -2
  50. data/lib/twterm/tab_manager.rb +20 -8
  51. data/lib/twterm/tweetbox.rb +5 -2
  52. data/lib/twterm/uri_opener.rb +25 -0
  53. data/lib/twterm/user.rb +11 -1
  54. data/lib/twterm/utils.rb +13 -0
  55. data/lib/twterm/version.rb +1 -1
  56. data/lib/twterm.rb +0 -3
  57. data/spec/twterm/event/screen/resize_spec.rb +11 -0
  58. data/spec/twterm/event_dispatcher_spec.rb +19 -0
  59. data/twterm.gemspec +1 -1
  60. metadata +29 -7
  61. data/lib/twterm/notification/base.rb +0 -24
  62. data/lib/twterm/notification/error.rb +0 -19
  63. data/lib/twterm/notification/message.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f098da25f566b0f23f9749d9f406b743b767c316
4
- data.tar.gz: 729b1e86520c873898705530f1da7ee92c700497
3
+ metadata.gz: 4b97eeb5e737a698dcfde20b7e1f9284fa9d60c7
4
+ data.tar.gz: 8cd8793ff080f41519449fac75e9a88cd9e84deb
5
5
  SHA512:
6
- metadata.gz: 2d2c9b570b9ab523e03f90fbc0ace1083f8ed747c4c2440b9637652fedaf8976d970836f2436288f509396f106ae8636e11f3fb7ead68e216bae0dc76a19ac86
7
- data.tar.gz: 23519d2aa0809a3eb05dc6b1efa20a78bbdc4698fb0df299ee1ee45132015b8073f394a0bd12e8eb8173c36e27020cba684a52c58cdbdc3fea7213553ed31c19
6
+ metadata.gz: 114e722d6092d263be12a5b1d4bd102011c47b8cf9ff0a1893fcd9f6b25b562735f19725b8958fbcdad5c5a29a64490c50fe71923357e17fed43764374b63551
7
+ data.tar.gz: f78c9f33143bf6a3b27f0adae41bb0983d187340fa021ce95a781948d1b3ec4dd4e81100b40619741974ed0e45d29a35e4a87340718b8895ff9ed9d9a0b7f73c
data/bin/twterm CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'twterm'
4
-
5
3
  if ARGV.count == 1 && (%w(-v --version).include?(ARGV.first))
4
+ require 'twterm/version'
6
5
  puts 'twterm version %s' % Twterm::VERSION
7
6
  exit
7
+ else
8
+ require 'twterm'
9
+ Twterm::App.instance.run
8
10
  end
9
-
10
- Twterm::App.instance.run
data/lib/twterm/app.rb CHANGED
@@ -1,8 +1,13 @@
1
+ require 'curses'
2
+ require 'twterm/event/screen/resize'
3
+ require 'twterm/uri_opener'
4
+
1
5
  module Twterm
2
6
  class App
7
+ include Publisher
3
8
  include Singleton
4
9
 
5
- DATA_DIR = "#{ENV['HOME']}/.twterm"
10
+ DATA_DIR = "#{ENV['HOME']}/.twterm".freeze
6
11
 
7
12
  def initialize
8
13
  Dir.mkdir(DATA_DIR, 0700) unless File.directory?(DATA_DIR)
@@ -16,18 +21,28 @@ module Twterm
16
21
  TabManager.instance.add_and_show(timeline)
17
22
 
18
23
  mentions_tab = Tab::Statuses::Mentions.new(client)
24
+
19
25
  TabManager.instance.add(mentions_tab)
20
26
  TabManager.instance.recover_tabs
21
27
 
22
28
  Screen.instance.refresh
23
29
 
24
- client.user_stream
30
+ client.connect_user_stream
25
31
 
26
32
  reset_interruption_handler
27
33
 
28
- Signal.trap(:WINCH) { Screen.instance.resize }
34
+ URIOpener.instance
35
+
36
+ resize = proc do
37
+ next if Curses.closed?
38
+
39
+ lines = `tput lines`.to_i
40
+ cols = `tput cols`.to_i
41
+ publish(Event::Screen::Resize.new(lines, cols))
42
+ end
29
43
 
30
- Scheduler.new(60) { Screen.instance.resize }
44
+ Signal.trap(:WINCH, &resize)
45
+ Scheduler.new(60, &resize)
31
46
  end
32
47
 
33
48
  def run
data/lib/twterm/client.rb CHANGED
@@ -1,122 +1,15 @@
1
+ require 'twterm/rest_client'
2
+ require 'twterm/streaming_client'
3
+
1
4
  module Twterm
2
5
  class Client
3
- attr_reader :user_id, :screen_name
6
+ include RESTClient
7
+ include StreamingClient
4
8
 
5
- CREATE_STATUS_PROC = -> (s) { Status.new(s) }
6
- CONSUMER_KEY = 'vLNSVFgXclBJQJRZ7VLMxL9lA'.freeze
7
- CONSUMER_SECRET = 'OFLKzrepRG2p1hq0nUB9j2S9ndFQoNTPheTpmOY0GYw55jGgS5'.freeze
9
+ attr_reader :user_id, :screen_name
8
10
 
9
11
  @@instances = []
10
12
 
11
- def block(*user_ids)
12
- send_request do
13
- rest_client.block(*user_ids)
14
- end.then do |users|
15
- users.each do |user|
16
- Friendship.block(self.user_id, user.id)
17
- end
18
- end
19
- end
20
-
21
- def destroy_status(status)
22
- send_request_without_catch do
23
- rest_client.destroy_status(status.id)
24
- Notifier.instance.show_message('Your tweet has been deleted')
25
- end.catch do |reason|
26
- case reason
27
- when Twitter::Error::NotFound, Twitter::Error::Forbidden
28
- Notifier.instance.show_error 'You cannot destroy that status'
29
- else
30
- raise reason
31
- end
32
- end.catch(&show_error)
33
- end
34
-
35
- def favorite(status)
36
- return false unless status.is_a? Status
37
-
38
- send_request do
39
- rest_client.favorite(status.id)
40
- end.then do
41
- status.favorite!
42
- Notifier.instance.show_message('Successfully liked: @%s "%s"' % [
43
- status.user.screen_name, status.text
44
- ])
45
- end
46
- end
47
-
48
- def favorites(user_id = nil)
49
- user_id ||= self.user_id
50
-
51
- send_request do
52
- rest_client.favorites(user_id, count: 200)
53
- end.then do |tweets|
54
- tweets.map(&CREATE_STATUS_PROC)
55
- end
56
- end
57
-
58
- def fetch_muted_users
59
- send_request do
60
- @muted_user_ids = rest_client.muted_ids.to_a
61
- end
62
- end
63
-
64
- def follow(*user_ids)
65
- send_request do
66
- rest_client.follow(*user_ids)
67
- end.then do |users|
68
- users.each do |user|
69
- if user.protected?
70
- Friendship.following_requested(self.user_id, user.id)
71
- else
72
- Friendship.follow(self.user_id, user.id)
73
- end
74
- end
75
- end
76
- end
77
-
78
- def followers(user_id = nil)
79
- user_id ||= self.user_id
80
-
81
- m = Mutex.new
82
-
83
- send_request do
84
- rest_client.follower_ids(user_id).each_slice(100) do |user_ids|
85
- m.synchronize do
86
- users = rest_client.users(*user_ids).map(& -> u { User.new(u) })
87
- users.each do |user|
88
- Friendship.follow(user.id, self.user_id)
89
- end if user_id == self.user_id
90
- yield users
91
- end
92
- end
93
- end
94
- end
95
-
96
- def friends(user_id = nil)
97
- user_id ||= self.user_id
98
-
99
- m = Mutex.new
100
-
101
- send_request do
102
- rest_client.friend_ids(user_id).each_slice(100) do |user_ids|
103
- m.synchronize do
104
- yield rest_client.users(*user_ids).map(& -> u { User.new(u) })
105
- end
106
- end
107
- end
108
- end
109
-
110
- def home_timeline
111
- send_request do
112
- rest_client.home_timeline(count: 200)
113
- end.then do |statuses|
114
- statuses
115
- .select(&@mute_filter)
116
- .map(&CREATE_STATUS_PROC)
117
- end
118
- end
119
-
120
13
  def initialize(user_id, screen_name, access_token, access_token_secret)
121
14
  @user_id, @screen_name = user_id, screen_name
122
15
  @access_token, @access_token_secret = access_token, access_token_secret
@@ -134,324 +27,9 @@ module Twterm
134
27
 
135
28
  initialize_user_stream
136
29
 
137
- @@instances << self
138
- end
139
-
140
- def initialize_user_stream
141
- return if user_stream_initialized?
142
-
143
- streaming_client.on_friends do
144
- user_stream_connected!
145
- end
146
-
147
- streaming_client.on_timeline_status do |tweet|
148
- status = Status.new(tweet)
149
- invoke_callbacks(:timeline_status, status)
150
- invoke_callbacks(:mention, status) if status.text.include? "@#{@screen_name}"
151
- end
152
-
153
- streaming_client.on_delete do |status_id|
154
- timeline.delete_status(status_id)
155
- end
156
-
157
- streaming_client.on_event(:favorite) do |event|
158
- break if event[:source][:screen_name] == @screen_name
30
+ direct_message_manager
159
31
 
160
- user = event[:source][:screen_name]
161
- text = event[:target_object][:text]
162
- message = "@#{user} has favorited your tweet: #{text}"
163
- Notifier.instance.show_message(message)
164
- end
165
-
166
- streaming_client.on_event(:follow) do |event|
167
- screen_name = event[:source][:screen_name]
168
- break if screen_name == @screen_name
169
-
170
- Notifier.instance.show_message('@%s has followed you' % screen_name)
171
- end
172
-
173
- streaming_client.on_no_data_received do
174
- user_stream_disconnected!
175
- user_stream
176
- end
177
-
178
- user_stream_initialized!
179
- end
180
-
181
- def list(list_id)
182
- send_request do
183
- rest_client.list(list_id)
184
- end.then do |list|
185
- List.new(list)
186
- end
187
- end
188
-
189
- def list_timeline(list)
190
- fail ArgumentError,
191
- 'argument must be an instance of List class' unless list.is_a? List
192
- send_request do
193
- rest_client.list_timeline(list.id, count: 200)
194
- end.then do |statuses|
195
- statuses
196
- .select(&@mute_filter)
197
- .map(&CREATE_STATUS_PROC)
198
- end
199
- end
200
-
201
- def lists
202
- send_request do
203
- rest_client.lists
204
- end.then do |lists|
205
- lists.map { |list| List.new(list) }
206
- end
207
- end
208
-
209
- def lookup_friendships
210
- user_ids = User.ids.reject { |id| Friendship.already_looked_up?(id) }
211
- send_request_without_catch do
212
- user_ids.each_slice(100) do |chunked_user_ids|
213
- friendships = rest_client.friendships(*chunked_user_ids)
214
- friendships.each do |friendship|
215
- id = friendship.id
216
- client_id = user_id
217
-
218
- conn = friendship.connections
219
- conn.include?('blocking') ? Friendship.block(client_id, id) : Friendship.unblock(client_id, id)
220
- conn.include?('following') ? Friendship.follow(client_id, id) : Friendship.unfollow(client_id, id)
221
- conn.include?('following_requested') ? Friendship.following_requested(client_id, id) : Friendship.following_not_requested(client_id, id)
222
- conn.include?('followed_by') ? Friendship.follow(id, client_id) : Friendship.unfollow(id, client_id)
223
- conn.include?('muting') ? Friendship.mute(client_id, id) : Friendship.unmute(client_id, id)
224
- end
225
- end
226
- end.catch do |e|
227
- case e
228
- when Twitter::Error::TooManyRequests
229
- # do nothing
230
- else
231
- raise e
232
- end
233
- end.catch(&show_error)
234
- end
235
-
236
- def mentions
237
- send_request do
238
- rest_client.mentions(count: 200)
239
- end.then do |statuses|
240
- statuses
241
- .select(&@mute_filter)
242
- .map(&CREATE_STATUS_PROC)
243
- end
244
- end
245
-
246
- def mute(user_ids)
247
- send_request do
248
- rest_client.mute(*user_ids)
249
- end.then do |users|
250
- users.each do |user|
251
- Friendship.mute(self.user_id, user.id)
252
- end
253
- end
254
- end
255
-
256
- def on_mention(&block)
257
- fail ArgumentError, 'no block given' unless block_given?
258
- on(:mention, &block)
259
- end
260
-
261
- def on_timeline_status(&block)
262
- fail ArgumentError, 'no block given' unless block_given?
263
- on(:timeline_status, &block)
264
- end
265
-
266
- def post(text, in_reply_to = nil)
267
- send_request do
268
- if in_reply_to.is_a? Status
269
- text = "@#{in_reply_to.user.screen_name} #{text}"
270
- rest_client.update(text, in_reply_to_status_id: in_reply_to.id)
271
- else
272
- rest_client.update(text)
273
- end
274
- Notifier.instance.show_message('Your tweet has been posted')
275
- end
276
- end
277
-
278
- def rest_client
279
- @rest_client ||= Twitter::REST::Client.new do |config|
280
- config.consumer_key = CONSUMER_KEY
281
- config.consumer_secret = CONSUMER_SECRET
282
- config.access_token = @access_token
283
- config.access_token_secret = @access_token_secret
284
- end
285
- end
286
-
287
- def retweet(status)
288
- fail ArgumentError,
289
- 'argument must be an instance of Status class' unless status.is_a? Status
290
-
291
- send_request_without_catch do
292
- rest_client.retweet!(status.id)
293
- end.then do
294
- status.retweet!
295
- Notifier.instance.show_message('Successfully retweeted: @%s "%s"' % [
296
- status.user.screen_name, status.text
297
- ])
298
- end.catch do |reason|
299
- message =
300
- case reason
301
- when Twitter::Error::AlreadyRetweeted
302
- 'The status is already retweeted'
303
- when Twitter::Error::NotFound
304
- 'The status is not found'
305
- when Twitter::Error::Forbidden
306
- if status.user.id == user_id # when the status is mine
307
- 'You cannot retweet your own status'
308
- else # when the status is not mine
309
- 'The status is protected'
310
- end
311
- else
312
- raise e
313
- end
314
- Notifier.instance.show_error "Retweet attempt failed: #{message}"
315
- end.catch(&show_error)
316
- end
317
-
318
- def saved_search
319
- send_request do
320
- rest_client.saved_searches
321
- end
322
- end
323
-
324
- def search(query)
325
- send_request do
326
- rest_client.search(query, count: 100).attrs[:statuses]
327
- end.then do |statuses|
328
- statuses
329
- .map(&Twitter::Tweet.method(:new))
330
- .map(&CREATE_STATUS_PROC)
331
- end
332
- end
333
-
334
- def show_status(status_id)
335
- send_request do
336
- rest_client.status(status_id)
337
- end.then do |status|
338
- Status.new(status)
339
- end
340
- end
341
-
342
- def show_user(query)
343
- send_request_without_catch do
344
- rest_client.user(query)
345
- end.catch do |reason|
346
- case reason
347
- when Twitter::Error::NotFound
348
- nil
349
- else
350
- raise reason
351
- end
352
- end.catch(&show_error).then do |user|
353
- user.nil? ? nil : User.new(user)
354
- end
355
- end
356
-
357
- def streaming_client
358
- @streaming_client ||= TweetStream::Client.new(
359
- consumer_key: CONSUMER_KEY,
360
- consumer_secret: CONSUMER_SECRET,
361
- oauth_token: @access_token,
362
- oauth_token_secret: @access_token_secret,
363
- auth_method: :oauth
364
- )
365
- end
366
-
367
- def unblock(*user_ids)
368
- send_request do
369
- rest_client.unblock(*user_ids)
370
- end.then do |users|
371
- users.each do |user|
372
- Friendship.unblock(self.user_id, user.id)
373
- end
374
- end
375
- end
376
-
377
- def unfavorite(status)
378
- fail ArgumentError,
379
- 'argument must be an instance of Status class' unless status.is_a? Status
380
-
381
- send_request do
382
- rest_client.unfavorite(status.id)
383
- end.then do
384
- status.unfavorite!
385
- Notifier.instance.show_message('Successfully unliked: @%s "%s"' % [
386
- status.user.screen_name, status.text
387
- ])
388
- end
389
- end
390
-
391
- def unfollow(*user_ids)
392
- send_request do
393
- rest_client.unfollow(*user_ids)
394
- end.then do |users|
395
- users.each do |user|
396
- Friendship.unfollow(self.user_id, user.id)
397
- end
398
- end
399
- end
400
-
401
- def unmute(user_ids)
402
- send_request do
403
- rest_client.unmute(*user_ids)
404
- end.then do |users|
405
- users.each do |user|
406
- Friendship.unmute(self.user_id, user.id)
407
- end
408
- end
409
- end
410
-
411
- def user_stream
412
- streaming_client.stop_stream
413
-
414
- @streaming_thread = Thread.new do
415
- begin
416
- Notifier.instance.show_message 'Trying to connect to Twitter...'
417
- streaming_client.userstream
418
- rescue EventMachine::ConnectionError
419
- Notifier.instance.show_error 'Connection failed'
420
- sleep 30
421
- retry
422
- end
423
- end
424
- end
425
-
426
- def user_stream_connected?
427
- @user_stream_connected || false
428
- end
429
-
430
- def user_stream_connected!
431
- Notifier.instance.show_message 'Connection established' unless user_stream_connected?
432
- @user_stream_connected = true
433
- end
434
-
435
- def user_stream_disconnected!
436
- @user_stream_connected = false
437
- end
438
-
439
- def user_stream_initialized?
440
- @user_stream_initialized || false
441
- end
442
-
443
- def user_stream_initialized!
444
- @user_stream_initialized = true
445
- end
446
-
447
- def user_timeline(user_id)
448
- send_request do
449
- rest_client.user_timeline(user_id, count: 200)
450
- end.then do |statuses|
451
- statuses
452
- .select(&@mute_filter)
453
- .map(&CREATE_STATUS_PROC)
454
- end
32
+ @@instances << self
455
33
  end
456
34
 
457
35
  def self.new(user_id, screen_name, token, secret)
@@ -463,45 +41,5 @@ module Twterm
463
41
  def self.current
464
42
  @@instances[0]
465
43
  end
466
-
467
- private
468
-
469
- def show_error
470
- proc do |e|
471
- case e
472
- when Twitter::Error
473
- Notifier.instance.show_error "Failed to send request: #{e.message}"
474
- else
475
- raise e
476
- end
477
- end.freeze
478
- end
479
-
480
- def invoke_callbacks(event, data = nil)
481
- return if @callbacks[event].nil?
482
-
483
- @callbacks[event].each { |cb| cb.call(data) }
484
- self
485
- end
486
-
487
- def on(event, &block)
488
- @callbacks[event] ||= []
489
- @callbacks[event] << block
490
- self
491
- end
492
-
493
- def send_request(&block)
494
- send_request_without_catch(&block).catch(&show_error)
495
- end
496
-
497
- def send_request_without_catch(&block)
498
- Promise.new do |resolve, reject|
499
- begin
500
- resolve.(block.call)
501
- rescue Twitter::Error => reason
502
- reject.(reason)
503
- end
504
- end
505
- end
506
44
  end
507
45
  end
@@ -0,0 +1,82 @@
1
+ require 'twterm/user'
2
+ require 'twterm/utils'
3
+
4
+ module Twterm
5
+ class DirectMessage
6
+ attr_reader :id, :created_at, :recipient, :sender, :text
7
+
8
+ @@instances = {}
9
+
10
+ def initialize(message)
11
+ @id = message.id
12
+ update!(message)
13
+
14
+ @@instances[id] = self
15
+ end
16
+
17
+ def ==(other)
18
+ other.is_a?(self.class) && id == other.id
19
+ end
20
+
21
+ def date
22
+ format = Time.now - @created_at < 86_400 ? '%H:%M:%S' : '%Y-%m-%d %H:%M:%S'
23
+ @created_at.strftime(format)
24
+ end
25
+
26
+ def matches?(q)
27
+ [
28
+ sender.name,
29
+ sender.screen_name,
30
+ text
31
+ ].map(&:downcase).any? { |x| x.include?(q) }
32
+ end
33
+
34
+ def update!(message)
35
+ @created_at = message.created_at.dup.localtime
36
+ @recipient = User.new(message.recipient)
37
+ @sender = User.new(message.sender)
38
+ @text = message.text
39
+
40
+ self
41
+ end
42
+
43
+ class Conversation
44
+ include Utils
45
+
46
+ attr_reader :collocutor, :messages
47
+
48
+ def initialize(collocutor)
49
+ check_type User, collocutor
50
+
51
+ @collocutor = collocutor
52
+ @messages = []
53
+ end
54
+
55
+ def <<(message)
56
+ @messages << message if messages.find { |m| m == message }.nil?
57
+ @messages.sort_by!(&:created_at).reverse!
58
+
59
+ self
60
+ end
61
+
62
+ def matches?(q)
63
+ [
64
+ collocutor.screen_name,
65
+ collocutor.name,
66
+ preview
67
+ ].map(&:downcase).any? { |x| x.include?(q.downcase) }
68
+ end
69
+
70
+ def preview
71
+ messages.sort_by(&:created_at).last.text.gsub("\n", ' ')
72
+ end
73
+
74
+ def updated_at
75
+ updated_at = @messages.map(&:created_at).max
76
+
77
+ format = Time.now - updated_at < 86_400 ? '%H:%M:%S' : '%Y-%m-%d %H:%M:%S'
78
+ updated_at.strftime(format)
79
+ end
80
+ end
81
+ end
82
+ end