tuiter 0.0.1 → 0.0.2

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/AUTHORS CHANGED
@@ -7,8 +7,11 @@ Both projects were latter adopted by WebCo Internet (http://webcointernet.com).
7
7
 
8
8
  The authors and contributors of Tuiter are:
9
9
 
10
- * Manoel Lemos (manoel@lemos.net)
11
- * Luiz Rocha (lsdr@lsdr.net)
12
- * Luis Cipriani (lfcipriani@talleye.com)
13
- * Lucas Húngaro (lucashungaro@gmail.com)
10
+ * Manoel Lemos (manoel@lemos.net) - initial work
11
+ * Celestino Gomes (tinorj@gmail.com)
12
+ * Leandro Silva (leandrodoze@gmail.com)
13
+ * Lucas Fais (lfais@webcointernet.com)
14
+ * Lucas Húngaro (lucashungaro@gmail.com)
15
+ * Luis Cipriani (lfcipriani@talleye.com)
16
+ * Luiz Rocha (lsdr@lsdr.net)
14
17
 
data/README.rdoc CHANGED
@@ -1,16 +1,31 @@
1
1
  = Tuiter
2
2
 
3
- Tuiter was design and developed by {Manoel Lemos}[http://manoellemos.com] to provide access to the Twitter API. It was developed for the experimental project called {Tuitersfera Brasil}[http://tuitersfera.com.br], an application to monitor the Twitter usage in Brazil.
3
+ Tuiter was design and developed by {Manoel Lemos}[http://manoellemos.com] to
4
+ provide access to the Twitter API. It was developed for the experimental
5
+ project called {Tuitersfera Brasil}[http://tuitersfera.com.br], an application
6
+ to monitor the Twitter usage in Brazil.
4
7
 
5
- Both Tuiter and Tuitersfera were adopted, further developed and maintained by {Webco Internet}[http://webcointernet.com].
8
+ Both Tuiter and Tuitersfera were adopted, further developed and maintained by
9
+ {Webco Internet}[http://webcointernet.com].
6
10
 
7
11
  == Instalation
8
12
 
9
- A tuiter gem is avaliable in Github. To install simply run on a console:
13
+ Tuiter is avaliable as a gem on
14
+ {Rubyforge}[http://rubyforge.org/projects/tuiter/], so you can easily install
15
+ using rubygems:
10
16
 
11
- gem install webco-utils --source=http://gems.github.com
17
+ gem install tuiter
12
18
 
13
- If you already have Github gem repository on you gem source, you can leave the source part out.
19
+ Although it is recommended to use the gem published on Rubyforge, tuiter is also
20
+ avaliable at Github. This might be useful if you want to experiment with forks
21
+ or live on the bleeding edge.
22
+
23
+ To install the Github version, simply run on a console:
24
+
25
+ gem install webco-tuiter --source=http://gems.github.com
26
+
27
+ If you already have Github gem repository on you gem source, you can leave the
28
+ source part out.
14
29
 
15
30
  == Basic Usage
16
31
 
@@ -19,9 +34,11 @@ If you already have Github gem repository on you gem source, you can leave the s
19
34
 
20
35
  client.update('Hey Ho, Twitters!')
21
36
 
22
- There are (or at least we pretend to add :-) another examples in the examples/ folder.
37
+ There are (or at least we want to add :-) another examples in the examples/
38
+ folder.
23
39
 
24
40
  == Roadmap and TO-DO list
25
41
 
26
- Check out the library roadmap and to-do list {in the wiki}[http://wiki.github.com/webco/tuiter]
42
+ Check out the library roadmap and to-do list
43
+ {in the project wiki}[http://wiki.github.com/webco/tuiter]
27
44
 
data/Rakefile CHANGED
@@ -4,6 +4,10 @@ require "rake"
4
4
  require "rake/testtask"
5
5
  require "rake/rdoctask"
6
6
 
7
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].each do |req|
8
+ load req
9
+ end
10
+
7
11
  require "lib/tuiter/version"
8
12
 
9
13
  desc "Run test suite"
@@ -112,14 +116,14 @@ task "install" => "build" do
112
116
  end
113
117
 
114
118
  desc "Publish the gem to Rubyforge"
115
- task "rubyforge" => "build" do
119
+ task "publish" => "build" do
116
120
  require 'rubyforge'
117
121
  rubyforge_config_path = File.expand_path(File.join('~', '.rubyforge'))
118
122
  user_config = YAML::load(File.open(rubyforge_config_path + '/user-config.yml'))
119
123
  auto_config = YAML::load(File.open(rubyforge_config_path + '/auto-config.yml'))
120
124
 
121
- @rubyforge = RubyForge.new(user_config, auto_config)
122
-
125
+ @rubyforge = RubyForge::Client.new(user_config, auto_config)
126
+
123
127
  @rubyforge.login
124
128
  @rubyforge.add_release('tuiter', 'tuiter', "#{spec.version}", "#{spec.name}-#{spec.version}.gem")
125
129
  end
data/lib/tuiter.log ADDED
@@ -0,0 +1,68 @@
1
+ # Logfile created on Sat Mar 21 16:21:26 -0300 2009 by /
2
+ I, [2009-03-21T16:21:26.630191 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:21:26 -0300 2009 : initialize()
3
+ I, [2009-03-21T16:21:54.173399 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:21:54 -0300 2009 : request() query: http://twitter.com/account/rate_limit_status.json
4
+ I, [2009-03-21T16:21:55.040625 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:21:55 -0300 2009 : request() debug: http status is 200 OK
5
+ I, [2009-03-21T16:25:50.347735 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:25:50 -0300 2009 : request() query: http://twitter.com/statuses/show/lsdr.json
6
+ I, [2009-03-21T16:25:50.818158 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:25:50 -0300 2009 : request() http error: 404 Not Found in /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open-uri.rb:278:in `open_http'
7
+ I, [2009-03-21T16:25:57.859336 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:25:57 -0300 2009 : request() query: http://twitter.com/statuses/show/34751.json
8
+ I, [2009-03-21T16:25:58.344673 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:25:58 -0300 2009 : request() debug: http status is 200 OK
9
+ I, [2009-03-21T16:26:18.827014 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:26:18 -0300 2009 : request() query: http://twitter.com/users/show/lucasfais.json
10
+ I, [2009-03-21T16:26:19.573533 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:26:19 -0300 2009 : request() debug: http status is 200 OK
11
+ I, [2009-03-21T16:26:28.962982 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:26:28 -0300 2009 : request() query: http://twitter.com/users/show/jacktorrance.json
12
+ I, [2009-03-21T16:26:29.498437 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:26:29 -0300 2009 : request() debug: http status is 200 OK
13
+ I, [2009-03-21T16:30:43.347043 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:30:43 -0300 2009 : request() query: http://twitter.com/statuses/followers.json
14
+ I, [2009-03-21T16:30:43.862539 #2112] INFO -- : [Tuiter:2112] Sat Mar 21 16:30:43 -0300 2009 : request() debug: http status is 200 OK
15
+ I, [2009-03-21T20:08:51.185245 #2265] INFO -- : [Tuiter:2265] Sat Mar 21 20:08:51 -0300 2009 : initialize()
16
+ I, [2009-03-21T20:08:54.287965 #2265] INFO -- : [Tuiter:2265] Sat Mar 21 20:08:54 -0300 2009 : request() query: http://twitter.com/users/show/jacktorrance.json
17
+ I, [2009-03-21T20:09:09.302025 #2265] INFO -- : [Tuiter:2265] Sat Mar 21 20:09:09 -0300 2009 : request() error: timeout error
18
+ I, [2009-03-21T20:09:46.075840 #2265] INFO -- : [Tuiter:2265] Sat Mar 21 20:09:46 -0300 2009 : request() query: http://twitter.com/statuses/show/34751.json
19
+ I, [2009-03-21T20:10:01.095919 #2265] INFO -- : [Tuiter:2265] Sat Mar 21 20:10:01 -0300 2009 : request() error: timeout error
20
+ I, [2009-03-21T20:10:15.372542 #2457] INFO -- : [Tuiter:2457] Sat Mar 21 20:10:15 -0300 2009 : initialize()
21
+ I, [2009-03-21T20:10:22.107576 #2457] INFO -- : [Tuiter:2457] Sat Mar 21 20:10:22 -0300 2009 : request() query: http://twitter.com/account/rate_limit_status.json
22
+ I, [2009-03-21T20:10:22.771328 #2457] INFO -- : [Tuiter:2457] Sat Mar 21 20:10:22 -0300 2009 : request() debug: http status is 200 OK
23
+ I, [2009-03-21T20:11:40.731980 #2457] INFO -- : [Tuiter:2457] Sat Mar 21 20:11:40 -0300 2009 : update() sending: #<Tuiter::Status:0x57f710>
24
+ I, [2009-03-21T20:11:56.729236 #2457] INFO -- : [Tuiter:2457] Sat Mar 21 20:11:56 -0300 2009 : update() success: OK
25
+ I, [2009-04-03T08:53:43.427986 #4321] INFO -- : [Tuiter:4321] Fri Apr 03 08:53:43 -0300 2009 : initialize()
26
+ I, [2009-04-03T09:10:50.463761 #4321] INFO -- : [Tuiter:4321] Fri Apr 03 09:10:50 -0300 2009 : request() query: http://twitter.com/account/rate_limit_status.json
27
+ I, [2009-04-03T09:10:51.298101 #4321] INFO -- : [Tuiter:4321] Fri Apr 03 09:10:51 -0300 2009 : request() debug: http status is 200 OK
28
+ I, [2009-04-03T10:02:23.578571 #8903] INFO -- : [Tuiter:8903] Fri Apr 03 10:02:23 -0300 2009 : initialize()
29
+ I, [2009-04-03T10:02:28.009525 #8903] INFO -- : [Tuiter:8903] Fri Apr 03 10:02:28 -0300 2009 : request() query: http://twitter.com/direct_messages.json
30
+ I, [2009-04-03T10:02:31.793239 #8903] INFO -- : [Tuiter:8903] Fri Apr 03 10:02:31 -0300 2009 : request() debug: http status is 200 OK
31
+ I, [2009-04-04T10:46:52.065881 #652] INFO -- : [Tuiter:652] Sat Apr 04 10:46:52 -0300 2009 : initialize()
32
+ I, [2009-04-04T10:46:56.967758 #652] INFO -- : [Tuiter:652] Sat Apr 04 10:46:56 -0300 2009 : request() query: http://twitter.com/account/rate_limit_status.json
33
+ I, [2009-04-04T10:46:57.442538 #652] INFO -- : [Tuiter:652] Sat Apr 04 10:46:57 -0300 2009 : request() debug: http status is 200 OK
34
+ I, [2009-04-04T10:48:17.721315 #720] INFO -- : [Tuiter:720] Sat Apr 04 10:48:17 -0300 2009 : initialize()
35
+ I, [2009-04-04T10:48:21.166143 #720] INFO -- : [Tuiter:720] Sat Apr 04 10:48:21 -0300 2009 : request() query: http://twitter.com/account/rate_limit_status.json
36
+ I, [2009-04-04T10:48:21.765680 #720] INFO -- : [Tuiter:720] Sat Apr 04 10:48:21 -0300 2009 : request() debug: http status is 200 OK
37
+ I, [2009-04-04T10:48:33.733567 #720] INFO -- : [Tuiter:720] Sat Apr 04 10:48:33 -0300 2009 : request() query: http://twitter.com/direct_messages.json
38
+ I, [2009-04-04T10:48:34.636358 #720] INFO -- : [Tuiter:720] Sat Apr 04 10:48:34 -0300 2009 : request() debug: http status is 200 OK
39
+ I, [2009-04-04T10:59:19.665326 #652] INFO -- : [Tuiter:652] Sat Apr 04 10:59:19 -0300 2009 : request() query: http://twitter.com/direct_messages.json
40
+ I, [2009-04-04T10:59:20.229616 #652] INFO -- : [Tuiter:652] Sat Apr 04 10:59:20 -0300 2009 : request() debug: http status is 200 OK
41
+ I, [2009-04-04T11:06:28.427837 #652] INFO -- : [Tuiter:652] Sat Apr 04 11:06:28 -0300 2009 : request() query: http://twitter.com/direct_messages.json
42
+ I, [2009-04-04T11:06:29.077480 #652] INFO -- : [Tuiter:652] Sat Apr 04 11:06:29 -0300 2009 : request() debug: http status is 200 OK
43
+ I, [2009-04-04T11:06:51.125856 #754] INFO -- : [Tuiter:754] Sat Apr 04 11:06:51 -0300 2009 : initialize()
44
+ I, [2009-04-04T11:06:54.684243 #754] INFO -- : [Tuiter:754] Sat Apr 04 11:06:54 -0300 2009 : request() query: http://twitter.com/direct_messages.json
45
+ I, [2009-04-04T11:06:55.296060 #754] INFO -- : [Tuiter:754] Sat Apr 04 11:06:55 -0300 2009 : request() debug: http status is 200 OK
46
+ I, [2009-04-04T11:08:29.059308 #766] INFO -- : [Tuiter:766] Sat Apr 04 11:08:29 -0300 2009 : initialize()
47
+ I, [2009-04-04T11:08:32.425009 #766] INFO -- : [Tuiter:766] Sat Apr 04 11:08:32 -0300 2009 : request() query: http://twitter.com/direct_messages.json
48
+ I, [2009-04-04T11:08:33.088710 #766] INFO -- : [Tuiter:766] Sat Apr 04 11:08:33 -0300 2009 : request() debug: http status is 200 OK
49
+ I, [2009-04-04T11:10:22.162594 #777] INFO -- : [Tuiter:777] Sat Apr 04 11:10:22 -0300 2009 : initialize()
50
+ I, [2009-04-04T11:10:24.984837 #777] INFO -- : [Tuiter:777] Sat Apr 04 11:10:24 -0300 2009 : request() query: http://twitter.com/direct_messages.json
51
+ I, [2009-04-04T11:10:25.459088 #777] INFO -- : [Tuiter:777] Sat Apr 04 11:10:25 -0300 2009 : request() debug: http status is 200 OK
52
+ I, [2009-04-04T11:10:33.344786 #777] INFO -- : [Tuiter:777] Sat Apr 04 11:10:33 -0300 2009 : request() query: http://twitter.com/direct_messages.json
53
+ I, [2009-04-04T11:10:33.954567 #777] INFO -- : [Tuiter:777] Sat Apr 04 11:10:33 -0300 2009 : request() debug: http status is 200 OK
54
+ I, [2009-04-04T11:13:45.335715 #789] INFO -- : [Tuiter:789] Sat Apr 04 11:13:45 -0300 2009 : initialize()
55
+ I, [2009-04-04T11:13:50.022233 #789] INFO -- : [Tuiter:789] Sat Apr 04 11:13:50 -0300 2009 : request() query: http://twitter.com/direct_messages.json
56
+ I, [2009-04-04T11:13:51.264725 #789] INFO -- : [Tuiter:789] Sat Apr 04 11:13:51 -0300 2009 : request() debug: http status is 200 OK
57
+ I, [2009-04-04T11:13:57.622508 #789] INFO -- : [Tuiter:789] Sat Apr 04 11:13:57 -0300 2009 : request() query: http://twitter.com/direct_messages.json
58
+ I, [2009-04-04T11:13:58.246439 #789] INFO -- : [Tuiter:789] Sat Apr 04 11:13:58 -0300 2009 : request() debug: http status is 200 OK
59
+ I, [2009-04-04T11:22:32.286894 #817] INFO -- : [Tuiter:817] Sat Apr 04 11:22:32 -0300 2009 : initialize()
60
+ I, [2009-04-04T11:22:42.397339 #817] INFO -- : [Tuiter:817] Sat Apr 04 11:22:42 -0300 2009 : request() query: http://twitter.com/direct_messages.json
61
+ I, [2009-04-04T11:22:43.736985 #817] INFO -- : [Tuiter:817] Sat Apr 04 11:22:43 -0300 2009 : request() debug: http status is 200 OK
62
+ I, [2009-04-04T11:24:51.155070 #877] INFO -- : [Tuiter:877] Sat Apr 04 11:24:51 -0300 2009 : initialize()
63
+ I, [2009-04-04T11:27:05.763596 #877] INFO -- : [Tuiter:877] Sat Apr 04 11:27:05 -0300 2009 : request() query: http://twitter.com/direct_messages.json
64
+ I, [2009-04-04T11:27:06.886668 #877] INFO -- : [Tuiter:877] Sat Apr 04 11:27:06 -0300 2009 : request() debug: http status is 200 OK
65
+ I, [2009-04-04T11:27:16.028439 #877] INFO -- : [Tuiter:877] Sat Apr 04 11:27:16 -0300 2009 : request() query: http://twitter.com/direct_messages.json
66
+ I, [2009-04-04T11:27:16.798857 #877] INFO -- : [Tuiter:877] Sat Apr 04 11:27:16 -0300 2009 : request() debug: http status is 200 OK
67
+ I, [2009-04-04T11:27:32.333157 #877] INFO -- : [Tuiter:877] Sat Apr 04 11:27:32 -0300 2009 : request() query: http://twitter.com/direct_messages.json?page=2
68
+ I, [2009-04-04T11:27:33.356890 #877] INFO -- : [Tuiter:877] Sat Apr 04 11:27:33 -0300 2009 : request() debug: http status is 200 OK
data/lib/tuiter.rb CHANGED
@@ -5,7 +5,15 @@ require 'logger'
5
5
 
6
6
  require 'json'
7
7
 
8
+ libdir = File.dirname(__FILE__)
9
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
10
+
11
+ # Tuiter client and end points
8
12
  require 'tuiter/client'
13
+
14
+ # Tuiter data structures
9
15
  require 'tuiter/data/user'
10
16
  require 'tuiter/data/status'
11
17
  require 'tuiter/data/rate_limit'
18
+ require 'tuiter/data/direct_message'
19
+
data/lib/tuiter.rb~ ADDED
@@ -0,0 +1,19 @@
1
+ require 'open-uri'
2
+ require 'uri'
3
+ require 'net/http'
4
+ require 'logger'
5
+
6
+ require 'json'
7
+
8
+ libdir = File.dirname(__FILE__)
9
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
10
+
11
+ # Tuiter client and end points
12
+ require 'tuiter/client'
13
+
14
+ # Tuiter data structures
15
+ require 'tuiter/data/user'
16
+ require 'tuiter/data/status'
17
+ require 'tuiter/data/rate_limit'
18
+ require 'tuiter/data/direct_message'
19
+
data/lib/tuiter/client.rb CHANGED
@@ -8,6 +8,7 @@ module Tuiter
8
8
  @logger = options[:logger] || Logger.new('tuiter.log')
9
9
  @username = options[:username]
10
10
  @password = options[:password]
11
+ @use_proxy = setup_a_proxy?
11
12
  log("initialize()")
12
13
  end
13
14
 
@@ -17,7 +18,7 @@ module Tuiter
17
18
  req = Net::HTTP::Post.new(url.path)
18
19
  req.basic_auth @username, @password
19
20
  req.set_form_data({'status'=>status, 'in_reply_to_status_id'=>in_reply_to_status_id })
20
- res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
21
+ res = new_http_for(url).start {|http| http.request(req) }
21
22
  case res
22
23
  when Net::HTTPSuccess, Net::HTTPRedirection
23
24
  log("update() success: OK")
@@ -34,7 +35,7 @@ module Tuiter
34
35
  req = Net::HTTP::Post.new(url.path)
35
36
  req.basic_auth @username, @password
36
37
  req.set_form_data({'user'=>user, 'text'=>text })
37
- res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
38
+ res = new_http_for(url).start {|http| http.request(req) }
38
39
  case res
39
40
  when Net::HTTPSuccess, Net::HTTPRedirection
40
41
  log("direct_new() success: OK")
@@ -44,14 +45,26 @@ module Tuiter
44
45
  res.error!
45
46
  end
46
47
  end
47
-
48
+
49
+ def direct_list(options = {})
50
+ url = 'http://twitter.com/direct_messages.json'
51
+ params = parse_options(options) || ""
52
+
53
+ if res = request(url+params)
54
+ data = JSON.parse(res)
55
+ return data.map { |d| DirectMessage.new(d) }
56
+ else
57
+ return nil
58
+ end
59
+ end
60
+
48
61
  def friendship_new(user, follow = nil)
49
62
  log("friendship_new() following: #{user}")
50
63
  url = URI.parse("http://twitter.com/friendships/create/#{user}.json")
51
64
  req = Net::HTTP::Post.new(url.path)
52
65
  req.basic_auth @username, @password
53
66
  req.set_form_data({'follow'=>"true"}) if follow
54
- res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
67
+ res = new_http_for(url).start {|http| http.request(req) }
55
68
  case res
56
69
  when Net::HTTPSuccess, Net::HTTPRedirection
57
70
  log("friendship_new() success: OK")
@@ -177,7 +190,49 @@ module Tuiter
177
190
  rescue Exception => e
178
191
  log("request() error: #{e.message} in #{e.backtrace.first.to_s}")
179
192
  return nil
180
- end
193
+ end
194
+
195
+ def parse_options(options)
196
+ if options[:since]
197
+ params = "?since=#{options[:since]}"
198
+ elsif options[:since_id]
199
+ params = "?since_id=#{options[:since_id]}"
200
+ else
201
+ params = ""
202
+ end
203
+
204
+ if options[:page]
205
+ if params == ""
206
+ params = "?page=#{options[:page]}"
207
+ else
208
+ params = params + "&" + "page=#{options[:page]}"
209
+ end
210
+ end
211
+
212
+ return params
213
+ end
214
+
215
+ def setup_a_proxy?
216
+ http_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] || nil
217
+
218
+ if http_proxy
219
+ proxy = URI.parse(http_proxy)
220
+
221
+ @proxy_host = proxy.host
222
+ @proxy_port = proxy.port
223
+ @proxy_user, @proxy_pass = proxy.userinfo.split(/:/) if proxy.userinfo
224
+ end
225
+
226
+ http_proxy != nil
227
+ end
228
+
229
+ def new_http_for(url)
230
+ if @use_proxy
231
+ http = Net::HTTP.new(url.host, url.port, @proxy_host, @proxy_port, @proxy_user, @proxy_pass)
232
+ else
233
+ http = Net::HTTP.new(url.host, url.port)
234
+ end
235
+ end
181
236
 
182
237
  def log(message)
183
238
  @logger.info "[Tuiter:#{@pid}] #{Time.now.to_s} : #{message}"
@@ -0,0 +1,244 @@
1
+ module Tuiter
2
+
3
+ class Client
4
+ attr_accessor :username, :password
5
+
6
+ def initialize(options = {})
7
+ @pid = Process.pid
8
+ @logger = options[:logger] || Logger.new('tuiter.log')
9
+ @username = options[:username]
10
+ @password = options[:password]
11
+ @use_proxy = setup_a_proxy?
12
+ log("initialize()")
13
+ end
14
+
15
+ def update(status, in_reply_to_status_id = nil)
16
+ log("update() sending: #{status}")
17
+ url = URI.parse('http://twitter.com/statuses/update.json')
18
+ req = Net::HTTP::Post.new(url.path)
19
+ req.basic_auth @username, @password
20
+ req.set_form_data({'status'=>status, 'in_reply_to_status_id'=>in_reply_to_status_id })
21
+ res = new_http_for(url).start {|http| http.request(req) }
22
+ case res
23
+ when Net::HTTPSuccess, Net::HTTPRedirection
24
+ log("update() success: OK")
25
+ return res # OK
26
+ else
27
+ log("update() error: #{res.error!}")
28
+ res.error!
29
+ end
30
+ end
31
+
32
+ def direct_new(user, text)
33
+ log("direct_new() sending: #{text} to #{user}")
34
+ url = URI.parse('http://twitter.com/direct_messages/new.json')
35
+ req = Net::HTTP::Post.new(url.path)
36
+ req.basic_auth @username, @password
37
+ req.set_form_data({'user'=>user, 'text'=>text })
38
+ res = new_http_for(url).start {|http| http.request(req) }
39
+ case res
40
+ when Net::HTTPSuccess, Net::HTTPRedirection
41
+ log("direct_new() success: OK")
42
+ return res # OK
43
+ else
44
+ log("direct_new() error: #{res.error!}")
45
+ res.error!
46
+ end
47
+ end
48
+
49
+ def direct_list(options = {})
50
+ url = 'http://twitter.com/direct_messages.json')
51
+ params = parse_options(options) || ""
52
+
53
+ if res = request(url+params)
54
+ data = JSON.parse(res)
55
+ return data.map { |d| DirectMessage.new(d) }
56
+ else
57
+ return nil
58
+ end
59
+ end
60
+
61
+ def friendship_new(user, follow = nil)
62
+ log("friendship_new() following: #{user}")
63
+ url = URI.parse("http://twitter.com/friendships/create/#{user}.json")
64
+ req = Net::HTTP::Post.new(url.path)
65
+ req.basic_auth @username, @password
66
+ req.set_form_data({'follow'=>"true"}) if follow
67
+ res = new_http_for(url).start {|http| http.request(req) }
68
+ case res
69
+ when Net::HTTPSuccess, Net::HTTPRedirection
70
+ log("friendship_new() success: OK")
71
+ return res # OK
72
+ else
73
+ log("friendship_new() error: #{res.error!}")
74
+ res.error!
75
+ end
76
+ end
77
+
78
+ def verify_credentials?
79
+ if res = request("http://twitter.com/account/verify_credentials.json")
80
+ return UserExtended.new(JSON.parse(res))
81
+ else
82
+ return nil
83
+ end
84
+ end
85
+
86
+ def get_followers(options = {})
87
+ if options[:id]
88
+ query = "http://twitter.com/statuses/followers/#{options[:id]}.json"
89
+ else
90
+ query = "http://twitter.com/statuses/followers.json"
91
+ end
92
+ if options[:page]
93
+ params = "?page=#{options[:page]}"
94
+ else
95
+ params = ""
96
+ end
97
+ if res = request(query+params)
98
+ data = JSON.parse(res)
99
+ return data.map { |d| User.new(d) }
100
+ else
101
+ return nil
102
+ end
103
+ end
104
+
105
+ def get_replies(options = {})
106
+ query = "http://twitter.com/statuses/replies.json"
107
+ if options[:since]
108
+ params = "?since=#{options[:since]}"
109
+ elsif options[:since_id]
110
+ params = "?since_id=#{options[:since_id]}"
111
+ else
112
+ params = ""
113
+ end
114
+ if options[:page]
115
+ if params == ""
116
+ params = "?page=#{options[:page]}"
117
+ else
118
+ params = params + "&" + "page=#{options[:page]}"
119
+ end
120
+ end
121
+ if res = request(query+params)
122
+ data = JSON.parse(res)
123
+ return data.map { |d| Status.new(d) }
124
+ else
125
+ return nil
126
+ end
127
+ end
128
+
129
+ def get_client
130
+ if res = request("http://twitter.com/users/show/#{@username}.json")
131
+ return UserExtended.new(JSON.parse(res))
132
+ else
133
+ return nil
134
+ end
135
+ end
136
+
137
+ def get_user(id)
138
+ if res = request("http://twitter.com/users/show/#{id}.json")
139
+ return UserExtended.new(JSON.parse(res))
140
+ else
141
+ return nil
142
+ end
143
+ end
144
+
145
+ def get_status(id)
146
+ if res = request("http://twitter.com/statuses/show/#{id}.json")
147
+ return Status.new(JSON.parse(res))
148
+ else
149
+ return nil
150
+ end
151
+ end
152
+
153
+ def rate_limit
154
+ if res = request("http://twitter.com/account/rate_limit_status.json")
155
+ return RateLimit.new(JSON.parse(res))
156
+ else
157
+ return nil
158
+ end
159
+ end
160
+
161
+ def follows_me?(id)
162
+ if res = request("http://twitter.com/friendships/exists.json?user_a=#{id}&user_b=#{@username}")
163
+ return true if res == "true"
164
+ return false
165
+ else
166
+ return nil
167
+ end
168
+ end
169
+
170
+ private
171
+
172
+ def request(url)
173
+ http = nil
174
+ status = Timeout::timeout(10) do
175
+ log("request() query: #{url}")
176
+ http = open(url, :http_basic_authentication=>[@username, @password])
177
+ log("request() debug: http status is #{http.status.join(' ')}")
178
+ if http.status == ["200", "OK"]
179
+ res = http.read
180
+ return res
181
+ end
182
+ return nil
183
+ end
184
+ rescue Timeout::Error
185
+ log("request() error: timeout error")
186
+ return nil
187
+ rescue OpenURI::HTTPError => e
188
+ log("request() http error: #{e.message} in #{e.backtrace.first.to_s}")
189
+ return nil
190
+ rescue Exception => e
191
+ log("request() error: #{e.message} in #{e.backtrace.first.to_s}")
192
+ return nil
193
+ end
194
+
195
+ def parse_options(options)
196
+ if options[:since]
197
+ params = "?since=#{options[:since]}"
198
+ elsif options[:since_id]
199
+ params = "?since_id=#{options[:since_id]}"
200
+ else
201
+ params = ""
202
+ end
203
+
204
+ if options[:page]
205
+ if params == ""
206
+ params = "?page=#{options[:page]}"
207
+ else
208
+ params = params + "&" + "page=#{options[:page]}"
209
+ end
210
+ end
211
+
212
+ return params
213
+ end
214
+
215
+ def setup_a_proxy?
216
+ http_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] || nil
217
+
218
+ if http_proxy
219
+ proxy = URI.parse(http_proxy)
220
+
221
+ @proxy_host = proxy.host
222
+ @proxy_port = proxy.port
223
+ @proxy_user, @proxy_pass = proxy.userinfo.split(/:/) if proxy.userinfo
224
+ end
225
+
226
+ http_proxy != nil
227
+ end
228
+
229
+ def new_http_for(url)
230
+ if @use_proxy
231
+ http = Net::HTTP.new(url.host, url.port, @proxy_host, @proxy_port, @proxy_user, @proxy_pass)
232
+ else
233
+ http = Net::HTTP.new(url.host, url.port)
234
+ end
235
+ end
236
+
237
+ def log(message)
238
+ @logger.info "[Tuiter:#{@pid}] #{Time.now.to_s} : #{message}"
239
+ end
240
+
241
+ end
242
+
243
+ end
244
+
@@ -0,0 +1,44 @@
1
+ module Tuiter
2
+
3
+ class DirectMessageBasic
4
+ attr_accessor :id
5
+ attr_accessor :text
6
+ attr_accessor :created_at
7
+ attr_accessor :sender_id
8
+ attr_accessor :sender_screen_name
9
+ attr_accessor :recipient_id
10
+ attr_accessor :recipient_screen_name
11
+
12
+ def initialize(data = nil)
13
+ unless data.nil?
14
+ @id = data['id']
15
+ @text = data['text']
16
+ @created_at = (data['created_at'] ? DateTime.parse(data['created_at']) : DateTime.now)
17
+ @sender_id = data['sender_id']
18
+ @sender_screen_name = data['sender_screen_name']
19
+ @recipient_id = data['recipient_id']
20
+ @recipient_screen_name = data['recipient_screen_name']
21
+ else
22
+ @created_at = DateTime.now
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+
29
+ class DirectMessage < DirectMessageBasic
30
+ attr_accessor :sender
31
+ attr_accessor :recipient
32
+
33
+ def initialize(data = nil)
34
+ unless data.nil?
35
+ super(data)
36
+ @sender = UserBasic.new(data['sender'])
37
+ @recipient = UserBasic.new(data['recipient'])
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,44 @@
1
+ module Tuiter
2
+
3
+ class DirectMessageBasic
4
+ attr_accessor :id
5
+ attr_accessor :text
6
+ attr_accessor :created_at
7
+ attr_accessor :sender_id
8
+ attr_accessor :sender_screen_name
9
+ attr_accessor :recipient_id
10
+ attr_accessor :recipient_screen_name
11
+
12
+ def initialize(data = nil)
13
+ unless data.nil?
14
+ @id = data['id']
15
+ @text = data['text']
16
+ @created_at = (data['created_at'] ? DateTime.parse(data['created_at']) : DateTime.now)
17
+ @sender_id = data['sender_id']
18
+ @sender_screen_name = data['sender_screen_name']
19
+ @recipient_id = data['recipient_id']
20
+ @recipient_screen_name = data['recipient_screen_name']
21
+ else
22
+ @created_at = DateTime.now
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+
29
+ class DirectMessage < DirectMessageBasic
30
+ attr_accessor :sender
31
+ attr_accessor :recipient
32
+
33
+ def initialize(data = nil)
34
+ unless data.nil?
35
+ super(data)
36
+ @sender = UserBasic.new(data['sender'])
37
+ @recipient = UserBasic.new(data['recipient'])
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
@@ -13,7 +13,7 @@ module Tuiter
13
13
 
14
14
  def initialize(data = nil)
15
15
  unless data.nil?
16
- @created_at = Time.parse(data["created_at"])
16
+ @created_at = (data["created_at"] ? DateTime.parse(data["created_at"]) : DateTime.now)
17
17
  @id = data["id"]
18
18
  @text = data["text"]
19
19
  @source = data["source"]
@@ -22,6 +22,8 @@ module Tuiter
22
22
  @in_reply_to_user_id = data["in_reply_to_user_id"]
23
23
  @favorited = data["favorited"]
24
24
  @in_reply_to_screen_name = data["in_reply_to_screen_name"]
25
+ else
26
+ @created_at = DateTime.now
25
27
  end
26
28
  end
27
29
 
@@ -53,7 +53,7 @@ module Tuiter
53
53
  @profile_sidebar_fill_color = data["profile_sidebar_fill_color"]
54
54
  @profile_sidebar_border_color = data["profile_sidebar_border_color"]
55
55
  @friends_count = data["friends_count"].to_i
56
- @created_at = Time.parse(data["created_at"])
56
+ @created_at = (data["created_at"] ? DateTime.parse(data["created_at"]) : DateTime.now)
57
57
  @favourites_count = data["favourites_count"].to_i
58
58
  @utc_offset = data["utc_offset"]
59
59
  @time_zone = data["time_zone"]
@@ -62,6 +62,8 @@ module Tuiter
62
62
  @following = data["following"]
63
63
  @notifications = data["notifications"]
64
64
  @statuses_count = data["statuses_count"].to_i
65
+ else
66
+ @created_at = DateTime.now
65
67
  end
66
68
  end
67
69
 
@@ -0,0 +1,9 @@
1
+ module Tuiter
2
+
3
+ DIRECT_MESSAGES = { :list => 'http://twitter.com/direct_messages',
4
+ :sent => 'http://twitter.com/direct_messages/sent',
5
+ :new => 'http://twitter.com/direct_messages/new',
6
+ :destroy => "http://twitter.com/direct_messages/destroy/#{id}" }
7
+
8
+ end
9
+
@@ -7,7 +7,7 @@ unless defined? Tuiter::VERSION
7
7
  module VERSION
8
8
  MAJOR = 0
9
9
  MINOR = 0
10
- TINY = 1
10
+ TINY = 2
11
11
 
12
12
  STRING = [MAJOR, MINOR, TINY].join('.')
13
13
  end
@@ -0,0 +1,16 @@
1
+ #
2
+ # Tuiter, Copyright (c) 2009 Manoel Lemos & WebCo Internet
3
+ #
4
+
5
+ unless defined? Tuiter::VERSION
6
+ module Tuiter
7
+ module VERSION
8
+ MAJOR = 0
9
+ MINOR = 0
10
+ TINY = 1
11
+
12
+ STRING = [MAJOR, MINOR, TINY].join('.')
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,68 @@
1
+ [
2
+ {
3
+ "description":"Follower #1",
4
+ "followers_count":300,
5
+ "url":"http:\/\/tuitersfera.com.br\/",
6
+ "name":"Joe Doe",
7
+ "protected":false,
8
+ "status":
9
+ {
10
+ "in_reply_to_status_id":null,
11
+ "truncated":false,
12
+ "text":"I am fine",
13
+ "created_at":"Mon Mar 23 18:25:41 +0000 2009",
14
+ "favorited":false,
15
+ "id":1203219398,
16
+ "in_reply_to_user_id":null,
17
+ "source":"web"
18
+ },
19
+ "profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png",
20
+ "location":"S\u00e3o Paulo",
21
+ "id":11111111,
22
+ "screen_name":"follower#1"
23
+ },
24
+ {
25
+ "description":"Follower #2",
26
+ "followers_count":15,
27
+ "url":"http:\/\/tuitersfera.com.br\/",
28
+ "name":"Mark Knoffler",
29
+ "protected":false,
30
+ "status":
31
+ {
32
+ "in_reply_to_status_id":null,
33
+ "truncated":false,
34
+ "text":"Playing the blues",
35
+ "created_at":"Mon Mar 23 09:30:10 +0000 2009",
36
+ "favorited":false,
37
+ "id":1203219398,
38
+ "in_reply_to_user_id":null,
39
+ "source":"web"
40
+ },
41
+ "profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png",
42
+ "location":"S\u00e3o Paulo",
43
+ "id":22222222,
44
+ "screen_name":"follower#2"
45
+ },
46
+ {
47
+ "description":"Follower #3",
48
+ "followers_count":200,
49
+ "url":"http:\/\/tuitersfera.com.br\/",
50
+ "name":"Iron Man",
51
+ "protected":false,
52
+ "status":
53
+ {
54
+ "in_reply_to_status_id":null,
55
+ "truncated":false,
56
+ "text":"Saving the world",
57
+ "created_at":"Mon Mar 23 09:30:10 +0000 2009",
58
+ "favorited":false,
59
+ "id":1203219398,
60
+ "in_reply_to_user_id":null,
61
+ "source":"web"
62
+ },
63
+ "profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png",
64
+ "location":"San Francisco",
65
+ "id":33333333,
66
+ "screen_name":"follower#3"
67
+ }
68
+ ]
@@ -0,0 +1,48 @@
1
+ [
2
+ {
3
+ "in_reply_to_user_id":19815179,
4
+ "truncated":false,
5
+ "user":
6
+ {
7
+ "description":"I am cool",
8
+ "followers_count":50,
9
+ "profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png",
10
+ "url":"http:\/\/tuitersfera.com.br\/",
11
+ "name":"Morgan Freeman",
12
+ "protected":false,
13
+ "screen_name":"morgan",
14
+ "location":"Hollywood, CA, USA",
15
+ "id":99999999
16
+ },
17
+ "favorited":false,
18
+ "text":"@tuitersfera hello?",
19
+ "created_at":"Sun Mar 22 18:56:38 +0000 2009",
20
+ "id":3333,
21
+ "in_reply_to_screen_name":"tuitersfera",
22
+ "in_reply_to_status_id":null,
23
+ "source":"web"
24
+ },
25
+ {
26
+ "in_reply_to_user_id":19815179,
27
+ "truncated":false,
28
+ "user":
29
+ {
30
+ "description":"Just relaxing",
31
+ "followers_count":300,
32
+ "profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png",
33
+ "url":"http:\/\/tuitersfera.com.br\/",
34
+ "name":"Carla Gugino",
35
+ "protected":false,
36
+ "screen_name":"HotCarla",
37
+ "location":"Hollywood, CA, USA",
38
+ "id":88888888
39
+ },
40
+ "favorited":false,
41
+ "text":"@tuitersfera I am fine, thanks.",
42
+ "created_at":"Sun Mar 22 13:50:38 +0000 2009",
43
+ "id":2222,
44
+ "in_reply_to_screen_name":"tuitersfera",
45
+ "in_reply_to_status_id":1,
46
+ "source":"web"
47
+ }
48
+ ]
@@ -0,0 +1,37 @@
1
+ {
2
+ "profile_background_image_url":"http:\/\/static.twitter.com\/images\/themes\/theme1\/bg.gif",
3
+ "description":"Projeto focado em medir a twittersfera brasileira.",
4
+ "utc_offset":-10800,
5
+ "profile_sidebar_fill_color":"e0ff92",
6
+ "following":false,
7
+ "friends_count":2053,
8
+ "notifications":false,
9
+ "profile_sidebar_border_color":"87bc44",
10
+ "profile_background_tile":false,
11
+ "time_zone":"Brasilia",
12
+ "favourites_count":0,
13
+ "profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/102032546\/tuit_normal.jpg",
14
+ "url":"http:\/\/tuitersfera.com.br\/",
15
+ "name":"Tuitersfera Brasil",
16
+ "protected":false,
17
+ "status":
18
+ {
19
+ "text":"Yesbaaaaaaa.... Completamos 1.000 usu\u00e1rios no Tuitersfera. http:\/\/tuitersfera.com.br\/",
20
+ "favorited":false,
21
+ "in_reply_to_user_id":null,
22
+ "in_reply_to_status_id":null,
23
+ "truncated":false,
24
+ "created_at":"Thu Feb 12 16:53:55 +0000 2009",
25
+ "id":1203219398,
26
+ "source":"<a href=\"http:\/\/www.twhirl.org\/\">twhirl<\/a>"
27
+ },
28
+ "profile_background_color":"9ae4e8",
29
+ "followers_count":1946,
30
+ "screen_name":"tuitersfera",
31
+ "profile_text_color":"000000",
32
+ "statuses_count":122,
33
+ "created_at":"Sat Jan 31 13:39:45 +0000 2009",
34
+ "location":"S\u00e3o Paulo, Brasil",
35
+ "id":19815179,
36
+ "profile_link_color":"0000ff"
37
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "id":11111111,
3
+ "name":"Joe Doe",
4
+ "screen_name":"follower#1"
5
+ "description":"Follower #1",
6
+ "location":"S\u00e3o Paulo",
7
+ "profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png",
8
+ "url":"http:\/\/tuitersfera.com.br\/",
9
+ "protected":false,
10
+ "followers_count":300,
11
+ "status":
12
+ {
13
+ "in_reply_to_status_id":null,
14
+ "truncated":false,
15
+ "text":"I am fine",
16
+ "created_at":"Mon Mar 23 18:25:41 +0000 2009",
17
+ "favorited":false,
18
+ "id":1203219398,
19
+ "in_reply_to_user_id":null,
20
+ "source":"web"
21
+ },
22
+ }
@@ -0,0 +1,48 @@
1
+ [
2
+ {
3
+ "user":
4
+ {
5
+ "description":"Projeto focado em medir a twittersfera brasileira.",
6
+ "profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/102032546\/tuit_normal.jpg",
7
+ "url":"http:\/\/tuitersfera.com.br\/",
8
+ "name":"Tuitersfera Brasil",
9
+ "protected":false,
10
+ "followers_count":1946,
11
+ "screen_name":"tuitersfera",
12
+ "location":"S\u00e3o Paulo, Brasil",
13
+ "id":19815179
14
+ },
15
+ "text":"Yesbaaaaaaa.... Completamos 1.000 usu\u00e1rios no Tuitersfera. http:\/\/tuitersfera.com.br\/",
16
+ "in_reply_to_screen_name":null,
17
+ "favorited":false,
18
+ "in_reply_to_user_id":null,
19
+ "in_reply_to_status_id":null,
20
+ "truncated":false,
21
+ "created_at":"Thu Feb 12 16:53:55 +0000 2009",
22
+ "id":1203219398,
23
+ "source":"<a href=\"http:\/\/www.twhirl.org\/\">twhirl<\/a>"
24
+ },
25
+ {
26
+ "user":
27
+ {
28
+ "description":"Projeto focado em medir a twittersfera brasileira.",
29
+ "profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/102032546\/tuit_normal.jpg",
30
+ "url":"http:\/\/tuitersfera.com.br\/",
31
+ "name":"Tuitersfera Brasil",
32
+ "protected":false,
33
+ "followers_count":1946,
34
+ "screen_name":"tuitersfera",
35
+ "location":"S\u00e3o Paulo, Brasil",
36
+ "id":19815179
37
+ },
38
+ "text":"Hello beautiful, how you're doing?",
39
+ "in_reply_to_screen_name":"HotCarla",
40
+ "favorited":false,
41
+ "in_reply_to_user_id":88888888,
42
+ "in_reply_to_status_id":null,
43
+ "truncated":false,
44
+ "created_at":"Sun Mar 22 12:10:21 +0000 2009",
45
+ "id":1203219398,
46
+ "source":"<a href=\"http:\/\/www.twhirl.org\/\">twhirl<\/a>"
47
+ }
48
+ ]
@@ -0,0 +1,29 @@
1
+ class Test::Unit::TestCase
2
+
3
+ def self.should_attr_accessor_for(klass, attributes)
4
+ object = klass.new
5
+
6
+ attributes.each do |attribute|
7
+ should "respond_to #{attribute}" do
8
+ assert object.respond_to?(attribute)
9
+ end
10
+
11
+ should "respond_to #{attribute}=" do
12
+ assert object.respond_to?("#{attribute}=")
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.should_load_attribute_on_initialize(klass, attributes, expected_value = "value", setter_value = expected_value)
18
+
19
+ attributes.each do |attribute|
20
+ should "load attribute '#{attribute}' on initialize" do
21
+ data = eval("{'#{attribute}' => #{setter_value.inspect}}")
22
+
23
+ object = klass.new data
24
+ assert_equal(expected_value, object.send(attribute))
25
+ end
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,25 @@
1
+ require "rubygems"
2
+ require "test/unit"
3
+ require "shoulda"
4
+ require "mocha"
5
+ require 'fakeweb'
6
+
7
+ # begin
8
+ # require "quietbacktrace"
9
+ # Test::Unit::TestCase.quiet_backtrace = true
10
+ # Test::Unit::TestCase.backtrace_silencers = [:test_unit, :gem_root, :e1]
11
+ # Test::Unit::TestCase.backtrace_filters = [:method_name]
12
+ # rescue LoadError
13
+ # # Just ignore it
14
+ # rescue NoMethodError
15
+ # # Just ignore it
16
+ # end
17
+
18
+ require File.dirname(__FILE__) + "/../lib/tuiter"
19
+
20
+ #Load shoulda macros
21
+ %w(macros).each do |dirname|
22
+ Dir[File.dirname(__FILE__) + "/#{dirname}/*.rb"].each do |file|
23
+ require file
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ClientTest < Test::Unit::TestCase
4
+
5
+ context "A valid Tuiter client" do
6
+
7
+ setup do
8
+ @username = "username"
9
+ @password = "password"
10
+ @client = Tuiter::Client.new(:username => @username, :password => @password)
11
+ end
12
+
13
+ context "posting data" do
14
+ setup do
15
+ @update_message = "I'm fine"
16
+ FakeWeb.register_uri(:post, "http://twitter.com/statuses/update.json", :string => @update_message, :status => "200")
17
+ end
18
+
19
+ should "allow the user to post an update to Twitter" do
20
+ # basic authentication and form data
21
+ Net::HTTP::Post.any_instance.expects(:basic_auth).with(@username, @password)
22
+ Net::HTTP::Post.any_instance.expects(:set_form_data).with('status' => @update_message, 'in_reply_to_status_id' => nil)
23
+
24
+ @response = @client.update(@update_message)
25
+
26
+ assert_instance_of Net::HTTPOK, @response
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ class StatusTest < Test::Unit::TestCase
4
+
5
+ STATUS_BASIC_ATTRIBUTES = %w(id text source truncated in_reply_to_status_id in_reply_to_user_id favorited in_reply_to_screen_name)
6
+
7
+ context "Status" do
8
+
9
+ context "Basic" do
10
+
11
+ should_attr_accessor_for Tuiter::StatusBasic, STATUS_BASIC_ATTRIBUTES
12
+ should_load_attribute_on_initialize Tuiter::StatusBasic, STATUS_BASIC_ATTRIBUTES
13
+
14
+ should "load attribute 'created_at' on initialize" do
15
+ now_str = "2009-10-31 18:59:20"
16
+ now = DateTime.parse(now_str)
17
+ user = Tuiter::UserExtended.new("created_at" => now_str)
18
+ assert_equal now, user.created_at
19
+ end
20
+
21
+ should "load attribute 'created_at' with current time" do
22
+ current_time = DateTime.now
23
+ DateTime.stubs(:now).returns(current_time)
24
+
25
+ user_extended = Tuiter::UserExtended.new
26
+ assert_equal current_time, user_extended.created_at
27
+ end
28
+
29
+ end # context "Basic"
30
+
31
+ context "for Twitter" do
32
+ should_attr_accessor_for Tuiter::Status, STATUS_BASIC_ATTRIBUTES
33
+ should_load_attribute_on_initialize Tuiter::Status, STATUS_BASIC_ATTRIBUTES
34
+
35
+ should "load attribute 'created_at' on initialize" do
36
+ now_str = "2009-10-31 18:59:20"
37
+ now = DateTime.parse(now_str)
38
+ user = Tuiter::UserExtended.new("created_at" => now_str)
39
+ assert_equal now, user.created_at
40
+ end
41
+
42
+ should "load attribute 'created_at' with current time" do
43
+ current_time = DateTime.now
44
+ DateTime.stubs(:now).returns(current_time)
45
+
46
+ user_extended = Tuiter::UserExtended.new
47
+ assert_equal current_time, user_extended.created_at
48
+ end
49
+
50
+ should "load user correctly" do
51
+ user_expected = Tuiter::UserBasic.new
52
+ Tuiter::UserBasic.expects(:new).with("user_data").returns(user_expected)
53
+ status = Tuiter::Status.new "user" => "user_data"
54
+ assert_equal user_expected, status.user
55
+ end
56
+ end # context "for Twitter"
57
+
58
+ end # context "Status"
59
+
60
+ end
61
+
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ class UserTest < Test::Unit::TestCase
4
+
5
+ USER_BASICS_ATTRIBUTES = %w(id name screen_name location description profile_image_url url protected followers_count)
6
+ USER_EXTEDNED_ATTRIBUTES = USER_BASICS_ATTRIBUTES + %w(profile_background_color profile_text_color profile_link_color profile_sidebar_fill_color profile_sidebar_border_color utc_offset time_zone profile_background_image_url profile_background_tile following notifications)
7
+ USER_EXTEDNED_ATTRIBUTES_INTEGER = %w(friends_count statuses_count favourites_count)
8
+ USER_EXTEDNED_ATTRIBUTES_TIME = %w(created_at)
9
+ USER_TWITTER_ATTRIBUTES = USER_BASICS_ATTRIBUTES + %w(status)
10
+
11
+ context "User" do
12
+ context "Basic" do
13
+ should_attr_accessor_for Tuiter::UserBasic, USER_BASICS_ATTRIBUTES
14
+ should_load_attribute_on_initialize Tuiter::UserBasic, USER_BASICS_ATTRIBUTES
15
+ end # context "Basic"
16
+
17
+ context "Extended" do
18
+ setup do
19
+ @now_str = "2009-10-31 18:59:20"
20
+ @now = DateTime.parse(@now_str)
21
+ end
22
+ should_attr_accessor_for Tuiter::UserExtended, USER_EXTEDNED_ATTRIBUTES
23
+ should_load_attribute_on_initialize Tuiter::UserExtended, USER_EXTEDNED_ATTRIBUTES
24
+ should_load_attribute_on_initialize Tuiter::UserExtended, USER_EXTEDNED_ATTRIBUTES_INTEGER, 10
25
+
26
+ should "load attribute 'created_at' on initialize" do
27
+ now_str = "2009-10-31 18:59:20"
28
+ now = DateTime.parse(now_str)
29
+ user = Tuiter::UserExtended.new("created_at" => now_str)
30
+ assert_equal now, user.created_at
31
+ end
32
+
33
+ should "load attribute 'created_at' with current time" do
34
+ current_time = DateTime.now
35
+ DateTime.stubs(:now).returns(current_time)
36
+
37
+ user_extended = Tuiter::UserExtended.new
38
+ assert_equal current_time, user_extended.created_at
39
+ end
40
+ end # context "Extended"
41
+
42
+ context "for Twitter" do
43
+ should_attr_accessor_for Tuiter::User, USER_TWITTER_ATTRIBUTES
44
+ should_load_attribute_on_initialize Tuiter::User, USER_BASICS_ATTRIBUTES
45
+
46
+ should "load attribute 'status' correctly" do
47
+ status_expected = Tuiter::StatusBasic.new
48
+ Tuiter::StatusBasic.expects(:new).with("teste").returns(status_expected)
49
+ user = Tuiter::User.new "status" => "teste"
50
+ assert_equal status_expected, user.status
51
+ end
52
+
53
+ end # context "for Twitter"
54
+
55
+
56
+
57
+ end # context "User"
58
+
59
+
60
+ end
61
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tuiter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manoel Lemos
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-03-20 00:00:00 -03:00
13
+ date: 2009-04-04 00:00:00 -03:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -39,13 +39,33 @@ files:
39
39
  - README.rdoc
40
40
  - lib/tuiter
41
41
  - lib/tuiter/client.rb
42
+ - lib/tuiter/client.rb~
42
43
  - lib/tuiter/data
44
+ - lib/tuiter/data/direct_message.rb
45
+ - lib/tuiter/data/direct_message.rb~
43
46
  - lib/tuiter/data/rate_limit.rb
44
47
  - lib/tuiter/data/status.rb
45
48
  - lib/tuiter/data/user.rb
49
+ - lib/tuiter/end_points.rb
46
50
  - lib/tuiter/version.rb
51
+ - lib/tuiter/version.rb~
52
+ - lib/tuiter.log
47
53
  - lib/tuiter.rb
54
+ - lib/tuiter.rb~
48
55
  - examples/basic_example.rb
56
+ - test/fixtures
57
+ - test/fixtures/followers.json
58
+ - test/fixtures/replies.json
59
+ - test/fixtures/tuitersfera.json
60
+ - test/fixtures/user_basic.json
61
+ - test/fixtures/user_timeline.json
62
+ - test/macros
63
+ - test/macros/attr_accessor_macro.rb
64
+ - test/test_helper.rb
65
+ - test/unit
66
+ - test/unit/client_test.rb
67
+ - test/unit/status_test.rb
68
+ - test/unit/user_test.rb
49
69
  has_rdoc: false
50
70
  homepage: http://github.com/webco/tuiter
51
71
  post_install_message: