twitter4r 0.1.1 → 0.2.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.
@@ -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