dambalah-twitter4r 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGES +124 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +32 -0
  4. data/TODO +9 -0
  5. data/lib/twitter.rb +31 -0
  6. data/lib/twitter/client.rb +21 -0
  7. data/lib/twitter/client/account.rb +24 -0
  8. data/lib/twitter/client/auth.rb +27 -0
  9. data/lib/twitter/client/base.rb +87 -0
  10. data/lib/twitter/client/blocks.rb +35 -0
  11. data/lib/twitter/client/favorites.rb +53 -0
  12. data/lib/twitter/client/friendship.rb +47 -0
  13. data/lib/twitter/client/messaging.rb +79 -0
  14. data/lib/twitter/client/status.rb +46 -0
  15. data/lib/twitter/client/timeline.rb +72 -0
  16. data/lib/twitter/client/user.rb +87 -0
  17. data/lib/twitter/config.rb +71 -0
  18. data/lib/twitter/console.rb +28 -0
  19. data/lib/twitter/core.rb +137 -0
  20. data/lib/twitter/ext.rb +2 -0
  21. data/lib/twitter/ext/stdlib.rb +51 -0
  22. data/lib/twitter/extras.rb +39 -0
  23. data/lib/twitter/meta.rb +56 -0
  24. data/lib/twitter/model.rb +344 -0
  25. data/lib/twitter/rails.rb +92 -0
  26. data/lib/twitter/version.rb +19 -0
  27. data/spec/twitter/client/auth_spec.rb +34 -0
  28. data/spec/twitter/client/base_spec.rb +242 -0
  29. data/spec/twitter/client/blocks_spec.rb +76 -0
  30. data/spec/twitter/client/favorites_spec.rb +183 -0
  31. data/spec/twitter/client/friendship_spec.rb +76 -0
  32. data/spec/twitter/client/messaging_spec.rb +135 -0
  33. data/spec/twitter/client/status_spec.rb +92 -0
  34. data/spec/twitter/client/timeline_spec.rb +79 -0
  35. data/spec/twitter/client/user_spec.rb +203 -0
  36. data/spec/twitter/client_spec.rb +2 -0
  37. data/spec/twitter/config_spec.rb +86 -0
  38. data/spec/twitter/console_spec.rb +15 -0
  39. data/spec/twitter/core_spec.rb +127 -0
  40. data/spec/twitter/ext/stdlib_spec.rb +42 -0
  41. data/spec/twitter/extras_spec.rb +46 -0
  42. data/spec/twitter/meta_spec.rb +90 -0
  43. data/spec/twitter/model_spec.rb +464 -0
  44. data/spec/twitter/rails_spec.rb +110 -0
  45. data/spec/twitter/version_spec.rb +19 -0
  46. metadata +109 -0
