t 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Twitter CLI [![Build Status](https://secure.travis-ci.org/sferik/t.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/sferik/t.png?travis)][gemnasium]
1
+ # Twitter CLI [![Build Status](https://secure.travis-ci.org/sferik/t.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/sferik/t.png?travis)][gemnasium] [![Click here to make a donation to T](http://www.pledgie.com/campaigns/17330.png)][pledgie]
2
2
  ### A command-line power tool for Twitter.
3
3
 
4
4
  The CLI takes syntactic cues from the [Twitter SMS commands][sms], however it
@@ -6,6 +6,7 @@ offers vastly more commands and capabilities than are available via SMS.
6
6
 
7
7
  [travis]: http://travis-ci.org/sferik/t
8
8
  [gemnasium]: https://gemnasium.com/sferik/t
9
+ [pledgie]: http://www.pledgie.com/campaigns/17330
9
10
  [gem]: https://rubygems.org/gems/twitter
10
11
  [sms]: https://support.twitter.com/articles/14020-twitter-sms-command
11
12
 
@@ -198,10 +199,10 @@ the original code.
198
199
  ![History](https://github.com/sferik/t/raw/master/screenshots/history.png)
199
200
 
200
201
  ## Contributing
201
- In the spirit of [free software][fsf], **everyone** is encouraged to help
202
+ In the spirit of [free software][free-sw], **everyone** is encouraged to help
202
203
  improve this project.
203
204
 
204
- [fsf]: http://www.fsf.org/licensing/essays/free-sw.html
205
+ [free-sw]: http://www.fsf.org/licensing/essays/free-sw.html
205
206
 
206
207
  Here are some ways *you* can contribute:
207
208
 
@@ -215,6 +216,7 @@ Here are some ways *you* can contribute:
215
216
  * by refactoring code
216
217
  * by fixing [issues][]
217
218
  * by reviewing patches
219
+ * [financially][pledgie]
218
220
 
219
221
  [issues]: https://github.com/sferik/t/issues
220
222
 
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env rake
2
-
3
1
  require 'bundler'
4
2
  Bundler::GemHelper.install_tasks
5
3
 
data/lib/t.rb CHANGED
@@ -1 +1,16 @@
1
+ require 'active_support/string_inquirer'
1
2
  require 't/cli'
3
+
4
+ module T
5
+ class << self
6
+
7
+ def env
8
+ @env
9
+ end
10
+
11
+ def env=(environment)
12
+ @env = ActiveSupport::StringInquirer.new(environment)
13
+ end
14
+
15
+ end
16
+ end
data/lib/t/cli.rb CHANGED
@@ -7,6 +7,7 @@ require 'csv'
7
7
  # 'fastercsv' required on Ruby versions < 1.9
8
8
  require 'fastercsv' unless Array.new.respond_to?(:to_csv)
9
9
  require 'open-uri'
10
+ require 'retryable'
10
11
  require 't/authorizable'
11
12
  require 't/collectable'
12
13
  require 't/core_ext/string'
@@ -41,7 +42,7 @@ module T
41
42
  check_unknown_options!
42
43
 
43
44
  option "host", :aliases => "-H", :type => :string, :default => DEFAULT_HOST, :desc => "Twitter API server"
44
- option "no-color", :aliases => "-N", :type => :boolean, :banner => "Disable colorization in output"
45
+ option "no-color", :aliases => "-N", :type => :boolean, :desc => "Disable colorization in output"
45
46
  option "no-ssl", :aliases => "-U", :type => :boolean, :default => false, :desc => "Disable SSL"
46
47
  option "profile", :aliases => "-P", :type => :string, :default => File.join(File.expand_path("~"), RCFile::FILE_NAME), :desc => "Path to RC file", :banner => "FILE"
47
48
 
@@ -62,8 +63,8 @@ module T
62
63
  end
63
64
 
64
65
  desc "authorize", "Allows an application to request user authorization"
65
- method_option "consumer-key", :aliases => "-c", :required => true, :desc => "This can be found at https://dev.twitter.com/apps"
66
- method_option "consumer-secret", :aliases => "-s", :required => true, :desc => "This can be found at https://dev.twitter.com/apps"
66
+ method_option "consumer-key", :aliases => "-c", :required => true, :desc => "This can be found at https://dev.twitter.com/apps", :banner => "KEY"
67
+ method_option "consumer-secret", :aliases => "-s", :required => true, :desc => "This can be found at https://dev.twitter.com/apps", :banner => "SECRET"
67
68
  method_option "display-url", :aliases => "-d", :type => :boolean, :default => false, :desc => "Display the authorization URL instead of attempting to open it."
68
69
  method_option "prompt", :aliases => "-p", :type => :boolean, :default => true
69
70
  def authorize
@@ -132,22 +133,15 @@ module T
132
133
  end
133
134
  direct_messages.reverse! if options['reverse']
134
135
  if options['csv']
135
- say ["ID", "Posted at", "Screen name", "Text"].to_csv unless direct_messages.empty?
136
+ say DIRECT_MESSAGE_HEADINGS.to_csv unless direct_messages.empty?
136
137
  direct_messages.each do |direct_message|
137
- say [direct_message.id, direct_message.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), direct_message.sender.screen_name, direct_message.text].to_csv
138
+ say [direct_message.id, csv_formatted_time(direct_message), direct_message.sender.screen_name, direct_message.text].to_csv
138
139
  end
139
140
  elsif options['long']
140
141
  array = direct_messages.map do |direct_message|
141
- 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")
142
- [direct_message.id, created_at, "@#{direct_message.sender.screen_name}", HTMLEntities.new.decode(direct_message.text).gsub(/\n+/, ' ')]
143
- end
144
- if STDOUT.tty?
145
- headings = ["ID", "Posted at", "Screen name", "Text"]
146
- array.unshift(headings) unless direct_messages.empty?
147
- print_table(array, :truncate => true)
148
- else
149
- print_table(array)
142
+ [direct_message.id, ls_formatted_time(direct_message), "@#{direct_message.sender.screen_name}", HTMLEntities.new.decode(direct_message.text).gsub(/\n+/, ' ')]
150
143
  end
144
+ print_table_with_headings(array, DIRECT_MESSAGE_HEADINGS)
151
145
  else
152
146
  direct_messages.each do |direct_message|
153
147
  say "#{direct_message.sender.screen_name.rjust(MAX_SCREEN_NAME_SIZE)}: #{direct_message.text.gsub(/\n+/, ' ')} (#{time_ago_in_words(direct_message.created_at)} ago)"
@@ -168,22 +162,15 @@ module T
168
162
  end
169
163
  direct_messages.reverse! if options['reverse']
170
164
  if options['csv']
171
- say ["ID", "Posted at", "Screen name", "Text"].to_csv unless direct_messages.empty?
165
+ say DIRECT_MESSAGE_HEADINGS.to_csv unless direct_messages.empty?
172
166
  direct_messages.each do |direct_message|
173
- say [direct_message.id, direct_message.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), direct_message.recipient.screen_name, direct_message.text].to_csv
167
+ say [direct_message.id, csv_formatted_time(direct_message), direct_message.recipient.screen_name, direct_message.text].to_csv
174
168
  end
175
169
  elsif options['long']
176
170
  array = direct_messages.map do |direct_message|
177
- 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")
178
- [direct_message.id, created_at, "@#{direct_message.recipient.screen_name}", HTMLEntities.new.decode(direct_message.text).gsub(/\n+/, ' ')]
179
- end
180
- if STDOUT.tty?
181
- headings = ["ID", "Posted at", "Screen name", "Text"]
182
- array.unshift(headings) unless direct_messages.empty?
183
- print_table(array, :truncate => true)
184
- else
185
- print_table(array)
171
+ [direct_message.id, ls_formatted_time(direct_message), "@#{direct_message.recipient.screen_name}", HTMLEntities.new.decode(direct_message.text).gsub(/\n+/, ' ')]
186
172
  end
173
+ print_table_with_headings(array, DIRECT_MESSAGE_HEADINGS)
187
174
  else
188
175
  direct_messages.each do |direct_message|
189
176
  say "#{direct_message.recipient.screen_name.rjust(MAX_SCREEN_NAME_SIZE)}: #{direct_message.text.gsub(/\n+/, ' ')} (#{time_ago_in_words(direct_message.created_at)} ago)"
@@ -512,6 +499,11 @@ module T
512
499
  print_lists(lists)
513
500
  end
514
501
 
502
+ desc "matrix", "Unfortunately, no one can be told what the Matrix is. You have to see it for yourself."
503
+ def matrix
504
+ T::Stream.new.matrix
505
+ end
506
+
515
507
  desc "mentions", "Returns the #{DEFAULT_NUM_RESULTS} most recent Tweets mentioning you."
516
508
  method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
517
509
  method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
@@ -537,19 +529,36 @@ module T
537
529
  Launchy.open("https://twitter.com/#{user.screen_name}", :dry_run => options['display-url'])
538
530
  elsif options['status']
539
531
  status = client.status(user.to_i, :include_my_retweet => false)
540
- Launchy.open("https://twitter.com/#{status.user.screen_name}/status/#{status.id}", :dry_run => options['display-url'])
532
+ Launchy.open("https://twitter.com/#{status.from_user}/status/#{status.id}", :dry_run => options['display-url'])
541
533
  else
542
534
  Launchy.open("https://twitter.com/#{user.strip_ats}", :dry_run => options['display-url'])
543
535
  end
544
536
  end
545
537
 
538
+ desc "rate_limit", "Returns information related to Twitter API rate limiting."
539
+ method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
540
+ def rate_limit
541
+ rate_limit_status = client.rate_limit_status
542
+ if options['csv']
543
+ say ["Hourly limit", "Remaining hits", "Reset time"].to_csv
544
+ say [rate_limit_status.hourly_limit, rate_limit_status.remaining_hits, csv_formatted_time(rate_limit_status, :reset_time)].to_csv
545
+ else
546
+ array = []
547
+ array << ["Hourly limit", number_with_delimiter(rate_limit_status.hourly_limit)]
548
+ array << ["Remaining hits", number_with_delimiter(rate_limit_status.remaining_hits)]
549
+ array << ["Reset time", ls_formatted_time(rate_limit_status, :reset_time)]
550
+ print_table(array)
551
+ end
552
+ end
553
+ map %w(ratelimit rl) => :rate_limit
554
+
546
555
  desc "reply STATUS_ID MESSAGE", "Post your Tweet as a reply directed at another person."
547
556
  method_option "all", :aliases => "-a", :type => "boolean", :default => false, :desc => "Reply to all users mentioned in the Tweet."
548
557
  method_option "location", :aliases => "-l", :type => :boolean, :default => false
549
558
  def reply(status_id, message)
550
559
  status_id = status_id.strip_commas
551
560
  status = client.status(status_id.to_i, :include_my_retweet => false)
552
- users = Array(status.user.screen_name)
561
+ users = Array(status.from_user)
553
562
  if options['all']
554
563
  # twitter-text requires $KCODE to be set to UTF8 on Ruby versions < 1.8
555
564
  major, minor, patch = RUBY_VERSION.split('.')
@@ -653,18 +662,18 @@ module T
653
662
  end
654
663
  if options['csv']
655
664
  say ["ID", "Text", "Screen name", "Posted at", "Location", "Retweets", "Source", "URL"].to_csv
656
- say [status.id, HTMLEntities.new.decode(status.text), status.user.screen_name, status.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), location, status.retweet_count, strip_tags(status.source), "https://twitter.com/#{status.user.screen_name}/status/#{status.id}"].to_csv
665
+ say [status.id, HTMLEntities.new.decode(status.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
657
666
  else
658
667
  array = []
659
668
  array << ["ID", status.id.to_s]
660
669
  array << ["Text", HTMLEntities.new.decode(status.text).gsub(/\n+/, ' ')]
661
- array << ["Screen name", "@#{status.user.screen_name}"]
670
+ array << ["Screen name", "@#{status.from_user}"]
662
671
  posted_at = status.created_at > 6.months.ago ? status.created_at.strftime("%b %e %H:%M") : status.created_at.strftime("%b %e %Y")
663
672
  array << ["Posted at", posted_at]
664
673
  array << ["Location", location] unless location.nil?
665
674
  array << ["Retweets", number_with_delimiter(status.retweet_count)]
666
675
  array << ["Source", strip_tags(status.source)]
667
- array << ["URL", "https://twitter.com/#{status.user.screen_name}/status/#{status.id}"]
676
+ array << ["URL", "https://twitter.com/#{status.from_user}/status/#{status.id}"]
668
677
  print_table(array)
669
678
  end
670
679
  end
@@ -727,13 +736,7 @@ module T
727
736
  opts = {}
728
737
  opts.merge!(:exclude => "hashtags") if options['exclude-hashtags']
729
738
  trends = client.trends(woe_id, opts)
730
- if STDOUT.tty?
731
- print_in_columns(trends.map(&:name))
732
- else
733
- trends.each do |trend|
734
- say trend.name
735
- end
736
- end
739
+ print_attribute(trends, :name)
737
740
  end
738
741
 
739
742
  desc "trends_locations", "Returns the locations for which Twitter has trending topic information."
@@ -746,7 +749,7 @@ module T
746
749
  places = places.sort_by{|places| places.name.downcase} unless options['unsorted']
747
750
  places.reverse! if options['reverse']
748
751
  if options['csv']
749
- say ["WOEID", "Parent ID", "Type", "Name", "Country"].to_csv unless places.empty?
752
+ say TREND_HEADINGS.to_csv unless places.empty?
750
753
  places.each do |place|
751
754
  say [place.woeid, place.parent_id, place.place_type, place.name, place.country].to_csv
752
755
  end
@@ -754,21 +757,9 @@ module T
754
757
  array = places.map do |place|
755
758
  [place.woeid, place.parent_id, place.place_type, place.name, place.country]
756
759
  end
757
- if STDOUT.tty?
758
- headings = ["WOEID", "Parent ID", "Type", "Name", "Country"]
759
- array.unshift(headings) unless places.empty?
760
- print_table(array, :truncate => true)
761
- else
762
- print_table(array)
763
- end
760
+ print_table_with_headings(array, TREND_HEADINGS)
764
761
  else
765
- if STDOUT.tty?
766
- print_in_columns(places.map(&:name))
767
- else
768
- places.each do |place|
769
- say place.name
770
- end
771
- end
762
+ print_attribute(places, :name)
772
763
  end
773
764
  end
774
765
  map %w(locations trendlocations) => :trend_locations
@@ -847,19 +838,16 @@ module T
847
838
  user = client.user(user)
848
839
  if options['csv']
849
840
  say ["ID", "Verified", "Name", "Screen name", "Bio", "Location", "Following", "Last update", "Lasted updated at", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "URL"].to_csv
850
- say [user.id, user.verified?, user.name, user.screen_name, user.description, user.location, user.following?, HTMLEntities.new.decode(user.status.text), user.status.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), user.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), user.statuses_count, user.favourites_count, user.listed_count, user.friends_count, user.followers_count, user.url].to_csv
841
+ 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
851
842
  else
