tweetwine 0.3.2 → 0.4.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/.gitignore +6 -0
- data/CHANGELOG.rdoc +9 -0
- data/Gemfile +5 -13
- data/LICENSE.txt +1 -1
- data/README.md +3 -2
- data/Rakefile +8 -2
- data/lib/tweetwine/character_encoding.rb +1 -1
- data/lib/tweetwine/cli.rb +9 -3
- data/lib/tweetwine/config.rb +3 -3
- data/lib/tweetwine/exceptions.rb +54 -0
- data/lib/tweetwine/http.rb +1 -1
- data/lib/tweetwine/{util.rb → support.rb} +19 -12
- data/lib/tweetwine/tweet.rb +69 -0
- data/lib/tweetwine/twitter.rb +70 -72
- data/lib/tweetwine/ui.rb +36 -41
- data/lib/tweetwine/uri.rb +31 -0
- data/lib/tweetwine/version.rb +15 -0
- data/lib/tweetwine.rb +6 -64
- data/man/tweetwine.7 +4 -3
- data/man/tweetwine.7.ronn +3 -2
- data/release-script.txt +10 -0
- data/test/example/authorization_example.rb +40 -0
- data/test/example/example_helper.rb +1 -1
- data/test/example/global_options_example.rb +64 -0
- data/test/example/search_statuses_example.rb +36 -31
- data/test/example/show_followers_example.rb +1 -1
- data/test/example/show_friends_example.rb +1 -1
- data/test/example/show_home_example.rb +17 -29
- data/test/example/show_mentions_example.rb +2 -2
- data/test/example/show_user_example.rb +14 -12
- data/test/example/update_status_example.rb +9 -9
- data/test/example/use_http_proxy_example.rb +7 -6
- data/test/example/{application_behavior_example.rb → user_help_example.rb} +6 -39
- data/test/unit/config_test.rb +1 -1
- data/test/unit/http_test.rb +1 -21
- data/test/unit/oauth_test.rb +11 -11
- data/test/unit/{util_test.rb → support_test.rb} +37 -38
- data/test/unit/tweet_helper.rb +83 -0
- data/test/unit/tweet_test.rb +153 -0
- data/test/unit/twitter_test.rb +240 -248
- data/test/unit/ui_test.rb +174 -78
- data/test/unit/unit_helper.rb +18 -6
- data/test/unit/uri_test.rb +41 -0
- data/test/unit/url_shortener_test.rb +7 -7
- data/tweetwine.gemspec +12 -22
- metadata +52 -73
data/.gitignore
ADDED
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 0.4.0 released 2011-02-22
|
2
|
+
|
3
|
+
* Add option <tt>-r</tt> to reverse the order of showing tweets
|
4
|
+
* Show retweets as whole tweets
|
5
|
+
* Properly display error message on invalid argument to <tt>--page</tt> or
|
6
|
+
<tt>--num</tt> options
|
7
|
+
* Fix deprecation warning about <tt>URI.escape</tt> on MRI 1.9.2
|
8
|
+
* Minor cleanups
|
9
|
+
|
1
10
|
=== 0.3.2 released 2010-11-17
|
2
11
|
|
3
12
|
* Drop <tt>json</tt> gem dependency from gemspec in order to allow the user to
|
data/Gemfile
CHANGED
@@ -1,17 +1,9 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
1
3
|
source :rubygems
|
2
4
|
|
5
|
+
gemspec
|
6
|
+
|
7
|
+
# Special handling at runtime.
|
3
8
|
gem 'json', '>= 1.0.0', :platforms => [:ruby_18, :jruby]
|
4
9
|
gem 'nokogiri', '~> 1.4.4'
|
5
|
-
gem 'oauth', '~> 0.4.4'
|
6
|
-
|
7
|
-
group :test do
|
8
|
-
gem 'contest', '~> 0.1.2'
|
9
|
-
gem 'coulda', '~> 0.6.0'
|
10
|
-
gem 'gem-man', '~> 0.2.0'
|
11
|
-
gem 'mcmire-matchy', '~> 0.5.2', :require => 'matchy'
|
12
|
-
gem 'mocha', '= 0.9.8'
|
13
|
-
gem 'open4', '~> 1.0.1'
|
14
|
-
gem 'ronn', '~> 0.7.3'
|
15
|
-
gem 'timecop', '~> 0.3.5'
|
16
|
-
gem 'webmock', '~> 1.6.1'
|
17
|
-
end
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -77,6 +77,7 @@ enabled via `shorten_urls` field in the configuration file; for example:
|
|
77
77
|
|
78
78
|
username: spoonman
|
79
79
|
colors: true
|
80
|
+
show_reverse: true
|
80
81
|
shorten_urls:
|
81
82
|
service_url: http://is.gd/create.php
|
82
83
|
method: post
|
@@ -124,8 +125,8 @@ snippet to your Bash initialization script (such as `~/.bashrc`):
|
|
124
125
|
|
125
126
|
## COPYRIGHT
|
126
127
|
|
127
|
-
Tweetwine is
|
128
|
+
Tweetwine is copyright © 2009-2011 Tuomas Kareinen. See `LICENSE.txt`.
|
128
129
|
|
129
130
|
## SEE ALSO
|
130
131
|
|
131
|
-
<https://github.com/
|
132
|
+
<https://github.com/tkareine/tweetwine>
|
data/Rakefile
CHANGED
@@ -4,8 +4,8 @@ require 'rake/clean'
|
|
4
4
|
|
5
5
|
$LOAD_PATH.unshift(File.expand_path('lib', File.dirname(__FILE__)))
|
6
6
|
name = 'tweetwine'
|
7
|
-
require name
|
8
|
-
version = Tweetwine.version
|
7
|
+
require "#{name}/version"
|
8
|
+
version = Tweetwine.version
|
9
9
|
|
10
10
|
namespace :gem do
|
11
11
|
CLOBBER.include "#{name}-*.gem"
|
@@ -42,6 +42,12 @@ namespace :man do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
CLOBBER.include 'rdoc'
|
46
|
+
desc "Generate RDoc"
|
47
|
+
task :rdoc do
|
48
|
+
sh %{rdoc --encoding=UTF-8 --line-numbers --title='#{name} #{version}' --output=rdoc *.rdoc LICENSE.txt lib}
|
49
|
+
end
|
50
|
+
|
45
51
|
namespace :test do
|
46
52
|
def create_test_task(type, options = {})
|
47
53
|
base_dir = options[:base_dir]
|
data/lib/tweetwine/cli.rb
CHANGED
@@ -8,6 +8,9 @@ module Tweetwine
|
|
8
8
|
:config_file => "#{(ENV['HOME'] || ENV['USERPROFILE'])}/.tweetwine",
|
9
9
|
:env_lookouts => [:http_proxy],
|
10
10
|
:excludes => [:command],
|
11
|
+
:num_tweets => 20,
|
12
|
+
:page => 1,
|
13
|
+
:show_reverse => false,
|
11
14
|
:shorten_urls => {:disable => true},
|
12
15
|
:username => ENV['USER']
|
13
16
|
}.freeze
|
@@ -84,12 +87,15 @@ module Tweetwine
|
|
84
87
|
options[:shorten_urls] ||= {}
|
85
88
|
options[:shorten_urls][:disable] = true
|
86
89
|
end
|
87
|
-
parser.on '-n', '--num <n>', Integer, "Number of
|
88
|
-
options[:
|
90
|
+
parser.on '-n', '--num <n>', Integer, "Number of tweets per page (default #{DEFAULT_CONFIG[:num_tweets]})." do |arg|
|
91
|
+
options[:num_tweets] = arg
|
89
92
|
end
|
90
|
-
parser.on '-p', '--page <p>', Integer, "Page number for
|
93
|
+
parser.on '-p', '--page <p>', Integer, "Page number for tweets (default #{DEFAULT_CONFIG[:page]})." do |arg|
|
91
94
|
options[:page] = arg
|
92
95
|
end
|
96
|
+
parser.on '-r', '--reverse', "Show tweets in reverse order (default #{DEFAULT_CONFIG[:show_reverse]})." do
|
97
|
+
options[:show_reverse] = true
|
98
|
+
end
|
93
99
|
parser.on '-u', '--username <user>', String, "User to authenticate (default '#{DEFAULT_CONFIG[:username]}')." do |arg|
|
94
100
|
options[:username] = arg
|
95
101
|
end
|
data/lib/tweetwine/config.rb
CHANGED
@@ -27,7 +27,7 @@ module Tweetwine
|
|
27
27
|
should_set_file_access_to_user_only = !File.exist?(@file)
|
28
28
|
File.open(@file, 'w') do |io|
|
29
29
|
io.chmod(0600) if should_set_file_access_to_user_only
|
30
|
-
YAML.dump(
|
30
|
+
YAML.dump(Support.stringify_hash_keys(to_file), io)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -52,14 +52,14 @@ module Tweetwine
|
|
52
52
|
def self.parse_env_vars(env_lookouts)
|
53
53
|
env_lookouts.inject({}) do |result, env_var_name|
|
54
54
|
env_option = ENV[env_var_name.to_s]
|
55
|
-
result[env_var_name.to_sym] = env_option
|
55
|
+
result[env_var_name.to_sym] = env_option if Support.present?(env_option)
|
56
56
|
result
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
60
|
def self.parse_config_file(config_file)
|
61
61
|
options = File.open(config_file, 'r') { |io| YAML.load(io) }
|
62
|
-
|
62
|
+
Support.symbolize_hash_keys(options)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Tweetwine
|
4
|
+
class Error < StandardError
|
5
|
+
@status_code = 42
|
6
|
+
|
7
|
+
# Idea got from Bundler.
|
8
|
+
def self.status_code(code = nil)
|
9
|
+
return @status_code unless code
|
10
|
+
@status_code = code
|
11
|
+
end
|
12
|
+
|
13
|
+
def status_code
|
14
|
+
self.class.status_code
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class CommandLineError < Error; status_code(13); end
|
19
|
+
class UnknownCommandError < Error; status_code(14); end
|
20
|
+
|
21
|
+
class RequiredOptionError < Error
|
22
|
+
status_code(15)
|
23
|
+
|
24
|
+
attr_reader :key, :owner
|
25
|
+
|
26
|
+
def initialize(key, owner)
|
27
|
+
@key, @owner = key, owner
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"#{key} is required for #{owner}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ConnectionError < Error; status_code(21); end
|
36
|
+
class TimeoutError < Error; status_code(22); end
|
37
|
+
|
38
|
+
class HttpError < Error
|
39
|
+
status_code(25)
|
40
|
+
|
41
|
+
attr_reader :http_code, :http_message
|
42
|
+
|
43
|
+
def initialize(code, message)
|
44
|
+
@http_code, @http_message = code.to_i, message
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
"#{http_code} #{http_message}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class TranscodeError < Error; status_code(31); end
|
53
|
+
class AuthorizationError < Error; status_code(32); end
|
54
|
+
end
|
data/lib/tweetwine/http.rb
CHANGED
@@ -1,15 +1,26 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require "uri"
|
3
|
+
require 'cgi'
|
4
|
+
require 'time'
|
6
5
|
|
7
6
|
module Tweetwine
|
8
|
-
module
|
7
|
+
module Support
|
9
8
|
extend self
|
10
9
|
|
11
|
-
def blank?(
|
12
|
-
|
10
|
+
def blank?(var)
|
11
|
+
var.nil? || var.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def present?(var)
|
15
|
+
!blank?(var)
|
16
|
+
end
|
17
|
+
|
18
|
+
def presence(var)
|
19
|
+
if present? var
|
20
|
+
block_given? ? yield(var) : var
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
13
24
|
end
|
14
25
|
|
15
26
|
def humanize_time_diff(from, to)
|
@@ -69,10 +80,6 @@ module Tweetwine
|
|
69
80
|
dup_str
|
70
81
|
end
|
71
82
|
|
72
|
-
def percent_encode(str)
|
73
|
-
URI.escape(str.to_s, /[^#{URI::PATTERN::UNRESERVED}]/)
|
74
|
-
end
|
75
|
-
|
76
83
|
def unescape_html(str)
|
77
84
|
CGI.unescapeHTML(str.gsub(' ', ' '))
|
78
85
|
end
|
@@ -99,8 +106,8 @@ module Tweetwine
|
|
99
106
|
end
|
100
107
|
|
101
108
|
def pluralize_unit(value, unit)
|
102
|
-
if
|
103
|
-
unit = unit +
|
109
|
+
if %w{hour day}.include?(unit) && value > 1
|
110
|
+
unit = unit + 's'
|
104
111
|
end
|
105
112
|
unit
|
106
113
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Tweetwine
|
4
|
+
class Tweet
|
5
|
+
attr_reader :from_user, :to_user, :rt_user, :created_at, :status
|
6
|
+
|
7
|
+
def initialize(record, paths)
|
8
|
+
if field_present? record, paths[:retweet]
|
9
|
+
@rt_user = parse_string_field record, paths[:from_user]
|
10
|
+
fields = Support.find_hash_path record, paths[:retweet]
|
11
|
+
else
|
12
|
+
@rt_user = nil
|
13
|
+
fields = record
|
14
|
+
end
|
15
|
+
@to_user = parse_string_field fields, paths[:to_user]
|
16
|
+
@from_user = parse_string_field fields, paths[:from_user]
|
17
|
+
raise ArgumentError, 'from user record field is required' unless @from_user
|
18
|
+
@created_at = parse_time_field fields, paths[:created_at]
|
19
|
+
@status = parse_string_field fields, paths[:status]
|
20
|
+
end
|
21
|
+
|
22
|
+
def timestamped?
|
23
|
+
!@created_at.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def retweet?
|
27
|
+
!@rt_user.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
def status?
|
31
|
+
!@status.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def reply?
|
35
|
+
!@to_user.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def ==(other)
|
39
|
+
other.is_a?(self.class) &&
|
40
|
+
self.rt_user == other.rt_user &&
|
41
|
+
self.to_user == other.to_user &&
|
42
|
+
self.from_user == other.from_user &&
|
43
|
+
self.created_at == other.created_at &&
|
44
|
+
self.status == other.status
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def field_present?(record, path)
|
50
|
+
!!find_field(record, path) { |f| Support.present?(f) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def field_presence(record, path, &block)
|
54
|
+
find_field(record, path) { |f| Support.presence(f, &block) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_string_field(record, path)
|
58
|
+
field_presence(record, path) { |f| f.to_s }
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_time_field(record, path)
|
62
|
+
field_presence(record, path) { |f| Time.parse(f.to_s) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_field(record, path)
|
66
|
+
yield(Support.find_hash_path(record, path)) rescue nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/tweetwine/twitter.rb
CHANGED
@@ -4,36 +4,56 @@ require "uri"
|
|
4
4
|
|
5
5
|
module Tweetwine
|
6
6
|
class Twitter
|
7
|
-
DEFAULT_NUM_STATUSES = 20
|
8
|
-
DEFAULT_PAGE_NUM = 1
|
9
7
|
MAX_STATUS_LENGTH = 140
|
10
8
|
|
11
|
-
|
9
|
+
REST_API_STATUS_PATHS = {
|
10
|
+
:from_user => %w{user screen_name},
|
11
|
+
:to_user => %w{in_reply_to_screen_name},
|
12
|
+
:retweet => %w{retweeted_status},
|
13
|
+
:created_at => %w{created_at},
|
14
|
+
:status => %w{text}
|
15
|
+
}
|
16
|
+
|
17
|
+
REST_API_USER_PATHS = {
|
18
|
+
:from_user => %w{screen_name},
|
19
|
+
:to_user => %w{status in_reply_to_screen_name},
|
20
|
+
:retweet => %w{retweeted_status},
|
21
|
+
:created_at => %w{status created_at},
|
22
|
+
:status => %w{status text}
|
23
|
+
}
|
24
|
+
|
25
|
+
SEARCH_API_STATUS_PATHS = {
|
26
|
+
:from_user => %w{from_user},
|
27
|
+
:to_user => %w{to_user},
|
28
|
+
:retweet => %w{retweeted_status},
|
29
|
+
:created_at => %w{created_at},
|
30
|
+
:status => %w{text}
|
31
|
+
}
|
32
|
+
|
33
|
+
attr_reader :num_tweets, :page, :username
|
12
34
|
|
13
35
|
def initialize(options = {})
|
14
|
-
@
|
15
|
-
@page
|
16
|
-
@username
|
36
|
+
@num_tweets = Support.parse_int_gt(options[:num_tweets], CLI::DEFAULT_CONFIG[:num_tweets], 1, "number of tweets to show")
|
37
|
+
@page = Support.parse_int_gt(options[:page], CLI::DEFAULT_CONFIG[:page], 1, "page number")
|
38
|
+
@username = options[:username].to_s
|
39
|
+
rescue ArgumentError => e
|
40
|
+
raise CommandLineError, e
|
17
41
|
end
|
18
42
|
|
19
43
|
def followers
|
20
|
-
|
21
|
-
show_users_from_rest_api(*response)
|
44
|
+
show_users_from_rest_api(get_from_rest_api("statuses/followers"))
|
22
45
|
end
|
23
46
|
|
24
47
|
def friends
|
25
|
-
|
26
|
-
show_users_from_rest_api(*response)
|
48
|
+
show_users_from_rest_api(get_from_rest_api("statuses/friends"))
|
27
49
|
end
|
28
50
|
|
29
51
|
def home
|
30
|
-
|
31
|
-
show_statuses_from_rest_api(*response)
|
52
|
+
show_tweets_from_rest_api(get_from_rest_api("statuses/home_timeline"))
|
32
53
|
end
|
33
54
|
|
34
55
|
def mentions
|
35
|
-
|
36
|
-
show_statuses_from_rest_api(*response)
|
56
|
+
show_tweets_from_rest_api(get_from_rest_api("statuses/mentions"))
|
37
57
|
end
|
38
58
|
|
39
59
|
def search(words = [], operator = nil)
|
@@ -41,7 +61,7 @@ module Tweetwine
|
|
41
61
|
operator = :and unless operator
|
42
62
|
query = operator == :and ? words.join(' ') : words.join(' OR ')
|
43
63
|
response = get_from_search_api query
|
44
|
-
|
64
|
+
show_tweets_from_search_api(response["results"])
|
45
65
|
end
|
46
66
|
|
47
67
|
def update(msg = nil)
|
@@ -53,7 +73,7 @@ module Tweetwine
|
|
53
73
|
if CLI.ui.confirm("Really send?")
|
54
74
|
response = post_to_rest_api("statuses/update", :status => status_in_utf8)
|
55
75
|
CLI.ui.info "Sent status update.\n\n"
|
56
|
-
|
76
|
+
show_tweets_from_rest_api([response])
|
57
77
|
completed = true
|
58
78
|
end
|
59
79
|
end
|
@@ -61,25 +81,24 @@ module Tweetwine
|
|
61
81
|
end
|
62
82
|
|
63
83
|
def user(who = username)
|
64
|
-
|
84
|
+
show_tweets_from_rest_api(get_from_rest_api(
|
65
85
|
"statuses/user_timeline",
|
66
86
|
common_rest_api_query_params.merge!({ :screen_name => who })
|
67
|
-
)
|
68
|
-
show_statuses_from_rest_api(*response)
|
87
|
+
))
|
69
88
|
end
|
70
89
|
|
71
90
|
private
|
72
91
|
|
73
92
|
def common_rest_api_query_params
|
74
93
|
{
|
75
|
-
:count => @
|
94
|
+
:count => @num_tweets,
|
76
95
|
:page => @page
|
77
96
|
}
|
78
97
|
end
|
79
98
|
|
80
99
|
def common_search_api_query_params
|
81
100
|
{
|
82
|
-
:rpp => @
|
101
|
+
:rpp => @num_tweets,
|
83
102
|
:page => @page
|
84
103
|
}
|
85
104
|
end
|
@@ -113,7 +132,7 @@ module Tweetwine
|
|
113
132
|
end
|
114
133
|
|
115
134
|
def get_from_search_api(query, params = common_search_api_query_params)
|
116
|
-
query = "q=#{
|
135
|
+
query = "q=#{Uri.percent_encode(query)}&" << format_query_params(params)
|
117
136
|
JSON.parse search_api["search.json?#{query}"].get
|
118
137
|
end
|
119
138
|
|
@@ -133,55 +152,34 @@ module Tweetwine
|
|
133
152
|
CLI.config.save
|
134
153
|
end
|
135
154
|
|
136
|
-
def
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
)
|
146
|
-
end
|
147
|
-
|
148
|
-
def
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
:status => ["status", "text"]
|
156
|
-
}
|
157
|
-
)
|
158
|
-
end
|
159
|
-
|
160
|
-
def show_statuses_from_search_api(*responses)
|
161
|
-
show_records(
|
162
|
-
responses,
|
163
|
-
{
|
164
|
-
:from_user => "from_user",
|
165
|
-
:to_user => "to_user",
|
166
|
-
:created_at => "created_at",
|
167
|
-
:status => "text"
|
168
|
-
}
|
169
|
-
)
|
170
|
-
end
|
171
|
-
|
172
|
-
def show_records(twitter_records, paths)
|
173
|
-
twitter_records.each do |twitter_record|
|
174
|
-
internal_record = [ :from_user, :to_user, :created_at, :status ].inject({}) do |result, key|
|
175
|
-
result[key] = Util.find_hash_path(twitter_record, paths[key])
|
176
|
-
result
|
155
|
+
def show_tweets_from_rest_api(records)
|
156
|
+
show_tweets(records, REST_API_STATUS_PATHS)
|
157
|
+
end
|
158
|
+
|
159
|
+
def show_users_from_rest_api(records)
|
160
|
+
show_tweets(records, REST_API_USER_PATHS)
|
161
|
+
end
|
162
|
+
|
163
|
+
def show_tweets_from_search_api(records)
|
164
|
+
show_tweets(records, SEARCH_API_STATUS_PATHS)
|
165
|
+
end
|
166
|
+
|
167
|
+
def show_tweets(records, paths)
|
168
|
+
tweets = records.map do |record|
|
169
|
+
begin
|
170
|
+
Tweet.new(record, paths)
|
171
|
+
rescue ArgumentError
|
172
|
+
CLI.ui.warn "Invalid tweet. Skipping..."
|
173
|
+
nil
|
177
174
|
end
|
178
|
-
CLI.ui.show_record(internal_record)
|
179
175
|
end
|
176
|
+
tweets.reject! { |tweet| tweet.nil? }
|
177
|
+
CLI.ui.show_tweets tweets
|
180
178
|
end
|
181
179
|
|
182
180
|
def create_status_update(status)
|
183
|
-
status = if
|
184
|
-
CLI.ui.prompt
|
181
|
+
status = if Support.blank? status
|
182
|
+
CLI.ui.prompt "Status update"
|
185
183
|
else
|
186
184
|
status.dup
|
187
185
|
end
|
@@ -192,11 +190,11 @@ module Tweetwine
|
|
192
190
|
end
|
193
191
|
|
194
192
|
def shorten_urls_in(status)
|
195
|
-
url_pairs =
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
193
|
+
url_pairs = Uri.
|
194
|
+
extract(status, %w{http https}).
|
195
|
+
uniq.
|
196
|
+
map { |full_url| [full_url, CLI.url_shortener.shorten(full_url)] }.
|
197
|
+
reject { |(full_url, short_url)| Support.blank? short_url }
|
200
198
|
url_pairs.each { |(full_url, short_url)| status.gsub!(full_url, short_url) }
|
201
199
|
rescue HttpError, LoadError => e
|
202
200
|
CLI.ui.warn "#{e}\nSkipping URL shortening..."
|
@@ -204,7 +202,7 @@ module Tweetwine
|
|
204
202
|
|
205
203
|
def truncate_status(status)
|
206
204
|
status.replace status[0...MAX_STATUS_LENGTH]
|
207
|
-
CLI.ui.warn
|
205
|
+
CLI.ui.warn "Status will be truncated."
|
208
206
|
end
|
209
207
|
end
|
210
208
|
end
|