tit 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog.markdown CHANGED
@@ -1,3 +1,7 @@
1
+ # tit 1.1.0 2010-01-23
2
+
3
+ * moved to oauth for chris
4
+
1
5
  # tit 1.0.1 2010-01-22
2
6
 
3
7
  * made even more spiteful in a few rather non-clever ways
data/README.markdown CHANGED
@@ -12,28 +12,54 @@ install
12
12
  usage
13
13
  -----
14
14
 
15
+ ### authz ###
16
+
17
+ first, you need to authenticate yourself with the stupid fucking twitter oauth
18
+ stuff
19
+
20
+ to do this, just run tit by itself
21
+
15
22
  $ tit
16
23
 
17
- or
24
+ it'll prompt you with the auth url, so plug that in your fucking browser, click
25
+ "ok", and twitter will give you a stupid fucking pin number
18
26
 
19
- $ tit -u "look at my stupid fucking tweet" -G 88.918:-34.879
27
+ $ tit --pin 8675309
28
+
29
+ now you're done and your goddamn access token should be stored for a real
30
+ fucking long time
31
+
32
+ ### looking at tits ###
33
+
34
+ get the shit you'd see by visiting twitter's fucking homepage:
20
35
 
21
- or
36
+ $ tit
37
+
38
+ annoyingly poll twitter and add some stupid fucking notifications too:
22
39
 
23
40
  $ tit -P -n
24
41
 
42
+ there's some more fucking options for you if you look at `tit -h`
43
+
44
+ ### showing other people your tits ###
45
+
46
+ $ tit -u "look at my stupid fucking tweet" -G 88.918:-34.879
47
+
25
48
  dependencies
26
49
  ------------
27
50
 
28
- [rest-client][] and [nokogiri][]
51
+ [oauth][] and [nokogiri][]
52
+
53
+ [oauth]: http://oauth.rubyforge.org/
54
+ [nokogiri]: http://nokogiri.org/
29
55
 
30
56
  caveats
31
57
  -------
32
58
 
33
59
  geotags are of the form `LAT:LONG`, where `LAT` and `LONG` are floating point
34
60
  numbers, indicating, respectively, the number of degrees north or east of the
35
- center of the earth; make them negative if you live on one or both of the dark
36
- hemispheres
61
+ fucking center of the earth; make them negative if you live on one or both of
62
+ the dark hemispheres
37
63
 
38
64
  bugs
39
65
  ----
data/Rakefile CHANGED
@@ -7,8 +7,8 @@ begin
7
7
  gemspec.email = "leif.walsh@gmail.com"
8
8
  gemspec.homepage = "http://github.com/adlaiff6/tit"
9
9
  gemspec.authors = ["Leif Walsh"]
10
- gemspec.add_dependency('nokogiri', '>= 1.4.0')
11
- gemspec.add_dependency('rest-client', '>= 1.2.0')
10
+ gemspec.add_dependency('nokogiri', '>= 0')
11
+ gemspec.add_dependency('oauth', '>= 0')
12
12
  end
13
13
  Jeweler::GemcutterTasks.new
14
14
  rescue LoadError
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- :patch: 1
3
- :minor: 0
2
+ :patch: 0
3
+ :minor: 1
4
4
  :major: 1
5
5
  :build:
data/bin/tit CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'tit'
4
4
 
5
+ require 'optparse'
6
+
5
7
  def main