852
843
  array = []
853
- name_label = user.verified ? "Name (Verified)" : "Name"
854
844
  array << ["ID", user.id.to_s]
855
- array << [name_label, user.name] unless user.name.nil?
845
+ array << [user.verified ? "Name (Verified)" : "Name", user.name] unless user.name.nil?
856
846
  array << ["Bio", user.description.gsub(/\n+/, ' ')] unless user.description.nil?
857
847
  array << ["Location", user.location] unless user.location.nil?
858
- status = user.following ? "Following" : "Not following"
859
- array << ["Status", status]
848
+ array << ["Status", user.following ? "Following" : "Not following"]
860
849
  array << ["Last update", "#{HTMLEntities.new.decode(user.status.text).gsub(/\n+/, ' ')} (#{time_ago_in_words(user.status.created_at)} ago)"] unless user.status.nil?
861
- created_at = user.created_at > 6.months.ago ? user.created_at.strftime("%b %e %H:%M") : user.created_at.strftime("%b %e %Y")
862
- array << ["Since", created_at]
850
+ array << ["Since", ls_formatted_time(user)]
863
851
  array << ["Tweets", number_with_delimiter(user.statuses_count)]
864
852
  array << ["Favorites", number_with_delimiter(user.favourites_count)]
865
853
  array << ["Listed", number_with_delimiter(user.listed_count)]
