t 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,3 +5,4 @@ rvm:
5
5
  - 1.9.3
6
6
  - rbx-18mode
7
7
  - rbx-19mode
8
+ - ruby-head
@@ -3,14 +3,17 @@ require 'active_support/core_ext/array/grouping'
3
3
  require 'active_support/core_ext/date/calculations'
4
4
  require 'active_support/core_ext/integer/time'
5
5
  require 'active_support/core_ext/numeric/time'
6
- require 'highline'
6
+ require 'geokit'
7
7
  require 'launchy'
8
8
  require 'oauth'
9
+ require 'open-uri'
9
10
  require 't/collectable'
10
11
  require 't/core_ext/string'
11
12
  require 't/delete'
12
13
  require 't/list'
14
+ require 't/printable'
13
15
  require 't/rcfile'
16
+ require 't/requestable'
14
17
  require 't/search'
15
18
  require 't/set'
16
19
  require 't/version'
@@ -23,10 +26,11 @@ module T
23
26
  class CLI < Thor
24
27
  include ActionView::Helpers::DateHelper
25
28
  include ActionView::Helpers::NumberHelper
29
+ include ActionView::Helpers::TextHelper
26
30
  include T::Collectable
31
+ include T::Printable
32
+ include T::Requestable
27
33
 
28
- DEFAULT_HOST = 'api.twitter.com'
29
- DEFAULT_PROTOCOL = 'https'
30
34
  DEFAULT_NUM_RESULTS = 20
31
35
  MAX_SCREEN_NAME_SIZE = 20
32
36
  MAX_USERS_PER_REQUEST = 100
@@ -95,7 +99,7 @@ module T
95
99
  def block(screen_name, *screen_names)
96
100
  screen_names.unshift(screen_name)
97
101
  screen_names.threaded_each do |screen_name|
98
- screen_name.strip_at
102
+ screen_name.strip_ats
99
103
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
100
104
  client.block(screen_name, :include_entities => false)
101
105
  end
@@ -107,8 +111,8 @@ module T
107
111
 
108
112
  desc "direct_messages", "Returns the #{DEFAULT_NUM_RESULTS} most recent Direct Messages sent to you."
109
113
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
110
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
111
- method_option :reverse, :aliases => "-r", :type => :boolean, :default => false
114
+ method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
115
+ method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
112
116
  def direct_messages
113
117
  count = options['number'] || DEFAULT_NUM_RESULTS
114
118
  direct_messages = client.direct_messages(:count => count, :include_entities => false)
@@ -116,11 +120,11 @@ module T
116
120
  if options['long']
117
121
  array = direct_messages.map do |direct_message|
118
122
  created_at = direct_message.created_at > 6.months.ago ? direct_message.created_at.strftime("%b %e %H:%M") : direct_message.created_at.strftime("%b %e %Y")
119
- [direct_message.id.to_s, created_at, direct_message.sender.screen_name, direct_message.text.gsub(/\n+/, ' ')]
123
+ [number_with_delimiter(direct_message.id), created_at, direct_message.sender.screen_name, direct_message.text.gsub(/\n+/, ' ')]
120
124
  end
121
125
  if STDOUT.tty?
122
- headings = ["ID", "Created at", "Screen name", "Text"]
123
- array.unshift(headings)
126
+ headings = ["ID", "Posted at", "Screen name", "Text"]
127
+ array.unshift(headings) unless direct_messages.empty?
124
128
  end
125
129
  print_table(array)
126
130
  else
@@ -133,8 +137,8 @@ module T
133
137
 
134
138
  desc "direct_messages_sent", "Returns the #{DEFAULT_NUM_RESULTS} most recent Direct Messages sent to you."
135
139
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
136
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
137
- method_option :reverse, :aliases => "-r", :type => :boolean, :default => false
140
+ method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
141
+ method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
138
142
  def direct_messages_sent
139
143
  count = options['number'] || DEFAULT_NUM_RESULTS
140
144
  direct_messages = client.direct_messages_sent(:count => count, :include_entities => false)
@@ -142,11 +146,11 @@ module T
142
146
  if options['long']
143
147
  array = direct_messages.map do |direct_message|
