tit 1.0.1 → 1.1.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/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