twitter4r 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,81 @@
1
+ class Twitter::Client
2
+ protected
3
+ attr_accessor :login, :password
4
+
5
+ # Returns the response of the HTTP connection.
6
+ def http_connect(body = nil, require_auth = true, &block)
7
+ require_block(block_given?)
8
+ connection = create_http_connection
9
+ connection.start do |connection|
10
+ request = yield connection if block_given?
11
+ request.basic_auth(@login, @password) if require_auth
12
+ response = connection.request(request, body)
13
+ handle_rest_response(response)
14
+ response
15
+ end
16
+ end
17
+
18
+ # "Blesses" model object with client information
19
+ def bless_model(model)
20
+ model.bless(self) if model
21
+ end
22
+
23
+ def bless_models(list)
24
+ return bless_model(list) if list.respond_to?(:client=)
25
+ list.collect { |model| bless_model(model) } if list.respond_to?(:collect)
26
+ end
27
+
28
+ private
29
+ @@http_header = nil
30
+
31
+ def raise_rest_error(response, uri = nil)
32
+ raise Twitter::RESTError.new(:code => response.code,
33
+ :message => response.message,
34
+ :uri => uri)
35
+ end
36
+
37
+ def handle_rest_response(response, uri = nil)
38
+ unless response.is_a?(Net::HTTPSuccess)
39
+ raise_rest_error(response, uri)
40
+ end
41
+ end
42
+
43
+ def create_http_connection
44
+ conn = Net::HTTP.new(@@config.host, @@config.port,
45
+ @@config.proxy_host, @@config.proxy_port,
46
+ @@config.proxy_user, @@config.proxy_pass)
47
+ if @@config.protocol == :ssl
48
+ conn.use_ssl = true
49
+ conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
50
+ end
51
+ conn
52
+ end
53
+
54
+ def http_header
55
+ # can cache this in class variable since all "variables" used to
56
+ # create the contents of the HTTP header are determined by other
57
+ # class variables that are not designed to change after instantiation.
58
+ @@http_header ||= {
59
+ 'User-Agent' => "Twitter4R v#{Twitter::Version.to_version} [#{@@config.user_agent}]",
60
+ 'Accept' => 'text/x-json',
61
+ 'X-Twitter-Client' => @@config.application_name,
62
+ 'X-Twitter-Client-Version' => @@config.application_version,
63
+ 'X-Twitter-Client-URL' => @@config.application_url,
64
+ }
65
+ @@http_header
66
+ end
67
+
68
+ def create_http_get_request(uri, params = {})
69
+ path = (params.size > 0) ? "#{uri}?#{params.to_http_str}" : uri
70
+ Net::HTTP::Get.new(path, http_header)
71
+ end
72
+
73
+ def create_http_post_request(uri)
74
+ Net::HTTP::Post.new(uri, http_header)
75
+ end
76
+
77
+ def create_http_delete_request(uri, params = {})
78
+ path = (params.size > 0) ? "#{uri}?#{params.to_http_str}" : uri
79
+ Net::HTTP::Delete.new(path, http_header)
80
+ end
81
+ end
@@ -0,0 +1,34 @@
1
+ class Twitter::Client
2
+ @@FRIENDSHIP_URIS = {
3
+ :add => 'http://twitter.com/friendships/create',
4
+ :remove => 'http://twitter.com/friendships/destroy',
5
+ }
6
+
7
+ # Provides access to the Twitter Friendship API.
8
+ #
9
+ # You can add and remove friends using this method.
10
+ #
11
+ # <tt>action</tt> can be any of the following values:
12
+ # * <tt>:add</tt> - to add a friend, you would use this <tt>action</tt> value
13
+ # * <tt>:remove</tt> - to remove an existing friend from your friends list use this.
14
+ #
15
+ # The <tt>value</tt> must be either the user to befriend or defriend's
16
+ # screen name, integer unique user ID or Twitter::User object representation.
17
+ #
18
+ # Examples:
19
+ # screen_name = 'dictionary'
20
+ # client.friend(:add, 'dictionary')
21
+ # client.friend(:remove, 'dictionary')
22
+ # id = 1260061
23
+ # client.friend(:add, id)
24
+ # client.friend(:remove, id)
25
+ # user = Twitter::User.find(id, client)
26
+ # client.friend(:add, user)
27
+ # client.friend(:remove, user)
28
+ def friend(action, value)
29
+ value = value.to_i unless value.is_a?(String)
30
+ uri = "#{@@FRIENDSHIP_URIS[action]}/#{value}.json"
31
+ response = http_connect {|conn| create_http_get_request(uri) }
32
+ bless_model(Twitter::User.unmarshal(response.body))
33
+ end
34
+ end
@@ -0,0 +1,61 @@
1
+ class Twitter::Client
2
+
3
+ @@MESSAGING_URIS = {
4
+ :received => 'http://twitter.com/direct_messages.json',
5
+ :sent => 'http://twitter.com/direct_messages/sent.json',
6
+ :post => 'http://twitter.com/direct_messages/new.json',
7
+ :delete => 'http://twitter.com/direct_messages/destroy',
8
+ }
9
+
10
+ # Provides access to Twitter's Messaging API for received and
11
+ # sent direct messages.
12
+ #
13
+ #
14
+ def messages(action)
15
+ uri = @@MESSAGING_URIS[action]
16
+ response = http_connect {|conn| create_http_get_request(uri) }
17
+ bless_models(Twitter::Message.unmarshal(response.body))
18
+ end
19
+
20
+ # Provides access to Twitter's Messaging API for sending and deleting
21
+ # direct messages to other users.
22
+ #
23
+ # <tt>action</tt> can be:
24
+ # * <tt>:post</tt> - to send a new direct message, <tt>value</tt>, to <tt>user</tt> given.
25
+ # * <tt>:delete</tt> - to delete direct message with message ID <tt>value</tt>.
26
+ #
27
+ # <tt>value</tt> should be:
28
+ # * <tt>String</tt> when action is <tt>:post</tt>. Will be the message text sent to given <tt>user</tt>.
29
+ # * <tt>Integer</tt> or <tt>Twitter::Message</tt> object when action is <tt>:delete</tt>. Will refer to the unique message ID to delete. When passing in an instance of <tt>Twitter::Message</tt> that Status will be
30
+ #
31
+ # <tt>user</tt> should be:
32
+ # * <tt>Twitter::User</tt> or <tt>Integer</tt> object when <tt>action</tt> is <tt>:post</tt>.
33
+ # * totally ignore when <tt>action</tt> is <tt>:delete</tt>. It has no purpose in this use case scenario.
34
+ #
35
+ # Examples:
36
+ # The example below sends the message text 'Are you coming over at 6pm for the BBQ tonight?' to user with screen name 'myfriendslogin'...
37
+ # @twitter.message(:post, 'Are you coming over at 6pm for the BBQ tonight?', 'myfriendslogin')
38
+ # The example below sends the same message text as above to user with unique integer ID of 1234567890...
39
+ # the example below sends the same message text as above to user represented by <tt>user</tt> object instance of <tt>Twitter::User</tt>...
40
+ # @twitter.message(:post, 'Are you coming over at 6pm for the BBQ tonight?', user)
41
+ # message = @twitter.message(:post, 'Are you coming over at 6pm for the BBQ tonight?', 1234567890)
42
+ # the example below delete's the message send directly above to user with unique ID 1234567890...
43
+ # @twitter.message(:delete, message)
44
+ # Or the following can also be done...
45
+ # @twitter.message(:delete, message.id)
46
+ #
47
+ # In both scenarios (<tt>action</tt> is <tt>:post</tt> or
48
+ # <tt>:delete</tt>) a blessed <tt>Twitter::Message</tt> object is
49
+ # returned that represents the newly posted or newly deleted message.
50
+ def message(action, value, user = nil)
51
+ uri = @@MESSAGING_URIS[action]
52
+ case action
53
+ when :post
54
+ response = http_connect({:text => value, :user => user.to_i}.to_http_str) {|conn| create_http_post_request(uri) }
55
+ when :delete
56
+ response = http_connect {|conn| create_http_delete_request(uri, :id => value.to_i) }
57
+ end
58
+ message = Twitter::Message.unmarshal(response.body)
59
+ bless_model(message)
60
+ end
61
+ end
@@ -0,0 +1,39 @@
1
+ class Twitter::Client
2
+ @@STATUS_URIS = {
3
+ :get => '/statuses/show.json',
4
+ :post => '/statuses/update.json',
5
+ :delete => '/statuses/destroy.json',
6
+ }
7
+
8
+ # Provides access to individual statuses via Twitter's Status APIs
9
+ #
10
+ # <tt>action</tt> can be of the following values:
11
+ # * <tt>:get</tt> to retrieve status content. Assumes <tt>value</tt> given responds to :to_i message in meaningful way to yield intended status id.
12
+ # * <tt>:post</tt> to publish a new status
13
+ # * <tt>:delete</tt> to remove an existing status. Assumes <tt>value</tt> given responds to :to_i message in meaningful way to yield intended status id.
14
+ #
15
+ # <tt>value</tt> should be set to:
16
+ # * the status identifier for <tt>:get</tt> case
17
+ # * the status text message for <tt>:post</tt> case
18
+ # * none necessary for <tt>:delete</tt> case
19
+ #
20
+ # Examples:
21
+ # twitter.status(:get, 107786772)
22
+ # twitter.status(:post, "New Ruby open source project Twitter4R version 0.2.0 released.")
23
+ # twitter.status(:delete, 107790712)
24
+ #
25
+ def status(action, value)
26
+ return nil unless value
27
+ uri = @@STATUS_URIS[action]
28
+ response = nil
29
+ case action
30
+ when :get
31
+ response = http_connect {|conn| create_http_get_request(uri, :id => value.to_i) }
32
+ when :post
33
+ response = http_connect({:status => value}.to_http_str) {|conn| create_http_post_request(uri) }
34
+ when :delete
35
+ response = http_connect {|conn| create_http_delete_request(uri, :id => value.to_i) }
36
+ end
37
+ bless_model(Twitter::Status.unmarshal(response.body))
38
+ end
39
+ end
@@ -0,0 +1,62 @@
1
+ class Twitter::Client
2
+ @@TIMELINE_URIS = {
3
+ :public => '/statuses/public_timeline.json',
4
+ :friends => '/statuses/friends_timeline.json',
5
+ :friend => '/statuses/friends_timeline.json',
6
+ :user => '/statuses/user_timeline.json',
7
+ :me => '/statuses/user_timeline.json',
8
+ }
9
+
10
+ # Provides access to Twitter's Timeline APIs
11
+ #
12
+ # Returns timeline for given <tt>type</tt>.
13
+ #
14
+ # <tt>type</tt> can take the following values:
15
+ # * <tt>public</tt>
16
+ # * <tt>friends</tt> or <tt>friend</tt>
17
+ # * <tt>user</tt> or <tt>me</tt>
18
+ #
19
+ # <tt>:id</tt> is on key applicable to be defined in </tt>options</tt>:
20
+ # * the id or screen name (aka login) for :friends
21
+ # * the id or screen name (aka login) for :user
22
+ # * meaningless for the :me case, since <tt>twitter.timeline_for(:user, 'mylogin')</tt> and <tt>twitter.timeline_for(:me)</tt> are the same assuming 'mylogin' is the authenticated user's screen name (aka login).
23
+ #
24
+ # Examples:
25
+ # # returns the public statuses since status with id of 6543210
26
+ # twitter.timeline_for(:public, id => 6543210)
27
+ # # returns the statuses for friend with user id 43210
28
+ # twitter.timeline_for(:friend, :id => 43210)
29
+ # # returns the statuses for friend with screen name (aka login) of 'otherlogin'
30
+ # twitter.timeline_for(:friend, :id => 'otherlogin')
31
+ # # returns the statuses for user with screen name (aka login) of 'otherlogin'
32
+ # twitter.timeline_for(:user, :id => 'otherlogin')
33
+ #
34
+ # <tt>options</tt> can also include the following keys:
35
+ # * <tt>:id</tt> is the user ID, screen name of Twitter::User representation of a <tt>Twitter</tt> user.
36
+ # * <tt>:since</tt> is a Time object specifying the date-time from which to return results for. Applicable for the :friend, :friends, :user and :me cases.
37
+ # * <tt>:count</tt> specifies the number of statuses to retrieve. Only applicable for the :user case.
38
+ # * <tt>since_id</tt> is the status id of the public timeline from which to retrieve statuses for <tt>:public</tt>. Only applicable for the :public case.
39
+ #
40
+ # You can also pass this method a block, which will iterate through the results
41
+ # of the requested timeline and apply the block logic for each status returned.
42
+ #
43
+ # Example:
44
+ # twitter.timeline_for(:public) do |status|
45
+ # puts status.user.screen_name, status.text
46
+ # end
47
+ #
48
+ # twitter.timeline_for(:friend, :id => 'myfriend', :since => 30.minutes.ago) do |status|
49
+ # puts status.user.screen_name, status.text
50
+ # end
51
+ #
52
+ # timeline = twitter.timeline_for(:me) do |status|
53
+ # puts status.text
54
+ # end
55
+ def timeline_for(type, options = {}, &block)
56
+ uri = @@TIMELINE_URIS[type]
57
+ response = http_connect {|conn| create_http_get_request(uri, options) }
58
+ timeline = Twitter::Status.unmarshal(response.body)
59
+ timeline.each {|status| bless_model(status); yield status if block_given? }
60
+ timeline
61
+ end
62
+ end
@@ -0,0 +1,33 @@
1
+ class Twitter::Client
2
+ @@USER_URIS = {
3
+ :info => 'http://twitter.com/users/show',
4
+ :friends => 'http://twitter.com/statuses/friends.json',
5
+ :followers => 'http://twitter.com/statuses/followers.json',
6
+ }
7
+
8
+ # Provides access to Twitter's User APIs
9
+ #
10
+ # Returns user instance for the <tt>id</tt> given. The <tt>id</tt>
11
+ # can either refer to the numeric user ID or the user's screen name.
12
+ #
13
+ # For example,
14
+ # @twitter.user(234943) #=> Twitter::User object instance for user with numeric id of 234943
15
+ # @twitter.user('mylogin') #=> Twitter::User object instance for user with screen name 'mylogin'
16
+ def user(id, action = :info)
17
+ response = http_connect {|conn| create_http_get_request(@@USER_URIS[action], :id => id) }
18
+ bless_models(Twitter::User.unmarshal(response.body))
19
+ end
20
+
21
+ # Syntactic sugar for queries relating to authenticated user in Twitter's User API
22
+ #
23
+ # When <tt>action</tt> is:
24
+ # * <tt>:info</tt> - Returns user instance for the authenticated user.
25
+ # * <tt>:friends</tt> - Returns Array of users that are authenticated user's friends
26
+ # * <tt>:followers</tt> - Returns Array of users that are authenticated user's followers
27
+ def my(action)
28
+ response = http_connect {|conn| create_http_get_request(@@USER_URIS[action], :id => @login) }
29
+ json = response.body
30
+ users = Twitter::User.unmarshal(json)
31
+ bless_models(users)
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ # client.rb contains the classes, methods and extends <tt>Twitter4R</tt>
2
+ # features to define client calls to the Twitter REST API.
3
+ #
4
+ # See:
5
+ # * <tt>Twitter::Client</tt>
6
+
7
+ # Used to query or post to the Twitter REST API to simplify code.
8
+ class Twitter::Client
9
+ include Twitter::ClassUtilMixin
10
+ end
11
+
12
+ require('twitter/client/base.rb')
13
+ require('twitter/client/timeline.rb')
14
+ require('twitter/client/status.rb')
15
+ require('twitter/client/friendship.rb')
16
+ require('twitter/client/messaging.rb')
17
+ require('twitter/client/user.rb')
18
+
@@ -0,0 +1,69 @@
1
+ # config.rb contains classes, methods and extends existing Twitter4R classes
2
+ # to provide easy configuration facilities.
3
+
4
+ module Twitter
5
+ # Represents global configuration for Twitter::Client.
6
+ # Can override the following configuration options:
7
+ # * <tt>protocol</tt> - <tt>:http</tt>, <tt>:https</tt> or <tt>:ssl</tt> supported. <tt>:ssl</tt> is an alias for <tt>:https</tt>. Defaults to <tt>:ssl</tt>
8
+ # * <tt>host</tt> - hostname to connect to for the Twitter service. Defaults to <tt>'twitter.com'</tt>.
9
+ # * <tt>port</tt> - port to connect to for the Twitter service. Defaults to <tt>443</tt>.
10
+ # * <tt>proxy_host</tt> - proxy host to use. Defaults to nil.
11
+ # * <tt>proxy_port</tt> - proxy host to use. Defaults to nil.
12
+ # * <tt>proxy_user</tt> - proxy username to use. Defaults to nil.
13
+ # * <tt>proxy_pass</tt> - proxy password to use. Defaults to nil.
14
+ # * <tt>user_agent</tt> - user agent string to use for each request of the HTTP header.
15
+ # * <tt>application_name</tt> - name of your client application. Defaults to 'Twitter4R'
16
+ # * <tt>application_version</tt> - version of your client application. Defaults to current <tt>Twitter::Version.to_version</tt>.
17
+ # * <tt>application_url</tt> - URL of your client application. Defaults to http://twitter4r.rubyforge.org.
18
+
19
+ class Config
20
+ include ClassUtilMixin
21
+ @@ATTRIBUTES = [
22
+ :protocol,
23
+ :host,
24
+ :port,
25
+ :proxy_host,
26
+ :proxy_port,
27
+ :proxy_user,
28
+ :proxy_pass,
29
+ :user_agent,
30
+ :application_name,
31
+ :application_version,
32
+ :application_url,
33
+ ]
34
+ attr_accessor *@@ATTRIBUTES
35
+
36
+ # Override of Object#eql? to ensure RSpec specifications run
37
+ # correctly. Also done to follow Ruby best practices.
38
+ def eql?(other)
39
+ return true if self == other
40
+ @@ATTRIBUTES.each do |att|
41
+ return false unless self.send(att).eql?(other.send(att))
42
+ end
43
+ true
44
+ end
45
+ end
46
+
47
+ class Client
48
+ @@defaults = { :host => 'twitter.com',
49
+ :port => 443,
50
+ :protocol => :ssl,
51
+ :proxy_host => nil,
52
+ :proxy_port => nil,
53
+ :user_agent => "default",
54
+ :application_name => 'Twitter4R',
55
+ :application_version => Twitter::Version.to_version,
56
+ :application_url => 'http://twitter4r.rubyforge.org',
57
+ }
58
+ @@config = Twitter::Config.new(@@defaults)
59
+
60
+ # Twitter::Client class methods
61
+ class << self
62
+ # Yields to given <tt>block</tt> to configure the Twitter4R API.
63
+ def configure(&block)
64
+ raise ArgumentError, "Block must be provided to configure" unless block_given?
65
+ yield @@config
66
+ end # configure
67
+ end # class << self
68
+ end # Client class
69
+ end # Twitter module
@@ -0,0 +1,28 @@
1
+ # Contains hooks for the twitter console
2
+
3
+ module Twitter
4
+ class Client
5
+ class << self
6
+ # Helper method mostly for irb shell prototyping.
7
+ #
8
+ # Reads in login/password Twitter credentials from YAML file
9
+ # found at the location given by <tt>config_file</tt> that has
10
+ # the following format:
11
+ # envname:
12
+ # login: mytwitterlogin
13
+ # password: mytwitterpassword
14
+ #
15
+ # Where <tt>envname</tt> is the name of the environment like 'test',
16
+ # 'dev' or 'prod'. The <tt>env</tt> argument defaults to 'test'.
17
+ #
18
+ # To use this in the shell you would do something like the following
19
+ # examples:
20
+ # twitter = Twitter::Client.from_config('config/twitter.yml', 'dev')
21
+ # twitter = Twitter::Client.from_config('config/twitter.yml')
22
+ def from_config(config_file, env = 'test')
23
+ yaml_hash = YAML.load(File.read(config_file))
24
+ self.new yaml_hash[env]
25
+ end
26
+ end # class << self
27
+ end
28
+ end