twat 0.4.15 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/TODO CHANGED
@@ -29,3 +29,22 @@ PENDING
29
29
  Add some commands to retweet/favourite etc
30
30
 
31
31
  Consider allowing to -f multiple accounts at once
32
+
33
+ Refactor the calls to Twitter to hook my own object, which in turn hooks
34
+ the current_account to work out which service it uses.
35
+
36
+ (Bonus points for adding a hook which can also use an arbitrary user
37
+ specified url)
38
+
39
+ Allow -f #hashtag to follow that hashtag instead of your newsfeed
40
+
41
+ Seriously consider moving to subcommands
42
+
43
+ MOAR BACKENDS
44
+ =============
45
+
46
+ Abstract all the logic for the various operations (add, follow, post,
47
+ etc etc)
48
+
49
+ into a wrapper for each service so that twat can natively support
50
+ facebook, g+ etc etc as I get around to writing the new modules.
@@ -6,7 +6,7 @@ require 'yaml'
6
6
  require 'optparse'
7
7
  require 'oauth'
8
8
 
9
- %w[config exceptions argparse actions migration options].each do |filename|
9
+ %w[config exceptions argparse actions migration options endpoint].each do |filename|
10
10
  require "twat/#{filename}"
11
11
  end
12
12
 
@@ -44,8 +44,8 @@ end
44
44
 
45
45
  module Twat
46
46
  VERSION_MAJOR = 0
47
- VERSION_MINOR = 4
48
- VERSION_PATCH = 15
47
+ VERSION_MINOR = 5
48
+ VERSION_PATCH = 0
49
49
 
50
50
  VERSION = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_PATCH}"
51
51
  class Twat
@@ -56,6 +56,11 @@ module Twat
56
56
  # FIXME Handing in the opts like this feels dirty
57
57
  with_handled_exceptions(ArgParse.new) do |opts|
58
58
  actor = Actions.new
59
+
60
+ if opts[:account] && opts[:action] != :add
61
+ config.account = opts[:account]
62
+ end
63
+
59
64
  actor.config = config
60
65
  actor.opts = opts
61
66
  actor.send(opts.options[:action])
@@ -1,6 +1,7 @@
1
1
  module Twat
2
2
  OAUTH_TOKENS = [ :oauth_token, :oauth_token_secret ]
3
3
  CONSUMER_TOKENS = [ :consumer_key, :consumer_secret ]
4
+
4
5
  class Actions
5
6
 
6
7
  attr_accessor :config, :opts, :failcount
@@ -14,23 +15,30 @@ module Twat
14
15
  #puts opts.msg
15
16
  end
16
17
 
18
+ # Add is somewhat of a special case, everything else hangs off config for
19
+ # it's magic, However we're forced to do it manually here- config doesn't
20
+ # know anything about it yet
17
21
  def add
18
- v = Config.consumer_info.map do |key, value|
22
+ endpoint = Endpoint.new(opts[:endpoint])
23
+ v = endpoint.consumer_info.map do |key, value|
19
24
  value
20
25
  end
21
- # FIXME probably allow something other than
22
- # twitter
23
- oauth = OAuth::Consumer.new( v[0], v[1],
24
- { site: "http://twitter.com" })
26
+
27
+ oauth_options = { :site => endpoint.url }
28
+ oauth_options.merge!(endpoint.oauth_options)
29
+
30
+ oauth = OAuth::Consumer.new( v[0], v[1], oauth_options )
25
31
  token_request = oauth.get_request_token()
26
32
  puts "Please authenticate the application at #{token_request.authorize_url}, then enter pin"
27
- pin = gets.chomp
33
+ pin = STDIN.gets.chomp
28
34
  begin
29
35
  access_token = token_request.get_access_token(oauth_verifier: pin)