144
148
  created_at = direct_message.created_at > 6.months.ago ? direct_message.created_at.strftime("%b %e %H:%M") : direct_message.created_at.strftime("%b %e %Y")
145
- [direct_message.id.to_s, created_at, direct_message.recipient.screen_name, direct_message.text.gsub(/\n+/, ' ')]
149
+ [number_with_delimiter(direct_message.id), created_at, direct_message.recipient.screen_name, direct_message.text.gsub(/\n+/, ' ')]
146
150
  end
147
151
  if STDOUT.tty?
148
- headings = ["ID", "Created at", "Screen name", "Text"]
149
- array.unshift(headings)
152
+ headings = ["ID", "Posted at", "Screen name", "Text"]
153
+ array.unshift(headings) unless direct_messages.empty?
150
154
  end
151
155
  print_table(array)
152
156
  else
@@ -159,7 +163,7 @@ module T
159
163
 
160
164
  desc "dm SCREEN_NAME MESSAGE", "Sends that person a Direct Message."
161
165
  def dm(screen_name, message)
162
- screen_name = screen_name.strip_at
166
+ screen_name = screen_name.strip_ats
163
167
  direct_message = client.direct_message_create(screen_name, message, :include_entities => false)
164
168
  say "Direct Message sent from @#{@rcfile.default_profile[0]} to @#{direct_message.recipient.screen_name} (#{time_ago_in_words(direct_message.created_at)} ago)."
165
169
  end
@@ -168,6 +172,7 @@ module T
168
172
  desc "favorite STATUS_ID [STATUS_ID...]", "Marks Tweets as favorites."
169
173
  def favorite(status_id, *status_ids)
170
174
  status_ids.unshift(status_id)
175
+ status_ids.map!(&:strip_commas).map!(&:to_i)
171
176
  favorites = status_ids.threaded_map do |status_id|
172
177
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
173
178
  client.favorite(status_id, :include_entities => false)
@@ -183,8 +188,8 @@ module T
183
188
 
184
189
  desc "favorites", "Returns the #{DEFAULT_NUM_RESULTS} most recent Tweets you favorited."
185
190
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
186
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
187
- method_option :reverse, :aliases => "-r", :type => :boolean, :default => false
191
+ method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
192
+ method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
188
193
  def favorites
189
194
  count = options['number'] || DEFAULT_NUM_RESULTS
190
195
  statuses = client.favorites(:count => count, :include_entities => false)
@@ -208,14 +213,14 @@ module T
208
213
 
209
214
  desc "followings", "Returns a list of the people you follow on Twitter."
210
215
  method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created."
211
- method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
212
- method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
216
+ method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by number of favorites."
217
+ method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
218
+ method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of friends."
213
219
  method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
214
220
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
215
221
  method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
216
- method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets."
222
+ method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by number of Tweets."
217
223
  method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
218
- method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites."
219
224
  def followings
220
225
  following_ids = collect_with_cursor do |cursor|
221
226
  client.friend_ids(:cursor => cursor)
@@ -230,14 +235,14 @@ module T
230
235
 
231
236
  desc "followers", "Returns a list of the people who follow you on Twitter."
232
237
  method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created."
233
- method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
234
- method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
238
+ method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by number of favorites."
239
+ method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
240
+ method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of friends."
235
241
  method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
236
242
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
237
243
  method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
238
- method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets."
244
+ method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by number of Tweets."
239
245
  method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
240
- method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites."
241
246
  def followers
242
247
  follower_ids = collect_with_cursor do |cursor|
243
248
  client.follower_ids(:cursor => cursor)
@@ -252,14 +257,14 @@ module T
252
257
 
253
258
  desc "friends", "Returns the list of people who you follow and follow you back."
254
259
  method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created."
255
- method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
256
- method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
260
+ method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by number of favorites."
261
+ method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
262
+ method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of friends."
257
263
  method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
258
264
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
259
265
  method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
260
- method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets."
266
+ method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by number of Tweets."
261
267
  method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
262
- method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites."
263
268
  def friends
264
269
  following_ids = collect_with_cursor do |cursor|