data/lib/t/collectable.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'retryable'
2
+
1
3
  module T
2
4
  module Collectable
3
5
 
@@ -8,16 +10,20 @@ module T
8
10
  end
9
11
 
10
12
  def collect_with_cursor(collection=[], cursor=-1, &block)
11
- object = yield cursor
13
+ object = retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
14
+ yield cursor
15
+ end
12
16
  collection += object.collection
13
- object.last? ? collection : collect_with_cursor(collection, object.next_cursor, &block)
17
+ object.last? ? collection.flatten : collect_with_cursor(collection, object.next_cursor, &block)
14
18
  end
15
19
 
16
20
  def collect_with_max_id(collection=[], max_id=nil, &block)
17
- array = yield max_id
18
- return collection unless !array.nil?
21
+ array = retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
22
+ yield max_id
23
+ end
24
+ return collection if array.nil?
19
25
  collection += array
20
- array.empty? ? collection : collect_with_max_id(collection, array.last.id - 1, &block)
26
+ array.empty? ? collection.flatten : collect_with_max_id(collection, array.last.id - 1, &block)
21
27
  end
22
28
 
23
29
  def collect_with_number(number, key, &block)
@@ -28,9 +34,7 @@ module T
28
34
  opts[key] = number unless number >= MAX_NUM_RESULTS
