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 +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:
|