265
270
  client.friend_ids(:cursor => cursor)
@@ -278,14 +283,14 @@ module T
278
283
 
279
284
  desc "leaders", "Returns the list of people who you follow but don't follow you back."
280
285
  method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created."
281
- method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
282
- method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
286
+ method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by number of favorites."
287
+ method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
288
+ method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of friends."
283
289
  method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
284
290
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
285
291
  method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
286
- method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets."
292
+ method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by number of Tweets."
287
293
  method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
288
- method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites."
289
294
  def leaders
290
295
  following_ids = collect_with_cursor do |cursor|
291
296
  client.friend_ids(:cursor => cursor)
@@ -302,30 +307,10 @@ module T
302
307
  print_user_list(users)
303
308
  end
304
309
 
305
- desc "members [SCREEN_NAME] LIST_NAME", "Returns the members of a Twitter list."
306
- method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created."
307
- method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
308
- method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
309
- method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
310
- method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
311
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
312
- method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
313
- method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets."
314
- method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
315
- method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites."
316
- def members(*args)
317
- list = args.pop
318
- owner = args.pop || @rcfile.default_profile[0]
319
- users = collect_with_cursor do |cursor|
320
- client.list_members(owner, list, :cursor => cursor, :include_entities => false, :skip_status => true)
321
- end
322
- print_user_list(users)
323
- end
324
-
325
310
  desc "mentions", "Returns the #{DEFAULT_NUM_RESULTS} most recent Tweets mentioning you."
326
311
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
327
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
328
- method_option :reverse, :aliases => "-r", :type => :boolean, :default => false
312
+ method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
313
+ method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
329
314
  def mentions
330
315
  count = options['number'] || DEFAULT_NUM_RESULTS
331
316
  statuses = client.mentions(:count => count, :include_entities => false)
@@ -336,13 +321,14 @@ module T
336
321
  desc "open SCREEN_NAME", "Opens that user's profile in a web browser."
337
322
  method_option :dry_run, :type => :boolean
338
323
  def open(screen_name)
339
- screen_name = screen_name.strip_at
324
+ screen_name = screen_name.strip_ats
340
325
  Launchy.open("https://twitter.com/#{screen_name}", :dry_run => options.fetch('dry_run', false))
341
326
  end
342
327
 
343
328
  desc "reply STATUS_ID MESSAGE", "Post your Tweet as a reply directed at another person."
344
329
  method_option :location, :aliases => "-l", :type => :boolean, :default => false
345
330
  def reply(status_id, message)
331
+ status_id = status_id.strip_commas
346
332
  status = client.status(status_id, :include_entities => false, :include_my_retweet => false, :trim_user => true)
347
333
  opts = {:in_reply_to_status_id => status.id, :include_entities => false, :trim_user => true}
348
334
  opts.merge!(:lat => location.lat, :long => location.lng) if options['location']
@@ -356,7 +342,7 @@ module T
356
342
  def report_spam(screen_name, *screen_names)
357
343
  screen_names.unshift(screen_name)
358
344
  screen_names.threaded_each do |screen_name|
359
- screen_name.strip_at
345
+ screen_name.strip_ats
360
346
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
361
347
  client.report_spam(screen_name, :include_entities => false)
362
348
  end
@@ -368,6 +354,7 @@ module T
368
354
  desc "retweet STATUS_ID [STATUS_ID...]", "Sends Tweets to your followers."
369
355
  def retweet(status_id, *status_ids)
370
356
  status_ids.unshift(status_id)
357
+ status_ids.map!(&:strip_commas).map!(&:to_i)
371
358
  retweets = status_ids.threaded_map do |status_id|
372
359
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
373
360
  client.retweet(status_id, :include_entities => false, :trim_user => true)
@@ -383,39 +370,52 @@ module T
383
370
 
384
371
  desc "retweets [SCREEN_NAME]", "Returns the #{DEFAULT_NUM_RESULTS} most recent Retweets by a user."
385
372
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
386
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
387
- method_option :reverse, :aliases => "-r", :type => :boolean, :default => false
373
+ method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
374
+ method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
388
375
  def retweets(screen_name=nil)