29
35
  if number > 0
30
36
  number -= MAX_NUM_RESULTS
31
- retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
32
- yield opts
33
- end
37
+ yield opts
34
38
  end
35
39
  end.flatten.compact
36
40
  end
data/lib/t/delete.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'retryable'
1
2
  require 't/core_ext/enumerable'
2
3
  require 't/core_ext/string'
3
4
  require 't/rcfile'
@@ -60,10 +61,10 @@ module T
60
61
  status_ids.each do |status_id|
61
62
  unless options['force']
62
63
  status = client.status(status_id.to_i, :include_my_retweet => false, :trim_user => true)
63
- return unless yes? "Are you sure you want to remove @#{status.user.screen_name}'s status: \"#{status.text}\" from your favorites? [y/N]"
64
+ return unless yes? "Are you sure you want to remove @#{status.from_user}'s status: \"#{status.text}\" from your favorites? [y/N]"
64
65
  end
65
66
  status = client.unfavorite(status_id.to_i)
66
- say "@#{@rcfile.active_profile[0]} unfavorited @#{status.user.screen_name}'s status: \"#{status.text}\""
67
+ say "@#{@rcfile.active_profile[0]} unfavorited @#{status.from_user}'s status: \"#{status.text}\""
67
68
  end
68
69
  end
