t 1.7.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/README.md +21 -8
- data/lib/t.rb +1 -1
- data/lib/t/cli.rb +62 -73
- data/lib/t/collectable.rb +2 -10
- data/lib/t/core_ext/kernel.rb +4 -4
- data/lib/t/delete.rb +4 -4
- data/lib/t/editor.rb +35 -0
- data/lib/t/list.rb +3 -6
- data/lib/t/printable.rb +7 -13
- data/lib/t/requestable.rb +6 -21
- data/lib/t/search.rb +16 -17
- data/lib/t/set.rb +4 -4
- data/lib/t/stream.rb +15 -27
- data/lib/t/utils.rb +10 -10
- data/lib/t/version.rb +3 -3
- data/spec/cli_spec.rb +223 -109
- data/spec/delete_spec.rb +26 -26
- data/spec/editor_spec.rb +102 -0
- data/spec/fixtures/bearer_token.json +1 -0
- data/spec/fixtures/status.json +1 -1
- data/spec/fixtures/status_no_attributes.json +1 -1
- data/spec/fixtures/status_no_country.json +1 -1
- data/spec/fixtures/status_no_full_name.json +1 -1
- data/spec/fixtures/status_no_locality.json +1 -1
- data/spec/fixtures/status_no_place.json +1 -1
- data/spec/fixtures/status_no_street_address.json +1 -1
- data/spec/helper.rb +6 -2
- data/spec/list_spec.rb +3 -3
- data/spec/rcfile_spec.rb +20 -6
- data/spec/search_spec.rb +19 -19
- data/spec/set_spec.rb +4 -4
- data/spec/stream_spec.rb +77 -101
- data/t.gemspec +4 -5
- metadata +11 -57
- metadata.gz.sig +0 -0
- data/spec/fixtures/activity_summary.json +0 -1
data.tar.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
[][travis]
|
7
7
|
[][gemnasium]
|
8
8
|
[][coveralls]
|
9
|
-
[][pledgie]
|
10
10
|
[][flattr]
|
11
11
|
|
12
12
|
[gem]: https://rubygems.org/gems/t
|
@@ -38,6 +38,16 @@ If the output looks more like this, you need to [install Ruby][ruby]:
|
|
38
38
|
|
39
39
|
ruby: command not found
|
40
40
|
|
41
|
+
**On Linux**, for Debian-based systems, open a terminal and type:
|
42
|
+
|
43
|
+
sudo apt-get install ruby-dev
|
44
|
+
|
45
|
+
or for Red Hat-based distros like Fedora and CentOS, type:
|
46
|
+
|
47
|
+
sudo yum install ruby-devel
|
48
|
+
|
49
|
+
(if necessary, adapt for your package manager)
|
50
|
+
|
41
51
|
**On Windows**, you can install Ruby with [RubyInstaller][].
|
42
52
|
[rubyinstaller]: http://rubyinstaller.org/
|
43
53
|
|
@@ -49,7 +59,7 @@ To ensure the code you're installing hasn't been tampered with, it's
|
|
49
59
|
recommended that you verify the signature. To do this, you need to add my
|
50
60
|
public key as a trusted certificate (you only need to do this once):
|
51
61
|
|
52
|
-
gem cert --add <(curl -Ls https://
|
62
|
+
gem cert --add <(curl -Ls https://raw.github.com/sferik/t/master/certs/sferik.pem)
|
53
63
|
|
54
64
|
Then, install the gem with the high security trust policy:
|
55
65
|
|
@@ -157,7 +167,7 @@ example, send a user a direct message only if he already follows you:
|
|
157
167
|
t leaders | xargs t unfollow
|
158
168
|
|
159
169
|
#### Unfollow 10 people who haven't tweeted in the longest time
|
160
|
-
t followings -l --sort=
|
170
|
+
t followings -l --sort=tweeted | head -10 | awk '{print $1}' | xargs t unfollow -i
|
161
171
|
|
162
172
|
#### Twitter roulette: randomly follow someone who follows you (who you don't already follow)
|
163
173
|
t groupies | shuf | head -1 | xargs t follow
|
@@ -172,7 +182,7 @@ example, send a user a direct message only if he already follows you:
|
|
172
182
|
t stream timeline
|
173
183
|
|
174
184
|
#### Count the number of employees who work for Twitter
|
175
|
-
t list members twitter
|
185
|
+
t list members twitter/team | wc -l
|
176
186
|
|
177
187
|
#### Search Twitter for the 20 most recent Tweets that match a specified query
|
178
188
|
t search all "query"
|
@@ -218,8 +228,12 @@ your Twitter account.
|
|
218
228
|
|
219
229
|
`t` was also mentioned on [an episode of the Ruby 5 podcast][ruby5].
|
220
230
|
|
231
|
+
`t` was also discussed on [an episode of the Ruby Rogues podcast][rubyrogues].
|
232
|
+
|
221
233
|
[ruby5]: http://ruby5.envylabs.com/episodes/273-episode-269-may-4th-2012/stories/2400-t-command-line-power-tool-for-twitter
|
222
234
|
|
235
|
+
[rubyrogues]: http://rubyrogues.com/127-rr-erik-michaels-ober/
|
236
|
+
|
223
237
|
If you discuss `t` in a blog post or podcast, [let me know][email] and I'll
|
224
238
|
link it here.
|
225
239
|
|
@@ -258,8 +272,8 @@ flags.
|
|
258
272
|
Don't run Zsh? Why not [contribute][] completion support for your favorite
|
259
273
|
shell?
|
260
274
|
|
261
|
-
[completion]: etc
|
262
|
-
[contribute]: CONTRIBUTING.md
|
275
|
+
[completion]: https://github.com/sferik/t/tree/master/etc
|
276
|
+
[contribute]: https://github.com/sferik/t/blob/master/CONTRIBUTING.md
|
263
277
|
|
264
278
|
## History
|
265
279
|
The [twitter gem][gem] previously contained a command-line interface, up until
|
@@ -275,7 +289,6 @@ the original code.
|
|
275
289
|
This library aims to support and is [tested against][travis] the following Ruby
|
276
290
|
implementations:
|
277
291
|
|
278
|
-
* Ruby 1.8.7
|
279
292
|
* Ruby 1.9.2
|
280
293
|
* Ruby 1.9.3
|
281
294
|
* Ruby 2.0.0
|
@@ -302,5 +315,5 @@ If you are running t on a remote computer you can use the flag --display-url dur
|
|
302
315
|
Copyright (c) 2011-2013 Erik Michaels-Ober. See [LICENSE][] for details.
|
303
316
|
Application icon by [@nvk][nvk].
|
304
317
|
|
305
|
-
[license]: LICENSE.md
|
318
|
+
[license]: https://github.com/sferik/t/blob/master/LICENSE.md
|
306
319
|
[nvk]: http://rodolfonovak.com
|
data/lib/t.rb
CHANGED
@@ -6,7 +6,7 @@ module T
|
|
6
6
|
|
7
7
|
# Convert time to local time by applying the `utc_offset` setting.
|
8
8
|
def local_time(time)
|
9
|
-
utc_offset ? (time.utc + utc_offset) : time.localtime
|
9
|
+
utc_offset ? (time.dup.utc + utc_offset) : time.localtime
|
10
10
|
end
|
11
11
|
|
12
12
|
# UTC offset in seconds to apply time instances before displaying.
|
data/lib/t/cli.rb
CHANGED
@@ -5,6 +5,7 @@ require 'thor'
|
|
5
5
|
require 'twitter'
|
6
6
|
require 't/collectable'
|
7
7
|
require 't/delete'
|
8
|
+
require 't/editor'
|
8
9
|
require 't/list'
|
9
10
|
require 't/printable'
|
10
11
|
require 't/rcfile'
|
@@ -28,9 +29,7 @@ module T
|
|
28
29
|
|
29
30
|
check_unknown_options!
|
30
31
|
|
31
|
-
class_option "host", :aliases => "-H", :type => :string, :default => T::Requestable::DEFAULT_HOST, :desc => "Twitter API server"
|
32
32
|
class_option "color", :aliases => "-C", :type => :string, :enum => %w(auto never), :default => "auto", :desc => "Control how color is used in output"
|
33
|
-
class_option "no-ssl", :aliases => "-U", :type => :boolean, :default => false, :desc => "Disable SSL"
|
34
33
|
class_option "profile", :aliases => "-P", :type => :string, :default => File.join(File.expand_path("~"), T::RCFile::FILE_NAME), :desc => "Path to RC file", :banner => "FILE"
|
35
34
|
|
36
35
|
def initialize(*)
|
@@ -50,7 +49,7 @@ module T
|
|
50
49
|
end
|
51
50
|
|
52
51
|
desc "authorize", "Allows an application to request user authorization"
|
53
|
-
method_option "display-
|
52
|
+
method_option "display-uri", :aliases => "-d", :type => :boolean, :default => false, :desc => "Display the authorization URL instead of attempting to open it."
|
54
53
|
def authorize
|
55
54
|
@rcfile.path = options['profile'] if options['profile']
|
56
55
|
if @rcfile.empty?
|
@@ -79,12 +78,12 @@ module T
|
|
79
78
|
say
|
80
79
|
end
|
81
80
|
require 'launchy'
|
82
|
-
open_or_print( "https://dev.twitter.com/apps", :dry_run => options['display-
|
81
|
+
open_or_print( "https://dev.twitter.com/apps", :dry_run => options['display-uri'] )
|
83
82
|
key = ask "Enter your consumer key:"
|
84
83
|
secret = ask "Enter your consumer secret:"
|
85
|
-
consumer = OAuth::Consumer.new(key, secret, :site =>
|
84
|
+
consumer = OAuth::Consumer.new(key, secret, :site => Twitter::REST::Client::ENDPOINT)
|
86
85
|
request_token = consumer.get_request_token
|
87
|
-
|
86
|
+
uri = generate_authorize_uri(consumer, request_token)
|
88
87
|
say
|
89
88
|
say "In a moment, you will be directed to the Twitter app authorization page."
|
90
89
|
say "Perform the following steps to complete the authorization process:"
|
@@ -94,7 +93,7 @@ module T
|
|
94
93
|
say
|
95
94
|
ask "Press [Enter] to open the Twitter app authorization page."
|
96
95
|
say
|
97
|
-
open_or_print(
|
96
|
+
open_or_print(uri, :dry_run => options['display-uri'])
|
98
97
|
pin = ask "Enter the supplied PIN:"
|
99
98
|
access_token = request_token.get_access_token(:oauth_verifier => pin.chomp)
|
100
99
|
oauth_response = access_token.get('/1.1/account/verify_credentials.json?include_entities=false&skip_status=true')
|
@@ -137,7 +136,6 @@ module T
|
|
137
136
|
require 'htmlentities'
|
138
137
|
if options['csv']
|
139
138
|
require 'csv'
|
140
|
-
require 'fastercsv' unless Array.new.respond_to?(:to_csv)
|
141
139
|
say DIRECT_MESSAGE_HEADINGS.to_csv unless direct_messages.empty?
|
142
140
|
direct_messages.each do |direct_message|
|
143
141
|
say [direct_message.id, csv_formatted_time(direct_message), direct_message.sender.screen_name, HTMLEntities.new.decode(direct_message.text)].to_csv
|
@@ -170,7 +168,6 @@ module T
|
|
170
168
|
require 'htmlentities'
|
171
169
|
if options['csv']
|
172
170
|
require 'csv'
|
173
|
-
require 'fastercsv' unless Array.new.respond_to?(:to_csv)
|
174
171
|
say DIRECT_MESSAGE_HEADINGS.to_csv unless direct_messages.empty?
|
175
172
|
direct_messages.each do |direct_message|
|
176
173
|
say [direct_message.id, csv_formatted_time(direct_message), direct_message.recipient.screen_name, HTMLEntities.new.decode(direct_message.text)].to_csv
|
@@ -208,18 +205,14 @@ module T
|
|
208
205
|
client.verify_credentials.screen_name
|
209
206
|
end
|
210
207
|
follower_ids = Thread.new do
|
211
|
-
|
212
|
-
client.follower_ids(user, :cursor => cursor)
|
213
|
-
end
|
208
|
+
client.follower_ids(user).to_a
|
214
209
|
end
|
215
210
|
following_ids = Thread.new do
|
216
|
-
|
217
|
-
client.friend_ids(user, :cursor => cursor)
|
218
|
-
end
|
211
|
+
client.friend_ids(user).to_a
|
219
212
|
end
|
220
213
|
disciple_ids = (follower_ids.value - following_ids.value)
|
221
214
|
require 'retryable'
|
222
|
-
users = retryable(:tries => 3, :on => Twitter::Error
|
215
|
+
users = retryable(:tries => 3, :on => Twitter::Error, :sleep => 0) do
|
223
216
|
client.users(disciple_ids)
|
224
217
|
end
|
225
218
|
print_users(users)
|
@@ -295,7 +288,7 @@ module T
|
|
295
288
|
status_ids.unshift(status_id)
|
296
289
|
status_ids.map!(&:to_i)
|
297
290
|
require 'retryable'
|
298
|
-
favorites = retryable(:tries => 3, :on => Twitter::Error
|
291
|
+
favorites = retryable(:tries => 3, :on => Twitter::Error, :sleep => 0) do
|
299
292
|
client.favorite(status_ids)
|
300
293
|
end
|
301
294
|
number = favorites.length
|
@@ -309,9 +302,17 @@ module T
|
|
309
302
|
method_option "csv", :aliases => "-c", :type => :boolean, :default => false, :desc => "Output in CSV format."
|
310
303
|
method_option "id", :aliases => "-i", :type => :boolean, :default => false, :desc => "Specify user via ID instead of screen name."
|
311
304
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
305
|
+
method_option "max_id", :aliases => "-m", :type => :numeric, :desc => "Returns only the results with an ID less than the specified ID."
|
312
306
|
method_option "number", :aliases => "-n", :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => "Limit the number of results."
|
313
307
|
method_option "reverse", :aliases => "-r", :type => :boolean, :default => false, :desc => "Reverse the order of the sort."
|
308
|
+
method_option "since_id", :aliases => "-s", :type => :numeric, :desc => "Returns only the results with an ID greater than the specified ID."
|
314
309
|
def favorites(user=nil)
|
310
|
+
count = options['number'] || DEFAULT_NUM_RESULTS
|
311
|
+
opts = {}
|
312
|
+
opts[:exclude_replies] = true if options['exclude'] == 'replies'
|
313
|
+
opts[:include_rts] = false if options['exclude'] == 'retweets'
|
314
|
+
opts[:max_id] = options['max_id'] if options['max_id']
|
315
|
+
opts[:since_id] = options['since_id'] if options['since_id']
|
315
316
|
if user
|
316
317
|
require 't/core_ext/string'
|
317
318
|
user = if options['id']
|
@@ -320,9 +321,8 @@ module T
|
|
320
321
|
user.strip_ats
|
321
322
|
end
|
322
323
|
end
|
323
|
-
count = options['number'] || DEFAULT_NUM_RESULTS
|
324
324
|
tweets = collect_with_count(count) do |count_opts|
|
325
|
-
client.favorites(user, count_opts)
|
325
|
+
client.favorites(user, count_opts.merge(opts))
|
326
326
|
end
|
327
327
|
print_tweets(tweets)
|
328
328
|
end
|
@@ -355,11 +355,9 @@ module T
|
|
355
355
|
user.strip_ats
|
356
356
|
end
|
357
357
|
end
|
358
|
-
following_ids =
|
359
|
-
client.friend_ids(user, :cursor => cursor)
|
360
|
-
end
|
358
|
+
following_ids = client.friend_ids(user).to_a
|
361
359
|
require 'retryable'
|
362
|
-
users = retryable(:tries => 3, :on => Twitter::Error
|
360
|
+
users = retryable(:tries => 3, :on => Twitter::Error, :sleep => 0) do
|
363
361
|
client.users(following_ids)
|
364
362
|
end
|
365
363
|
print_users(users)
|
@@ -381,11 +379,9 @@ module T
|
|
381
379
|
user.strip_ats
|
382
380
|
end
|
383
381
|
end
|
384
|
-
follower_ids =
|
385
|
-
client.follower_ids(user, :cursor => cursor)
|
386
|
-
end
|
382
|
+
follower_ids = client.follower_ids(user).to_a
|
387
383
|
require 'retryable'
|
388
|
-
users = retryable(:tries => 3, :on => Twitter::Error
|
384
|
+
users = retryable(:tries => 3, :on => Twitter::Error, :sleep => 0) do
|
389
385
|
client.users(follower_ids)
|
390
386
|
end
|
391
387
|
print_users(users)
|
@@ -410,18 +406,14 @@ module T
|
|
410
406
|
client.verify_credentials.screen_name
|
411
407
|
end
|
412
408
|
following_ids = Thread.new do
|
413
|
-
|
414
|
-
client.friend_ids(user, :cursor => cursor)
|
415
|
-
end
|
409
|
+
client.friend_ids(user).to_a
|
416
410
|
end
|
417
411
|
follower_ids = Thread.new do
|
418
|
-
|
419
|
-
client.follower_ids(user, :cursor => cursor)
|
420
|
-
end
|
412
|
+
client.follower_ids(user).to_a
|
421
413
|
end
|
422
414
|
friend_ids = (following_ids.value & follower_ids.value)
|
423
415
|
require 'retryable'
|
424
|
-
users = retryable(:tries => 3, :on => Twitter::Error
|
416
|
+
users = retryable(:tries => 3, :on => Twitter::Error, :sleep => 0) do
|
425
417
|
client.users(friend_ids)
|
426
418
|
end
|
427
419
|
print_users(users)
|
@@ -446,18 +438,14 @@ module T
|
|
446
438
|
client.verify_credentials.screen_name
|
447
439
|
end
|
448
440
|
following_ids = Thread.new do
|
449
|
-
|
450
|
-
client.friend_ids(user, :cursor => cursor)
|
451
|
-
end
|
441
|
+
client.friend_ids(user).to_a
|
452
442
|
end
|
453
443
|
follower_ids = Thread.new do
|
454
|
-
|
455
|
-
client.follower_ids(user, :cursor => cursor)
|
456
|
-
end
|
444
|
+
client.follower_ids(user).to_a
|
457
445
|
end
|
458
446
|
leader_ids = (following_ids.value - follower_ids.value)
|
459
447
|
require 'retryable'
|
460
|
-
users = retryable(:tries => 3, :on => Twitter::Error
|
448
|
+
users = retryable(:tries => 3, :on => Twitter::Error, :sleep => 0) do
|
461
449
|
client.users(leader_ids)
|
462
450
|
end
|
463
451
|
print_users(users)
|
@@ -503,29 +491,29 @@ module T
|
|
503
491
|
map %w(replies) => :mentions
|
504
492
|
|
505
493
|
desc "open USER", "Opens that user's profile in a web browser."
|
506
|
-
method_option "display-
|
494
|
+
method_option "display-uri", :aliases => "-d", :type => :boolean, :default => false, :desc => "Display the requested URL instead of attempting to open it."
|
507
495
|
method_option "id", :aliases => "-i", :type => :boolean, :default => false, :desc => "Specify user via ID instead of screen name."
|
508
496
|
method_option "status", :aliases => "-s", :type => :boolean, :default => false, :desc => "Specify input as a Twitter status ID instead of a screen name."
|
509
497
|
def open(user)
|
510
498
|
require 'launchy'
|
511
499
|
if options['id']
|
512
500
|
user = client.user(user.to_i)
|
513
|
-
open_or_print(
|
501
|
+
open_or_print(user.website, :dry_run => options['display-uri'])
|
514
502
|
elsif options['status']
|
515
503
|
status = client.status(user.to_i, :include_my_retweet => false)
|
516
|
-
open_or_print(
|
504
|
+
open_or_print(status.uri, :dry_run => options['display-uri'])
|
517
505
|
else
|
518
506
|
require 't/core_ext/string'
|
519
|
-
open_or_print("https://twitter.com/#{user.strip_ats}", :dry_run => options['display-
|
507
|
+
open_or_print("https://twitter.com/#{user.strip_ats}", :dry_run => options['display-uri'])
|
520
508
|
end
|
521
509
|
end
|
522
510
|
|
523
511
|
desc "reply TWEET_ID MESSAGE", "Post your Tweet as a reply directed at another person."
|
524
512
|
method_option "all", :aliases => "-a", :type => :boolean, :default => false, :desc => "Reply to all users mentioned in the Tweet."
|
525
|
-
method_option "location", :aliases => "-l", :type => :
|
513
|
+
method_option "location", :aliases => "-l", :type => :string, :default => "location", :desc => "Add location information. If the optional 'latitude,longitude' parameter is not supplied, looks up location by IP address."
|
526
514
|
def reply(status_id, message)
|
527
515
|
status = client.status(status_id.to_i, :include_my_retweet => false)
|
528
|
-
users = Array(status.
|
516
|
+
users = Array(status.user.screen_name)
|
529
517
|
if options['all']
|
530
518
|
users += extract_mentioned_screen_names(status.full_text)
|
531
519
|
users.uniq!
|
@@ -533,7 +521,7 @@ module T
|
|
533
521
|
require 't/core_ext/string'
|
534
522
|
users.map!(&:prepend_at)
|
535
523
|
opts = {:in_reply_to_status_id => status.id, :trim_user => true}
|
536
|
-
|
524
|
+
add_location!(options, opts)
|
537
525
|
reply = client.update("#{users.join(' ')} #{message}", opts)
|
538
526
|
say "Reply posted by @#{@rcfile.active_profile[0]} to #{users.join(' ')}."
|
539
527
|
say
|
@@ -555,7 +543,7 @@ module T
|
|
555
543
|
status_ids.unshift(status_id)
|
556
544
|
status_ids.map!(&:to_i)
|
557
545
|
require 'retryable'
|
558
|
-
retweets = retryable(:tries => 3, :on => Twitter::Error
|
546
|
+
retweets = retryable(:tries => 3, :on => Twitter::Error, :sleep => 0) do
|
559
547
|
client.retweet(status_ids, :trim_user => true)
|
560
548
|
end
|
561
549
|
number = retweets.length
|
@@ -595,7 +583,8 @@ module T
|
|
595
583
|
desc "ruler", "Prints a 140-character ruler"
|
596
584
|
method_option "indent", :aliases => "-i", :type => :numeric, :default => 0, :desc => "The number of space to print before the ruler."
|
597
585
|
def ruler
|
598
|
-
|
586
|
+
markings = '----|'.chars.cycle.take(140).join
|
587
|
+
say "#{' ' * options['indent'].to_i}#{markings}"
|
599
588
|
end
|
600
589
|
|
601
590
|
desc "status TWEET_ID", "Retrieves detailed information about a Tweet."
|
@@ -603,8 +592,7 @@ module T
|
|
603
592
|
method_option "long", :aliases => "-l", :type => :boolean, :default => false, :desc => "Output in long format."
|
604
593
|
def status(status_id)
|
605
594
|
status = client.status(status_id.to_i, :include_my_retweet => false)
|
606
|
-
|
607
|
-
location = if status.place
|
595
|
+
location = if status.place?
|
608
596
|
if status.place.name && status.place.attributes && status.place.attributes[:street_address] && status.place.attributes[:locality] && status.place.attributes[:region] && status.place.country
|
609
597
|
[status.place.name, status.place.attributes[:street_address], status.place.attributes[:locality], status.place.attributes[:region], status.place.country].join(", ")
|
610
598
|
elsif status.place.name && status.place.attributes && status.place.attributes[:locality] && status.place.attributes[:region] && status.place.country
|
@@ -618,28 +606,26 @@ module T
|
|
618
606
|
else
|
619
607
|
status.place.name
|
620
608
|
end
|
621
|
-
elsif status.geo
|
609
|
+
elsif status.geo?
|
622
610
|
reverse_geocode(status.geo)
|
623
611
|
end
|
624
|
-
status_headings = ["ID", "Posted at", "Screen name", "Text", "Retweets", "Favorites", "
|
612
|
+
status_headings = ["ID", "Posted at", "Screen name", "Text", "Retweets", "Favorites", "Source", "Location"]
|
625
613
|
if options['csv']
|
626
614
|
require 'csv'
|
627
|
-
require 'fastercsv' unless Array.new.respond_to?(:to_csv)
|
628
615
|
say status_headings.to_csv
|
629
|
-
say [status.id, csv_formatted_time(status), status.
|
616
|
+
say [status.id, csv_formatted_time(status), status.user.screen_name, decode_full_text(status), status.retweet_count, status.favorite_count, strip_tags(status.source), location].to_csv
|
630
617
|
elsif options['long']
|
631
|
-
array = [status.id, ls_formatted_time(status), "@#{status.
|
618
|
+
array = [status.id, ls_formatted_time(status), "@#{status.user.screen_name}", decode_full_text(status).gsub(/\n+/, ' '), status.retweet_count, status.favorite_count, strip_tags(status.source), location]
|
632
619
|
format = options['format'] || status_headings.size.times.map{"%s"}
|
633
620
|
print_table_with_headings([array], status_headings, format)
|
634
621
|
else
|
635
622
|
array = []
|
636
623
|
array << ["ID", status.id.to_s]
|
637
624
|
array << ["Text", decode_full_text(status).gsub(/\n+/, ' ')]
|
638
|
-
array << ["Screen name", "@#{status.
|
625
|
+
array << ["Screen name", "@#{status.user.screen_name}"]
|
639
626
|
array << ["Posted at", "#{ls_formatted_time(status)} (#{time_ago_in_words(status.created_at)} ago)"]
|
640
627
|
array << ["Retweets", number_with_delimiter(status.retweet_count)]
|
641
|
-
array << ["Favorites", number_with_delimiter(
|
642
|
-
array << ["Replies", number_with_delimiter(status_activity.repliers_count)]
|
628
|
+
array << ["Favorites", number_with_delimiter(status.favorite_count)]
|
643
629
|
array << ["Source", strip_tags(status.source)]
|
644
630
|
array << ["Location", location] unless location.nil?
|
645
631
|
print_table(array)
|
@@ -713,7 +699,6 @@ module T
|
|
713
699
|
places.reverse! if options['reverse']
|
714
700
|
if options['csv']
|
715
701
|
require 'csv'
|
716
|
-
require 'fastercsv' unless Array.new.respond_to?(:to_csv)
|
717
702
|
say TREND_HEADINGS.to_csv unless places.empty?
|
718
703
|
places.each do |place|
|
719
704
|
say [place.woeid, place.parent_id, place.place_type, place.name, place.country].to_csv
|
@@ -741,12 +726,13 @@ module T
|
|
741
726
|
say "Run `#{File.basename($0)} follow #{users.map{|user| "@#{user.screen_name}"}.join(' ')}` to follow again."
|
742
727
|
end
|
743
728
|
|
744
|
-
desc "update MESSAGE", "Post a Tweet."
|
745
|
-
method_option "location", :aliases => "-l", :type => :
|
729
|
+
desc "update [MESSAGE]", "Post a Tweet."
|
730
|
+
method_option "location", :aliases => "-l", :type => :string, :default => "location", :desc => "Add location information. If the optional 'latitude,longitude' parameter is not supplied, looks up location by IP address."
|
746
731
|
method_option "file", :aliases => "-f", :type => :string, :desc => "The path to an image to attach to your tweet."
|
747
|
-
def update(message)
|
732
|
+
def update(message=nil)
|
733
|
+
message = T::Editor.gets if message.nil? || message.empty?
|
748
734
|
opts = {:trim_user => true}
|
749
|
-
|
735
|
+
add_location!(options, opts)
|
750
736
|
status = if options['file']
|
751
737
|
client.update_with_media(message, File.new(File.expand_path(options['file'])), opts)
|
752
738
|
else
|
@@ -808,13 +794,13 @@ module T
|
|
808
794
|
array << ["Screen name", "@#{user.screen_name}"]
|
809
795
|
array << [user.verified ? "Name (Verified)" : "Name", user.name] unless user.name.nil?
|
810
796
|
array << ["Tweets", number_with_delimiter(user.statuses_count)]
|
811
|
-
array << ["Favorites", number_with_delimiter(user.
|
797
|
+
array << ["Favorites", number_with_delimiter(user.favorites_count)]
|
812
798
|
array << ["Listed", number_with_delimiter(user.listed_count)]
|
813
799
|
array << ["Following", number_with_delimiter(user.friends_count)]
|
814
800
|
array << ["Followers", number_with_delimiter(user.followers_count)]
|
815
801
|
array << ["Bio", user.description.gsub(/\n+/, ' ')] unless user.description.nil?
|
816
802
|
array << ["Location", user.location] unless user.location.nil?
|
817
|
-
array << ["URL", user.
|
803
|
+
array << ["URL", user.website] unless user.website.nil?
|
818
804
|
print_table(array)
|
819
805
|
end
|
820
806
|
end
|
@@ -853,24 +839,27 @@ module T
|
|
853
839
|
end
|
854
840
|
end
|
855
841
|
|
856
|
-
def
|
857
|
-
"#{protocol}://#{host}"
|
858
|
-
end
|
859
|
-
|
860
|
-
def generate_authorize_url(consumer, request_token)
|
842
|
+
def generate_authorize_uri(consumer, request_token)
|
861
843
|
request = consumer.create_signed_request(:get, consumer.authorize_path, request_token, pin_auth_parameters)
|
862
844
|
params = request['Authorization'].sub(/^OAuth\s+/, '').split(/,\s+/).map do |param|
|
863
845
|
key, value = param.split('=')
|
864
846
|
value =~ /"(.*?)"/
|
865
847
|
"#{key}=#{CGI::escape($1)}"
|
866
848
|
end.join('&')
|
867
|
-
"#{
|
849
|
+
"#{Twitter::REST::Client::ENDPOINT}#{request.path}?#{params}"
|
868
850
|
end
|
869
851
|
|
870
852
|
def pin_auth_parameters
|
871
853
|
{:oauth_callback => 'oob'}
|
872
854
|
end
|
873
855
|
|
856
|
+
def add_location!(options, opts)
|
857
|
+
if options['location']
|
858
|
+
lat, lng = options['location'] == 'location' ? [location.lat, location.lng] : options['location'].split(',').map(&:to_f)
|
859
|
+
opts.merge!(:lat => lat, :long => lng)
|
860
|
+
end
|
861
|
+
end
|
862
|
+
|
874
863
|
def location
|
875
864
|
return @location if @location
|
876
865
|
require 'geokit'
|