389
- screen_name = screen_name.strip_at if screen_name
376
+ screen_name = screen_name.strip_ats if screen_name
390
377
  count = options['number'] || DEFAULT_NUM_RESULTS
391
378
  statuses = client.retweeted_by(screen_name, :count => count, :include_entities => false)
392
379
  print_status_list(statuses)
393
380
  end
394
381
  map %w(rts) => :retweets
395
382
 
396
- desc "status MESSAGE", "Post a Tweet."
397
- method_option :location, :aliases => "-l", :type => :boolean, :default => false
398
- def status(message)
399
- opts = {:include_entities => false, :trim_user => true}
400
- opts.merge!(:lat => location.lat, :long => location.lng) if options['location']
401
- status = client.update(message, opts)
402
- say "Tweet created by @#{@rcfile.default_profile[0]} (#{time_ago_in_words(status.created_at)} ago)."
403
- say
404
- say "Run `#{File.basename($0)} delete status #{status.id}` to delete."
383
+ desc "status STATUS_ID", "Retrieves detailed information about a Tweet."
384
+ def status(status_id)
385
+ status_id = status_id.strip_commas
386
+ status = client.status(status_id, :include_entities => false, :include_my_retweet => false)
387
+ created_at = status.created_at > 6.months.ago ? status.created_at.strftime("%b %e %H:%M") : status.created_at.strftime("%b %e %Y")
388
+ array = []
389
+ array << ["Text", status.text.gsub(/\n+/, ' ')]
390
+ array << ["Screen name", "@#{status.user.screen_name}"]
391
+ array << ["Posted at", created_at]
392
+ unless status.geo.nil?
393
+ location = Geokit::Geocoders::MultiGeocoder.reverse_geocode(status.geo.coordinates)
394
+ if location.city && location.state && location.country
395
+ array << ["Location", [location.city, location.state, location.country].join(", ")]
396
+ elsif location.state && location.country
397
+ array << ["Location", [location.state, location.country].join(", ")]
398
+ elsif location.country
399
+ array << ["Location", [location.country].join(", ")]
400
+ end
401
+ end
402
+ array << ["Retweets", number_with_delimiter(status.retweet_count)] unless status.retweet_count.zero?
403
+ array << ["Source", strip_tags(status.source)]
404
+ array << ["URL", "https://twitter.com/#{status.user.screen_name}/status/#{status.id}"]
405
+ print_table(array)
405
406
  end
406
- map %w(post tweet update) => :status
407
407
 
408
408
  desc "suggest", "This command returns a listing of Twitter users' accounts we think you might enjoy following."
409
409
  method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created."
410
- method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
410
+ method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by number of favorites."
411
+ method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
412
+ method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of friends."
411
413
  method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
412
414
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
413
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
414
- method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
415
+ method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
415
416
  method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
416
- method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets."
417
+ method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by number of Tweets."
417
418
  method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
418
- method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites."
419
419
  def suggest
420
420
  limit = options['number'] || DEFAULT_NUM_RESULTS
421
421
  users = client.recommendations(:limit => limit, :include_entities => false)
@@ -424,12 +424,12 @@ module T
424
424
 
425
425
  desc "timeline [SCREEN_NAME]", "Returns the #{DEFAULT_NUM_RESULTS} most recent Tweets posted by a user."
426
426
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
427
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
428
- method_option :reverse, :aliases => "-r", :type => :boolean, :default => false
427
+ method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
428
+ method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
429
429
  def timeline(screen_name=nil)
430
430
  count = options['number'] || DEFAULT_NUM_RESULTS
431
431
  if screen_name
432
- screen_name = screen_name.strip_at
432
+ screen_name = screen_name.strip_ats
433
433
  statuses = client.user_timeline(screen_name, :count => count, :include_entities => false)
434
434
  else
435
435
  statuses = client.home_timeline(:count => count, :include_entities => false)
@@ -452,17 +452,28 @@ module T
452
452
  say "Run `#{File.basename($0)} follow users #{screen_names.join(' ')}` to follow again."
453
453
  end
454
454
 
