tuiter 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +7 -4
- data/README.rdoc +24 -7
- data/Rakefile +7 -3
- data/lib/tuiter.log +68 -0
- data/lib/tuiter.rb +8 -0
- data/lib/tuiter.rb~ +19 -0
- data/lib/tuiter/client.rb +60 -5
- data/lib/tuiter/client.rb~ +244 -0
- data/lib/tuiter/data/direct_message.rb +44 -0
- data/lib/tuiter/data/direct_message.rb~ +44 -0
- data/lib/tuiter/data/status.rb +3 -1
- data/lib/tuiter/data/user.rb +3 -1
- data/lib/tuiter/end_points.rb +9 -0
- data/lib/tuiter/version.rb +1 -1
- data/lib/tuiter/version.rb~ +16 -0
- data/test/fixtures/followers.json +68 -0
- data/test/fixtures/replies.json +48 -0
- data/test/fixtures/tuitersfera.json +37 -0
- data/test/fixtures/user_basic.json +22 -0
- data/test/fixtures/user_timeline.json +48 -0
- data/test/macros/attr_accessor_macro.rb +29 -0
- data/test/test_helper.rb +25 -0
- data/test/unit/client_test.rb +32 -0
- data/test/unit/status_test.rb +61 -0
- data/test/unit/user_test.rb +61 -0
- metadata +22 -2
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
|
11
|
-
*
|
12
|
-
*
|
13
|
-
* Lucas
|
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
|
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
|
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
|
-
|
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
|
17
|
+
gem install tuiter
|
12
18
|
|
13
|
-
|
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
|
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
|
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 "
|
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 =
|
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 =
|
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 =
|
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
|
+
|
data/lib/tuiter/data/status.rb
CHANGED
@@ -13,7 +13,7 @@ module Tuiter
|
|
13
13
|
|
14
14
|
def initialize(data = nil)
|
15
15
|
unless data.nil?
|
16
|
-
@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
|
|
data/lib/tuiter/data/user.rb
CHANGED
@@ -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 =
|
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
|
+
|
data/lib/tuiter/version.rb
CHANGED
@@ -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
|
data/test/test_helper.rb
ADDED
@@ -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.
|
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-
|
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:
|