jnunemaker / twitter

API wrapper for Twitter and Twitter Search API's

twitter / lib / twitter / request.rb
100644 102 lines (85 sloc) 2.857 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
module Twitter
  class Request
    extend Forwardable
    
    def self.get(client, path, options={})
      new(client, :get, path, options).perform
    end
    
    def self.post(client, path, options={})
      new(client, :post, path, options).perform
    end
    
    attr_reader :client, :method, :path, :options
    
    def_delegators :client, :get, :post
    
    def initialize(client, method, path, options={})
      @client, @method, @path, @options = client, method, path, {:mash => true}.merge(options)
    end
    
    def uri
      @uri ||= begin
        uri = URI.parse(path)
        
        if options[:query] && options[:query] != {}
          uri.query = to_query(options[:query])
        end
        
        uri.to_s
      end
    end
    
    def perform
      make_friendly(send("perform_#{method}"))
    end
    
    private
      def perform_get
        send(:get, uri, options[:headers])
      end
      
      def perform_post
        send(:post, uri, options[:body], options[:headers])
      end
      
      def make_friendly(response)
        raise_errors(response)
        data = parse(response)
        options[:mash] ? mash(data) : data
      end
      
      def raise_errors(response)
        case response.code.to_i
          when 400
            data = parse(response)
            raise RateLimitExceeded.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
          when 401
            data = parse(response)
            raise Unauthorized.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
          when 403
            data = parse(response)
            raise General.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
          when 404
            raise NotFound, "(#{response.code}): #{response.message}"
          when 500
            raise InformTwitter, "Twitter had an internal error. Please let them know in the group. (#{response.code}): #{response.message}"
          when 502..503
            raise Unavailable, "(#{response.code}): #{response.message}"
        end
      end
      
      def parse(response)
        Crack::JSON.parse(response.body)
      end
      
      def mash(obj)
        if obj.is_a?(Array)
          obj.map { |item| make_mash_with_consistent_hash(item) }
        elsif obj.is_a?(Hash)
          make_mash_with_consistent_hash(obj)
        else
          obj
        end
      end
 
      # Lame workaround for the fact that mash doesn't hash correctly
      def make_mash_with_consistent_hash(obj)
        m = Mash.new(obj)
        def m.hash
          inspect.hash
        end
        return m
      end
      
      def to_query(options)
        options.inject([]) do |collection, opt|
          collection << "#{opt[0]}=#{opt[1]}"
          collection
        end * '&'
      end
  end
end