455
+ desc "update MESSAGE", "Post a Tweet."
456
+ method_option :location, :aliases => "-l", :type => :boolean, :default => false
457
+ def update(message)
458
+ opts = {:include_entities => false, :trim_user => true}
459
+ opts.merge!(:lat => location.lat, :long => location.lng) if options['location']
460
+ status = client.update(message, opts)
461
+ say "Tweet created by @#{@rcfile.default_profile[0]} (#{time_ago_in_words(status.created_at)} ago)."
462
+ say
463
+ say "Run `#{File.basename($0)} delete status #{status.id}` to delete."
464
+ end
465
+ map %w(post tweet) => :update
466
+
455
467
  desc "users SCREEN_NAME [SCREEN_NAME...]", "Returns a list of users you specify."
456
468
  method_option :created, :aliases => "-c", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter acount was created."
457
- method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
458
- method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
469
+ method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by number of favorites."
470
+ method_option :followers, :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
471
+ method_option :friends, :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of friends."
459
472
  method_option :listed, :aliases => "-i", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
460
473
  method_option :long, :aliases => "-l", :type => :boolean, :default => false, :desc => "List in long format."
461
- method_option :number, :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS
462
474
  method_option :reverse, :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
463
- method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by total number of Tweets."
475
+ method_option :tweets, :aliases => "-t", :type => :boolean, :default => false, :desc => "Sort by number of Tweets."
464
476
  method_option :unsorted, :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
465
- method_option :favorites, :aliases => "-v", :type => :boolean, :default => false, :desc => "Sort by total number of favorites."
466
477
  def users(screen_name, *screen_names)
467
478
  screen_names.unshift(screen_name)
468
479
  users = client.users(screen_names, :include_entities => false)
@@ -478,13 +489,26 @@ module T
478
489
 
479
490
  desc "whois SCREEN_NAME", "Retrieves profile information for the user."
480
491
  def whois(screen_name)
481
- screen_name = screen_name.strip_at
492
+ screen_name = screen_name.strip_ats
482
493
  user = client.user(screen_name, :include_entities => false)
483
- say "id: ##{number_with_delimiter(user.id)}"
484
- say "#{user.name}, since #{user.created_at.strftime("%b %Y")}."
485
- say "bio: #{user.description}"
486
- say "location: #{user.location}"
487
- say "web: #{user.url}"
494
+ array = []
495
+ name_label = user.verified ? "Name (Verified)" : "Name"
496
+ array << ["ID", number_with_delimiter(user.id)]
497
+ array << [name_label, user.name] unless user.name.nil?
498
+ array << ["Bio", user.description.gsub(/\n+/, ' ')] unless user.description.nil?
499
+ array << ["Location", user.location] unless user.location.nil?
500
+ array << ["URL", user.url] unless user.url.nil?
501
+ following = user.following ? "Following" : "Not following"
502
+ array << ["Status", following] unless user.following.nil?
503
+ array << ["Last update", "#{user.status.text.gsub(/\n+/, ' ')} (#{time_ago_in_words(user.status.created_at)} ago)"] unless user.status.nil?
504
+ created_at = user.created_at > 6.months.ago ? user.created_at.strftime("%b %e %H:%M") : user.created_at.strftime("%b %e %Y")
505
+ array << ["Since", created_at]
506
+ array << ["Tweets", number_with_delimiter(user.statuses_count)]
507
+ array << ["Favorites", number_with_delimiter(user.favourites_count)]
508
+ array << ["Listed", number_with_delimiter(user.listed_count)]
509
+ array << ["Following", number_with_delimiter(user.friends_count)]
510
+ array << ["Followers", number_with_delimiter(user.followers_count)]
511
+ print_table(array)
488
512
  end
489
513
 
490
514
  desc "delete SUBCOMMAND ...ARGS", "Delete Tweets, Direct Messages, etc."
@@ -503,22 +527,6 @@ module T
503
527
 
504
528
  private
505
529
 
