t 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/t.rb CHANGED
@@ -1,6 +1,6 @@
1
- require 'time'
2
1
  require 'active_support/string_inquirer'
3
2
  require 't/cli'
3
+ require 'time'
4
4
 
5
5
  module T
6
6
  class << self
@@ -1,9 +1,17 @@
1
- require 'oauth'
2
-
3
1
  module T
4
2
  module Authorizable
5
3
 
4
+ DEFAULT_HOST = 'api.twitter.com'
5
+ DEFAULT_PROTOCOL = 'https'
6
+
7
+ private
8
+
9
+ def base_url
10
+ "#{protocol}://#{host}"
11
+ end
12
+
6
13
  def consumer
14
+ require 'oauth'
7
15
  OAuth::Consumer.new(
8
16
  options['consumer-key'],
9
17
  options['consumer-secret'],
@@ -1,31 +1,18 @@
1
- require 'active_support/core_ext/array/grouping'
2
- require 'active_support/core_ext/date/calculations'
3
- require 'active_support/core_ext/integer/time'
4
- require 'active_support/core_ext/numeric/time'
5
- require 't/format_helpers'
6
- require 'csv'
7
- # 'fastercsv' required on Ruby versions < 1.9
8
- require 'fastercsv' unless Array.new.respond_to?(:to_csv)
9
- require 'open-uri'
10
- require 'retryable'
11
- require 't/authorizable'
12
- require 't/collectable'
13
- require 't/core_ext/string'
14
- require 't/delete'
15
- require 't/list'
16
- require 't/printable'
17
- require 't/rcfile'
18
- require 't/requestable'
19
- require 't/search'
20
- require 't/set'
21
- require 't/stream'
22
- require 't/version'
23
1
  require 'thor'
24
- require 'time'
25
- require 'twitter'
26
- require 'yaml'
27
2
 
28
3
  module T
4
+ autoload :Authorizable, 't/authorizable'
5
+ autoload :Collectable, 't/collectable'
6
+ autoload :Delete, 't/delete'
7
+ autoload :FormatHelpers, 't/format_helpers'
8
+ autoload :List, 't/list'
9
+ autoload :Printable, 't/printable'
10
+ autoload :RCFile, 't/rcfile'
11
+ autoload :Requestable, 't/requestable'
12
+ autoload :Search, 't/search'
13
+ autoload :Set, 't/set'
14
+ autoload :Stream, 't/stream'
15
+ autoload :Version, 't/version'
29
16
  class CLI < Thor
30
17
  include T::Authorizable
31
18
  include T::Collectable
@@ -105,11 +92,15 @@ module T
105
92
  method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify input as Twitter user IDs instead of screen names."
106
93
  def block(user, *users)
107
94
  users.unshift(user)
95
+ require 't/core_ext/string'
108
96
  if options['id']
109
97
  users.map!(&:to_i)
110
98
  else
111
99
  users.map!(&:strip_ats)
112
100
  end
101
+ require 't/core_ext/enumerable'
102
+ require 'retryable'
103
+ require 'twitter'
113
104
  users = users.threaded_map do |user|
114
105
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
115
106
  client.block(user)
@@ -132,10 +123,13 @@ module T
132
123
  client.direct_messages(opts)
133
124
  end
134
125
  direct_messages.reverse! if options['reverse']
126
+ require 'htmlentities'
135
127
  if options['csv']
128
+ require 'csv'
129
+ require 'fastercsv' unless Array.new.respond_to?(:to_csv)
136
130
  say DIRECT_MESSAGE_HEADINGS.to_csv unless direct_messages.empty?
137
131
  direct_messages.each do |direct_message|
138
- say [direct_message.id, csv_formatted_time(direct_message), direct_message.sender.screen_name, direct_message.text].to_csv
132
+ say [direct_message.id, csv_formatted_time(direct_message), direct_message.sender.screen_name, HTMLEntities.new.decode(direct_message.text)].to_csv
139
133
  end
140
134
  elsif options['long']
141
135
  array = direct_messages.map do |direct_message|
@@ -162,10 +156,13 @@ module T
162
156
  client.direct_messages_sent(opts)
163
157
  end
164
158
  direct_messages.reverse! if options['reverse']
159
+ require 'htmlentities'
165
160
  if options['csv']
161
+ require 'csv'
162
+ require 'fastercsv' unless Array.new.respond_to?(:to_csv)
166
163
  say DIRECT_MESSAGE_HEADINGS.to_csv unless direct_messages.empty?
167
164
  direct_messages.each do |direct_message|
168
- say [direct_message.id, csv_formatted_time(direct_message), direct_message.recipient.screen_name, direct_message.text].to_csv
165
+ say [direct_message.id, csv_formatted_time(direct_message), direct_message.recipient.screen_name, HTMLEntities.new.decode(direct_message.text)].to_csv
169
166
  end
170
167
  elsif options['long']
171
168
  array = direct_messages.map do |direct_message|
@@ -195,6 +192,7 @@ module T
195
192
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
196
193
  def groupies(user=nil)
197
194
  if user
195
+ require 't/core_ext/string'
198
196
  user = if options['id']
199
197
  user.to_i
200
198
  else
@@ -208,6 +206,10 @@ module T
208
206
  client.friend_ids(user, :cursor => cursor)
209
207
  end
210
208
  disciple_ids = (follower_ids - following_ids)
209
+ require 'active_support/core_ext/array/grouping'
210
+ require 't/core_ext/enumerable'
211
+ require 'retryable'
212
+ require 'twitter'
211
213
  users = disciple_ids.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_map do |disciple_id_group|
212
214
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
213
215
  client.users(disciple_id_group)
@@ -220,6 +222,7 @@ module T
220
222
  desc "dm USER MESSAGE", "Sends that person a Direct Message."
221
223
  method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
222
224
  def dm(user, message)
225
+ require 't/core_ext/string'
223
226
  user = if options['id']
224
227
  user.to_i
225
228
  else
@@ -238,6 +241,7 @@ module T
238
241
  list = owner
239
242
  owner = @rcfile.active_profile[0]
240
243
  else
244
+ require 't/core_ext/string'
241
245
  owner = if options['id']
242
246
  client.user(owner.to_i).screen_name
243
247
  else
@@ -247,6 +251,7 @@ module T
247
251
  if user.nil?
248
252
  user = @rcfile.active_profile[0]
249
253
  else
254
+ require 't/core_ext/string'
250
255
  user = if options['id']
251
256
  user = client.user(user.to_i).screen_name
252
257
  else
@@ -265,6 +270,7 @@ module T
265
270
  desc "does_follow USER [USER]", "Find out whether one user follows another."
266
271
  method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
267
272
  def does_follow(user1, user2=nil)
273
+ require 't/core_ext/string'
268
274
  user1 = if options['id']
269
275
  client.user(user1.to_i).screen_name
270
276
  else
@@ -292,6 +298,9 @@ module T
292
298
  def favorite(status_id, *status_ids)
293
299
  status_ids.unshift(status_id)
294
300
  status_ids.map!(&:to_i)
301
+ require 't/core_ext/enumerable'
302
+ require 'retryable'
303
+ require 'twitter'
295
304
  favorites = status_ids.threaded_map do |status_id|
296
305
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
297
306
  client.favorite(status_id)
@@ -312,6 +321,7 @@ module T
312
321
  method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
313
322
  def favorites(user=nil)
314
323
  if user
324
+ require 't/core_ext/string'
315
325
  user = if options['id']
316
326
  user.to_i
317
327
  else
@@ -330,11 +340,15 @@ module T
330
340
  method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify input as Twitter user IDs instead of screen names."
331
341
  def follow(user, *users)
332
342
  users.unshift(user)
343
+ require 't/core_ext/string'
333
344
  if options['id']
334
345
  users.map!(&:to_i)
335
346
  else
336
347
  users.map!(&:strip_ats)
337
348
  end
349
+ require 't/core_ext/enumerable'
350
+ require 'retryable'
351
+ require 'twitter'
338
352
  users = users.threaded_map do |user|
339
353
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
340
354
  client.follow(user)
@@ -360,6 +374,7 @@ module T
360
374
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
361
375
  def followings(user=nil)
362
376
  if user
377
+ require 't/core_ext/string'
363
378
  user = if options['id']
364
379
  user.to_i
365
380
  else
@@ -369,6 +384,10 @@ module T
369
384
  following_ids = collect_with_cursor do |cursor|
370
385
  client.friend_ids(user, :cursor => cursor)
371
386
  end
387
+ require 'active_support/core_ext/array/grouping'
388
+ require 't/core_ext/enumerable'
389
+ require 'retryable'
390
+ require 'twitter'
372
391
  users = following_ids.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_map do |following_id_group|
373
392
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
374
393
  client.users(following_id_group)
@@ -391,6 +410,7 @@ module T
391
410
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
392
411
  def followers(user=nil)
393
412
  if user
413
+ require 't/core_ext/string'
394
414
  user = if options['id']
395
415
  user.to_i
396
416
  else
@@ -400,6 +420,10 @@ module T
400
420
  follower_ids = collect_with_cursor do |cursor|
401
421
  client.follower_ids(user, :cursor => cursor)
402
422
  end
423
+ require 'active_support/core_ext/array/grouping'
424
+ require 't/core_ext/enumerable'
425
+ require 'retryable'
426
+ require 'twitter'
403
427
  users = follower_ids.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_map do |follower_id_group|
404
428
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
405
429
  client.users(follower_id_group)
@@ -422,6 +446,7 @@ module T
422
446
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
423
447
  def friends(user=nil)
424
448
  if user
449
+ require 't/core_ext/string'
425
450
  user = if options['id']
426
451
  user.to_i
427
452
  else
@@ -435,6 +460,10 @@ module T
435
460
  client.follower_ids(user, :cursor => cursor)
436
461
  end
437
462
  friend_ids = (following_ids & follower_ids)
463
+ require 'active_support/core_ext/array/grouping'
464
+ require 't/core_ext/enumerable'
465
+ require 'retryable'
466
+ require 'twitter'
438
467
  users = friend_ids.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_map do |friend_id_group|
439
468
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
440
469
  client.users(friend_id_group)
@@ -457,6 +486,7 @@ module T
457
486
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
458
487
  def leaders(user=nil)
459
488
  if user
489
+ require 't/core_ext/string'
460
490
  user = if options['id']
461
491
  user.to_i
462
492
  else
@@ -470,6 +500,10 @@ module T
470
500
  client.follower_ids(user, :cursor => cursor)
471
501
  end
472
502
  leader_ids = (following_ids - follower_ids)
503
+ require 'active_support/core_ext/array/grouping'
504
+ require 't/core_ext/enumerable'
505
+ require 'retryable'
506
+ require 'twitter'
473
507
  users = leader_ids.in_groups_of(MAX_USERS_PER_REQUEST, false).threaded_map do |leader_id_group|
474
508
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
475
509
  client.users(leader_id_group)
@@ -490,6 +524,7 @@ module T
490
524
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
491
525
  def lists(user=nil)
492
526
  if user
527
+ require 't/core_ext/string'
493
528
  user = if options['id']
494
529
  user.to_i
495
530
  else
@@ -534,6 +569,7 @@ module T
534
569
  status = client.status(user.to_i, :include_my_retweet => false)
535
570
  Launchy.open("https://twitter.com/#{status.from_user}/status/#{status.id}", :dry_run => options['display-url'])
536
571
  else
572
+ require 't/core_ext/string'
537
573
  Launchy.open("https://twitter.com/#{user.strip_ats}", :dry_run => options['display-url'])
538
574
  end
539
575
  end
@@ -543,13 +579,15 @@ module T
543
579
  def rate_limit
544
580
  rate_limit_status = client.rate_limit_status
545
581
  if options['csv']
582
+ require 'csv'
583
+ require 'fastercsv' unless Array.new.respond_to?(:to_csv)
546
584
  say ["Hourly limit", "Remaining hits", "Reset time"].to_csv
547
585
  say [rate_limit_status.hourly_limit, rate_limit_status.remaining_hits, csv_formatted_time(rate_limit_status, :reset_time)].to_csv
548
586
  else
549
587
  array = []
550
588
  array << ["Hourly limit", number_with_delimiter(rate_limit_status.hourly_limit)]
551
589
  array << ["Remaining hits", number_with_delimiter(rate_limit_status.remaining_hits)]
552
- array << ["Reset time", "#{ls_formatted_time(rate_limit_status, :reset_time)} (#{distance_of_time_in_words_to_now(rate_limit_status.reset_time)} from now)"]
590
+ array << ["Reset time", "#{ls_formatted_time(rate_limit_status, :reset_time)} (#{time_from_now_in_words(rate_limit_status.reset_time)} from now)"]
553
591
  print_table(array)
554
592
  end
555
593
  end
@@ -569,6 +607,7 @@ module T
569
607
  users += Twitter::Extractor.extract_mentioned_screen_names(status.full_text)
570
608
  users.uniq!
571
609
  end
610
+ require 't/core_ext/string'
572
611
  users.map!(&:prepend_at)
573
612
  opts = {:in_reply_to_status_id => status.id, :trim_user => true}
574
613
  opts.merge!(:lat => location.lat, :long => location.lng) if options['location']
@@ -582,11 +621,15 @@ module T
582
621
  method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify input as Twitter user IDs instead of screen names."
583
622
  def report_spam(user, *users)
584
623
  users.unshift(user)
624
+ require 't/core_ext/string'
585
625
  if options['id']
586
626
  users.map!(&:to_i)
587
627
  else
588
628
  users.map!(&:strip_ats)
589
629
  end
630
+ require 't/core_ext/enumerable'
631
+ require 'retryable'
632
+ require 'twitter'
590
633
  users = users.threaded_map do |user|
591
634
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
592
635
  client.report_spam(user)
@@ -601,6 +644,9 @@ module T
601
644
  def retweet(status_id, *status_ids)
602
645
  status_ids.unshift(status_id)
603
646
  status_ids.map!(&:to_i)
647
+ require 't/core_ext/enumerable'
648
+ require 'retryable'
649
+ require 'twitter'
604
650
  retweets = status_ids.threaded_map do |status_id|
605
651
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
606
652
  client.retweet(status_id, :trim_user => true)
@@ -621,6 +667,7 @@ module T
621
667
  method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
622
668
  def retweets(user=nil)
623
669
  if user
670
+ require 't/core_ext/string'
624
671
  user = if options['id']
625
672
  user.to_i
626
673
  else
@@ -661,7 +708,10 @@ module T
661
708
  elsif status.geo
662
709
  reverse_geocode(status.geo)
663
710
  end
711
+ require 'htmlentities'
664
712
  if options['csv']
713
+ require 'csv'
714
+ require 'fastercsv' unless Array.new.respond_to?(:to_csv)
665
715
  say ["ID", "Text", "Screen name", "Posted at", "Location", "Retweets", "Source", "URL"].to_csv
666
716
  say [status.id, HTMLEntities.new.decode(status.full_text), status.from_user, csv_formatted_time(status), location, status.retweet_count, strip_tags(status.source), "https://twitter.com/#{status.from_user}/status/#{status.id}"].to_csv
667
717
  else
@@ -693,6 +743,7 @@ module T
693
743
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
694
744
  def suggest(user=nil)
695
745
  if user
746
+ require 't/core_ext/string'
696
747
  user = if options['id']
697
748
  user.to_i
698
749
  else
@@ -713,6 +764,7 @@ module T
713
764
  def timeline(user=nil)
714
765
  count = options['number'] || DEFAULT_NUM_RESULTS
715
766
  if user
767
+ require 't/core_ext/string'
716
768
  user = if options['id']
717
769
  user.to_i
718
770
  else
@@ -749,6 +801,8 @@ module T
749
801
  places = places.sort_by{|places| places.name.downcase} unless options['unsorted']
750
802
  places.reverse! if options['reverse']
751
803
  if options['csv']
804
+ require 'csv'
805
+ require 'fastercsv' unless Array.new.respond_to?(:to_csv)
752
806
  say TREND_HEADINGS.to_csv unless places.empty?
753
807
  places.each do |place|
754
808
  say [place.woeid, place.parent_id, place.place_type, place.name, place.country].to_csv
@@ -769,11 +823,15 @@ module T
769
823
  method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify input as Twitter user IDs instead of screen names."
770
824
  def unfollow(user, *users)
771
825
  users.unshift(user)
826
+ require 't/core_ext/string'
772
827
  if options['id']
773
828
  users.map!(&:to_i)
774
829
  else
775
830
  users.map!(&:strip_ats)
776
831
  end
832
+ require 't/core_ext/enumerable'
833
+ require 'retryable'
834
+ require 'twitter'
777
835
  users = users.threaded_map do |user|
778
836
  retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
779
837
  client.unfollow(user)
@@ -811,6 +869,7 @@ module T
811
869
  method_option "unsorted", :aliases => "-u", :type => :boolean, :default => false, :desc => "Output is not sorted."
812
870
  def users(user, *users)
813
871
  users.unshift(user)
872
+ require 't/core_ext/string'
814
873
  if options['id']
815
874
  users.map!(&:to_i)
816
875
  else
@@ -831,13 +890,17 @@ module T
831
890
  method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
832
891
  method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
833
892
  def whois(user)
893
+ require 't/core_ext/string'
834
894
  user = if options['id']
835
895
  user.to_i
836
896
  else
837
897
  user.strip_ats
838
898
  end
839
899
  user = client.user(user)
900
+ require 'htmlentities'
840
901
  if options['csv']
902
+ require 'csv'
903
+ require 'fastercsv' unless Array.new.respond_to?(:to_csv)
841
904
  say ["ID", "Verified", "Name", "Screen name", "Bio", "Location", "Following", "Last update", "Lasted updated at", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "URL"].to_csv
842
905
  say [user.id, user.verified?, user.name, user.screen_name, user.description, user.location, user.following?, HTMLEntities.new.decode(user.status.text), csv_formatted_time(user.status), csv_formatted_time(user), user.statuses_count, user.favourites_count, user.listed_count, user.friends_count, user.followers_count, user.url].to_csv
843
906
  else
@@ -880,6 +943,7 @@ module T
880
943
  def location
881
944
  return @location if @location
882
945
  require 'geokit'
946
+ require 'open-uri'
883
947
  ip_address = Kernel::open("http://checkip.dyndns.org/") do |body|
884
948
  /(?:\d{1,3}\.){3}\d{1,3}/.match(body.read)[0]
885
949
  end
@@ -1,5 +1,3 @@
1
- require 'retryable'
2
-
3
1
  module T
4
2
  module Collectable
5
3
 
@@ -10,6 +8,8 @@ module T
10
8
  end
11
9
 
12
10
  def collect_with_cursor(collection=[], cursor=-1, &block)
11
+ require 'retryable'
12
+ require 'twitter'
13
13
  object = retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
14
14
  yield cursor
15
15
  end
@@ -18,6 +18,8 @@ module T
18
18
  end
19
19
 
20
20
  def collect_with_max_id(collection=[], max_id=nil, &block)
21
+ require 'retryable'
22
+ require 'twitter'
21
23
  array = retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
22
24
  yield max_id
23
25
  end
@@ -33,8 +35,9 @@ module T
33
35
  opts[:max_id] = max_id unless max_id.nil?
34
36
  opts[key] = number unless number >= MAX_NUM_RESULTS
35
37
  if number > 0
36
- number -= MAX_NUM_RESULTS
37
- yield opts
38
+ statuses = yield opts
39
+ number -= statuses.length
40
+ statuses
38
41
  end
39
42
  end.flatten.compact
40
43
  end