twat 0.6.3 → 0.9.2
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/.rvmrc +1 -1
- data/.travis.yml +6 -0
- data/Gemfile +1 -4
- data/Gemfile.lock +43 -23
- data/Gemfile.travis +12 -0
- data/Rakefile +9 -0
- data/TODO +4 -1
- data/lib/twat.rb +30 -26
- data/lib/twat/argparse.rb +36 -79
- data/lib/twat/config.rb +22 -34
- data/lib/twat/endpoint.rb +11 -5
- data/lib/twat/endpoints/base.rb +39 -0
- data/lib/twat/endpoints/identica.rb +5 -1
- data/lib/twat/endpoints/twitter.rb +5 -1
- data/lib/twat/exceptions.rb +93 -46
- data/lib/twat/follow_mixin.rb +134 -0
- data/lib/twat/options.rb +28 -12
- data/lib/twat/subcommand.rb +34 -0
- data/lib/twat/subcommands/add.rb +17 -0
- data/lib/twat/subcommands/base.rb +122 -0
- data/lib/twat/subcommands/config.rb +15 -0
- data/lib/twat/subcommands/delete.rb +24 -0
- data/lib/twat/subcommands/finger.rb +23 -0
- data/lib/twat/subcommands/follow.rb +18 -0
- data/lib/twat/subcommands/follow_tag.rb +19 -0
- data/lib/twat/subcommands/list.rb +17 -0
- data/lib/twat/subcommands/mentions.rb +20 -0
- data/lib/twat/subcommands/set.rb +19 -0
- data/lib/twat/subcommands/track.rb +33 -0
- data/lib/twat/subcommands/update.rb +21 -0
- data/lib/twat/subcommands/update_config.rb +16 -0
- data/lib/twat/subcommands/version.rb +14 -0
- data/lib/twat/twatopt.rb +0 -0
- data/lib/twat/tweetstack.rb +38 -0
- data/lib/twat/version.rb +7 -0
- data/man/twat.1 +8 -5
- data/spec/argparse_spec.rb +48 -0
- data/spec/helpers/environment.rb +47 -0
- data/spec/helpers/fileutils.rb +18 -0
- data/spec/helpers/fixtures/core.rb +30 -0
- data/spec/helpers/fixtures/migrations.rb +13 -0
- data/spec/helpers/oauth.rb +15 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/subcommands/add_spec.rb +61 -0
- data/spec/subcommands/config_spec.rb +13 -0
- data/spec/subcommands/delete_spec.rb +12 -0
- data/spec/subcommands/finger_spec.rb +41 -0
- data/spec/subcommands/follow_spec.rb +12 -0
- data/spec/subcommands/follow_tag_spec.rb +52 -0
- data/spec/subcommands/list_spec.rb +8 -0
- data/spec/subcommands/mentions_spec.rb +24 -0
- data/spec/subcommands/set_spec.rb +126 -0
- data/spec/subcommands/track_spec.rb +23 -0
- data/spec/subcommands/update_config_spec.rb +23 -0
- data/spec/subcommands/update_spec.rb +12 -0
- data/spec/subcommands/version_spec.rb +12 -0
- data/spec/twat_cli_spec.rb +102 -0
- data/spec/twat_spec.rb +12 -0
- data/twat.gemspec +6 -2
- metadata +135 -22
- data/lib/twat/actions.rb +0 -85
- data/lib/twat/actions/add.rb +0 -36
- data/lib/twat/actions/delete.rb +0 -14
- data/lib/twat/actions/follow.rb +0 -148
- data/lib/twat/actions/follow_user.rb +0 -11
- data/lib/twat/actions/setoption.rb +0 -14
- data/lib/twat/actions/show.rb +0 -12
- data/lib/twat/actions/tweet.rb +0 -14
- data/lib/twat/actions/updateconfig.rb +0 -9
- data/lib/twat/actions/user_feed.rb +0 -17
- data/lib/twat/actions/version.rb +0 -9
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm 1.9.3
|
1
|
+
rvm use 1.9.3
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,31 +1,51 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
twat (0.9.1)
|
5
|
+
oauth
|
6
|
+
readline-ng (>= 0.0.8)
|
7
|
+
twitter
|
8
|
+
|
1
9
|
GEM
|
2
10
|
remote: http://rubygems.org/
|
3
11
|
specs:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
activesupport (3.2.3)
|
13
|
+
i18n (~> 0.6)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
diff-lcs (1.1.3)
|
16
|
+
faraday (0.8.0)
|
17
|
+
multipart-post (~> 1.1)
|
18
|
+
i18n (0.6.0)
|
19
|
+
metaclass (0.0.1)
|
20
|
+
mktemp (0.0.1)
|
21
|
+
mocha (0.11.3)
|
22
|
+
metaclass (~> 0.0.1)
|
23
|
+
multi_json (1.3.2)
|
24
|
+
multipart-post (1.1.5)
|
25
|
+
oauth (0.4.6)
|
26
|
+
rake (0.9.2.2)
|
27
|
+
readline-ng (0.0.8)
|
28
|
+
rspec (2.9.0)
|
29
|
+
rspec-core (~> 2.9.0)
|
30
|
+
rspec-expectations (~> 2.9.0)
|
31
|
+
rspec-mocks (~> 2.9.0)
|
32
|
+
rspec-core (2.9.0)
|
33
|
+
rspec-expectations (2.9.1)
|
34
|
+
diff-lcs (~> 1.1.3)
|
35
|
+
rspec-mocks (2.9.0)
|
36
|
+
simple_oauth (0.1.7)
|
37
|
+
twitter (2.2.4)
|
38
|
+
activesupport (>= 2.3.9, < 4)
|
39
|
+
faraday (~> 0.8)
|
40
|
+
multi_json (~> 1.3)
|
41
|
+
simple_oauth (~> 0.1.6)
|
25
42
|
|
26
43
|
PLATFORMS
|
27
44
|
ruby
|
28
45
|
|
29
46
|
DEPENDENCIES
|
30
|
-
|
31
|
-
|
47
|
+
mktemp
|
48
|
+
mocha
|
49
|
+
rake
|
50
|
+
rspec
|
51
|
+
twat!
|
data/Gemfile.travis
ADDED
data/Rakefile
ADDED
data/TODO
CHANGED
@@ -5,7 +5,6 @@ COLORS!
|
|
5
5
|
|
6
6
|
Refactor tweet printing code, unify throughout
|
7
7
|
|
8
|
-
|
9
8
|
TODO
|
10
9
|
====
|
11
10
|
|
@@ -45,6 +44,10 @@ Allow -f #hashtag to follow that hashtag instead of your newsfeed
|
|
45
44
|
|
46
45
|
Seriously consider moving to subcommands
|
47
46
|
|
47
|
+
Still needs argv parsing for account etc
|
48
|
+
|
49
|
+
twat config to create the first account from scratch
|
50
|
+
|
48
51
|
MOAR BACKENDS
|
49
52
|
=============
|
50
53
|
|
data/lib/twat.rb
CHANGED
@@ -5,18 +5,20 @@ require 'twitter'
|
|
5
5
|
require 'yaml'
|
6
6
|
require 'optparse'
|
7
7
|
require 'oauth'
|
8
|
+
require 'readline-ng'
|
8
9
|
|
9
|
-
%w[
|
10
|
+
%w[follow_mixin endpoint exceptions config argparse migration options
|
11
|
+
subcommand version tweetstack].each do |filename|
|
10
12
|
require "twat/#{filename}"
|
11
13
|
end
|
12
14
|
|
13
|
-
%w[follow tweet add delete follow_user updateconfig setoption show user_feed version].each do |filename|
|
14
|
-
require "twat/actions/#{filename}"
|
15
|
-
end
|
16
|
-
|
17
15
|
class String
|
18
16
|
# TODO - It'd be nice to implement the colors support here, maybe even only
|
19
17
|
# mix this in if it's enabled?
|
18
|
+
def black
|
19
|
+
"[30m#{self}[39m"
|
20
|
+
end
|
21
|
+
|
20
22
|
def red
|
21
23
|
"[31m#{self}[39m"
|
22
24
|
end
|
@@ -44,33 +46,35 @@ class String
|
|
44
46
|
def mentions?(name)
|
45
47
|
return self.downcase.include?(name.to_s.downcase)
|
46
48
|
end
|
47
|
-
end
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
VERSION = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_PATCH}"
|
55
|
-
class Twat
|
50
|
+
def colorise!
|
51
|
+
colorise_handles!
|
52
|
+
colorise_hashtags!
|
53
|
+
colorise_urls!
|
54
|
+
end
|
56
55
|
|
57
|
-
|
56
|
+
def colorise_handles!
|
57
|
+
self.gsub!(/@[a-z0-9_+-]+/i) { |s| s.cyan }
|
58
|
+
return self
|
59
|
+
end
|
58
60
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
config.account = opts[:account]
|
64
|
-
end
|
61
|
+
def colorise_hashtags!
|
62
|
+
self.gsub!(/#[a-z0-9_+-]+/i) { |s| s.cyan }
|
63
|
+
return self
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
def colorise_urls!
|
67
|
+
self.gsub!(%r{https?://[a-z0-9./_+-]+}i) { |s| s.black }
|
68
|
+
return self
|
69
|
+
end
|
70
|
+
end
|
68
71
|
|
72
|
+
module Twat
|
73
|
+
class Twat
|
69
74
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
75
|
+
def cli_run
|
76
|
+
# FIXME exception handling is gone for now
|
77
|
+
Subcommand.run
|
74
78
|
end
|
75
79
|
end
|
76
80
|
end
|
data/lib/twat/argparse.rb
CHANGED
@@ -1,10 +1,36 @@
|
|
1
1
|
module Twat
|
2
|
-
|
3
|
-
|
2
|
+
class ArgWrapper
|
3
|
+
def initialize(data)
|
4
|
+
@data = data
|
5
|
+
end
|
4
6
|
|
5
|
-
|
7
|
+
def method_missing(sym)
|
8
|
+
@data[sym]
|
9
|
+
end
|
10
|
+
end
|
6
11
|
|
12
|
+
class Args
|
7
13
|
# TODO delegate specifically instead of shimming everything?
|
14
|
+
# TODO Twat::Subcommands.COMMANDS needs to be parsed and dumped
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
# XXX What the shit...
|
18
|
+
getopts
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(sym)
|
22
|
+
@options[sym]
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
@options[key]
|
27
|
+
end
|
28
|
+
|
29
|
+
def include?(key)
|
30
|
+
@options.include?(key)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
8
34
|
|
9
35
|
def usage(additional=nil)
|
10
36
|
puts additional if additional
|
@@ -14,100 +40,31 @@ module Twat
|
|
14
40
|
|
15
41
|
def getopts
|
16
42
|
options = Hash.new
|
17
|
-
options[:count] = 1
|
18
43
|
@optparser = OptionParser.new do |opts|
|
19
44
|
opts.banner = "Usage: twat <tweet>"
|
20
45
|
|
21
46
|
opts.on('-n', '--account ACCOUNT', 'Use ACCOUNT (or default)') do |acct| #{{{ --account ACCOUNT
|
22
47
|
options[:account] = acct.to_sym
|
23
48
|
end # }}}
|
24
|
-
opts.on('
|
25
|
-
options[:account] = acct.to_sym
|
26
|
-
options[:action] = :add
|
27
|
-
end #}}}
|
28
|
-
opts.on('--follow-user USER', 'Follow USER on twitter') do |user| #{{{ --follow-user USER
|
29
|
-
options[:action] = :follow_user
|
30
|
-
options[:user] = user
|
31
|
-
end #}}}
|
32
|
-
opts.on('--endpoint ENDPOINT', 'Specify a different endpoint for use with --add') do |endpoint| #{{{ --add ACCOUNT
|
49
|
+
opts.on('--endpoint ENDPOINT', 'Specify a different endpoint for use with add or config') do |endpoint| #{{{ --add ACCOUNT
|
33
50
|
options[:endpoint] = endpoint.to_sym
|
34
51
|
end #}}}
|
35
|
-
opts.on('-d', '--delete ACCOUNT', 'Delete ACCOUNT') do |acct| #{{{ --delete ACCOUNT
|
36
|
-
options[:account] = acct.to_sym
|
37
|
-
options[:action] = :delete
|
38
|
-
end #}}}
|
39
52
|
opts.on('-h', '--help', 'Display this screen') do #{{{ --help
|
40
53
|
puts opts
|
41
54
|
exit
|
42
55
|
end #}}}
|
43
|
-
opts.on('-l', '--list [COUNT]', 'Display [count] tweets from your newsfeed') do |count| #{{{ --list ACCOUNT
|
44
|
-
options[:count] = count || 10
|
45
|
-
options[:action] ||= :show
|
46
|
-
end #}}}
|
47
|
-
opts.on('-f', '--follow', 'Display tweets from your newsfeed indefinitely') do #{{{ --follow
|
48
|
-
options[:action] = :follow
|
49
|
-
end #}}}
|
50
56
|
opts.on('-v', '--version', 'Display version info') do #{{{ --version
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
options[:user] = (user || :default)
|
55
|
-
options[:action] = :user_feed
|
56
|
-
end #}}}
|
57
|
-
opts.on("--set OPTION=VALUE", 'Set OPTION to VALUE') do |optval| #{{{ --set OPTION=VALUE
|
58
|
-
options[:action] = :setoption
|
59
|
-
options[:optval] = optval
|
60
|
-
end #}}}
|
61
|
-
opts.on("--update-config", "Update config to latest version") do #{{{ --update-config
|
62
|
-
options[:action] = :updateconfig
|
57
|
+
# FIXME, this is /bad/
|
58
|
+
puts "twat #{::Twat::VERSION}"
|
59
|
+
exit
|
63
60
|
end #}}}
|
64
61
|
end
|
65
62
|
@optparser.parse!
|
66
|
-
# {{{ Validation ---
|
67
|
-
# Default action is to send a tweet
|
68
|
-
options[:action] ||= :tweet
|
69
|
-
|
70
|
-
# Only specify an endpoint when adding accounts
|
71
|
-
if options[:endpoint]
|
72
|
-
usage unless options[:action] == :add
|
73
|
-
end
|
74
|
-
# Similarly, default endpoint to twitter when we do add
|
75
|
-
if options[:action] == :add
|
76
|
-
options[:endpoint] ||= :twitter
|
77
|
-
end
|
78
|
-
|
79
|
-
REQUIRED.each do |req|
|
80
|
-
usage unless options[req]
|
81
|
-
end
|
82
|
-
if MSG_REQUIRED.include?(options[:action])
|
83
|
-
options[:msg] = msg
|
84
|
-
end
|
85
|
-
# }}} Validation End ---
|
86
|
-
options
|
87
|
-
end
|
88
|
-
|
89
|
-
def msg
|
90
|
-
usage unless ARGV.length > 0
|
91
|
-
ARGV.join(" ")
|
92
|
-
end
|
93
|
-
|
94
|
-
def [](key)
|
95
|
-
options[key]
|
96
|
-
end
|
97
63
|
|
98
|
-
|
99
|
-
options
|
100
|
-
end
|
64
|
+
# Only makes sense for add, but doesn't hurt anything else
|
65
|
+
options[:endpoint] ||= :twitter
|
101
66
|
|
102
|
-
|
103
|
-
begin
|
104
|
-
@configthingfucken ||= getopts
|
105
|
-
# FIXME, actually do something smart, not yell and barf
|
106
|
-
rescue OptionParser::InvalidOption
|
107
|
-
usage "Unknown option"
|
108
|
-
rescue OptionParser::MissingArgument
|
109
|
-
usage "Missing argument"
|
110
|
-
end
|
67
|
+
@options = options
|
111
68
|
end
|
112
69
|
|
113
70
|
end
|
data/lib/twat/config.rb
CHANGED
@@ -1,21 +1,19 @@
|
|
1
1
|
module Twat
|
2
|
-
class
|
3
|
-
def configure(&block)
|
4
|
-
yield config
|
2
|
+
class Config
|
5
3
|
|
6
|
-
|
7
|
-
# happened here?
|
8
|
-
end
|
4
|
+
include ::Twat::Exceptions
|
9
5
|
|
10
|
-
def
|
11
|
-
@
|
6
|
+
def config_path
|
7
|
+
@config_path ||= ENV['TWAT_CONFIG'] || "#{ENV['HOME']}/.twatrc"
|
12
8
|
end
|
13
|
-
end
|
14
9
|
|
15
|
-
|
10
|
+
def exists?
|
11
|
+
File.exist?(config_path)
|
12
|
+
end
|
16
13
|
|
17
|
-
def
|
18
|
-
@
|
14
|
+
def create!
|
15
|
+
@config = { accounts: {} }
|
16
|
+
save!
|
19
17
|
end
|
20
18
|
|
21
19
|
def create_unless_exists!
|
@@ -57,13 +55,15 @@ module Twat
|
|
57
55
|
end
|
58
56
|
|
59
57
|
def colors?
|
60
|
-
colors
|
61
|
-
Options.bool_true?(colors)
|
58
|
+
config[:colors].nil? ? false : config[:colors]
|
62
59
|
end
|
63
60
|
|
64
61
|
def beep?
|
65
|
-
beep
|
66
|
-
|
62
|
+
config[:beep].nil? ? false : config[:beep]
|
63
|
+
end
|
64
|
+
|
65
|
+
def show_mentions?
|
66
|
+
config[:show_mentions].nil? ? false : config[:show_mentions]
|
67
67
|
end
|
68
68
|
|
69
69
|
def polling_interval
|
@@ -78,34 +78,22 @@ module Twat
|
|
78
78
|
# it does this by calling a sequence of migration functions in order
|
79
79
|
# which rebuild the config in stages, saving and leaving it in a
|
80
80
|
# consistent step at each point
|
81
|
-
def
|
81
|
+
def update_config
|
82
|
+
raise NoConfigFile unless exists?
|
82
83
|
Migrate.new.migrate!(config_path)
|
83
84
|
end
|
84
85
|
|
85
|
-
# I don't know how rubyists feel about method returning something vastly
|
86
|
-
# different to what method= accepts, but I think the api makes sense
|
87
|
-
def account=(acct)
|
88
|
-
if accounts.include?(acct)
|
89
|
-
@account = acct
|
90
|
-
else
|
91
|
-
raise NoSuchAccount
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def account_set?
|
96
|
-
!!@account
|
97
|
-
end
|
98
|
-
|
99
86
|
def account_name
|
100
|
-
if
|
101
|
-
|
87
|
+
if $args[:account]
|
88
|
+
return $args[:account].to_sym
|
102
89
|
else
|
103
|
-
raise NoDefaultAccount unless config.include?(:default)
|
90
|
+
raise ::Twat::Exceptions::NoDefaultAccount unless config.include?(:default)
|
104
91
|
return config[:default].to_sym
|
105
92
|
end
|
106
93
|
end
|
107
94
|
|
108
95
|
def account
|
96
|
+
raise NoSuchAccount unless accounts.include?(account_name)
|
109
97
|
accounts[account_name]
|
110
98
|
end
|
111
99
|
|