506
- def base_url
507
- "#{protocol}://#{host}"
508
- end
509
-
510
- def client
511
- return @client if @client
512
- @rcfile.path = options['profile'] if options['profile']
513
- @client = Twitter::Client.new(
514
- :endpoint => base_url,
515
- :consumer_key => @rcfile.default_consumer_key,
516
- :consumer_secret => @rcfile.default_consumer_secret,
517
- :oauth_token => @rcfile.default_token,
518
- :oauth_token_secret => @rcfile.default_secret
519
- )
520
- end
521
-
522
530
  def consumer
523
531
  OAuth::Consumer.new(
524
532
  options['consumer_key'],
@@ -537,14 +545,8 @@ module T
537
545
  "#{base_url}#{request.path}?#{params}"
538
546
  end
539
547
 
540
- def host
541
- options['host'] || DEFAULT_HOST
542
- end
543
-
544
548
  def location
545
549
  return @location if @location
546
- require 'geokit'
547
- require 'open-uri'
548
550
  ip_address = Kernel::open("http://checkip.dyndns.org/") do |body|
549
551
  /(?:\d{1,3}\.){3}\d{1,3}/.match(body.read)[0]
550
552
  end
@@ -555,75 +557,5 @@ module T
555
557
  {:oauth_callback => 'oob'}
556
558
  end
557
559
 
558
- def print_in_columns(array)
559
- cols = HighLine::SystemExtensions.terminal_size[0]
560
- width = (array.map{|el| el.to_s.size}.max || 0) + 2
561
- array.each_with_index do |value, index|
562
- puts if (((index) % (cols / width))).zero? && !index.zero?
563
- printf("%-#{width}s", value)
564
- end
565
- puts
566
- end
567
-
568
- def print_status_list(statuses)
569
- statuses.reverse! if options['reverse']
570
- if options['long']
571
- array = statuses.map do |status|
572
- created_at = status.created_at > 6.months.ago ? status.created_at.strftime("%b %e %H:%M") : status.created_at.strftime("%b %e %Y")
573
- [status.id.to_s, created_at, status.user.screen_name, status.text.gsub(/\n+/, ' ')]
574
- end
575
- if STDOUT.tty?
576
- headings = ["ID", "Created at", "Screen name", "Text"]
577
- array.unshift(headings)
578
- end
579
- print_table(array)
580
- else
581
- statuses.each do |status|
582
- say "#{status.user.screen_name.rjust(MAX_SCREEN_NAME_SIZE)}: #{status.text.gsub(/\n+/, ' ')} (#{time_ago_in_words(status.created_at)} ago)"
583
- end
584
- end
585
- end
586
-
587
- def print_user_list(users)
588
- users = users.sort_by{|user| user.screen_name.downcase} unless options['unsorted']
589
- if options['created']
590
- users = users.sort_by{|user| user.created_at}
591
- elsif options['favorites']
592
- users = users.sort_by{|user| user.favourites_count}
593
- elsif options['followers']
594
- users = users.sort_by{|user| user.followers_count}
595
- elsif options['friends']
596
- users = users.sort_by{|user| user.friends_count}
597
- elsif options['listed']
598
- users = users.sort_by{|user| user.listed_count}
599
- elsif options['tweets']
600
- users = users.sort_by{|user| user.statuses_count}
601
- end
602
- users.reverse! if options['reverse']
603
- if options['long']
604
- array = users.map do |user|
605
- created_at = user.created_at > 6.months.ago ? user.created_at.strftime("%b %e %H:%M") : user.created_at.strftime("%b %e %Y")
606
- [user.id, created_at, user.statuses_count, user.friends_count, user.followers_count, user.favourites_count, user.listed_count, user.screen_name, user.name]
607
- end
608
- if STDOUT.tty?
609
- headings = ["ID", "Created at", "Tweets", "Following", "Followers", "Favorites", "Listed", "Screen name", "Name"]
610
- array.unshift(headings)
611
- end
612
- print_table(array)
613
- else
614
- if STDOUT.tty?
615
- print_in_columns(users.map(&:screen_name))
616
- else
617
- users.map(&:screen_name).each do |user|
618
- say user
619
- end
620
- end
621
- end
622
- end
623
-
624
- def protocol
625
- options['no_ssl'] ? 'http' : DEFAULT_PROTOCOL
626
- end
627
-
628
560
  end
629
561
  end