30
- config.accounts[opts[:account]] = {
36
+ account_settings = {
31
37
  oauth_token: access_token.token,
32
- oauth_token_secret: access_token.secret
38
+ oauth_token_secret: access_token.secret,
39
+ endpoint: opts[:endpoint]
33
40
  }
41
+ config.accounts[opts[:account]] = account_settings
34
42
  config.save!
35
43
  rescue OAuth::Unauthorized
36
44
  puts "Couldn't authenticate you, did you enter the pin correctly?"
@@ -61,7 +69,7 @@ module Twat
61
69
 
62
70
  def show
63
71
  twitter_auth
64
- Twitter.home_timeline(:count => opts[:count]).each do |tweet|
72
+ Twitter.home_timeline(:count => opts[:count]).reverse.each do |tweet|
65
73
  format(tweet)
66
74
  end
67
75
  end
@@ -72,7 +80,7 @@ module Twat
72
80
  def process_followed(tweets)
73
81
  last_id = nil
74
82
  tweets.reverse.each do |tweet|
75
- beep if config.beep? && tweet.text.mentions?(account_name)
83
+ beep if config.beep? && tweet.text.mentions?(config.account_name)
76
84
  format(tweet)
77
85
  last_id = tweet.id
78
86
  end
@@ -136,9 +144,9 @@ module Twat
136
144
  def format(twt)
137
145
  text = deentitize(twt.text)
138
146
  if config.colors?
139
- if twt.user.screen_name == account_name.to_s
147
+ if twt.user.screen_name == config.account_name.to_s
140
148
  puts "#{twt.user.screen_name.bold.blue}: #{text}"
141
- elsif text.mentions?(account_name)
149
+ elsif text.mentions?(config.account_name)
142
150
  puts "#{twt.user.screen_name.bold.red}: #{text}"
143
151
  else
144
152
  puts "#{twt.user.screen_name.bold.cyan}: #{text}"
@@ -157,12 +165,13 @@ module Twat
157
165
 
158
166
  def twitter_auth
159
167
  Twitter.configure do |twit|
160
- account.each do |key, value|
168
+ config.account.each do |key, value|
161
169
  twit.send("#{key}=", value)
162
170
  end
163
- Config.consumer_info.each do |key, value|
171
+ config.endpoint.consumer_info.each do |key, value|
164
172
  twit.send("#{key}=", value)
165
173
  end
174
+ twit.endpoint = config.endpoint.url
166
175
  end
167
176
  end
168
177
 
@@ -184,15 +193,6 @@ module Twat
184
193
  end
185
194
  end
186
195
 
187
- def account_name
188
- @account_name ||=
189
- if opts.include?(:account)
190
- opts[:account]
191
- else
192
- config.default_account
193
- end
194
- end
195
-
196
196
  def beep
197
197
  print "\a"
198
198
  end
@@ -25,6 +25,9 @@ module Twat
25
25
  options[:account] = acct.to_sym
26
26
  options[:action] = :add
27
27
  end #}}}
28
+ opts.on('--endpoint ENDPOINT', 'Specify a different endpoint for use with --add') do |endpoint| #{{{ --add ACCOUNT
29
+ options[:endpoint] = endpoint.to_sym
30
+ end #}}}
28
31
  opts.on('-d', '--delete ACCOUNT', 'Delete ACCOUNT') do |acct| #{{{ --delete ACCOUNT
29
32
  options[:account] = acct.to_sym
30
33
  options[:action] = :delete
@@ -56,13 +59,26 @@ module Twat
56
59
  end #}}}
57
60
  end
58
61
  @optparser.parse!
62
+ # {{{ Validation ---
63
+ # Default action is to send a tweet
59
64
  options[:action] ||= :tweet
65
+
66
+ # Only specify an endpoint when adding accounts
67
+ if options[:endpoint]
68
+ usage unless options[:action] == :add
69
+ end
70
+ # Similarly, default endpoint to twitter when we do add
71
+ if options[:action] == :add
72
+ options[:endpoint] ||= :twitter
73
+ end
74
+
60
75
  REQUIRED.each do |req|
61
76
  usage unless options[req]
62
77
  end
63
78
  if MSG_REQUIRED.include?(options[:action])
64
79
  options[:msg] = msg
65
80
  end
81
+ # }}} Validation End ---
66
82
  options
67
83
  end
68
84
 
@@ -62,18 +62,6 @@ module Twat
62
62
  config[:polling_interval] || 60
63
63
  end
64
64
 
65
- def default_account
66
- raise NoDefaultAccount unless config.include?(:default)
67
- return config[:default].to_sym
68
- end
69
-
70
- def self.consumer_info
71
- {
72
- consumer_key: "jtI2q3Z4NIJAehBG4ntPIQ",
73
- consumer_secret: "H6vQOGGn9qVJJa9lWyTd2s8ZZRXG4kh3SMfvZ2uxOXE"
74
- }
75
- end
76
-
77
65
  def []=(k, v)
78
66
  config[k] = v
79
67
  end
@@ -86,5 +74,40 @@ module Twat
86
74
  Migrate.new.migrate!(config_path)
87
75
  end
88
76
 
77
+ # I don't know how rubyists feel about method returning something vastly
78
+ # different to what method= accepts, but I think the api makes sense
79
+ def account=(acct)
80
+ if accounts.include?(acct)
81
+ @account = acct
82
+ else
83
+ raise NoSuchAccount
84
+ end
85
+ end
86
+
87
+ def account_set?
88
+ !!@account
89
+ end
90
+
91
+ def account_name
92
+ if account_set?
93
+ @account
94
+ else
95
+ raise NoDefaultAccount unless config.include?(:default)
96
+ return config[:default].to_sym
97
+ end
98
+ end
99
+
100
+ def account
101
+ accounts[account_name]
102
+ end
103
+
104
+ def endpoint_name
105
+ account[:endpoint] || :twitter
106
+ end
107
+
108
+ def endpoint
109
+ @endpoint ||= Endpoint.new(endpoint_name)
110
+ end
111
+
89
112
  end
90
113
  end
@@ -0,0 +1,16 @@
1
+ module Twat
2
+
3
+ %w[twitter identica].each do |filename|
4
+ require File.join(File.expand_path("../endpoints", __FILE__), filename)
5
+ end
6
+
7
+ # Proxies to the actual endpoint classes
8
+ class Endpoint
9
+ def self.new(endpoint)
10
+ @implementation = {
11
+ :twitter => Endpoints::Twitter,
12
+ :"identi.ca" => Endpoints::Identica
13
+ }[endpoint].new
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Twat::Endpoints
2
+ class Identica
3
+
4
+ def initialize
5
+ ::Twitter::Request.module_eval do
6
+ alias :_request :request
7
+ def request(method, path, params, options)
8
+ path.gsub!(%r|^1/|, '')
9
+ _request(method, path, params, options)
10
+ end
11
+ end
12
+ end
13
+
14
+ # this bails with /home/richo/code/ext/twat/lib/twat/endpoints/identica.rb:6:in `block in initialize': uninitialized constant Twat::Endpoints::Identica::Request (NameError)
15
+ # So I figured it's still relative to This module, so I tried
16
+ #
17
+ # ::Twitter.module_eval...
18
+
19
+ def url
20
+ "https://identi.ca/api"
21
+ end
22
+
23
+ def consumer_info
24
+ {
25
+ consumer_key: "0af040d41599f5d07b738fc90a487af7",
26
+ consumer_secret: "b6bb7284eaf975ab65a2dd3eb53fbf3d"
27
+ }
28
+ end
29
+
30
+ def oauth_options
31
+ {
32
+ request_token_url: "https://identi.ca/api/oauth/request_token",
33
+ access_token_url: "https://identi.ca/api/oauth/access_token",
34
+ authorize_url: "https://identi.ca/api/oauth/authorize"
35
+ }
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ module Twat::Endpoints
2
+ class Twitter
3
+
4
+ def url
5
+ "https://api.twitter.com/"
6
+ end
7
+
8
+ def consumer_info
9
+ {
10
+ consumer_key: "jtI2q3Z4NIJAehBG4ntPIQ",
11
+ consumer_secret: "H6vQOGGn9qVJJa9lWyTd2s8ZZRXG4kh3SMfvZ2uxOXE"
12
+ }
13
+ end
14
+
15
+ def oauth_options
16
+ {}
17
+ end
18
+
19
+ end
20
+ end
21
+
22
+
data/man/twat.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH twat 1 "September 2011" "" ""
1
+ .TH twat 1 "October 2011" "Rich Healey" ""
2
2
  .SH NAME
3
3
  twat \- a cli/ruby interface to twitter.
4
4
  .SH SYNOPSIS
@@ -18,6 +18,9 @@ config for an account named default.
18
18
  .IP -a
19
19
  Tell twat to execute the routines for authenticating itself with OAuth for your
20
20
  account.
21
+ .IP --endpoint
22
+ With -a to add an account specify a different endpoint than the twitter default.
23
+ At present, twitter and identi.ca are supported.
21
24
  .IP -d
22
25
  Delete speficied account.
23
26
  .IP -h
@@ -28,6 +31,13 @@ Watch your newsfeed in a similar manner to tail -f, updating as your feed does
28
31
  .IP -u USER
29
32
  Retrieve a list of USER's recent tweets. Note this will retrieve all of their
30
33
  tweets as opposed to just what would have appeared in your feed.
34
+ .SH OTHER ENDPOINTS
35
+ As of twat 0.5.0 endpoints other than twitter are supported. At present,
36
+ twitter and identi.ca are supported, you may specify which one you intend to
37
+ use at account creation time like
38
+ .B twat -a accountname --endpoint identi.ca
39
+ Other endpoints will be added in due course, as well as support for HTTP basic
40
+ authentication.
31
41
  .SH CONFIGURATION
32
42
  Options are configured with --set OPTION=VALUE.
33
43
  Options include
data/twat ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require 'twat'
5
+
6
+ inst = Twat::Twat.new
7
+ inst.cli_run
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.15
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-17 00:00:00.000000000Z
12
+ date: 2011-10-20 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: twitter
16
- requirement: &17618920 !ruby/object:Gem::Requirement
16
+ requirement: &18544900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *17618920
24
+ version_requirements: *18544900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: oauth
27
- requirement: &17618180 !ruby/object:Gem::Requirement
27
+ requirement: &18544400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *17618180
35
+ version_requirements: *18544400
36
36
  description: Command line tool for tweeting and whatnot
37
37
  email:
38
38
  - richo@psych0tik.net
@@ -52,10 +52,14 @@ files:
52
52
  - lib/twat/actions.rb
53
53
  - lib/twat/argparse.rb
54
54
  - lib/twat/config.rb
55
+ - lib/twat/endpoint.rb
56
+ - lib/twat/endpoints/identica.rb
57
+ - lib/twat/endpoints/twitter.rb
55
58
  - lib/twat/exceptions.rb
56
59
  - lib/twat/migration.rb
57
60
  - lib/twat/options.rb
58
61
  - man/twat.1
62
+ - twat
59
63
  - twat.gemspec
60
64
  homepage: http://github.com/richoH/twat
61
65
  licenses: []