69
70
  map %w(fave favourite) => :favorite
@@ -89,7 +90,7 @@ module T
89
90
  status_ids.each do |status_id|
90
91
  unless options['force']
91
92
  status = client.status(status_id.to_i, :include_my_retweet => false, :trim_user => true)
92
- return unless yes? "Are you sure you want to permanently delete @#{status.user.screen_name}'s status: \"#{status.text}\"? [y/N]"
93
+ return unless yes? "Are you sure you want to permanently delete @#{status.from_user}'s status: \"#{status.text}\"? [y/N]"
93
94
  end
94
95
  status = client.status_destroy(status_id.to_i, :trim_user => true)
95
96
  say "@#{@rcfile.active_profile[0]} deleted the status: \"#{status.text}\""
data/lib/t/list.rb CHANGED
@@ -81,19 +81,17 @@ module T
81
81
  list = client.list(owner, list)
82
82
  if options['csv']
83
83
  say ["ID", "Description", "Slug", "Screen name", "Created at", "Members", "Subscribers", "Following", "Mode", "URL"].to_csv
84
- say [list.id, list.description, list.slug, list.user.screen_name, list.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), list.member_count, list.subscriber_count, list.following?, list.mode, "https://twitter.com#{list.uri}"].to_csv
84
+ say [list.id, list.description, list.slug, list.user.screen_name, csv_formatted_time(list), list.member_count, list.subscriber_count, list.following?, list.mode, "https://twitter.com#{list.uri}"].to_csv
85
85
  else
