rubytter 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +0 -0
- data/README.rdoc +97 -0
- data/examples/friends_timeline.rb +14 -0
- data/examples/update_status.rb +12 -0
- data/lib/rubytter/connection.rb +37 -0
- data/lib/rubytter.rb +133 -0
- data/spec/rubytter_spec.rb +132 -0
- data/spec/spec_helper.rb +4 -0
- metadata +73 -0
data/History.txt
ADDED
File without changes
|
data/README.rdoc
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
= rubytter
|
2
|
+
|
3
|
+
http://github.com/jugyo/rubytter
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Rubytter is simple twitter library.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
implemented methods:
|
12
|
+
|
13
|
+
- /statuses/update
|
14
|
+
- /statuses/destroy/id
|
15
|
+
- /statuses/public_timeline
|
16
|
+
- /statuses/friends_timeline
|
17
|
+
- /statuses/replies
|
18
|
+
- /statuses/user_timeline/id
|
19
|
+
- /statuses/show/id
|
20
|
+
- /statuses/friends/id
|
21
|
+
- /statuses/followers/id
|
22
|
+
- /users/show/id
|
23
|
+
- /direct_messages
|
24
|
+
- /direct_messages/sent
|
25
|
+
- /direct_messages/new
|
26
|
+
- /direct_messages/destroy/id
|
27
|
+
- /friendships/create/id
|
28
|
+
- /friendships/destroy/id
|
29
|
+
- /friendships/exists
|
30
|
+
- /followers/ids/id
|
31
|
+
- /friends/ids/id
|
32
|
+
- /favorites
|
33
|
+
- /favorites/create/id
|
34
|
+
- /favorites/destroy/id
|
35
|
+
- /account/verify_credentials
|
36
|
+
- /account/end_session
|
37
|
+
- /account/update_delivery_device
|
38
|
+
- /account/update_profile_colors
|
39
|
+
- /account/rate_limit_status
|
40
|
+
- /account/update_profile
|
41
|
+
- /notifications/follow/id
|
42
|
+
- /notifications/leave/id
|
43
|
+
- /blocks/create/id
|
44
|
+
- /blocks/destroy/id
|
45
|
+
|
46
|
+
== SYNOPSIS:
|
47
|
+
|
48
|
+
update status
|
49
|
+
|
50
|
+
client = Rubytter.new(user_id, password)
|
51
|
+
client.update('hello twitter!!')
|
52
|
+
|
53
|
+
get friends timeline
|
54
|
+
|
55
|
+
client = Rubytter.new(user_id, password)
|
56
|
+
client.friends_timeline.each do |status|
|
57
|
+
puts "#{status.user.screen_name}: #{status.text}"
|
58
|
+
end
|
59
|
+
|
60
|
+
== REQUIREMENTS:
|
61
|
+
|
62
|
+
* json
|
63
|
+
|
64
|
+
== INSTALL:
|
65
|
+
|
66
|
+
gem source -a http://gems.github.com
|
67
|
+
sudo gem install jugyo-rubytter
|
68
|
+
|
69
|
+
== TODO:
|
70
|
+
|
71
|
+
- search
|
72
|
+
- favorite
|
73
|
+
|
74
|
+
== LICENSE:
|
75
|
+
|
76
|
+
(The MIT License)
|
77
|
+
|
78
|
+
Copyright (c) 2008-2009 jugyo
|
79
|
+
|
80
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
81
|
+
a copy of this software and associated documentation files (the
|
82
|
+
'Software'), to deal in the Software without restriction, including
|
83
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
84
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
85
|
+
permit persons to whom the Software is furnished to do so, subject to
|
86
|
+
the following conditions:
|
87
|
+
|
88
|
+
The above copyright notice and this permission notice shall be
|
89
|
+
included in all copies or substantial portions of the Software.
|
90
|
+
|
91
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
92
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
93
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
94
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
95
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
96
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
97
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubytter'
|
5
|
+
|
6
|
+
if ARGV.size < 2
|
7
|
+
puts "Usage: ruby #{File.basename(__FILE__)} user_id password"
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
|
11
|
+
client = Rubytter.new(ARGV[0], ARGV[1])
|
12
|
+
client.friends_timeline.each do |status|
|
13
|
+
puts "#{status.user.screen_name}: #{status.text}"
|
14
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Rubytter
|
2
|
+
class Connection
|
3
|
+
attr_reader :protocol, :port, :proxy_uri
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@proxy_host = options[:proxy_host]
|
7
|
+
@proxy_port = options[:proxy_port]
|
8
|
+
@proxy_user = options[:proxy_user_name]
|
9
|
+
@proxy_password = options[:proxy_password]
|
10
|
+
@proxy_uri = nil
|
11
|
+
@enable_ssl = options[:enable_ssl]
|
12
|
+
|
13
|
+
if @proxy_host
|
14
|
+
@http_class = Net::HTTP::Proxy(@proxy_host, @proxy_port,
|
15
|
+
@proxy_user, @proxy_password)
|
16
|
+
@proxy_uri = "http://" + @proxy_host + ":" + @proxy_port.to_s + "/"
|
17
|
+
else
|
18
|
+
@http_class = Net::HTTP
|
19
|
+
end
|
20
|
+
|
21
|
+
if @enable_ssl
|
22
|
+
@protocol = "https"
|
23
|
+
@port = 443
|
24
|
+
else
|
25
|
+
@protocol = "http"
|
26
|
+
@port = 80
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def start(host, port = nil, &block)
|
31
|
+
http = @http_class.new(host, port || @port)
|
32
|
+
http.use_ssl = @enable_ssl
|
33
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl?
|
34
|
+
http.start(&block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/rubytter.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
require 'net/https'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
require 'rubytter/connection'
|
7
|
+
|
8
|
+
class Rubytter
|
9
|
+
APP_NAME = 'Rubytter'
|
10
|
+
HOMEPAGE = 'http://github.com/jugyo/rubytter'
|
11
|
+
|
12
|
+
def initialize(login, password, options = {})
|
13
|
+
@login = login
|
14
|
+
@password = password
|
15
|
+
@host = options[:host] || 'twitter.com'
|
16
|
+
@connection = Connection.new(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.api_settings
|
20
|
+
# method name path for API http method
|
21
|
+
"
|
22
|
+
status_update /statuses/update post
|
23
|
+
destroy /statuses/destroy/%s delete
|
24
|
+
public_timeline /statuses/public_timeline
|
25
|
+
friends_timeline /statuses/friends_timeline
|
26
|
+
replies /statuses/replies
|
27
|
+
user_timeline /statuses/user_timeline/%s
|
28
|
+
show /statuses/show/%s
|
29
|
+
friends /statuses/friends/%s
|
30
|
+
followers /statuses/followers/%s
|
31
|
+
user /users/show/%s
|
32
|
+
direct_messages /direct_messages
|
33
|
+
sent_direct_messages /direct_messages/sent
|
34
|
+
send_direct_message /direct_messages/new post
|
35
|
+
destroy_direct_message /direct_messages/destroy/%s delete
|
36
|
+
create_friendship /friendships/create/%s post
|
37
|
+
destroy_friendship /friendships/destroy/%s delete
|
38
|
+
friendship_exists /friendships/exists
|
39
|
+
followers_ids /followers/ids/%s
|
40
|
+
friends_ids /friends/ids/%s
|
41
|
+
favorites /favorites
|
42
|
+
favorite /favorites/create/%s post
|
43
|
+
unfavorite /favorites/destroy/%s delete
|
44
|
+
verify_credentials /account/verify_credentials get
|
45
|
+
end_session /account/end_session post
|
46
|
+
update_delivery_device /account/update_delivery_device post
|
47
|
+
update_profile_colors /account/update_profile_colors post
|
48
|
+
rate_limit_status /account/rate_limit_status
|
49
|
+
update_profile /account/update_profile post
|
50
|
+
enable_notification /notifications/follow/%s post
|
51
|
+
disable_notification /notifications/leave/%s post
|
52
|
+
block /blocks/create/%s post
|
53
|
+
unblock /blocks/destroy/%s delete
|
54
|
+
".strip.split("\n").map{|line| line.strip.split(/\s+/)}
|
55
|
+
end
|
56
|
+
|
57
|
+
api_settings.each do |array|
|
58
|
+
method, path, http_method = *array
|
59
|
+
http_method ||= 'get'
|
60
|
+
if /%s$/ =~ path
|
61
|
+
eval <<-EOS
|
62
|
+
def #{method}(id, params = {})
|
63
|
+
#{http_method}('#{path}' % id, params)
|
64
|
+
end
|
65
|
+
EOS
|
66
|
+
else
|
67
|
+
eval <<-EOS
|
68
|
+
def #{method}(params = {})
|
69
|
+
#{http_method}('#{path}', params)
|
70
|
+
end
|
71
|
+
EOS
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def update(status, params = {})
|
76
|
+
status_update(params.merge({:status => status}))
|
77
|
+
end
|
78
|
+
|
79
|
+
def direct_message(user, text, params = {})
|
80
|
+
send_direct_message(params.merge({:user => user, :text => text}))
|
81
|
+
end
|
82
|
+
|
83
|
+
def get(path, params = {})
|
84
|
+
path += '.json'
|
85
|
+
param_str = '?' + params.to_a.map{|i| i[0].to_s + '=' + CGI.escape(i[1]) }.join('&')
|
86
|
+
path = path + param_str unless param_str.empty?
|
87
|
+
req = prepare_request(Net::HTTP::Get.new(path))
|
88
|
+
res_body = @connection.start(@host) do |http|
|
89
|
+
http.request(req).body
|
90
|
+
end
|
91
|
+
json_to_struct(JSON.parse(res_body))
|
92
|
+
end
|
93
|
+
|
94
|
+
def post(path, params = {})
|
95
|
+
path += '.json'
|
96
|
+
param_str = params.to_a.map{|i| i[0].to_s + '=' + CGI.escape(i[1]) }.join('&')
|
97
|
+
req = prepare_request(Net::HTTP::Post.new(path))
|
98
|
+
res_body = @connection.start(@host) do |http|
|
99
|
+
http.request(req, param_str).body
|
100
|
+
end
|
101
|
+
json_to_struct(JSON.parse(res_body))
|
102
|
+
end
|
103
|
+
|
104
|
+
alias delete post
|
105
|
+
|
106
|
+
def prepare_request(req)
|
107
|
+
req.add_field('User-Agent', "#{APP_NAME} #{HOMEPAGE}")
|
108
|
+
req.basic_auth(@login, @password)
|
109
|
+
return req
|
110
|
+
end
|
111
|
+
|
112
|
+
def json_to_struct(json)
|
113
|
+
case json
|
114
|
+
when Array
|
115
|
+
json.map{|i| json_to_struct(i)}
|
116
|
+
when Hash
|
117
|
+
struct_values = {}
|
118
|
+
json.each do |k, v|
|
119
|
+
case k
|
120
|
+
when String, Symbol
|
121
|
+
struct_values[k.to_sym] = json_to_struct(v)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
unless struct_values.empty?
|
125
|
+
Struct.new(*struct_values.keys).new(*struct_values.values)
|
126
|
+
else
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
else
|
130
|
+
json
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
4
|
+
|
5
|
+
class Rubytter
|
6
|
+
describe Rubytter do
|
7
|
+
before do
|
8
|
+
@rubytter = Rubytter.new('test', 'test')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should receive ...' do
|
12
|
+
@rubytter.should_receive(:user_timeline).with(1)
|
13
|
+
@rubytter.user_timeline(1)
|
14
|
+
@rubytter.should_receive(:friend_timeline)
|
15
|
+
@rubytter.friend_timeline
|
16
|
+
@rubytter.should_receive(:replies).with({:page => 2})
|
17
|
+
@rubytter.replies(:page => 2)
|
18
|
+
# more...
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should get or post' do
|
22
|
+
# TODO: split specs
|
23
|
+
@rubytter.should_receive(:get).with('/statuses/replies', {})
|
24
|
+
@rubytter.replies
|
25
|
+
|
26
|
+
@rubytter.should_receive(:get).with('/statuses/replies', {:page => 2})
|
27
|
+
@rubytter.replies(:page => 2)
|
28
|
+
|
29
|
+
@rubytter.should_receive(:get).with('/statuses/user_timeline/1', {})
|
30
|
+
@rubytter.user_timeline(1)
|
31
|
+
|
32
|
+
@rubytter.should_receive(:get).with('/users/show/1', {})
|
33
|
+
@rubytter.user(1)
|
34
|
+
|
35
|
+
@rubytter.should_receive(:delete).with('/statuses/destroy/1', {})
|
36
|
+
@rubytter.destroy(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
# direct_messages
|
40
|
+
|
41
|
+
it 'should respond to direct_messages' do
|
42
|
+
@rubytter.should_receive(:get).with('/direct_messages', {})
|
43
|
+
@rubytter.direct_messages()
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should respond to sent_direct_messages' do
|
47
|
+
@rubytter.should_receive(:get).with('/direct_messages/sent', {})
|
48
|
+
@rubytter.sent_direct_messages()
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should respond to send_direct_message' do
|
52
|
+
@rubytter.should_receive(:post).with('/direct_messages/new', {})
|
53
|
+
@rubytter.send_direct_message()
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should respond to destroy_direct_message' do
|
57
|
+
@rubytter.should_receive(:delete).with('/direct_messages/destroy/1', {})
|
58
|
+
@rubytter.destroy_direct_message(1)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should respond to direct_message' do
|
62
|
+
@rubytter.should_receive(:post).with('/direct_messages/new', {:user => 'test', :text => 'aaaaaaaaaaaaa'})
|
63
|
+
@rubytter.direct_message('test', 'aaaaaaaaaaaaa')
|
64
|
+
end
|
65
|
+
|
66
|
+
# statuses
|
67
|
+
|
68
|
+
it 'should respond to update' do
|
69
|
+
@rubytter.should_receive(:post).with('/statuses/update', {:status => 'test'})
|
70
|
+
@rubytter.update('test')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should respond to status_update' do
|
74
|
+
@rubytter.should_receive(:post).with('/statuses/update', {:status => 'test'})
|
75
|
+
@rubytter.status_update(:status => 'test')
|
76
|
+
end
|
77
|
+
|
78
|
+
# friendship
|
79
|
+
|
80
|
+
it 'should respond to create_friendship' do
|
81
|
+
@rubytter.should_receive(:post).with('/friendships/create/test', {})
|
82
|
+
@rubytter.create_friendship('test')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should respond to destroy_friendship' do
|
86
|
+
@rubytter.should_receive(:delete).with('/friendships/destroy/test', {})
|
87
|
+
@rubytter.destroy_friendship('test')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should respond to friendship_exists' do
|
91
|
+
@rubytter.should_receive(:get).with('/friendships/exists', {:user_a => 'a', :user_b => 'b'})
|
92
|
+
@rubytter.friendship_exists(:user_a => 'a', :user_b => 'b')
|
93
|
+
end
|
94
|
+
|
95
|
+
# Social Graph Methods
|
96
|
+
|
97
|
+
it 'should respond to followers_ids' do
|
98
|
+
@rubytter.should_receive(:get).with('/friends/ids/test', {})
|
99
|
+
@rubytter.friends_ids('test')
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should respond to followers_ids' do
|
103
|
+
@rubytter.should_receive(:get).with('/followers/ids/test', {})
|
104
|
+
@rubytter.followers_ids('test')
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should create struct from json' do
|
108
|
+
hash = {
|
109
|
+
:a => 'a',
|
110
|
+
'b' => 1,
|
111
|
+
1 => 'a',
|
112
|
+
/regex/ => 'regex',
|
113
|
+
nil => nil,
|
114
|
+
:c => {:a => 1, :b => 2},
|
115
|
+
:d => {:a => {:a => 1, :b => 2}, :b => 1},
|
116
|
+
:e => [{:a => 1, :b => 2}, {:c => 3}]
|
117
|
+
}
|
118
|
+
struct = @rubytter.json_to_struct(hash)
|
119
|
+
struct.a.should == 'a'
|
120
|
+
struct.b.should == 1
|
121
|
+
struct.c.a.should == 1
|
122
|
+
struct.c.b.should == 2
|
123
|
+
struct.d.a.a.should == 1
|
124
|
+
struct.e[0].a.should == 1
|
125
|
+
struct.e[0].b.should == 2
|
126
|
+
struct.e[1].c.should == 3
|
127
|
+
lambda {struct.x}.should raise_error(NoMethodError)
|
128
|
+
lambda {struct.regex}.should raise_error(NoMethodError)
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubytter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jugyo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-14 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json_pure
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.1.3
|
24
|
+
version:
|
25
|
+
description: Rubytter is a simple twitter client.
|
26
|
+
email: jugyo.org@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
- History.txt
|
34
|
+
files:
|
35
|
+
- lib/rubytter.rb
|
36
|
+
- lib/rubytter/connection.rb
|
37
|
+
- examples/friends_timeline.rb
|
38
|
+
- examples/update_status.rb
|
39
|
+
- spec/rubytter_spec.rb
|
40
|
+
- spec/spec_helper.rb
|
41
|
+
- README.rdoc
|
42
|
+
- History.txt
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/jugyo/rubytter
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --main
|
48
|
+
- README.rdoc
|
49
|
+
- --exclude
|
50
|
+
- spec
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project: rubytter
|
68
|
+
rubygems_version: 1.3.1
|
69
|
+
signing_key:
|
70
|
+
specification_version: 2
|
71
|
+
summary: Simple twitter client.
|
72
|
+
test_files: []
|
73
|
+
|