t 0.8.3 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +11 -9
- data/lib/t/authorizable.rb +27 -0
- data/lib/t/cli.rb +19 -35
- data/lib/t/list.rb +1 -1
- data/lib/t/printable.rb +51 -26
- data/lib/t/search.rb +44 -6
- data/lib/t/stream.rb +91 -0
- data/lib/t/version.rb +2 -2
- data/spec/cli_spec.rb +6 -10
- data/spec/list_spec.rb +1 -2
- data/spec/search_spec.rb +104 -33
- data/t.gemspec +2 -0
- metadata +301 -266
data/README.md
CHANGED
@@ -121,6 +121,9 @@ follows you:
|
|
121
121
|
### Output the last 200 tweets in your timeline to a CSV file
|
122
122
|
t timeline -n 200 --csv > timeline.csv
|
123
123
|
|
124
|
+
### Start streaming a real-time sample of all Tweets (Control-C to stop)
|
125
|
+
t stream all
|
126
|
+
|
124
127
|
### Count the number of employees who work for Twitter
|
125
128
|
t list members twitter team | wc -l
|
126
129
|
|
@@ -155,7 +158,7 @@ follows you:
|
|
155
158
|
like grep, cut, awk, bc, wc, and xargs for advanced text processing.
|
156
159
|
* Generate spreadsheets: Convert the output of any command to CSV format simply
|
157
160
|
by adding the `--csv` flag.
|
158
|
-
*
|
161
|
+
* 95% C0 Code Coverage: Well tested, with a 2.5:1 test-to-code ratio.
|
159
162
|
|
160
163
|
[search]: https://dev.twitter.com/docs/using-search
|
161
164
|
|
@@ -210,7 +213,7 @@ Here are some ways *you* can contribute:
|
|
210
213
|
* by writing code (**no patch is too small**: fix typos, add comments, clean up
|
211
214
|
inconsistent whitespace)
|
212
215
|
* by refactoring code
|
213
|
-
* by
|
216
|
+
* by fixing [issues][]
|
214
217
|
* by reviewing patches
|
215
218
|
|
216
219
|
[issues]: https://github.com/sferik/t/issues
|
@@ -218,11 +221,10 @@ Here are some ways *you* can contribute:
|
|
218
221
|
## Submitting an Issue
|
219
222
|
We use the [GitHub issue tracker][issues] to track bugs and features. Before
|
220
223
|
submitting a bug report or feature request, check to make sure it hasn't
|
221
|
-
already been submitted.
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
bug report should include a pull request with failing specs.
|
224
|
+
already been submitted. When submitting a bug report, please include a [Gist][]
|
225
|
+
that includes a stack trace and any details that may be necessary to reproduce
|
226
|
+
the bug, including your gem version, Ruby version, and operating system.
|
227
|
+
Ideally, a bug report should include a pull request with failing specs.
|
226
228
|
|
227
229
|
[gist]: https://gist.github.com/
|
228
230
|
|
@@ -235,8 +237,8 @@ bug report should include a pull request with failing specs.
|
|
235
237
|
6. Run `bundle exec rake spec`. If your specs fail, return to step 5.
|
236
238
|
7. Run `open coverage/index.html`. If your changes are not completely covered
|
237
239
|
by your tests, return to step 3.
|
238
|
-
|
239
|
-
|
240
|
+
8. Add, commit, and push your changes.
|
241
|
+
9. [Submit a pull request.][pr]
|
240
242
|
|
241
243
|
[fork]: http://help.github.com/fork-a-repo/
|
242
244
|
[branch]: http://learn.github.com/p/branching.html
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module T
|
2
|
+
module Authorizable
|
3
|
+
|
4
|
+
def consumer
|
5
|
+
OAuth::Consumer.new(
|
6
|
+
options['consumer-key'],
|
7
|
+
options['consumer-secret'],
|
8
|
+
:site => base_url
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_authorize_url(request_token)
|
13
|
+
request = consumer.create_signed_request(:get, consumer.authorize_path, request_token, pin_auth_parameters)
|
14
|
+
params = request['Authorization'].sub(/^OAuth\s+/, '').split(/,\s+/).map do |param|
|
15
|
+
key, value = param.split('=')
|
16
|
+
value =~ /"(.*?)"/
|
17
|
+
"#{key}=#{CGI::escape($1)}"
|
18
|
+
end.join('&')
|
19
|
+
"#{base_url}#{request.path}?#{params}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def pin_auth_parameters
|
23
|
+
{:oauth_callback => 'oob'}
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/t/cli.rb
CHANGED
@@ -10,6 +10,7 @@ require 'geokit'
|
|
10
10
|
require 'launchy'
|
11
11
|
require 'oauth'
|
12
12
|
require 'open-uri'
|
13
|
+
require 't/authorizable'
|
13
14
|
require 't/collectable'
|
14
15
|
require 't/core_ext/string'
|
15
16
|
require 't/delete'
|
@@ -19,6 +20,7 @@ require 't/rcfile'
|
|
19
20
|
require 't/requestable'
|
20
21
|
require 't/search'
|
21
22
|
require 't/set'
|
23
|
+
require 't/stream'
|
22
24
|
require 't/version'
|
23
25
|
require 'thor'
|
24
26
|
require 'time'
|
@@ -35,6 +37,7 @@ module T
|
|
35
37
|
include ActionView::Helpers::DateHelper
|
36
38
|
include ActionView::Helpers::NumberHelper
|
37
39
|
include ActionView::Helpers::TextHelper
|
40
|
+
include T::Authorizable
|
38
41
|
include T::Collectable
|
39
42
|
include T::Printable
|
40
43
|
include T::Requestable
|
@@ -142,7 +145,7 @@ module T
|
|
142
145
|
elsif options['long']
|
143
146
|
array = direct_messages.map do |direct_message|
|
144
147
|
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, created_at, "@#{direct_message.sender.screen_name}", direct_message.text.gsub(/\n+/, ' ')]
|
148
|
+
[direct_message.id, created_at, "@#{direct_message.sender.screen_name}", HTMLEntities.new.decode(direct_message.text).gsub(/\n+/, ' ')]
|
146
149
|
end
|
147
150
|
if STDOUT.tty?
|
148
151
|
headings = ["ID", "Posted at", "Screen name", "Text"]
|
@@ -176,7 +179,7 @@ module T
|
|
176
179
|
elsif options['long']
|
177
180
|
array = direct_messages.map do |direct_message|
|
178
181
|
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")
|
179
|
-
[direct_message.id, created_at, "@#{direct_message.recipient.screen_name}", direct_message.text.gsub(/\n+/, ' ')]
|
182
|
+
[direct_message.id, created_at, "@#{direct_message.recipient.screen_name}", HTMLEntities.new.decode(direct_message.text).gsub(/\n+/, ' ')]
|
180
183
|
end
|
181
184
|
if STDOUT.tty?
|
182
185
|
headings = ["ID", "Posted at", "Screen name", "Text"]
|
@@ -199,7 +202,7 @@ module T
|
|
199
202
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
|
200
203
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by number of friends."
|
201
204
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
202
|
-
method_option "listed", :aliases => "-
|
205
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
203
206
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
204
207
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
205
208
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
@@ -361,7 +364,7 @@ module T
|
|
361
364
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
|
362
365
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by number of friends."
|
363
366
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
364
|
-
method_option "listed", :aliases => "-
|
367
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
365
368
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
366
369
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
367
370
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
@@ -392,7 +395,7 @@ module T
|
|
392
395
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
|
393
396
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by number of friends."
|
394
397
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
395
|
-
method_option "listed", :aliases => "-
|
398
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
396
399
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
397
400
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
398
401
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
@@ -423,7 +426,7 @@ module T
|
|
423
426
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
|
424
427
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by number of friends."
|
425
428
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
426
|
-
method_option "listed", :aliases => "-
|
429
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
427
430
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
428
431
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
429
432
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
@@ -458,7 +461,7 @@ module T
|
|
458
461
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
|
459
462
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by number of friends."
|
460
463
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
461
|
-
method_option "listed", :aliases => "-
|
464
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
462
465
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
463
466
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
464
467
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
@@ -636,11 +639,11 @@ module T
|
|
636
639
|
end
|
637
640
|
if options['csv']
|
638
641
|
say ["ID", "Text", "Screen name", "Posted at", "Location", "Retweets", "Source", "URL"].to_csv
|
639
|
-
say [status.id, 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
|
642
|
+
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
|
640
643
|
else
|
641
644
|
array = []
|
642
645
|
array << ["ID", status.id.to_s]
|
643
|
-
array << ["Text", status.text.gsub(/\n+/, ' ')]
|
646
|
+
array << ["Text", HTMLEntities.new.decode(status.text).gsub(/\n+/, ' ')]
|
644
647
|
array << ["Screen name", "@#{status.user.screen_name}"]
|
645
648
|
posted_at = status.created_at > 6.months.ago ? status.created_at.strftime("%b %e %H:%M") : status.created_at.strftime("%b %e %Y")
|
646
649
|
array << ["Posted at", posted_at]
|
@@ -658,7 +661,7 @@ module T
|
|
658
661
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
|
659
662
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by number of friends."
|
660
663
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
661
|
-
method_option "listed", :aliases => "-
|
664
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
662
665
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
663
666
|
method_option "number", :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
|
664
667
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
@@ -790,7 +793,7 @@ module T
|
|
790
793
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by number of followers."
|
791
794
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by number of friends."
|
792
795
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify input as Twitter user IDs instead of screen names."
|
793
|
-
method_option "listed", :aliases => "-
|
796
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
794
797
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
795
798
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
796
799
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
@@ -826,7 +829,7 @@ module T
|
|
826
829
|
user = client.user(user, :include_entities => false)
|
827
830
|
if options['csv']
|
828
831
|
say ["ID", "Verified", "Name", "Screen name", "Bio", "Location", "Following", "Last update", "Lasted updated at", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "URL"].to_csv
|
829
|
-
say [user.id, user.verified?, user.name, user.screen_name, user.description, user.location, user.following?, 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
|
832
|
+
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
|
830
833
|
else
|
831
834
|
array = []
|
832
835
|
name_label = user.verified ? "Name (Verified)" : "Name"
|
@@ -836,7 +839,7 @@ module T
|
|
836
839
|
array << ["Location", user.location] unless user.location.nil?
|
837
840
|
status = user.following ? "Following" : "Not following"
|
838
841
|
array << ["Status", status]
|
839
|
-
array << ["Last update", "#{user.status.text.gsub(/\n+/, ' ')} (#{time_ago_in_words(user.status.created_at)} ago)"] unless user.status.nil?
|
842
|
+
array << ["Last update", "#{HTMLEntities.new.decode(user.status.text).gsub(/\n+/, ' ')} (#{time_ago_in_words(user.status.created_at)} ago)"] unless user.status.nil?
|
840
843
|
created_at = user.created_at > 6.months.ago ? user.created_at.strftime("%b %e %H:%M") : user.created_at.strftime("%b %e %Y")
|
841
844
|
array << ["Since", created_at]
|
842
845
|
array << ["Tweets", number_with_delimiter(user.statuses_count)]
|
@@ -862,25 +865,10 @@ module T
|
|
862
865
|
desc "set SUBCOMMAND ...ARGS", "Change various account settings."
|
863
866
|
subcommand 'set', T::Set
|
864
867
|
|
865
|
-
|
866
|
-
|
867
|
-
def consumer
|
868
|
-
OAuth::Consumer.new(
|
869
|
-
options['consumer-key'],
|
870
|
-
options['consumer-secret'],
|
871
|
-
:site => base_url
|
872
|
-
)
|
873
|
-
end
|
868
|
+
desc "stream SUBCOMMAND ...ARGS", "Commands for streaming Tweets."
|
869
|
+
subcommand 'stream', T::Stream
|
874
870
|
|
875
|
-
|
876
|
-
request = consumer.create_signed_request(:get, consumer.authorize_path, request_token, pin_auth_parameters)
|
877
|
-
params = request['Authorization'].sub(/^OAuth\s+/, '').split(/,\s+/).map do |param|
|
878
|
-
key, value = param.split('=')
|
879
|
-
value =~ /"(.*?)"/
|
880
|
-
"#{key}=#{CGI::escape($1)}"
|
881
|
-
end.join('&')
|
882
|
-
"#{base_url}#{request.path}?#{params}"
|
883
|
-
end
|
871
|
+
private
|
884
872
|
|
885
873
|
def location
|
886
874
|
return @location if @location
|
@@ -890,9 +878,5 @@ module T
|
|
890
878
|
@location = Geokit::Geocoders::MultiGeocoder.geocode(ip_address)
|
891
879
|
end
|
892
880
|
|
893
|
-
def pin_auth_parameters
|
894
|
-
{:oauth_callback => 'oob'}
|
895
|
-
end
|
896
|
-
|
897
881
|
end
|
898
882
|
end
|
data/lib/t/list.rb
CHANGED
@@ -107,7 +107,7 @@ module T
|
|
107
107
|
method_option "followers", :aliases => "-f", :type => :boolean, :default => false, :desc => "Sort by total number of followers."
|
108
108
|
method_option "friends", :aliases => "-e", :type => :boolean, :default => false, :desc => "Sort by total number of friends."
|
109
109
|
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
110
|
-
method_option "listed", :aliases => "-
|
110
|
+
method_option "listed", :aliases => "-d", :type => :boolean, :default => false, :desc => "Sort by number of list memberships."
|
111
111
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
112
112
|
method_option "posted", :aliases => "-p", :type => :boolean, :default => false, :desc => "Sort by the time when Twitter account was posted."
|
113
113
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
data/lib/t/printable.rb
CHANGED
@@ -3,6 +3,7 @@ require 'csv'
|
|
3
3
|
# 'fastercsv' required on Ruby versions < 1.9
|
4
4
|
require 'fastercsv' unless Array.new.respond_to?(:to_csv)
|
5
5
|
require 'highline'
|
6
|
+
require 'htmlentities'
|
6
7
|
require 'thor/shell/color'
|
7
8
|
|
8
9
|
module T
|
@@ -14,6 +15,36 @@ module T
|
|
14
15
|
|
15
16
|
private
|
16
17
|
|
18
|
+
def build_long_list(list)
|
19
|
+
created_at = list.created_at > 6.months.ago ? list.created_at.strftime("%b %e %H:%M") : list.created_at.strftime("%b %e %Y")
|
20
|
+
[list.id, created_at, list.full_name, number_with_delimiter(list.member_count), number_with_delimiter(list.subscriber_count), list.mode, list.description]
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_long_status(status)
|
24
|
+
created_at = status.created_at > 6.months.ago ? status.created_at.strftime("%b %e %H:%M") : status.created_at.strftime("%b %e %Y")
|
25
|
+
[status.id, created_at, "@#{status.user.screen_name}", HTMLEntities.new.decode(status.text).gsub(/\n+/, ' ')]
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_long_user(user)
|
29
|
+
created_at = user.created_at > 6.months.ago ? user.created_at.strftime("%b %e %H:%M") : user.created_at.strftime("%b %e %Y")
|
30
|
+
[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]
|
31
|
+
end
|
32
|
+
|
33
|
+
def print_csv_list(list)
|
34
|
+
created_at = list.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z")
|
35
|
+
say [list.id, created_at, list.user.screen_name, list.slug, list.member_count, list.subscriber_count, list.mode, list.description].to_csv
|
36
|
+
end
|
37
|
+
|
38
|
+
def print_csv_status(status)
|
39
|
+
created_at = status.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z")
|
40
|
+
say [status.id, created_at, status.user.screen_name, HTMLEntities.new.decode(status.text)].to_csv
|
41
|
+
end
|
42
|
+
|
43
|
+
def print_csv_user(user)
|
44
|
+
created_at = user.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z")
|
45
|
+
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
|
46
|
+
end
|
47
|
+
|
17
48
|
def print_in_columns(array)
|
18
49
|
cols = HighLine::SystemExtensions.terminal_size[0]
|
19
50
|
width = (array.map{|el| el.to_s.size}.max || 0) + 2
|
@@ -39,12 +70,11 @@ module T
|
|
39
70
|
if options['csv']
|
40
71
|
say ["ID", "Created at", "Screen name", "Slug", "Members", "Subscribers", "Mode", "Description"].to_csv unless lists.empty?
|
41
72
|
lists.each do |list|
|
42
|
-
|
73
|
+
print_csv_list(list)
|
43
74
|
end
|
44
75
|
elsif options['long']
|
45
76
|
array = lists.map do |list|
|
46
|
-
|
47
|
-
[list.id, created_at, list.full_name, number_with_delimiter(list.member_count), number_with_delimiter(list.subscriber_count), list.mode, list.description]
|
77
|
+
build_long_list(list)
|
48
78
|
end
|
49
79
|
if STDOUT.tty?
|
50
80
|
headings = ["ID", "Created at", "Slug", "Members", "Subscribers", "Mode", "Description"]
|
@@ -64,17 +94,27 @@ module T
|
|
64
94
|
end
|
65
95
|
end
|
66
96
|
|
97
|
+
def print_status(status)
|
98
|
+
if STDOUT.tty? && !options['no-color']
|
99
|
+
say(" #{Thor::Shell::Color::BOLD}@#{status.user.screen_name}", :yellow)
|
100
|
+
print_wrapped(HTMLEntities.new.decode(status.text), :indent => 3)
|
101
|
+
else
|
102
|
+
say(" @#{status.user.screen_name}")
|
103
|
+
print_wrapped(HTMLEntities.new.decode(status.text), :indent => 3)
|
104
|
+
end
|
105
|
+
say
|
106
|
+
end
|
107
|
+
|
67
108
|
def print_statuses(statuses)
|
68
|
-
statuses.reverse! if options['reverse']
|
109
|
+
statuses.reverse! if options['reverse'] || options['stream']
|
69
110
|
if options['csv']
|
70
111
|
say ["ID", "Posted at", "Screen name", "Text"].to_csv unless statuses.empty?
|
71
112
|
statuses.each do |status|
|
72
|
-
|
113
|
+
print_csv_status(status)
|
73
114
|
end
|
74
115
|
elsif options['long']
|
75
116
|
array = statuses.map do |status|
|
76
|
-
|
77
|
-
[status.id, created_at, "@#{status.user.screen_name}", status.text.gsub(/\n+/, ' ')]
|
117
|
+
build_long_status(status)
|
78
118
|
end
|
79
119
|
if STDOUT.tty?
|
80
120
|
headings = ["ID", "Posted at", "Screen name", "Text"]
|
@@ -84,22 +124,8 @@ module T
|
|
84
124
|
print_table(array)
|
85
125
|
end
|
86
126
|
else
|
87
|
-
|
88
|
-
|
89
|
-
statuses.each do |status|
|
90
|
-
say(" #{Thor::Shell::Color::BOLD}@#{status.user.screen_name}", :yellow)
|
91
|
-
print_wrapped(status.text, :indent => 3)
|
92
|
-
say(" #{Thor::Shell::Color::BOLD}#{time_ago_in_words(status.created_at)} ago", :black)
|
93
|
-
say
|
94
|
-
end
|
95
|
-
else
|
96
|
-
say unless statuses.empty?
|
97
|
-
statuses.each do |status|
|
98
|
-
say(" @#{status.user.screen_name}")
|
99
|
-
print_wrapped(status.text, :indent => 3)
|
100
|
-
say(" #{time_ago_in_words(status.created_at)} ago")
|
101
|
-
say
|
102
|
-
end
|
127
|
+
statuses.each do |status|
|
128
|
+
print_status(status)
|
103
129
|
end
|
104
130
|
end
|
105
131
|
end
|
@@ -123,12 +149,11 @@ module T
|
|
123
149
|
if options['csv']
|
124
150
|
say ["ID", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "Screen name", "Name"].to_csv unless users.empty?
|
125
151
|
users.each do |user|
|
126
|
-
|
152
|
+
print_csv_user(user)
|
127
153
|
end
|
128
154
|
elsif options['long']
|
129
155
|
array = users.map do |user|
|
130
|
-
|
131
|
-
[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]
|
156
|
+
build_long_user(user)
|
132
157
|
end
|
133
158
|
if STDOUT.tty?
|
134
159
|
headings = ["ID", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "Screen name", "Name"]
|
data/lib/t/search.rb
CHANGED
@@ -2,6 +2,7 @@ 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 'htmlentities'
|
5
6
|
require 'retryable'
|
6
7
|
require 't/collectable'
|
7
8
|
require 't/printable'
|
@@ -37,12 +38,12 @@ module T
|
|
37
38
|
if options['csv']
|
38
39
|
say ["ID", "Posted at", "Screen name", "Text"].to_csv unless statuses.empty?
|
39
40
|
statuses.each do |status|
|
40
|
-
say [status.id, status.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), status.from_user, status.text].to_csv
|
41
|
+
say [status.id, status.created_at.utc.strftime("%Y-%m-%d %H:%M:%S %z"), status.from_user, HTMLEntities.new.decode(status.text)].to_csv
|
41
42
|
end
|
42
43
|
elsif options['long']
|
43
44
|
array = statuses.map do |status|
|
44
45
|
created_at = status.created_at > 6.months.ago ? status.created_at.strftime("%b %e %H:%M") : status.created_at.strftime("%b %e %Y")
|
45
|
-
[status.id, created_at, "@#{status.from_user}", status.text.gsub(/\n+/, ' ')]
|
46
|
+
[status.id, created_at, "@#{status.from_user}", HTMLEntities.new.decode(status.text).gsub(/\n+/, ' ')]
|
46
47
|
end
|
47
48
|
if STDOUT.tty?
|
48
49
|
headings = ["ID", "Posted at", "Screen name", "Text"]
|
@@ -52,13 +53,21 @@ module T
|
|
52
53
|
print_table(array)
|
53
54
|
end
|
54
55
|
else
|
56
|
+
say unless statuses.empty?
|
55
57
|
statuses.each do |status|
|
56
|
-
|
58
|
+
if STDOUT.tty? && !options['no-color']
|
59
|
+
say(" #{Thor::Shell::Color::BOLD}@#{status.from_user}", :yellow)
|
60
|
+
print_wrapped(HTMLEntities.new.decode(status.text), :indent => 3)
|
61
|
+
else
|
62
|
+
say(" @#{status.from_user}")
|
63
|
+
print_wrapped(HTMLEntities.new.decode(status.text), :indent => 3)
|
64
|
+
end
|
65
|
+
say
|
57
66
|
end
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
61
|
-
desc "favorites QUERY", "Returns Tweets you've favorited that
|
70
|
+
desc "favorites QUERY", "Returns Tweets you've favorited that match a specified query."
|
62
71
|
method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
|
63
72
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
64
73
|
def favorites(query)
|
@@ -76,7 +85,36 @@ module T
|
|
76
85
|
end
|
77
86
|
map %w(faves) => :favorites
|
78
87
|
|
79
|
-
desc "
|
88
|
+
desc "list [USER/]LIST QUERY", "Returns Tweets on a list that match specified query."
|
89
|
+
method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
|
90
|
+
method_option "id", :aliases => "-i", :type => "boolean", :default => false, :desc => "Specify user via ID instead of screen name."
|
91
|
+
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
92
|
+
def list(list, query)
|
93
|
+
owner, list = list.split('/')
|
94
|
+
if list.nil?
|
95
|
+
list = owner
|
96
|
+
owner = @rcfile.active_profile[0]
|
97
|
+
else
|
98
|
+
owner = if options['id']
|
99
|
+
owner.to_i
|
100
|
+
else
|
101
|
+
owner.strip_ats
|
102
|
+
end
|
103
|
+
end
|
104
|
+
opts = {:count => MAX_NUM_RESULTS}
|
105
|
+
statuses = collect_with_max_id do |max_id|
|
106
|
+
opts[:max_id] = max_id unless max_id.nil?
|
107
|
+
retryable(:tries => 3, :on => Twitter::Error::ServerError, :sleep => 0) do
|
108
|
+
client.list_timeline(owner, list, opts)
|
109
|
+
end
|
110
|
+
end.flatten.compact
|
111
|
+
statuses = statuses.select do |status|
|
112
|
+
/#{query}/i.match(status.text)
|
113
|
+
end
|
114
|
+
print_statuses(statuses)
|
115
|
+
end
|
116
|
+
|
117
|
+
desc "mentions QUERY", "Returns Tweets mentioning you that match a specified query."
|
80
118
|
method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
|
81
119
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
82
120
|
def mentions(query)
|
@@ -94,7 +132,7 @@ module T
|
|
94
132
|
end
|
95
133
|
map %w(replies) => :mentions
|
96
134
|
|
97
|
-
desc "retweets QUERY", "Returns Tweets you've retweeted that
|
135
|
+
desc "retweets QUERY", "Returns Tweets you've retweeted that match a specified query."
|
98
136
|
method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
|
99
137
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
100
138
|
def retweets(query)
|