hashblue-api 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README +21 -0
- data/Rakefile +98 -0
- data/hashblue-api.gemspec +58 -0
- data/lib/dependency/mime_type.rb +231 -0
- data/lib/dependency/mime_types.rb +23 -0
- data/lib/hashblue/api.rb +89 -0
- data/lib/hashblue/api/contact.rb +26 -0
- data/lib/hashblue/api/error.rb +39 -0
- data/lib/hashblue/api/message.rb +37 -0
- data/lib/hashblue/api/model.rb +55 -0
- data/lib/hashblue/api/request.rb +36 -0
- data/lib/hashblue/api/subscriber.rb +65 -0
- data/lib/hashblue/api/test_helper.rb +87 -0
- data/test/helpers/test_helper_test.rb +115 -0
- data/test/test_helper.rb +32 -0
- data/test/unit/api_test.rb +17 -0
- data/test/unit/contact_test.rb +27 -0
- data/test/unit/message_api_test.rb +135 -0
- data/test/unit/message_test.rb +42 -0
- data/test/unit/model_test.rb +27 -0
- data/test/unit/subscriber_test.rb +42 -0
- metadata +110 -0
data/README
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
= It's the Hashblue API gem
|
2
|
+
|
3
|
+
For usage, look at Hashblue::API (in lib/firehose/api.rb)
|
4
|
+
|
5
|
+
|
6
|
+
= Short usage example
|
7
|
+
|
8
|
+
require 'active_support/all' # unless you have already loaded it
|
9
|
+
require 'hashblue/api'
|
10
|
+
|
11
|
+
Hashblue::API.base_uri "https://api.hashblue.apigee.com"
|
12
|
+
Hashblue::API.basic_auth "dave@example.com", "yourapikey"
|
13
|
+
|
14
|
+
subscriber = Hashblue::API::Subscriber.find("yourapikey")
|
15
|
+
|
16
|
+
subscriber.messages
|
17
|
+
|
18
|
+
|
19
|
+
= Testing against the Hashblue API
|
20
|
+
|
21
|
+
To learn about stubbing out the Hashblue API, see Hashblue::API::TestHelper
|
data/Rakefile
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake/gempackagetask"
|
3
|
+
require "rake/rdoctask"
|
4
|
+
require "rake/testtask"
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
# This builds the actual gem. For details of what all these options
|
9
|
+
# mean, and other ones you can add, check the documentation here:
|
10
|
+
#
|
11
|
+
# http://rubygems.org/read/chapter/20
|
12
|
+
#
|
13
|
+
path = File.expand_path("..", __FILE__)
|
14
|
+
|
15
|
+
spec = Dir.chdir(path) do
|
16
|
+
Gem::Specification.new do |s|
|
17
|
+
|
18
|
+
# Change these as appropriate
|
19
|
+
s.name = "hashblue-api"
|
20
|
+
s.version = "0.0.8"
|
21
|
+
s.summary = "It's the Hashblue API, stupid!"
|
22
|
+
s.author = "FreeRange"
|
23
|
+
s.email = "lets@gofreerange.com"
|
24
|
+
s.homepage = "http://gofreerange.com"
|
25
|
+
|
26
|
+
s.has_rdoc = true
|
27
|
+
s.extra_rdoc_files = %w(README)
|
28
|
+
s.rdoc_options = %w(--main README)
|
29
|
+
|
30
|
+
# Add any extra files to include in the gem
|
31
|
+
s.files = `cd #{path} && git ls-files`.split("\n").sort
|
32
|
+
|
33
|
+
# You need to put your code in a directory which can then be added to
|
34
|
+
# the $LOAD_PATH by rubygems. Typically this is lib, but you don't seem
|
35
|
+
# to have that directory. You'll need to set the line below to whatever
|
36
|
+
# directory your code is in. Rubygems is going to assume lib if you leave
|
37
|
+
# this blank.
|
38
|
+
#
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
|
41
|
+
# If you want to depend on other gems, add them here, along with any
|
42
|
+
# relevant versions
|
43
|
+
s.add_dependency 'httparty', '0.5.2'
|
44
|
+
s.add_dependency 'activesupport', '>= 2.3.5'
|
45
|
+
|
46
|
+
# If your tests use any gems, include them here
|
47
|
+
# s.add_development_dependency("mocha") # for example
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Stolen from jeweler
|
52
|
+
def prettyify_array(gemspec_ruby, array_name)
|
53
|
+
gemspec_ruby.gsub(/s\.#{array_name.to_s} = \[.+?\]/) do |match|
|
54
|
+
leadin, files = match[0..-2].split("[")
|
55
|
+
leadin + "[\n #{files.split(",").join(",\n ")}\n ]"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
Rake::TestTask.new do |t|
|
60
|
+
t.libs << "test"
|
61
|
+
t.test_files = FileList["#{path}/test/**/*test.rb"]
|
62
|
+
t.verbose = true
|
63
|
+
end
|
64
|
+
|
65
|
+
# This task actually builds the gem. We also regenerate a static
|
66
|
+
# .gemspec file, which is useful if something (i.e. GitHub) will
|
67
|
+
# be automatically building a gem for this project. If you're not
|
68
|
+
# using GitHub, edit as appropriate.
|
69
|
+
#
|
70
|
+
# To publish your gem online, install the 'gemcutter' gem; Read more
|
71
|
+
# about that here: http://gemcutter.org/pages/gem_docs
|
72
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
73
|
+
pkg.gem_spec = spec
|
74
|
+
end
|
75
|
+
|
76
|
+
task :gemspec do
|
77
|
+
output = spec.to_ruby
|
78
|
+
output = prettyify_array(output, :files)
|
79
|
+
output = prettyify_array(output, :test_files)
|
80
|
+
output = prettyify_array(output, :extra_rdoc_files)
|
81
|
+
|
82
|
+
file = File.expand_path("../#{spec.name}.gemspec", __FILE__)
|
83
|
+
File.open(file, "w") {|f| f << output }
|
84
|
+
end
|
85
|
+
|
86
|
+
task :package => :gemspec
|
87
|
+
|
88
|
+
# Generate documentation
|
89
|
+
Rake::RDocTask.new do |rd|
|
90
|
+
rd.main = "README"
|
91
|
+
rd.rdoc_files.include("README", "lib/**/*.rb")
|
92
|
+
rd.rdoc_dir = "rdoc"
|
93
|
+
end
|
94
|
+
|
95
|
+
desc 'Clear out RDoc and generated packages'
|
96
|
+
task :clean => [:clobber_rdoc, :clobber_package] do
|
97
|
+
rm "#{spec.name}.gemspec"
|
98
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{hashblue-api}
|
5
|
+
s.version = "0.0.8"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["FreeRange"]
|
9
|
+
s.date = %q{2010-05-06}
|
10
|
+
s.email = %q{lets@gofreerange.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"README"
|
13
|
+
]
|
14
|
+
s.files = [
|
15
|
+
"README",
|
16
|
+
"Rakefile",
|
17
|
+
"hashblue-api.gemspec",
|
18
|
+
"lib/dependency/mime_type.rb",
|
19
|
+
"lib/dependency/mime_types.rb",
|
20
|
+
"lib/hashblue/api.rb",
|
21
|
+
"lib/hashblue/api/contact.rb",
|
22
|
+
"lib/hashblue/api/error.rb",
|
23
|
+
"lib/hashblue/api/message.rb",
|
24
|
+
"lib/hashblue/api/model.rb",
|
25
|
+
"lib/hashblue/api/request.rb",
|
26
|
+
"lib/hashblue/api/subscriber.rb",
|
27
|
+
"lib/hashblue/api/test_helper.rb",
|
28
|
+
"test/helpers/test_helper_test.rb",
|
29
|
+
"test/test_helper.rb",
|
30
|
+
"test/unit/api_test.rb",
|
31
|
+
"test/unit/contact_test.rb",
|
32
|
+
"test/unit/message_api_test.rb",
|
33
|
+
"test/unit/message_test.rb",
|
34
|
+
"test/unit/model_test.rb",
|
35
|
+
"test/unit/subscriber_test.rb"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://gofreerange.com}
|
38
|
+
s.rdoc_options = ["--main", "README"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.3.6}
|
41
|
+
s.summary = %q{It's the Hashblue API, stupid!}
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_runtime_dependency(%q<httparty>, ["= 0.5.2"])
|
49
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.3.5"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<httparty>, ["= 0.5.2"])
|
52
|
+
s.add_dependency(%q<activesupport>, [">= 2.3.5"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<httparty>, ["= 0.5.2"])
|
56
|
+
s.add_dependency(%q<activesupport>, [">= 2.3.5"])
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
3
|
+
|
4
|
+
module Mime
|
5
|
+
class Mimes < Array
|
6
|
+
def symbols
|
7
|
+
@symbols ||= map {|m| m.to_sym }
|
8
|
+
end
|
9
|
+
|
10
|
+
%w(<< concat shift unshift push pop []= clear compact! collect!
|
11
|
+
delete delete_at delete_if flatten! map! insert reject! reverse!
|
12
|
+
replace slice! sort! uniq!).each do |method|
|
13
|
+
module_eval <<-CODE, __FILE__, __LINE__ + 1
|
14
|
+
def #{method}(*)
|
15
|
+
@symbols = nil
|
16
|
+
super
|
17
|
+
end
|
18
|
+
CODE
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
SET = Mimes.new
|
23
|
+
EXTENSION_LOOKUP = {}
|
24
|
+
LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? }
|
25
|
+
|
26
|
+
def self.[](type)
|
27
|
+
return type if type.is_a?(Type)
|
28
|
+
Type.lookup_by_extension(type.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Encapsulates the notion of a mime type. Can be used at render time, for example, with:
|
32
|
+
#
|
33
|
+
# class PostsController < ActionController::Base
|
34
|
+
# def show
|
35
|
+
# @post = Post.find(params[:id])
|
36
|
+
#
|
37
|
+
# respond_to do |format|
|
38
|
+
# format.html
|
39
|
+
# format.ics { render :text => post.to_ics, :mime_type => Mime::Type["text/calendar"] }
|
40
|
+
# format.xml { render :xml => @people.to_xml }
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
class Type
|
45
|
+
@@html_types = Set.new [:html, :all]
|
46
|
+
cattr_reader :html_types
|
47
|
+
|
48
|
+
# These are the content types which browsers can generate without using ajax, flash, etc
|
49
|
+
# i.e. following a link, getting an image or posting a form. CSRF protection
|
50
|
+
# only needs to protect against these types.
|
51
|
+
@@browser_generated_types = Set.new [:html, :url_encoded_form, :multipart_form, :text]
|
52
|
+
cattr_reader :browser_generated_types
|
53
|
+
attr_reader :symbol
|
54
|
+
|
55
|
+
@@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
|
56
|
+
def self.unverifiable_types
|
57
|
+
ActiveSupport::Deprecation.warn("unverifiable_types is deprecated and has no effect", caller)
|
58
|
+
@@unverifiable_types
|
59
|
+
end
|
60
|
+
|
61
|
+
# A simple helper class used in parsing the accept header
|
62
|
+
class AcceptItem #:nodoc:
|
63
|
+
attr_accessor :order, :name, :q
|
64
|
+
|
65
|
+
def initialize(order, name, q=nil)
|
66
|
+
@order = order
|
67
|
+
@name = name.strip
|
68
|
+
q ||= 0.0 if @name == Mime::ALL # default wilcard match to end of list
|
69
|
+
@q = ((q || 1.0).to_f * 100).to_i
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_s
|
73
|
+
@name
|
74
|
+
end
|
75
|
+
|
76
|
+
def <=>(item)
|
77
|
+
result = item.q <=> q
|
78
|
+
result = order <=> item.order if result == 0
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def ==(item)
|
83
|
+
name == (item.respond_to?(:name) ? item.name : item)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class << self
|
88
|
+
def lookup(string)
|
89
|
+
LOOKUP[string]
|
90
|
+
end
|
91
|
+
|
92
|
+
def lookup_by_extension(extension)
|
93
|
+
EXTENSION_LOOKUP[extension.to_s]
|
94
|
+
end
|
95
|
+
|
96
|
+
# Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for
|
97
|
+
# rendering different HTML versions depending on the user agent, like an iPhone.
|
98
|
+
def register_alias(string, symbol, extension_synonyms = [])
|
99
|
+
register(string, symbol, [], extension_synonyms, true)
|
100
|
+
end
|
101
|
+
|
102
|
+
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
|
103
|
+
Mime.instance_eval { const_set symbol.to_s.upcase, Type.new(string, symbol, mime_type_synonyms) }
|
104
|
+
|
105
|
+
SET << Mime.const_get(symbol.to_s.upcase)
|
106
|
+
|
107
|
+
([string] + mime_type_synonyms).each { |str| LOOKUP[str] = SET.last } unless skip_lookup
|
108
|
+
([symbol.to_s] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext] = SET.last }
|
109
|
+
end
|
110
|
+
|
111
|
+
def parse(accept_header)
|
112
|
+
if accept_header !~ /,/
|
113
|
+
[Mime::Type.lookup(accept_header)]
|
114
|
+
else
|
115
|
+
# keep track of creation order to keep the subsequent sort stable
|
116
|
+
list = []
|
117
|
+
accept_header.split(/,/).each_with_index do |header, index|
|
118
|
+
params, q = header.split(/;\s*q=/)
|
119
|
+
if params
|
120
|
+
params.strip!
|
121
|
+
list << AcceptItem.new(index, params, q) unless params.empty?
|
122
|
+
end
|
123
|
+
end
|
124
|
+
list.sort!
|
125
|
+
|
126
|
+
# Take care of the broken text/xml entry by renaming or deleting it
|
127
|
+
text_xml = list.index("text/xml")
|
128
|
+
app_xml = list.index(Mime::XML.to_s)
|
129
|
+
|
130
|
+
if text_xml && app_xml
|
131
|
+
# set the q value to the max of the two
|
132
|
+
list[app_xml].q = [list[text_xml].q, list[app_xml].q].max
|
133
|
+
|
134
|
+
# make sure app_xml is ahead of text_xml in the list
|
135
|
+
if app_xml > text_xml
|
136
|
+
list[app_xml], list[text_xml] = list[text_xml], list[app_xml]
|
137
|
+
app_xml, text_xml = text_xml, app_xml
|
138
|
+
end
|
139
|
+
|
140
|
+
# delete text_xml from the list
|
141
|
+
list.delete_at(text_xml)
|
142
|
+
|
143
|
+
elsif text_xml
|
144
|
+
list[text_xml].name = Mime::XML.to_s
|
145
|
+
end
|
146
|
+
|
147
|
+
# Look for more specific XML-based types and sort them ahead of app/xml
|
148
|
+
|
149
|
+
if app_xml
|
150
|
+
idx = app_xml
|
151
|
+
app_xml_type = list[app_xml]
|
152
|
+
|
153
|
+
while(idx < list.length)
|
154
|
+
type = list[idx]
|
155
|
+
break if type.q < app_xml_type.q
|
156
|
+
if type.name =~ /\+xml$/
|
157
|
+
list[app_xml], list[idx] = list[idx], list[app_xml]
|
158
|
+
app_xml = idx
|
159
|
+
end
|
160
|
+
idx += 1
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
list.map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
165
|
+
list
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def initialize(string, symbol = nil, synonyms = [])
|
171
|
+
@symbol, @synonyms = symbol, synonyms
|
172
|
+
@string = string
|
173
|
+
end
|
174
|
+
|
175
|
+
def to_s
|
176
|
+
@string
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_str
|
180
|
+
to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
def to_sym
|
184
|
+
@symbol || @string.to_sym
|
185
|
+
end
|
186
|
+
|
187
|
+
def ===(list)
|
188
|
+
if list.is_a?(Array)
|
189
|
+
(@synonyms + [ self ]).any? { |synonym| list.include?(synonym) }
|
190
|
+
else
|
191
|
+
super
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def ==(mime_type)
|
196
|
+
return false if mime_type.blank?
|
197
|
+
(@synonyms + [ self ]).any? do |synonym|
|
198
|
+
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def =~(mime_type)
|
203
|
+
return false if mime_type.blank?
|
204
|
+
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
205
|
+
(@synonyms + [ self ]).any? do |synonym|
|
206
|
+
synonym.to_s =~ regexp
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
|
211
|
+
# ActionController::RequestForgeryProtection.
|
212
|
+
def verify_request?
|
213
|
+
@@browser_generated_types.include?(to_sym)
|
214
|
+
end
|
215
|
+
|
216
|
+
def html?
|
217
|
+
@@html_types.include?(to_sym) || @string =~ /html/
|
218
|
+
end
|
219
|
+
|
220
|
+
private
|
221
|
+
def method_missing(method, *args)
|
222
|
+
if method.to_s =~ /(\w+)\?$/
|
223
|
+
$1.downcase.to_sym == to_sym
|
224
|
+
else
|
225
|
+
super
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
require 'dependency/mime_types'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Build list of Mime types for HTTP responses
|
2
|
+
# http://www.iana.org/assignments/media-types/
|
3
|
+
|
4
|
+
Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
|
5
|
+
Mime::Type.register "text/plain", :text, [], %w(txt)
|
6
|
+
Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )
|
7
|
+
Mime::Type.register "text/css", :css
|
8
|
+
Mime::Type.register "text/calendar", :ics
|
9
|
+
Mime::Type.register "text/csv", :csv
|
10
|
+
Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml )
|
11
|
+
Mime::Type.register "application/rss+xml", :rss
|
12
|
+
Mime::Type.register "application/atom+xml", :atom
|
13
|
+
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml )
|
14
|
+
|
15
|
+
Mime::Type.register "multipart/form-data", :multipart_form
|
16
|
+
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
|
17
|
+
|
18
|
+
# http://www.ietf.org/rfc/rfc4627.txt
|
19
|
+
# http://www.json.org/JSONRequest.html
|
20
|
+
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
|
21
|
+
|
22
|
+
# Create Mime::ALL but do not add it to the SET.
|
23
|
+
Mime::ALL = Mime::Type.new("*/*", :all, [])
|
data/lib/hashblue/api.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require 'httparty'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
# By using autoload rather than require, we only use our fallback
|
6
|
+
# dependency if Mime hasn't been loaded elsewhere
|
7
|
+
autoload :Mime, 'dependency/mime_type'
|
8
|
+
|
9
|
+
module Hashblue
|
10
|
+
|
11
|
+
# = It's the Hashblue API gem
|
12
|
+
#
|
13
|
+
# == Connecting
|
14
|
+
#
|
15
|
+
# Hashblue API requires ActiveSupport; if this isn't already loaded, you'll need
|
16
|
+
# to ensure that it is available - either by requiring rubygems, or ensuring
|
17
|
+
# it is in the +LOAD_PATH+ already.
|
18
|
+
#
|
19
|
+
# To connect to the Hashblue API, you need to set the base URL, and provide
|
20
|
+
# your credentials (you can find these in your hashblue.com account). For
|
21
|
+
# example:
|
22
|
+
#
|
23
|
+
# require 'active_support/all' # unless you have already loaded it
|
24
|
+
# require 'hashblue/api'
|
25
|
+
#
|
26
|
+
# Hashblue::API.base_uri "https://api.hashblue.apigee.com"
|
27
|
+
# Hashblue::API.basic_auth "dave@example.com", "yourapikey"
|
28
|
+
#
|
29
|
+
#
|
30
|
+
# == Using the API
|
31
|
+
#
|
32
|
+
# Everything is loaded via your subscriber:
|
33
|
+
#
|
34
|
+
# subscriber = Hashblue::API::Subscriber.find("yourapikey")
|
35
|
+
#
|
36
|
+
# Once you have this, you can load all messages, all contacts, or all
|
37
|
+
# messages for a specific contact:
|
38
|
+
#
|
39
|
+
# all_messages = subscriber.messages
|
40
|
+
# all_contacts = subscriber.contacts
|
41
|
+
# messages_between_me_and_a_contact = all_contacts.first.messages
|
42
|
+
#
|
43
|
+
# == Interacting with messages
|
44
|
+
#
|
45
|
+
# It's simple to delete a message:
|
46
|
+
#
|
47
|
+
# all_messages.first.delete
|
48
|
+
#
|
49
|
+
# This message is now deleted. You can see a list of all deleted messages
|
50
|
+
# via the subscriber:
|
51
|
+
#
|
52
|
+
# subscriber.deleted_messages
|
53
|
+
module API
|
54
|
+
autoload :Contact, 'hashblue/api/contact'
|
55
|
+
autoload :Message, 'hashblue/api/message'
|
56
|
+
autoload :Model, 'hashblue/api/model'
|
57
|
+
autoload :Request, 'hashblue/api/request'
|
58
|
+
autoload :Subscriber, 'hashblue/api/subscriber'
|
59
|
+
autoload :Error, 'hashblue/api/error'
|
60
|
+
autoload :TestHelper, 'hashblue/api/test_helper'
|
61
|
+
|
62
|
+
# Raised when the API fails to respond with a timeout. The timeout
|
63
|
+
# can be set using Hashblue::API.timeout
|
64
|
+
class NotRespondingError < StandardError; end
|
65
|
+
# Raised when the API responded in a way that we couldn't handle.
|
66
|
+
class BadResponseError < Hashblue::API::Error; end
|
67
|
+
# Raised when the object requested cannot be found.
|
68
|
+
class NotFoundError < Hashblue::API::Error; end
|
69
|
+
# Raised when the object requested is not available given the
|
70
|
+
# credentials used; most often is is because a Contact or Message
|
71
|
+
# belongs to a different Subscriber
|
72
|
+
class AccessDeniedError < Hashblue::API::Error
|
73
|
+
def status
|
74
|
+
:unauthorized
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Sets the timeout used before raising an error.
|
79
|
+
def self.timeout(value)
|
80
|
+
default_options[:timeout] = value
|
81
|
+
end
|
82
|
+
|
83
|
+
include HTTParty
|
84
|
+
extend Request
|
85
|
+
|
86
|
+
base_uri "https://api.hashblue.apigee.com"
|
87
|
+
timeout 5
|
88
|
+
end
|
89
|
+
end
|