86
86
  array = []
87
87
  array << ["ID", list.id.to_s]
88
88
  array << ["Description", list.description] unless list.description.nil?
89
89
  array << ["Slug", list.slug]
90
90
  array << ["Screen name", "@#{list.user.screen_name}"]
91
- created_at = list.created_at > 6.months.ago ? list.created_at.strftime("%b %e %H:%M") : list.created_at.strftime("%b %e %Y")
92
- array << ["Created at", created_at]
91
+ array << ["Created at", ls_formatted_time(list)]
93
92
  array << ["Members", number_with_delimiter(list.member_count)]
94
93
  array << ["Subscribers", number_with_delimiter(list.subscriber_count)]
95
- status = list.following ? "Following" : "Not following"
96
- array << ["Status", status]
94
+ array << ["Status", list.following ? "Following" : "Not following"]
97
95
  array << ["Mode", list.mode]
98
96
  array << ["URL", "https://twitter.com#{list.uri}"]
99
97
  print_table(array)
data/lib/t/printable.rb CHANGED
@@ -2,7 +2,6 @@ require 'action_view'
2
2
  require 'csv'
3
3
  # 'fastercsv' required on Ruby versions < 1.9
4
4
  require 'fastercsv' unless Array.new.respond_to?(:to_csv)
5
- require 'highline'
6
5
  require 'htmlentities'
7
6
  require 'thor/shell/color'
8
7
  require 'time'
@@ -10,6 +9,12 @@ require 'time'
10
9
  module T
11
10
  module Printable
12
11
  MAX_SCREEN_NAME_SIZE = 20
12
+ DIRECT_MESSAGE_HEADINGS = ["ID", "Posted at", "Screen name", "Text"]
13
+ LIST_HEADINGS =["ID", "Created at", "Screen name", "Slug", "Members", "Subscribers", "Mode", "Description"]
14
+ STATUS_HEADINGS = ["ID", "Posted at", "Screen name", "Text"]
15
+ TREND_HEADINGS = ["WOEID", "Parent ID", "Type", "Name", "Country"]
16
+ USER_HEADINGS = ["ID", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "Screen name", "Name"]
17
+
13
18
  include ActionView::Helpers::NumberHelper
14
19
 
15
20
  def self.included(base)
@@ -17,63 +22,39 @@ module T
17
22
  private
18
23
 
19
24
  def build_long_list(list)
20
- created_at = if Time.parse(list.created_at.to_s) > 6.months.ago
21
- list.created_at.strftime("%b %e %H:%M")
22
- else
23
- list.created_at.strftime("%b %e %Y")
24
- end
25
- [list.id, created_at, "@#{list.user.screen_name}", list.slug, number_with_delimiter(list.member_count), number_with_delimiter(list.subscriber_count), list.mode, list.description]
25
+ [list.id, ls_formatted_time(list), "@#{list.user.screen_name}", list.slug, number_with_delimiter(list.member_count), number_with_delimiter(list.subscriber_count), list.mode, list.description]
26
26
  end
27
27
 
28
28
  def build_long_status(status)
29
- created_at = if Time.parse(status.created_at.to_s) > 6.months.ago
30
- Time.parse(status.created_at.to_s).strftime("%b %e %H:%M")
31
- else
32
- Time.parse(status.created_at.to_s).strftime("%b %e %Y")
33
- end
34
- [status.id, created_at, "@#{status.user.screen_name}", HTMLEntities.new.decode(status.text).gsub(/\n+/, ' ')]
29
+ [status.id, ls_formatted_time(status), "@#{status.from_user}", HTMLEntities.new.decode(status.text).gsub(/\n+/, ' ')]
35
30
  end
