mbbx6spp-twitter4r 0.3.1

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.
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/client/account.rb +24 -0
  6. data/lib/twitter/client/auth.rb +27 -0
  7. data/lib/twitter/client/base.rb +87 -0
  8. data/lib/twitter/client/blocks.rb +35 -0
  9. data/lib/twitter/client/favorites.rb +53 -0
  10. data/lib/twitter/client/friendship.rb +35 -0
  11. data/lib/twitter/client/messaging.rb +79 -0
  12. data/lib/twitter/client/status.rb +46 -0
  13. data/lib/twitter/client/timeline.rb +72 -0
  14. data/lib/twitter/client/user.rb +65 -0
  15. data/lib/twitter/client.rb +21 -0
  16. data/lib/twitter/config.rb +71 -0
  17. data/lib/twitter/console.rb +28 -0
  18. data/lib/twitter/core.rb +137 -0
  19. data/lib/twitter/ext/stdlib.rb +51 -0
  20. data/lib/twitter/ext.rb +2 -0
  21. data/lib/twitter/extras.rb +39 -0
  22. data/lib/twitter/meta.rb +56 -0
  23. data/lib/twitter/model.rb +348 -0
  24. data/lib/twitter/rails.rb +92 -0
  25. data/lib/twitter/version.rb +19 -0
  26. data/lib/twitter.rb +31 -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 +108 -0
@@ -0,0 +1,65 @@
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
+ end
@@ -0,0 +1,21 @@
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
+ require('twitter/client/auth.rb')
19
+ require('twitter/client/favorites.rb')
20
+ require('twitter/client/blocks.rb')
21
+ require('twitter/client/account.rb')
@@ -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 => 'twitter4r',
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
@@ -0,0 +1,51 @@
1
+ # Contains Ruby standard library extensions specific to <tt>Twitter4R</tt> library.
2
+
3
+ # Extension to Hash to create URL encoded string from key-values
4
+ class Hash
5
+ # Returns string formatted for HTTP URL encoded name-value pairs.
6
+ # For example,
7
+ # {:id => 'thomas_hardy'}.to_http_str
8
+ # # => "id=thomas_hardy"
9
+ # {:id => 23423, :since => Time.now}.to_http_str
10
+ # # => "since=Thu,%2021%20Jun%202007%2012:10:05%20-0500&id=23423"
11
+ def to_http_str
12
+ result = ''
13
+ return result if self.empty?
14
+ self.each do |key, val|
15
+ result << "#{key}=#{CGI.escape(val.to_s)}&"
16
+ end
17
+ result.chop # remove the last '&' character, since it can be discarded
18
+ end
19
+ end
20
+
21
+ # Extension to Time that outputs RFC2822 compliant string on #to_s
22
+ class Time
23
+ alias :old_to_s :to_s
24
+
25
+ # Returns RFC2822 compliant string for <tt>Time</tt> object.
26
+ # For example,
27
+ # # Tony Blair's last day in office (hopefully)
28
+ # best_day_ever = Time.local(2007, 6, 27)
29
+ # best_day_ever.to_s # => "Wed, 27 Jun 2007 00:00:00 +0100"
30
+ # You can also pass in an option <tt>format</tt> argument that
31
+ # corresponds to acceptable values according to ActiveSupport's
32
+ # +Time#to_formatted_s+ method.
33
+ def to_s(format = nil)
34
+ format ? self.to_formatted_s(format) : self.rfc2822
35
+ end
36
+ end
37
+
38
+ # Extension to Kernel to add #gem_present? without any exceptions raised
39
+ module Kernel
40
+
41
+ # Returns whether or not a gem exists without raising a Gem::LoadError exception
42
+ def gem_present?(gem_name, version = nil)
43
+ present = false
44
+ begin
45
+ present = gem(gem_name, version)
46
+ rescue Gem::LoadError => le
47
+ warn("Gem load error: Couldn't load #{gem_name} with version requirement #{version}: #{le.to_s}")
48
+ end
49
+ present
50
+ end
51
+ end
@@ -0,0 +1,2 @@
1
+
2
+ require_local('twitter/ext/stdlib')
@@ -0,0 +1,39 @@
1
+ # extra.rb contains features that are not considered part of the core library.
2
+ # This file is not imported by doing <tt>require('twitter')</tt>, so you will
3
+ # need to import this file separately like:
4
+ # require('twitter')
5
+ # require('twitter/extras')
6
+
7
+ require('twitter')
8
+
9
+ class Twitter::Client
10
+ @@FEATURED_URIS = {
11
+ :users => 'http://twitter.com/statuses/featured.json'
12
+ }
13
+
14
+ # Provides access to the Featured Twitter API.
15
+ #
16
+ # Currently the only value for <tt>type</tt> accepted is <tt>:users</tt>,
17
+ # which will return an Array of blessed Twitter::User objects that
18
+ # represent Twitter's featured users.
19
+ def featured(type)
20
+ uri = @@FEATURED_URIS[type]
21
+ response = http_connect {|conn| create_http_get_request(uri) }
22
+ bless_models(Twitter::User.unmarshal(response.body))
23
+ end
24
+ end
25
+
26
+ class Twitter::User
27
+ class << self
28
+ # Provides access to the Featured Twitter API via the Twitter4R Model
29
+ # interface.
30
+ #
31
+ # The following lines of code are equivalent to each other:
32
+ # users1 = Twitter::User.features(client)
33
+ # users2 = client.featured(:users)
34
+ # where <tt>users1</tt> and <tt>users2</tt> would be logically equivalent.
35
+ def featured(client)
36
+ client.featured(:users)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,56 @@
1
+ # meta.rb contains <tt>Twitter::Meta</tt> and related classes that
2
+ # help define the metadata of the <tt>Twitter4R</tt> project.
3
+
4
+ require('rubygems')
5
+ require('erb')
6
+
7
+ class Twitter::Meta #:nodoc:
8
+ attr_accessor :root_dir
9
+ attr_reader :gem_spec, :project_files, :spec_files
10
+
11
+ # Initializer for Twitter::Meta class. Takes <tt>root_dir</tt> as parameter.
12
+ def initialize(root_dir)
13
+ @root_dir = root_dir
14
+ end
15
+
16
+ # Returns package information defined in <tt>root_dir</tt>/pkg-info.yml
17
+ def pkg_info
18
+ yaml_file = File.join(@root_dir, 'pkg-info.yml')
19
+ ryaml = ERB.new(File.read(yaml_file), 0)
20
+ s = ryaml.result(binding)
21
+ YAML.load(s)
22
+ end
23
+
24
+ # Returns RubyGems spec information
25
+ def spec_info
26
+ self.pkg_info['spec'] if self.pkg_info
27
+ end
28
+
29
+ # Returns list of project files
30
+ def project_files
31
+ @project_files ||= Dir.glob(File.join(@root_dir, 'lib/**/*.rb'))
32
+ @project_files
33
+ end
34
+
35
+ # Returns list of specification files
36
+ def spec_files
37
+ @spec_files ||= Dir.glob(File.join(@root_dir, 'spec/**/*_spec.rb'))
38
+ @spec_files
39
+ end
40
+
41
+ # Returns RubyGem specification for Twitter4R project
42
+ def gem_spec
43
+ @gem_spec ||= Gem::Specification.new do |spec|
44
+ self.spec_info.each do |key, val|
45
+ if val.is_a?(Hash)
46
+ val.each do |k, v|
47
+ spec.send(key, k, v)
48
+ end
49
+ else
50
+ spec.send("#{key}=", val)
51
+ end
52
+ end
53
+ end
54
+ @gem_spec
55
+ end
56
+ end