mbbx6spp-twitter4r 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +5 -0
- data/README +5 -0
- data/TODO +1 -3
- data/bin/t4rsh +80 -0
- data/lib/twitter.rb +7 -4
- data/lib/twitter/client.rb +13 -10
- data/lib/twitter/client/account.rb +16 -16
- data/lib/twitter/client/base.rb +15 -6
- data/lib/twitter/client/favorites.rb +37 -37
- data/lib/twitter/client/graph.rb +37 -0
- data/lib/twitter/client/profile.rb +29 -0
- data/lib/twitter/client/search.rb +27 -0
- data/lib/twitter/client/status.rb +7 -2
- data/lib/twitter/config.rb +6 -0
- data/lib/twitter/console.rb +3 -0
- data/lib/twitter/core.rb +3 -3
- data/lib/twitter/ext/stdlib.rb +3 -2
- data/lib/twitter/model.rb +14 -2
- data/lib/twitter/version.rb +2 -2
- data/spec/twitter/client/account_spec.rb +28 -0
- data/spec/twitter/client/graph_spec.rb +67 -0
- data/spec/twitter/client/profile_spec.rb +91 -0
- data/spec/twitter/client/search_spec.rb +68 -0
- data/spec/twitter/client/status_spec.rb +27 -0
- data/spec/twitter/ext/stdlib_spec.rb +17 -0
- data/spec/twitter/model_spec.rb +45 -1
- metadata +38 -32
- data/lib/twitter/rails.rb +0 -92
- data/spec/twitter/rails_spec.rb +0 -110
data/CHANGES
CHANGED
@@ -3,6 +3,11 @@
|
|
3
3
|
Catalog(ue) of changes for Twitter4R 0.1.x releases including Retrospectiva ticket cross-reference numbers. Refer to http://retro.tautology.net/projects/twitter4r/tickets for more information.
|
4
4
|
|
5
5
|
== 0.3.1 Changes
|
6
|
+
*
|
7
|
+
* Added specs for Twitter::Client#profile (:info, :colors and :device cases)
|
8
|
+
* Added Twitter4R shell
|
9
|
+
* Improved code coverage for twitter/ext/stdlib code and removed hard coded extension in GET request path for retrieving account information
|
10
|
+
* Changed Twitter::RESTError super class to be RuntimeError instead of Exception
|
6
11
|
* Added URI.encode => CGI.escape fix
|
7
12
|
* Added block methods
|
8
13
|
* Added Twitter::Client#inspect method to XXXX out passwords
|
data/README
CHANGED
@@ -7,10 +7,15 @@
|
|
7
7
|
* {Susan Potter}[http://SusanPotter.NET] <me at susanpotter dot net>
|
8
8
|
|
9
9
|
== Contributors
|
10
|
+
Code:
|
10
11
|
* Kaiichi Matsunaga <ma2 at lifemedia dot co dot jp> - proxy code suggestion
|
11
12
|
* Sergio Santos <> - message paging code suggestion
|
12
13
|
* Adam Stiles <adam at stilesoft dot com> - URI.encode => CGI.escape fix
|
13
14
|
* Carl Crawley <cwcrawley at gmail dot com> - Friendship get => post fix
|
15
|
+
* Christian Johansen <christian at cjohansen dot no> - in_reply_to attributes in Twitter::Status
|
16
|
+
|
17
|
+
Design Suggestions:
|
18
|
+
* Bosco So <rubymeetup at boscoso dot com> - making Twitter::Error a RuntimeError instead of an Exception to prevent irb from crashing out.
|
14
19
|
|
15
20
|
== Description
|
16
21
|
Twitter4R provides an object based API to query or update your Twitter account via pure Ruby. It hides the ugly HTTP/REST code from your code.
|
data/TODO
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
|
2
2
|
0.3.1 TODO:
|
3
3
|
* Add specs for :page, :lite and :since options support in Twitter::Client#my(...), Twitter::Client#user(....) and Twitter::User#followers calls
|
4
|
-
* Add specs for Kernel#gem_present? extension
|
5
|
-
* Add spec to test that warning is given to Rails 2.0+ users requiring 'twitter/rails'
|
6
4
|
* Add specs for :replies support in Twitter::Client#status(...) and Twitter::Client#timeline_for(...)
|
7
5
|
* Add RDoc for :replies support
|
8
6
|
* Add better RDoc for Twitter::Client.account_info(:rate_limit_status)
|
9
|
-
* Add specs for Twitter::Client.account_info(:rate_limit_status)
|
7
|
+
* Add specs for Twitter::Client.account_info(:rate_limit_status)
|
data/bin/t4rsh
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require("irb")
|
4
|
+
require("irb/completion")
|
5
|
+
require("rubygems")
|
6
|
+
|
7
|
+
begin
|
8
|
+
gem('twitter4r', '>0.3.0')
|
9
|
+
require("twitter")
|
10
|
+
require("twitter/console")
|
11
|
+
rescue Gem::LoadError
|
12
|
+
begin
|
13
|
+
gem("mbbx6spp-twitter4r", '>=0.3.1')
|
14
|
+
require("twitter")
|
15
|
+
require("twitter/console")
|
16
|
+
rescue Gem::LoadError
|
17
|
+
abort("Error: You must install either twitter4r gem from Rubyforge with version 0.3.1 or greater or the mbbx6spp-twitter4r gem from GitHub's servers with version 0.3.1 or greater (and make sure it is a recent version of the gem).")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Twitter
|
22
|
+
class Console
|
23
|
+
class << self
|
24
|
+
@@OPTIONS = { :debugger => false, :config => "~/.twitter4r/accounts.yml" }
|
25
|
+
def parse_options
|
26
|
+
OptionParser.new do |opt|
|
27
|
+
opt.banner = "Usage: t4rsh [environment] [options]"
|
28
|
+
opt.on("--config=[~/.twitter4r/accounts.yml]", 'Use a specific config file.') { |v| @@OPTIONS[:config] = v }
|
29
|
+
opt.parse!(ARGV)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def config_file
|
34
|
+
result = ENV["T4R_CONFIG"]
|
35
|
+
file_name = File.expand_path('twitter.yml')
|
36
|
+
result ||= file_name if File.exists?(file_name)
|
37
|
+
file_name = File.expand_path('twitter.yml', 'config')
|
38
|
+
result ||= file_name if File.exists?(file_name)
|
39
|
+
file_name = File.expand_path('~/.twitter.yml')
|
40
|
+
result ||= file_name if File.exists?(file_name)
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def account
|
45
|
+
ENV["T4R_ENV"] || ENV["MERB_ENV"] || ENV["RAILS_ENV"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def run(file)
|
49
|
+
IRB.init_config(nil)
|
50
|
+
# configuration...
|
51
|
+
IRB.conf[:IRB_NAME] = "t4rsh"
|
52
|
+
IRB.conf[:VERSION] = Twitter::Version.to_version
|
53
|
+
IRB.conf[:USE_READLINE] = true
|
54
|
+
IRB.conf[:PROMPT_MODE] = :T4RSH
|
55
|
+
IRB.conf[:PROMPT][:T4RSH] = {
|
56
|
+
:PROMPT_I => "%N[%3n:%i]> ", # top level prompt
|
57
|
+
:PROMPT_C => "%N[%3n:%i]* ", # after conditional like "if"
|
58
|
+
:PROMPT_S => "%N[%3n:%i]* ", # during continuing string
|
59
|
+
:RETURN => "=> %s\n", # return value
|
60
|
+
}
|
61
|
+
IRB.start(file)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#if __FILE__ == $0
|
68
|
+
@twitter = nil
|
69
|
+
config_file = Twitter::Console.config_file
|
70
|
+
account = Twitter::Console.account
|
71
|
+
|
72
|
+
if config_file && account
|
73
|
+
@twitter = Twitter::Client.from_config(config_file, account)
|
74
|
+
puts "Used #{config_file} to create client for #{account} account."
|
75
|
+
puts "Access @twitter for instantiated client."
|
76
|
+
Twitter::Console.run(__FILE__)
|
77
|
+
else
|
78
|
+
abort("Please make sure #{config_file} exists and contains your Twitter credentials (separated by account/environment) and that you specify the account/environment to use, e.g. if you have a 'test' section in your configuration file that you want to use set/export T4R_ENV=test as an environment variable or RAILS_ENV=test or MERB_ENV=test")
|
79
|
+
end
|
80
|
+
#end
|
data/lib/twitter.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
|
+
require('rubygems')
|
2
3
|
|
3
4
|
module Twitter; end
|
4
5
|
|
@@ -6,9 +7,11 @@ def require_local(suffix)
|
|
6
7
|
require(File.expand_path(File.join(File.dirname(__FILE__), suffix)))
|
7
8
|
end
|
8
9
|
|
9
|
-
# For better unicode support
|
10
|
-
|
11
|
-
|
10
|
+
# For better unicode support in 1.8
|
11
|
+
if RUBY_VERSION < '1.9'
|
12
|
+
$KCODE = 'u'
|
13
|
+
require 'jcode'
|
14
|
+
end
|
12
15
|
|
13
16
|
# External requires
|
14
17
|
require('yaml')
|
data/lib/twitter/client.rb
CHANGED
@@ -9,13 +9,16 @@ class Twitter::Client
|
|
9
9
|
include Twitter::ClassUtilMixin
|
10
10
|
end
|
11
11
|
|
12
|
-
require('twitter/client/base
|
13
|
-
require('twitter/client/timeline
|
14
|
-
require('twitter/client/status
|
15
|
-
require('twitter/client/friendship
|
16
|
-
require('twitter/client/messaging
|
17
|
-
require('twitter/client/user
|
18
|
-
require('twitter/client/auth
|
19
|
-
require('twitter/client/favorites
|
20
|
-
require('twitter/client/blocks
|
21
|
-
require('twitter/client/account
|
12
|
+
require('twitter/client/base')
|
13
|
+
require('twitter/client/timeline')
|
14
|
+
require('twitter/client/status')
|
15
|
+
require('twitter/client/friendship')
|
16
|
+
require('twitter/client/messaging')
|
17
|
+
require('twitter/client/user')
|
18
|
+
require('twitter/client/auth')
|
19
|
+
require('twitter/client/favorites')
|
20
|
+
require('twitter/client/blocks')
|
21
|
+
require('twitter/client/account')
|
22
|
+
require('twitter/client/graph')
|
23
|
+
require('twitter/client/profile')
|
24
|
+
require('twitter/client/search')
|
@@ -3,22 +3,22 @@ class Twitter::Client
|
|
3
3
|
:rate_limit_status => '/account/rate_limit_status',
|
4
4
|
}
|
5
5
|
|
6
|
-
|
7
|
-
#
|
8
|
-
# You can find out information about your account status. Currently the only
|
9
|
-
# supported type of account status is the <tt>:rate_limit_status</tt> which
|
10
|
-
# returns a <tt>Twitter::RateLimitStatus</tt> object.
|
6
|
+
# Provides access to the Twitter rate limit status API.
|
11
7
|
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
8
|
+
# You can find out information about your account status. Currently the only
|
9
|
+
# supported type of account status is the <tt>:rate_limit_status</tt> which
|
10
|
+
# returns a <tt>Twitter::RateLimitStatus</tt> object.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# account_status = client.account_info
|
14
|
+
# puts account_status.remaining_hits
|
15
|
+
def account_info(type = :rate_limit_status)
|
16
|
+
connection = create_http_connection
|
17
|
+
connection.start do |connection|
|
18
|
+
response = http_connect do |conn|
|
19
|
+
create_http_get_request(@@ACCOUNT_URIS[type])
|
20
|
+
end
|
21
|
+
bless_models(Twitter::RateLimitStatus.unmarshal(response.body))
|
22
22
|
end
|
23
|
-
|
23
|
+
end
|
24
24
|
end
|
data/lib/twitter/client/base.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
class Twitter::Client
|
2
2
|
alias :old_inspect :inspect
|
3
|
+
|
3
4
|
def inspect
|
4
5
|
s = old_inspect
|
5
6
|
s.gsub!(/@password=".*?"/, '@password="XXXX"')
|
6
7
|
end
|
8
|
+
|
7
9
|
protected
|
8
10
|
attr_accessor :login, :password
|
9
11
|
|
10
12
|
# Returns the response of the HTTP connection.
|
11
|
-
def http_connect(body = nil, require_auth = true, &block)
|
13
|
+
def http_connect(body = nil, require_auth = true, service = :rest, &block)
|
12
14
|
require_block(block_given?)
|
13
|
-
connection = create_http_connection
|
15
|
+
connection = create_http_connection(service)
|
14
16
|
connection.start do |connection|
|
15
17
|
request = yield connection if block_given?
|
16
18
|
request.basic_auth(@login, @password) if require_auth
|
@@ -34,8 +36,10 @@ class Twitter::Client
|
|
34
36
|
@@http_header = nil
|
35
37
|
|
36
38
|
def raise_rest_error(response, uri = nil)
|
39
|
+
map = JSON.parse(response.body)
|
37
40
|
raise Twitter::RESTError.new(:code => response.code,
|
38
41
|
:message => response.message,
|
42
|
+
:error => map["error"],
|
39
43
|
:uri => uri)
|
40
44
|
end
|
41
45
|
|
@@ -45,11 +49,17 @@ class Twitter::Client
|
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
48
|
-
def create_http_connection
|
49
|
-
|
52
|
+
def create_http_connection(service = :rest)
|
53
|
+
case service
|
54
|
+
when :rest
|
55
|
+
protocol, host, port = @@config.protocol, @@config.host, @@config.port
|
56
|
+
when :search
|
57
|
+
protocol, host, port = @@config.search_protocol, @@config.search_host, @@config.search_port
|
58
|
+
end
|
59
|
+
conn = Net::HTTP.new(host, port,
|
50
60
|
@@config.proxy_host, @@config.proxy_port,
|
51
61
|
@@config.proxy_user, @@config.proxy_pass)
|
52
|
-
if
|
62
|
+
if protocol == :ssl
|
53
63
|
conn.use_ssl = true
|
54
64
|
conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
55
65
|
end
|
@@ -84,4 +94,3 @@ class Twitter::Client
|
|
84
94
|
Net::HTTP::Delete.new(path, http_header)
|
85
95
|
end
|
86
96
|
end
|
87
|
-
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class Twitter::Client
|
2
2
|
# Why Twitter.com developers can't correctly document their API, I do not know!
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
@@FAVORITES_URIS = {
|
4
|
+
:add => '/favourings/create',
|
5
|
+
:remove => '/favourings/destroy',
|
6
|
+
}
|
7
7
|
|
8
8
|
# Provides access to the Twitter list favorites API.
|
9
9
|
#
|
@@ -13,41 +13,41 @@ class Twitter::Client
|
|
13
13
|
# To get a previous page you can provide options to this method. For example,
|
14
14
|
# statuses = client.favorites(:page => 2)
|
15
15
|
# The above one-liner will get the second page of favorites for the authenticated user.
|
16
|
-
|
17
|
-
|
16
|
+
def favorites(options = nil)
|
17
|
+
def uri_suffix(opts); opts && opts[:page] ? "?page=#{opts[:page]}" : ""; end
|
18
18
|
uri = '/favorites.json' + uri_suffix(options)
|
19
19
|
response = http_connect {|conn| create_http_get_request(uri) }
|
20
20
|
bless_models(Twitter::Status.unmarshal(response.body))
|
21
|
-
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
23
|
+
# Provides access to the Twitter add/remove favorite API.
|
24
|
+
#
|
25
|
+
# You can add and remove favorite status using this method.
|
26
|
+
#
|
27
|
+
# <tt>action</tt> can be any of the following values:
|
28
|
+
# * <tt>:add</tt> - to add a status to your favorites, you would use this <tt>action</tt> value
|
29
|
+
# * <tt>:remove</tt> - to remove an status from your existing favorites list use this.
|
30
|
+
#
|
31
|
+
# The <tt>value</tt> must be either the status object to add or remove or
|
32
|
+
# the integer unique status ID.
|
33
|
+
#
|
34
|
+
# Examples:
|
35
|
+
# id = 126006103423
|
36
|
+
# client.favorite(:add, id)
|
37
|
+
# client.favorite(:remove, id)
|
38
|
+
# status = Twitter::Status.find(id, client)
|
39
|
+
# client.favorite(:add, status)
|
40
|
+
# client.favorite(:remove, status)
|
41
|
+
def favorite(action, value)
|
42
|
+
raise ArgumentError, "Invalid favorite action provided: #{action}" unless @@FAVORITES_URIS.keys.member?(action)
|
43
|
+
value = value.to_i.to_s unless value.is_a?(String)
|
44
|
+
uri = "#{@@FAVORITES_URIS[action]}/#{value}.json"
|
45
|
+
case action
|
46
|
+
when :add
|
47
|
+
response = http_connect {|conn| create_http_post_request(uri) }
|
48
|
+
when :remove
|
49
|
+
response = http_connect {|conn| create_http_delete_request(uri) }
|
50
|
+
end
|
51
|
+
bless_model(Twitter::Status.unmarshal(response.body))
|
52
|
+
end
|
53
53
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Twitter::Client
|
2
|
+
@@GRAPH_URIS = {
|
3
|
+
:friends => '/friends/ids',
|
4
|
+
:followers => '/followers/ids',
|
5
|
+
}
|
6
|
+
|
7
|
+
# Provides access to the Twitter Social Graphing API.
|
8
|
+
#
|
9
|
+
# You can retrieve the full graph of a user's friends or followers in one method call.
|
10
|
+
#
|
11
|
+
# <tt>action</tt> can be any of the following values:
|
12
|
+
# * <tt>:friends</tt> - retrieves ids of all friends of a given user.
|
13
|
+
# * <tt>:followers</tt> - retrieves ids of all followers of a given user.
|
14
|
+
#
|
15
|
+
# The <tt>value</tt> must be either the user screen name, integer unique user ID or Twitter::User
|
16
|
+
# object representation.
|
17
|
+
#
|
18
|
+
# Examples:
|
19
|
+
# screen_name = 'dictionary'
|
20
|
+
# client.graph(:friends, 'dictionary')
|
21
|
+
# client.graph(:followers, 'dictionary')
|
22
|
+
# id = 1260061
|
23
|
+
# client.graph(:friends, id)
|
24
|
+
# client.graph(:followers, id)
|
25
|
+
# user = Twitter::User.find(id, client)
|
26
|
+
# client.graph(:friends, user)
|
27
|
+
# client.graph(:followers, user)
|
28
|
+
def graph(action, value = nil)
|
29
|
+
raise ArgumentError, "Invalid friend action provided: #{action}" unless @@GRAPH_URIS.keys.member?(action)
|
30
|
+
id = value.to_i unless value.nil? || value.is_a?(String)
|
31
|
+
id ||= value
|
32
|
+
id ||= @login
|
33
|
+
uri = "#{@@GRAPH_URIS[action]}.json"
|
34
|
+
response = http_connect {|conn| create_http_get_request(uri, :id => id) }
|
35
|
+
JSON.parse(response.body)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Twitter::Client
|
2
|
+
@@PROFILE_URIS = {
|
3
|
+
:info => '/account/update_profile',
|
4
|
+
:colors => '/account/update_profile_colors',
|
5
|
+
:device => '/account/update_delivery_device',
|
6
|
+
}
|
7
|
+
|
8
|
+
# Provides access to the Twitter Profile API.
|
9
|
+
#
|
10
|
+
# You can update profile information. You can update the types of profile
|
11
|
+
# information:
|
12
|
+
# * :info (name, email, url, location, description)
|
13
|
+
# * :colors (background_color, text_color, link_color, sidebar_fill_color,
|
14
|
+
# sidebar_border_color)
|
15
|
+
# * :device (set device to either "sms", "im" or "none")
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# user = client.profile(:info, :location => "University Library")
|
19
|
+
# puts user.inspect
|
20
|
+
def profile(action, attributes)
|
21
|
+
connection = create_http_connection
|
22
|
+
connection.start do |connection|
|
23
|
+
response = http_connect(attributes.to_http_str) do |conn|
|
24
|
+
create_http_post_request(@@PROFILE_URIS[action])
|
25
|
+
end
|
26
|
+
bless_models(Twitter::User.unmarshal(response.body))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Twitter::Client
|
2
|
+
|
3
|
+
@@SEARCH_URIS = {
|
4
|
+
:basic => "/search.json",
|
5
|
+
}
|
6
|
+
|
7
|
+
# Provides access to Twitter's Search API.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# # For keyword search
|
11
|
+
# iterator = @twitter.search(:q => "coworking")
|
12
|
+
# while (tweet = iterator.next)
|
13
|
+
# puts tweet.text
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# An <tt>ArgumentError</tt> will be raised if an invalid <tt>action</tt>
|
17
|
+
# is given. Valid actions are:
|
18
|
+
# * +:received+
|
19
|
+
# * +:sent+
|
20
|
+
def search(options = {})
|
21
|
+
# raise ArgumentError, "Invalid messaging action: #{action}"
|
22
|
+
uri = @@SEARCH_URIS[:basic]
|
23
|
+
response = http_connect(nil, false, :search) {|conn| create_http_get_request(uri, options) }
|
24
|
+
json = JSON.parse(response.body)
|
25
|
+
bless_models(Twitter::Status.unmarshal(JSON.dump(json["results"])))
|
26
|
+
end
|
27
|
+
end
|