twat 0.4.15 → 0.5.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/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: []