@@ -0,0 +1,47 @@
1
+ class Twitter::Client
2
+ @@FRIENDSHIP_URIS = {
3
+ :add => '/friendships/create',
4
+ :remove => '/friendships/destroy',
5
+ :exists => '/friendships/exists'
6
+ }
7
+
8
+ # Provides access to the Twitter Friendship API.
9
+ #
10
+ # You can add and remove friends using this method.
11
+ #
12
+ # <tt>action</tt> can be any of the following values:
13
+ # * <tt>:add</tt> - to add a friend, you would use this <tt>action</tt> value
14
+ # * <tt>:remove</tt> - to remove an existing friend from your friends list use this.
15
+ #
16
+ # The <tt>value</tt> must be either the user to befriend or defriend's
17
+ # screen name, integer unique user ID or Twitter::User object representation.
18
+ #
19
+ # Examples:
20
+ # screen_name = 'dictionary'
21
+ # client.friend(:add, 'dictionary')
22
+ # client.friend(:remove, 'dictionary')
23
+ # id = 1260061
24
+ # client.friend(:add, id)
25
+ # client.friend(:remove, id)
26
+ # user = Twitter::User.find(id, client)
27
+ # client.friend(:add, user)
28
+ # client.friend(:remove, user)
29
+ def friend(action, value)
30
+ raise ArgumentError, "Invalid friend action provided: #{action}" unless @@FRIENDSHIP_URIS.keys.member?(action)
31
+ value = value.to_i unless value.is_a?(String)
32
+ uri = "#{@@FRIENDSHIP_URIS[action]}/#{value}.json"
33
+ response = http_connect {|conn| create_http_post_request(uri) }
34
+ bless_model(Twitter::User.unmarshal(response.body))
35
+ end
36
+
37
+ # Tests if a friendship exists between two users.
38
+ #
39
+ # Examples:
40
+ # client.are_friends?(user1,user2) #=> returns true if user1 follows user2
41
+ # #=> returns false if user1 does not follower user2
42
+ def are_friends?(user1,user2)
43
+ uri = "#{@@FRIENDSHIP_URIS[:exists]}.json?user_a=#{user1}&user_b=#{user2}"
44
+ response = http_connect {|conn| create_http_post_request(uri) }
45
+ response.body.rindex('true') ? true : false
46
+ end
47
+ end
@@ -0,0 +1,79 @@
1
+ class Twitter::Client
2
+
3
+ @@MESSAGING_URIS = {
4
+ :received => '/direct_messages.json',
5
+ :sent => '/direct_messages/sent.json',
6
+ :post => '/direct_messages/new.json',
7
+ :delete => '/direct_messages/destroy',
8
+ }
9
+
10
+ # Provides access to Twitter's Messaging API for received and
11
+ # sent direct messages.
12
+ #
13
+ # Example:
14
+ # received_messages = @twitter.messages(:received)
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 messages(action, options = {})
21
+ raise ArgumentError, "Invalid messaging action: #{action}" unless [:sent, :received].member?(action)
22
+ uri = @@MESSAGING_URIS[action]
23
+ response = http_connect {|conn| create_http_get_request(uri, options) }
24
+ bless_models(Twitter::Message.unmarshal(response.body))
25
+ end
26
+
27
+ # Provides access to Twitter's Messaging API for sending and deleting
28
+ # direct messages to other users.
29
+ #
30
+ # <tt>action</tt> can be:
31
+ # * <tt>:post</tt> - to send a new direct message, <tt>value</tt>, to <tt>user</tt> given.
32
+ # * <tt>:delete</tt> - to delete direct message with message ID <tt>value</tt>.
33
+ #
34
+ # <tt>value</tt> should be:
35
+ # * <tt>String</tt> when action is <tt>:post</tt>. Will be the message text sent to given <tt>user</tt>.
36
+ # * <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
37
+ #
38
+ # <tt>user</tt> should be:
39
+ # * <tt>Twitter::User</tt>, <tt>Integer</tt> or <tt>String</tt> object when <tt>action</tt> is <tt>:post</tt>. The <tt>Integer</tt> must be the unique ID of the Twitter user you wish to send the direct message to and any <tt>String</tt>s passed in must be the screen name of the user you wish to send the direct message to.
40
+ # * totally ignore when <tt>action</tt> is <tt>:delete</tt>. It has no purpose in this use case scenario.
41
+ #
42
+ # Examples:
43
+ # The example below sends the message text 'Are you coming over at 6pm for the BBQ tonight?' to user with screen name 'myfriendslogin'...
44
+ # @twitter.message(:post, 'Are you coming over at 6pm for the BBQ tonight?', 'myfriendslogin')
45
+ # The example below sends the same message text as above to user with unique integer ID of 1234567890...
46
+ # the example below sends the same message text as above to user represented by <tt>user</tt> object instance of <tt>Twitter::User</tt>...
47
+ # @twitter.message(:post, 'Are you coming over at 6pm for the BBQ tonight?', user)
48
+ # message = @twitter.message(:post, 'Are you coming over at 6pm for the BBQ tonight?', 1234567890)
49
+ # the example below delete's the message send directly above to user with unique ID 1234567890...
50
+ # @twitter.message(:delete, message)
51
+ # Or the following can also be done...
52
+ # @twitter.message(:delete, message.id)
53
+ #
54
+ # In both scenarios (<tt>action</tt> is <tt>:post</tt> or
55
+ # <tt>:delete</tt>) a blessed <tt>Twitter::Message</tt> object is
56
+ # returned that represents the newly posted or newly deleted message.
57
+ #
58
+ # An <tt>ArgumentError</tt> will be raised if an invalid <tt>action</tt>
59
+ # is given. Valid actions are:
60
+ # * +:post+
61
+ # * +:delete+
62
+ #
63
+ # An <tt>ArgumentError</tt> is also raised when no user argument is
64
+ # supplied when <tt>action</tt> is +:post+.
65
+ def message(action, value, user = nil)
66
+ raise ArgumentError, "Invalid messaging action: #{action}" unless [:post, :delete].member?(action)
67
+ raise ArgumentError, "User argument must be supplied for :post case" if action.eql?(:post) and user.nil?
68
+ uri = @@MESSAGING_URIS[action]
69
+ user = user.to_i if user and user.is_a?(Twitter::User)
70
+ case action
71
+ when :post
72
+ response = http_connect({:text => value, :user => user, :source => @@config.source}.to_http_str) {|conn| create_http_post_request(uri) }
73
+ when :delete
74
+ response = http_connect {|conn| create_http_delete_request(uri, :id => value.to_i) }
75
+ end
76
+ message = Twitter::Message.unmarshal(response.body)
77
+ bless_model(message)
78
+ end
79
+ end
@@ -0,0 +1,46 @@
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
+ # An <tt>ArgumentError</tt> will be raised if an invalid <tt>action</tt>
26
+ # is given. Valid actions are:
27
+ # * +:get+
28
+ # * +:post+
29
+ # * +:delete+
30
+ def status(action, value = nil)
31
+ return self.timeline_for(action, value || {}) if :replies == action
32
+ raise ArgumentError, "Invalid status action: #{action}" unless @@STATUS_URIS.keys.member?(action)
33
+ return nil unless value
34
+ uri = @@STATUS_URIS[action]
35
+ response = nil
36
+ case action
37
+ when :get
38
+ response = http_connect {|conn| create_http_get_request(uri, :id => value.to_i) }
39
+ when :post
40
+ response = http_connect({:status => value, :source => @@config.source}.to_http_str) {|conn| create_http_post_request(uri) }
41
+ when :delete
42
+ response = http_connect {|conn| create_http_delete_request(uri, :id => value.to_i) }
43
+ end
44
+ bless_model(Twitter::Status.unmarshal(response.body))
45
+ end
46
+ end
@@ -0,0 +1,72 @@
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
+ :replies => '/statuses/replies.json',
9
+ }
10
+
11
+ # Provides access to Twitter's Timeline APIs
12
+ #
13
+ # Returns timeline for given <tt>type</tt>.
14
+ #
15
+ # <tt>type</tt> can take the following values:
16
+ # * <tt>public</tt>
17
+ # * <tt>friends</tt> or <tt>friend</tt>
18
+ # * <tt>user</tt> or <tt>me</tt>
19
+ #
20
+ # <tt>:id</tt> is on key applicable to be defined in </tt>options</tt>:
21
+ # * the id or screen name (aka login) for :friends
22
+ # * the id or screen name (aka login) for :user
23
+ # * 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).
24
+ #
25
+ # Examples:
26
+ # # returns the public statuses since status with id of 6543210
27
+ # twitter.timeline_for(:public, id => 6543210)
28
+ # # returns the statuses for friend with user id 43210
29
+ # twitter.timeline_for(:friend, :id => 43210)
30
+ # # returns the statuses for friend with screen name (aka login) of 'otherlogin'
31
+ # twitter.timeline_for(:friend, :id => 'otherlogin')
32
+ # # returns the statuses for user with screen name (aka login) of 'otherlogin'
33
+ # twitter.timeline_for(:user, :id => 'otherlogin')
34
+ #
35
+ # <tt>options</tt> can also include the following keys:
36
+ # * <tt>:id</tt> is the user ID, screen name of Twitter::User representation of a <tt>Twitter</tt> user.
37
+ # * <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.
38
+ # * <tt>:count</tt> specifies the number of statuses to retrieve. Only applicable for the :user case.
39
+ # * <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.
40
+ #
41
+ # You can also pass this method a block, which will iterate through the results
42
+ # of the requested timeline and apply the block logic for each status returned.
43
+ #
44
+ # Example:
45
+ # twitter.timeline_for(:public) do |status|
46
+ # puts status.user.screen_name, status.text
47
+ # end
48
+ #
49
+ # twitter.timeline_for(:friend, :id => 'myfriend', :since => 30.minutes.ago) do |status|
50
+ # puts status.user.screen_name, status.text
51
+ # end
52
+ #
53
+ # timeline = twitter.timeline_for(:me) do |status|
54
+ # puts status.text
55
+ # end
56
+ #
57
+ # An <tt>ArgumentError</tt> will be raised if an invalid <tt>type</tt>
58
+ # is given. Valid types are:
59
+ # * +:public+
60
+ # * +:friends+
61
+ # * +:friend+
62
+ # * +:user+
63
+ # * +:me+
64
+ def timeline_for(type, options = {}, &block)
65
+ raise ArgumentError, "Invalid timeline type: #{type}" unless @@TIMELINE_URIS.keys.member?(type)
66
+ uri = @@TIMELINE_URIS[type]
67
+ response = http_connect {|conn| create_http_get_request(uri, options) }
68
+ timeline = Twitter::Status.unmarshal(response.body)
69
+ timeline.each {|status| bless_model(status); yield status if block_given? }
70
+ timeline
71
+ end
72
+ end
@@ -0,0 +1,87 @@
1
+ class Twitter::Client
2
+ @@USER_URIS = {
3
+ :info => '/users/show',
4
+ :friends => '/statuses/friends.json',
5
+ :followers => '/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
+ #
17
+ # Where <tt>options</tt> is a +Hash+ of options that can include:
18
+ # * <tt>:page</tt> - optional. Retrieves the next set of friends. There are 100 friends per page. Default: 1.
19
+ # * <tt>:lite</tt> - optional. Prevents the inline inclusion of current status. Default: false.
20
+ # * <tt>:since</tt> - optional. Only relevant for <tt>:friends</tt> action. Narrows the results to just those friends added after the date given as value of this option. Must be HTTP-formatted date.
21
+ #
22
+ # An <tt>ArgumentError</tt> will be raised if an invalid <tt>action</tt>
23
+ # is given. Valid actions are:
24
+ # * +:info+
25
+ # * +:friends+
26
+ #
27
+ # +Note:+ You should not use this method to attempt to retrieve the
28
+ # authenticated user's followers. Please use any of the following
29
+ # ways of accessing this list:
30
+ # followers = client.my(:followers)
31
+ # OR
32
+ # followers = client.my(:info).followers
33
+ def user(id, action = :info, options = {})
34
+ raise ArgumentError, "Invalid user action: #{action}" unless @@USER_URIS.keys.member?(action)
35
+ id = id.to_i if id.is_a?(Twitter::User)
36
+ params = options.merge(:id => id)
37
+ response = http_connect {|conn| create_http_get_request(@@USER_URIS[action], params) }
38
+ bless_models(Twitter::User.unmarshal(response.body))
39
+ end
40
+
41
+ # Syntactic sugar for queries relating to authenticated user in Twitter's User API
42
+ #
43
+ # Where <tt>action</tt> is one of the following:
44
+ # * <tt>:info</tt> - Returns user instance for the authenticated user.
45
+ # * <tt>:friends</tt> - Returns Array of users that are authenticated user's friends
46
+ # * <tt>:followers</tt> - Returns Array of users that are authenticated user's followers
47
+ #
48
+ # Where <tt>options</tt> is a +Hash+ of options that can include:
49
+ # * <tt>:page</tt> - optional. Retrieves the next set of friends. There are 100 friends per page. Default: 1.
50
+ # * <tt>:lite</tt> - optional. Prevents the inline inclusion of current status. Default: false.
51
+ # * <tt>:since</tt> - optional. Only relevant for <tt>:friends</tt> action. Narrows the results to just those friends added after the date given as value of this option. Must be HTTP-formatted date.
52
+ #
53
+ # An <tt>ArgumentError</tt> will be raised if an invalid <tt>action</tt>
54
+ # is given. Valid actions are:
55
+ # * +:info+
56
+ # * +:friends+
57
+ # * +:followers+
58
+ def my(action, options = {})
59
+ raise ArgumentError, "Invalid user action: #{action}" unless @@USER_URIS.keys.member?(action)
60
+ params = options.merge(:id => @login)
61
+ response = http_connect {|conn| create_http_get_request(@@USER_URIS[action], params) }
62
+ users = Twitter::User.unmarshal(response.body)
63
+ bless_models(users)
64
+ end
65
+
66
+ # Returns all followers for an authenticated user.
67
+ #
68
+ # This method makes multiple call to the Twitter API to get all users.
69
+ # By default, the Twitter API only returns 100 followers at a time.
70
+ # This method was written for the case where you need all followers,no matter how many there are.
71
+ #
72
+ def all_followers
73
+ has_followers_remaining = true
74
+ followers_array = []
75
+ page = 1
76
+ while has_followers_remaining
77
+ tmp_followers = self.my(:followers, :page => page)
78
+ followers_array << tmp_followers
79
+ #puts "Page: #{page} , followers: #{tmp_followers.size}"
80
+ page += page
81
+ has_followers_remaining = false unless tmp_followers.size > 98
82
+ sleep 1
83
+ end
84
+ followers_array.flatten!
85
+ end
86
+
87
+ end
@@ -0,0 +1,71 @@
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
+ # * <tt>source</tt> - the source id given to you by Twitter to identify your application in their web interface. Note: you must contact Twitter.com developer directly so they can configure their servers appropriately.
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
+ :source,
34
+ ]
35
+ attr_accessor *@@ATTRIBUTES
36
+
37
+ # Override of Object#eql? to ensure RSpec specifications run
38
+ # correctly. Also done to follow Ruby best practices.
39
+ def eql?(other)
40
+ return true if self == other
41
+ @@ATTRIBUTES.each do |att|
42
+ return false unless self.send(att).eql?(other.send(att))
43
+ end
44
+ true
45
+ end
46
+ end
47
+
48
+ class Client
49
+ @@defaults = { :host => 'twitter.com',
50
+ :port => 443,
51
+ :protocol => :ssl,
52
+ :proxy_host => nil,
53
+ :proxy_port => nil,
54
+ :user_agent => "default",
55
+ :application_name => 'Twitter4R',
56
+ :application_version => Twitter::Version.to_version,
57
+ :application_url => 'http://twitter4r.rubyforge.org',
58
+ :source => 'sharememe',
59
+ }
60
+ @@config = Twitter::Config.new(@@defaults)
61
+
62
+ # Twitter::Client class methods
63
+ class << self
64
+ # Yields to given <tt>block</tt> to configure the Twitter4R API.
65
+ def configure(&block)
66
+ raise ArgumentError, "Block must be provided to configure" unless block_given?
67
+ yield @@config
68
+ end # configure
69
+ end # class << self
70
+ end # Client class
71
+ 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
@@ -0,0 +1,137 @@
1
+ # The Twitter4R API provides a nicer Ruby object API to work with
2
+ # instead of coding around the REST API.
3
+
4
+ # Module to encapsule the Twitter4R API.
5
+ module Twitter
6
+ # Mixin module for classes that need to have a constructor similar to
7
+ # Rails' models, where a <tt>Hash</tt> is provided to set attributes
8
+ # appropriately.
9
+ #
10
+ # To define a class that uses this mixin, use the following code:
11
+ # class FilmActor
12
+ # include ClassUtilMixin
13
+ # end
14
+ module ClassUtilMixin #:nodoc:
15
+ def self.included(base) #:nodoc:
16
+ base.send(:include, InstanceMethods)
17
+ end
18
+
19
+ # Instance methods defined for <tt>Twitter::ModelMixin</tt> module.
20
+ module InstanceMethods #:nodoc:
21
+ # Constructor/initializer that takes a hash of parameters that
22
+ # will initialize *members* or instance attributes to the
23
+ # values given. For example,
24
+ #
25
+ # class FilmActor
26
+ # include Twitter::ClassUtilMixin
27
+ # attr_accessor :name
28
+ # end
29
+ #
30
+ # class Production
31
+ # include Twitter::ClassUtilMixin
32
+ # attr_accessor :title, :year, :actors
33
+ # end
34
+ #
35
+ # # Favorite actress...
36
+ # jodhi = FilmActor.new(:name => "Jodhi May")
37
+ # jodhi.name # => "Jodhi May"
38
+ #
39
+ # # Favorite actor...
40
+ # robert = FilmActor.new(:name => "Robert Lindsay")
41
+ # robert.name # => "Robert Lindsay"
42
+ #
43
+ # # Jane is also an excellent pick...gotta love her accent!
44
+ # jane = FilmActor.new(name => "Jane Horrocks")
45
+ # jane.name # => "Jane Horrocks"
46
+ #
47
+ # # Witty BBC series...
48
+ # mrs_pritchard = Production.new(:title => "The Amazing Mrs. Pritchard",
49
+ # :year => 2005,
50
+ # :actors => [jodhi, jane])
51
+ # mrs_pritchard.title # => "The Amazing Mrs. Pritchard"
52
+ # mrs_pritchard.year # => 2005
53
+ # mrs_pritchard.actors # => [#<FilmActor:0xb79d6bbc @name="Jodhi May">,
54
+ # <FilmActor:0xb79d319c @name="Jane Horrocks">]
55
+ # # Any Ros Pritchard's out there to save us from the Tony Blair
56
+ # # and Gordon Brown *New Labour* debacle? You've got my vote!
57
+ #
58
+ # jericho = Production.new(:title => "Jericho",
59
+ # :year => 2005,
60
+ # :actors => [robert])
61
+ # jericho.title # => "Jericho"
62
+ # jericho.year # => 2005
63
+ # jericho.actors # => [#<FilmActor:0xc95d3eec @name="Robert Lindsay">]
64
+ #
65
+ # Assuming class <tt>FilmActor</tt> includes
66
+ # <tt>Twitter::ClassUtilMixin</tt> in the class definition
67
+ # and has an attribute of <tt>name</tt>, then that instance
68
+ # attribute will be set to "Jodhi May" for the <tt>actress</tt>
69
+ # object during object initialization (aka construction for
70
+ # you Java heads).
71
+ def initialize(params = {})
72
+ params.each do |key,val|
73
+ self.send("#{key}=", val) if self.respond_to? key
74
+ end
75
+ self.send(:init) if self.respond_to? :init
76
+ end
77
+
78
+ protected
79
+ # Helper method to provide an easy and terse way to require
80
+ # a block is provided to a method.
81
+ def require_block(block_given)
82
+ raise ArgumentError, "Must provide a block" unless block_given
83
+ end
84
+ end
85
+ end # ClassUtilMixin
86
+
87
+ # Exception subclass raised when there is an error encountered upon
88
+ # querying or posting to the remote Twitter REST API.
89
+ #
90
+ # To consume and query any <tt>RESTError</tt> raised by Twitter4R:
91
+ # begin
92
+ # # Do something with your instance of <tt>Twitter::Client</tt>.
93
+ # # Maybe something like:
94
+ # timeline = twitter.timeline_for(:public)
95
+ # rescue RESTError => re
96
+ # puts re.code, re.message, re.uri
97
+ # end
98
+ # Which on the code raising a <tt>RESTError</tt> will output something like:
99
+ # 404
100
+ # Resource Not Found
101
+ # /i_am_crap.json
102
+ class RESTError < Exception
103
+ include ClassUtilMixin
104
+ @@ATTRIBUTES = [:code, :message, :uri]
105
+ attr_accessor :code, :message, :uri
106
+
107
+ # Returns string in following format:
108
+ # "HTTP #{@code}: #{@message} at #{@uri}"
109
+ # For example,
110
+ # "HTTP 404: Resource Not Found at /i_am_crap.json"
111
+ def to_s
112
+ "HTTP #{@code}: #{@message} at #{@uri}"
113
+ end
114
+ end # RESTError
115
+
116
+ # Remote REST API interface representation
117
+ #
118
+ class RESTInterfaceSpec
119
+ include ClassUtilMixin
120
+
121
+ end
122
+
123
+ # Remote REST API method representation
124
+ #
125
+ class RESTMethodSpec
126
+ include ClassUtilMixin
127
+ attr_accessor :uri, :method, :parameters
128
+ end
129
+
130
+ # Remote REST API method parameter representation
131
+ #
132
+ class RESTParameterSpec
133
+ include ClassUtilMixin
134
+ attr_accessor :name, :type, :required
135
+ def required?; @required; end
136
+ end
137
+ end