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 +4 -0
- data/README.markdown +32 -6
- data/Rakefile +2 -2
- data/VERSION.yml +2 -2
- data/bin/tit +20 -2
- data/lib/tit.rb +70 -46
- data/tit.gemspec +8 -8
- metadata +5 -5
data/ChangeLog.markdown
CHANGED
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
|
-
|
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
|
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
|
-
|
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
|
-
[
|
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
|
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', '>=
|
11
|
-
gemspec.add_dependency('
|
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
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
|
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
|
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 '
|
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
|
-
|
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
|
-
@
|
92
|
-
|
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(
|
95
|
-
|
96
|
-
@
|
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
|
-
|
101
|
-
|
102
|
-
|
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
|
123
|
-
|
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(
|
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
|
-
|
151
|
-
|
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
|
-
|
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
|
-
|
186
|
+
tuts "#{person} said, #{at}:"
|
168
187
|
else
|
169
|
-
|
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
|
-
|
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,
|
205
|
-
|
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
|
223
|
-
puts
|
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
|
250
|
+
def abort(msg)
|
227
251
|
error(msg)
|
228
|
-
|
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
|
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-
|
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>, [">=
|
45
|
-
s.add_runtime_dependency(%q<
|
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>, [">=
|
48
|
-
s.add_dependency(%q<
|
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>, [">=
|
52
|
-
s.add_dependency(%q<
|
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
|
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-
|
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:
|
23
|
+
version: "0"
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
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:
|
33
|
+
version: "0"
|
34
34
|
version:
|
35
35
|
description: a stupid fucking twitter client
|
36
36
|
email: leif.walsh@gmail.com
|