6
8
  options = {
7
9
  :debug => false,
@@ -35,6 +37,10 @@ def main
35
37
  options[:payload] ||= {}
36
38
  options[:payload]["status"] = status || STDIN
37
39
  end
40
+ opts.on("--pin PIN", ("Set auth pin if this is your first time playing " +
41
+ "with this tit")) do |pin|
42
+ options[:pin] = pin
43
+ end
38
44
 
39
45
  opts.separator ""
40
46
  opts.separator "Receive options (public/home/mentions):"
@@ -86,6 +92,12 @@ def main
86
92
  tit.abort(e.message)
87
93
  end
88
94
 
95
+ if options.include? :pin
96
+ tit.use_pin(options[:pin])
97
+ end
98
+
99
+ tit.get_access
100
+
89
101
  # check for option errors
90
102
  if Tit::READERS.include? options[:action]
91
103
  tit.abort("cannot provide geotag when reading") unless options[:payload].nil?
@@ -102,18 +114,24 @@ def main
102
114
  if options[:debug]
103
115
  begin
104
116
  tit.run(options)
105
- rescue SocketError, Errno::ENETUNREACH, Errno::ETIMEDOUT, RestClient::Exception => e
117
+ rescue SocketError, Errno::ENETUNREACH, Errno::ETIMEDOUT => e
106
118
  tit.error "got a networking error, are you connected to the intarbutts?"
107
119
  puts e
108
120
  exit(-1)
121
+ rescue NoMethodError
122
+ tit.error "might have gotten a networking error, check your intarbutts."
123
+ exit(-1)
109
124
  end
110
125
  else
111
126
  begin
112
127
  tit.run(options)
113
- rescue SocketError, Errno::ENETUNREACH, Errno::ETIMEDOUT, RestClient::Exception => e
128
+ rescue SocketError, Errno::ENETUNREACH, Errno::ETIMEDOUT => e
114
129
  tit.error "got a networking error, are you connected to the intarbutts?"
115
130
  puts e
116
131
  exit(-1)
132
+ rescue NoMethodError
133
+ tit.error "might have gotten a networking error, check your intarbutts."
134
+ exit(-1)
117
135
  rescue => e
118
136
  tit.error "unknown error"
119
137
  puts e
data/lib/tit.rb CHANGED
@@ -3,8 +3,7 @@
3
3
  require 'rubygems'
4
4
  require 'ftools'
5
5
  require 'nokogiri'
6
- require 'optparse'
7
- require 'rest_client'
6
+ require 'oauth/consumer'
8
7
  require 'time' # heh.
9
8
  require 'yaml'
10
9
 
@@ -75,56 +74,76 @@ end
75
74
  Why are you reading the documentation, you cunt?
76
75
  =end
77
76
  class Tit
78
- RCFILE = File.join(ENV["HOME"], ".titrc")
77
+ RTFILE = File.join(ENV["HOME"], ".titrt")
78
+ ATFILE = File.join(ENV["HOME"], ".titat")
79
79
 
80
80
  READERS = [:public, :home, :mentions]
81
81
  WRITERS = [:update]
82
82
 
83
83
  URLS = {
84
- :public => "statuses/public_timeline.xml",
85
- :home => "statuses/home_timeline.xml",
86
- :mentions => "statuses/mentions.xml",
87
- :update => "statuses/update.xml"
84
+ :public => "/statuses/public_timeline.xml",
85
+ :home => "/statuses/home_timeline.xml",
86
+ :mentions => "/statuses/mentions.xml",
87
+ :update => "/statuses/update.xml"
88
88
  }
89
89
 
90
+ KEY = "K2OOlWbQodfm4YV9Fmeg"
91
+ SECRET = "B1HuqK8zoDDLboRAWPqlHTFbLVdkQfquzoUC1MkuM"
92
+
90
93
  def initialize
91
- @username = nil
92
- @password = nil
94
+ @consumer = OAuth::Consumer.new(KEY, SECRET,
95
+ { :site => "https://twitter.com" })
96
+
97
+ # get terminal width
98
+ @cols = %x[tput cols].to_i
99
+ end
100
+ attr_accessor :opts
101
+
102
+ def get_access
93
103
  begin
94
- File.open(RCFILE, "r") do |rc|
95
- data = YAML.load(rc)
96
- @username = data["username"]
97
- @password = data["password"]
104
+ @access_token = File.open(ATFILE, "r") do |at|
105
+ params = YAML.load(at)
106
+ OAuth::AccessToken.from_hash(@consumer, params)
98
107
  end
99
108
  rescue Errno::ENOENT => e
100
- File.open(RCFILE, "w") do |rc|
101
- YAML.dump({
102
- "username" => "<username>",
103
- "password" => "<password>"
104
- }, rc)
109
+ request_token = @consumer.get_request_token
110
+ File.open(RTFILE, "w") do |rt|
111
+ YAML.dump(request_token.params, rt)
105
112
  end
113
+ tuts "Please visit '#{request_token.authorize_url}'."
114
+ tuts "When you finish, provide your pin with `tit --pin PIN'"
115
+ exit(0)
106
116
  end
107
-
108
- if @username.nil? or @username.eql? "<username>" or
109
- @password.nil? or @password.eql? "<password>"
110
- puts "Please fill in your username and password in #{RCFILE}"
111
- exit(-1)
112
- end
113
-
114
- # set up proxy
115
- RestClient.proxy = ENV['https_proxy']
116
-
117
- # get terminal width
118
- @cols = %x[tput cols].to_i
119
117
  end
120
- attr_accessor :opts
121
118
 
122
- def resource
123
- RestClient::Resource.new("https://#{@username}:#{@password}@twitter.com/")
119
+ def use_pin(pin)
120
+ begin
121
+ request_token = File.open(RTFILE, "r") do |rt|
122
+ params = YAML.load(rt)
123
+ OAuth::RequestToken.from_hash(@consumer, params)
124
+ end
125
+ rescue Errno::ENOENT => e
126
+ tuts "You lost your old token, gotta try again."
127
+ get_access
128
+ end
129
+ begin
130
+ @access_token = request_token.get_access_token(:oauth_verifier => pin)
131
+ rescue OAuth::Unauthorized => e
132
+ tuts "Sorry, that's an old pin."
133
+ File.delete(RTFILE)
134
+ get_access
135
+ end
136
+ File.open(ATFILE, "w") do |at|
137
+ YAML.dump(@access_token.params, at)
138
+ end
139
+ File.delete(RTFILE)
140
+ tuts "Thanks, you're done with authentication."
141
+ tuts "Keep #{ATFILE} secure and intact. If it's compromised, I can't " +
142
+ "revoke your token."
124
143
  end
125
144
 
126
145
  def get_tits(action)
127
- Nokogiri.XML(resource[URLS[action]].get).xpath("//status").map do |xml|
146
+ Nokogiri.XML(@access_token.get(URLS[action]).body).xpath("//status").map do |xml|
128
147
  {
129
148
  :username => xml.at_xpath("./user/name").content,
130
149
  :userid => xml.at_xpath("./user/screen_name").content,
@@ -147,13 +166,13 @@ class Tit
147
166
  end
148
167
 
149
168
  if payload["status"].length > 140
150
- puts "your status is too long (by #{payload["status"].length - 140} characters)"
151
- puts "here is what would get posted:"
169
+ tuts "your status is too long (by #{payload["status"].length - 140} characters)"
170
+ tuts "here is what would get posted:"
152
171
  payload["status"][0...140].wrapped(@cols - 2).each { |l| puts " #{l}" }
153
172
  exit(-1)
154
173
  end
155
174
 
156
- resource[URLS[:update]].post(payload)
175
+ @access_token.post(URLS[:update], payload)
157
176
  end
158
177
 
159
178
  def show_tit(status)
@@ -164,9 +183,9 @@ class Tit
164
183
  end
165
184
  at = status[:timestamp].time_ago_in_words
166
185
  if status[:geo].nil?
167
- puts "#{person} said, #{at}:"
186
+ tuts "#{person} said, #{at}:"
168
187
  else
169
- puts "#{person} said, #{at}, from #{status[:geo]}:"
188
+ tuts "#{person} said, #{at}, from #{status[:geo]}:"
170
189
  end
171
190
 
172
191
  status[:text].each do |line|
@@ -194,15 +213,16 @@ class Tit
194
213
  tits.include? status[:id]
195
214
  end.each_with_index do |status, i|
196
215
  if i == 0
197
- puts "more updates (at #{Time.now.strftime "%X"}):\n"
216
+ tuts "more updates (at #{Time.now.strftime "%X"}):"
217
+ puts ""
198
218
  end
199
219
  show_tit(status)
200
220
  tits[status[:id]] = status
201
221
  end.length
202
222
  %x[#{notify} '#{num_tits} new tit#{num_tits == 1 ? '' : 's'}!'] unless notify.nil? or num_tits == 0
203
223
  last_update = Time.now()
204
- rescue SocketError, Errno::ENETUNREACH, Errno::ETIMEDOUT, RestClient::Exception => e
205
- puts "networking error, will try again later"
224
+ rescue SocketError, Errno::ENETUNREACH, Errno::ETIMEDOUT, NoMethodError => e
225
+ tuts "networking error, will try again later"
206
226
  end
207
227
  end
208
228
  end
@@ -219,13 +239,17 @@ class Tit
219
239
  end
220
240
  end
221
241
 
222
- def error msg
223
- puts "#{File.basename $0}: #{msg}"
242
+ def tuts(*strs)
243
+ strs.each { |s| puts s.wrapped(@cols) }
244
+ end
245
+
246
+ def error(msg)
247
+ tuts "#{File.basename $0}: #{msg}"
224
248
  end
225
249
 
226
- def abort msg
250
+ def abort(msg)
227
251
  error(msg)
228
- puts @opts
252
+ tuts @opts
229
253
  exit(-1)
230
254
  end
231
255
  end
data/tit.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tit}
8
- s.version = "1.0.1"
8
+ s.version = "1.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Leif Walsh"]
12
- s.date = %q{2010-01-22}
12
+ s.date = %q{2010-01-23}
13
13
  s.default_executable = %q{tit}
14
14
  s.description = %q{a stupid fucking twitter client}
15
15
  s.email = %q{leif.walsh@gmail.com}
@@ -41,15 +41,15 @@ Gem::Specification.new do |s|
41
41
  s.specification_version = 3
42
42
 
43
43
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
44
- s.add_runtime_dependency(%q<nokogiri>, [">= 1.4.0"])
45
- s.add_runtime_dependency(%q<rest-client>, [">= 1.2.0"])
44
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
45
+ s.add_runtime_dependency(%q<oauth>, [">= 0"])
46
46
  else
47
- s.add_dependency(%q<nokogiri>, [">= 1.4.0"])
48
- s.add_dependency(%q<rest-client>, [">= 1.2.0"])
47
+ s.add_dependency(%q<nokogiri>, [">= 0"])
48
+ s.add_dependency(%q<oauth>, [">= 0"])
49
49
  end
50
50
  else
51
- s.add_dependency(%q<nokogiri>, [">= 1.4.0"])
52
- s.add_dependency(%q<rest-client>, [">= 1.2.0"])
51
+ s.add_dependency(%q<nokogiri>, [">= 0"])
52
+ s.add_dependency(%q<oauth>, [">= 0"])
53
53
  end
54
54
  end
55
55
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leif Walsh
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-22 00:00:00 +01:00
12
+ date: 2010-01-23 00:00:00 +01:00
13
13
  default_executable: tit
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,17 +20,17 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 1.4.0
23
+ version: "0"
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
- name: rest-client
26
+ name: oauth
27
27
  type: :runtime
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.2.0
33
+ version: "0"
34
34
  version:
35
35
  description: a stupid fucking twitter client
36
36
  email: leif.walsh@gmail.com