36
31
 
37
32
  def build_long_user(user)
38
- created_at = if user.created_at > 6.months.ago
39
- Time.parse(user.created_at.to_s).strftime("%b %e %H:%M")
33
+ [user.id, ls_formatted_time(user), number_with_delimiter(user.statuses_count), number_with_delimiter(user.favourites_count), number_with_delimiter(user.listed_count), number_with_delimiter(user.friends_count), number_with_delimiter(user.followers_count), "@#{user.screen_name}", user.name]
34
+ end
35
+
36
+ def csv_formatted_time(object, key=:created_at)
37
+ Time.parse(object.send(key.to_sym).to_s).utc.strftime("%Y-%m-%d %H:%M:%S %z")
38
+ end
39
+
40
+ def ls_formatted_time(object, key=:created_at)
41
+ if object.send(key.to_sym) > 6.months.ago
42
+ Time.parse(object.send(key.to_sym).to_s).strftime("%b %e %H:%M")
40
43
  else
41
- user.created_at.strftime("%b %e %Y")
44
+ Time.parse(object.send(key.to_sym).to_s).strftime("%b %e %Y")
42
45
  end
43
- [user.id, created_at, number_with_delimiter(user.statuses_count), number_with_delimiter(user.favourites_count), number_with_delimiter(user.listed_count), number_with_delimiter(user.friends_count), number_with_delimiter(user.followers_count), "@#{user.screen_name}", user.name]
44
46
  end
45
47
 
46
48
  def print_csv_list(list)
47
- created_at = Time.parse(list.created_at.to_s).utc.strftime("%Y-%m-%d %H:%M:%S %z")
48
- say [list.id, created_at, list.user.screen_name, list.slug, list.member_count, list.subscriber_count, list.mode, list.description].to_csv
49
+ say [list.id, csv_formatted_time(list), list.user.screen_name, list.slug, list.member_count, list.subscriber_count, list.mode, list.description].to_csv
49
50
  end
50
51
 
51
52
  def print_csv_status(status)
52
- created_at = Time.parse(status.created_at.to_s).utc.strftime("%Y-%m-%d %H:%M:%S %z")
53
- say [status.id, created_at, status.user.screen_name, HTMLEntities.new.decode(status.text)].to_csv
53
+ say [status.id, csv_formatted_time(status), status.from_user, HTMLEntities.new.decode(status.text)].to_csv
54
54
  end
55
55
 
56
56
  def print_csv_user(user)
57
- created_at = Time.parse(user.created_at.to_s).utc.strftime("%Y-%m-%d %H:%M:%S %z")
58
- say [user.id, created_at, user.statuses_count, user.favourites_count, user.listed_count, user.friends_count, user.followers_count, user.screen_name, user.name].to_csv
59
- end
60
-
61
- def print_in_columns(array)
62
- cols = HighLine::SystemExtensions.terminal_size[0]
63
- width = (array.map{|el| el.to_s.size}.max || 0) + 2
64
- array.each_with_index do |value, index|
65
- puts if (((index) % (cols / width))).zero? && !index.zero?
66
- printf("%-#{width}s", value)
67
- end
68
- puts
69
- end
70
-
71
- def list_headings
72
- ["ID", "Created at", "Screen name", "Slug", "Members", "Subscribers", "Mode", "Description"]
73
- end
74
-
75
- def status_headings
76
- ["ID", "Posted at", "Screen name", "Text"]
57
+ say [user.id, csv_formatted_time(user), user.statuses_count, user.favourites_count, user.listed_count, user.friends_count, user.followers_count, user.screen_name, user.name].to_csv
77
58
  end
78
59
 
79
60
  def print_lists(lists)
@@ -89,7 +70,7 @@ module T
89
70
  end
90
71
  lists.reverse! if options['reverse']
91
72
  if options['csv']
92
- say list_headings.to_csv unless lists.empty?
73
+ say LIST_HEADINGS.to_csv unless lists.empty?
93
74
  lists.each do |list|
94
75
  print_csv_list(list)
95
76
  end
@@ -97,28 +78,36 @@ module T
97
78
  array = lists.map do |list|
98
79
  build_long_list(list)
99
80
  end
100
- if STDOUT.tty?
101
- array.unshift(list_headings) unless lists.empty?
102
- print_table(array, :truncate => true)
103
- else
104
- print_table(array)
105
- end
81
+ print_table_with_headings(array, LIST_HEADINGS)
82
+ else
83
+ print_attribute(lists, :full_name)
84
+ end
85
+ end
86
+
87
+ def print_attribute(array, attribute)
88
+ if STDOUT.tty?
89
+ print_in_columns(array.map(&attribute.to_sym))
106
90
  else
107
- if STDOUT.tty?
108
- print_in_columns(lists.map(&:full_name))
109
- else
110
- lists.each do |list|
111
- say list.full_name
112
- end
91
+ array.each do |element|
92
+ say element.send(attribute.to_sym)
113
93
  end
114
94
  end
115
95
  end
116
96
 
97
+ def print_table_with_headings(array, headings)
98
+ if STDOUT.tty?
99
+ array.unshift(headings) unless array.flatten.empty?
100
+ print_table(array, :truncate => true)
101
+ else
102
+ print_table(array)
103
+ end
104
+ end
105
+
117
106
  def print_status(status)
118
107
  if STDOUT.tty? && !options['no-color']
119
- say(" @#{status.user.screen_name}", [:bold, :yellow])
108
+ say(" @#{status.from_user}", [:bold, :yellow])
120
109
  else
121
- say(" @#{status.user.screen_name}")
110
+ say(" @#{status.from_user}")
122
111
  end
123
112
  print_wrapped(HTMLEntities.new.decode(status.text), :indent => 3)
124
113
  say
@@ -127,7 +116,7 @@ module T
127
116
  def print_statuses(statuses)
128
117
  statuses.reverse! if options['reverse'] || options['stream']
129
118
  if options['csv']
130
- say status_headings.to_csv unless statuses.empty?
119
+ say STATUS_HEADINGS.to_csv unless statuses.empty?
131
120
  statuses.each do |status|
132
121
  print_csv_status(status)
133
122
  end
@@ -135,12 +124,7 @@ module T
135
124
  array = statuses.map do |status|
136
125
  build_long_status(status)
137
126
  end
138
- if STDOUT.tty?
139
- array.unshift(status_headings) unless statuses.empty?
140
- print_table(array, :truncate => true)
141
- else
142
- print_table(array)
143
- end
127
+ print_table_with_headings(array, STATUS_HEADINGS)
144
128
  else
145
129
  statuses.each do |status|
146
130
  print_status(status)
@@ -148,10 +132,6 @@ module T
148
132
  end
149
133
  end
150
134
 
151
- def user_headings
152
- ["ID", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "Screen name", "Name"]
153
- end
154
-
155
135
  def print_users(users)
156
136
  users = users.sort_by{|user| user.screen_name.downcase} unless options['unsorted']
157
137
  if options['posted']
@@ -169,7 +149,7 @@ module T
169
149
  end
170
150
  users.reverse! if options['reverse']
171
151
  if options['csv']
172
- say user_headings.to_csv unless users.empty?
152
+ say USER_HEADINGS.to_csv unless users.empty?
173
153
  users.each do |user|
174
154
  print_csv_user(user)
175
155
  end
@@ -177,20 +157,9 @@ module T
177
157
  array = users.map do |user|
178
158
  build_long_user(user)
179
159
  end
180
- if STDOUT.tty?
181
- array.unshift(user_headings) unless users.empty?
182
- print_table(array, :truncate => true)
183
- else
184
- print_table(array)
185
- end
160
+ print_table_with_headings(array, USER_HEADINGS)
186
161
  else
187
- if STDOUT.tty?
188
- print_in_columns(users.map{|user| "@#{user.screen_name}"})
189
- else
190
- users.each do |user|
191
- say "@#{user.screen_name}"
192
- end
193
- end
162
+ print_attribute(users, :screen_name)
194
163
  end
195
164
  end
196
165