context-io 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +129 -0
- data/Rakefile +121 -0
- data/SPEC.md +49 -0
- data/context-io.gemspec +96 -0
- data/lib/context-io.rb +14 -0
- data/lib/context-io/account.rb +254 -0
- data/lib/context-io/authentication.rb +23 -0
- data/lib/context-io/config.rb +103 -0
- data/lib/context-io/connection.rb +45 -0
- data/lib/context-io/core_ext/hash.rb +31 -0
- data/lib/context-io/error.rb +24 -0
- data/lib/context-io/error/bad_request.rb +12 -0
- data/lib/context-io/error/client_error.rb +10 -0
- data/lib/context-io/error/forbidden.rb +12 -0
- data/lib/context-io/error/internal_server_error.rb +10 -0
- data/lib/context-io/error/not_found.rb +12 -0
- data/lib/context-io/error/payment_required.rb +13 -0
- data/lib/context-io/error/server_error.rb +10 -0
- data/lib/context-io/error/service_unavailable.rb +13 -0
- data/lib/context-io/error/unauthorized.rb +12 -0
- data/lib/context-io/file.rb +234 -0
- data/lib/context-io/folder.rb +90 -0
- data/lib/context-io/message.rb +160 -0
- data/lib/context-io/oauth_provider.rb +84 -0
- data/lib/context-io/request.rb +70 -0
- data/lib/context-io/request/oauth.rb +44 -0
- data/lib/context-io/resource.rb +16 -0
- data/lib/context-io/response.rb +5 -0
- data/lib/context-io/response/parse_json.rb +30 -0
- data/lib/context-io/response/raise_client_error.rb +59 -0
- data/lib/context-io/response/raise_server_error.rb +32 -0
- data/lib/context-io/source.rb +193 -0
- data/lib/context-io/version.rb +7 -0
- data/spec/account_spec.rb +247 -0
- data/spec/contextio_spec.rb +45 -0
- data/spec/file_spec.rb +101 -0
- data/spec/fixtures/accounts.json +21 -0
- data/spec/fixtures/files.json +41 -0
- data/spec/fixtures/files_group.json +47 -0
- data/spec/fixtures/folders.json +1 -0
- data/spec/fixtures/messages.json +1 -0
- data/spec/fixtures/oauth_providers.json +12 -0
- data/spec/fixtures/sources.json +1 -0
- data/spec/folder_spec.rb +48 -0
- data/spec/message_spec.rb +294 -0
- data/spec/oauth_provider_spec.rb +88 -0
- data/spec/source_spec.rb +248 -0
- data/spec/spec_helper.rb +4 -0
- metadata +214 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) Henrik Hodne
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
ContextIO - Extract data from email
|
2
|
+
===================================
|
3
|
+
|
4
|
+
[![Build Status](https://secure.travis-ci.org/dvyjones/context-io.png)](http://travis-ci.org/dvyjones/context-io)
|
5
|
+
[![Dependency Status](https://gemnasium.com/dvyjones/context-io.png)](https://gemnasium.com/dvyjones/context-io)
|
6
|
+
|
7
|
+
## Description
|
8
|
+
|
9
|
+
ContextIO is a Ruby wrapper for the [Context.IO][contextio] web service.
|
10
|
+
|
11
|
+
Context.IO is the missing email API that makes it easy and fast
|
12
|
+
to integrate your user's email data in your application.
|
13
|
+
|
14
|
+
ContextIO follows the rules of [Semantic Versioning][semver] and uses
|
15
|
+
[TomDoc][tomdoc] for inline documentation.
|
16
|
+
|
17
|
+
[contextio]: http://context.io
|
18
|
+
[semver]: http://semver.org
|
19
|
+
[tomdoc]: http://tomdoc.org
|
20
|
+
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
The best way to install ContextIO is through Rubygems:
|
25
|
+
|
26
|
+
```
|
27
|
+
$ [sudo] gem install context-io
|
28
|
+
```
|
29
|
+
|
30
|
+
If you're installing from source, you can use [Bundler][bundler] to pick up all
|
31
|
+
the gems:
|
32
|
+
|
33
|
+
```
|
34
|
+
$ bundle install
|
35
|
+
```
|
36
|
+
|
37
|
+
[bundler]: http://gembundler.org
|
38
|
+
|
39
|
+
## Usage
|
40
|
+
|
41
|
+
The ContextIO classes map pretty much one-to-one to the Context.IO API
|
42
|
+
resources, which you can find [on their documentation site][contextiodocs].
|
43
|
+
|
44
|
+
[contextiodocs]: http://context.io/docs/2.0
|
45
|
+
|
46
|
+
### Authenticate
|
47
|
+
|
48
|
+
ContextIO uses two-legged [OAuth][oauth] for authentication, which means you
|
49
|
+
need to get an API key from [Context.IO][contextio]. The API key consists of a
|
50
|
+
consumer key and a consumer secret, and once you have them you can set up
|
51
|
+
ContextIO like this:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
ContextIO.configure do |config|
|
55
|
+
config.consumer_key = 'consumer key'
|
56
|
+
config.consumer_secret = 'consumer secret'
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
[oauth]: http://oauth.net/
|
61
|
+
|
62
|
+
### Get an Account object
|
63
|
+
|
64
|
+
Once you're authenticated, you can get an `Account` object, which is what you
|
65
|
+
will be dealing with most of the time.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
account = ContextIO::Account.all.first
|
69
|
+
```
|
70
|
+
|
71
|
+
You can also find accounts matching a given email address.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
account = ContextIO::Account.all(:email => 'me@example.org').first
|
75
|
+
```
|
76
|
+
|
77
|
+
## Contributing
|
78
|
+
|
79
|
+
In the spirit of [free software][free-sw], **everyone** is encouraged to help
|
80
|
+
improve this project.
|
81
|
+
|
82
|
+
Here are some ways *you* can contribute:
|
83
|
+
|
84
|
+
* by using alpha, beta and prerelease versions
|
85
|
+
* by reporting bugs
|
86
|
+
* by suggesting new features
|
87
|
+
* by writing or editing documentation
|
88
|
+
* by writing specifications
|
89
|
+
* by writing code (**no patch is too small**: fix typos, add comments, clean up
|
90
|
+
inconsistent whitespace)
|
91
|
+
* by refactoring code
|
92
|
+
* by closing [issues][issues]
|
93
|
+
* by reviewing patches
|
94
|
+
|
95
|
+
### Submitting an Issue
|
96
|
+
|
97
|
+
We use the [GitHub issue tracker][issues] to track bugs and features. Before
|
98
|
+
submitting a bug report or feature request, check to make sure it hasn't
|
99
|
+
already been submitted. You can indicate support for an existing issue by
|
100
|
+
writing a comment saying you have the same issue (please include what version
|
101
|
+
of the gem you are using, as well as what version of ruby). When submitting a
|
102
|
+
bug report, please include a [gist][gist] that includes a stack trace and any
|
103
|
+
details that may be necessary to reproduce the bug, including your gem version,
|
104
|
+
Ruby version and operating system. Ideally, a bug report should include a pull
|
105
|
+
request with failing specs.
|
106
|
+
|
107
|
+
### Submitting a Pull Request
|
108
|
+
|
109
|
+
1. Fork the project.
|
110
|
+
2. Create a topic branch.
|
111
|
+
3. Implement your feature or bug fix.
|
112
|
+
4. Add documentation for your feature or bug fix.
|
113
|
+
5. Run `bundle exec rake rdoc`. If your changes are not 100% documented, go
|
114
|
+
back to step 4.
|
115
|
+
6. Add specs for your feature or bug fix.
|
116
|
+
7. Run `bundle exec rake spec`. If your changes are not 100% covered, go back
|
117
|
+
to step 6.
|
118
|
+
8. Commit your changes. If necessary, merge in upstream and rebase your
|
119
|
+
changes. Push your changes.
|
120
|
+
9. Submit a pull request. Please do not include changes to the gemspec,
|
121
|
+
version or history file.
|
122
|
+
|
123
|
+
[free-sw]: http://www.gnu.org/philosophy/free-sw.html
|
124
|
+
[issues]: https://github.com/dvyjones/context-io/issues
|
125
|
+
|
126
|
+
|
127
|
+
## Copyright
|
128
|
+
|
129
|
+
Copyright (c) 2012 Henrik Hodne. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
#############################################################################
|
6
|
+
#
|
7
|
+
# Helper functions
|
8
|
+
#
|
9
|
+
#############################################################################
|
10
|
+
|
11
|
+
def name
|
12
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
13
|
+
end
|
14
|
+
|
15
|
+
def version
|
16
|
+
line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
|
17
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
18
|
+
end
|
19
|
+
|
20
|
+
def date
|
21
|
+
Date.today.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def rubyforge_project
|
25
|
+
name
|
26
|
+
end
|
27
|
+
|
28
|
+
def gemspec_file
|
29
|
+
"#{name}.gemspec"
|
30
|
+
end
|
31
|
+
|
32
|
+
def gem_file
|
33
|
+
"#{name}-#{version}.gem"
|
34
|
+
end
|
35
|
+
|
36
|
+
def replace_header(head, header_name)
|
37
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'" }
|
38
|
+
end
|
39
|
+
|
40
|
+
#############################################################################
|
41
|
+
#
|
42
|
+
# Standard tasks
|
43
|
+
#
|
44
|
+
#############################################################################
|
45
|
+
|
46
|
+
task :default => :spec
|
47
|
+
|
48
|
+
require 'rspec/core/rake_task'
|
49
|
+
|
50
|
+
RSpec::Core::RakeTask.new(:spec)
|
51
|
+
|
52
|
+
require 'yard'
|
53
|
+
YARD::Rake::YardocTask.new
|
54
|
+
|
55
|
+
#############################################################################
|
56
|
+
#
|
57
|
+
# Packaging tasks
|
58
|
+
#
|
59
|
+
#############################################################################
|
60
|
+
|
61
|
+
desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
|
62
|
+
task :release => :build do
|
63
|
+
unless `git branch` =~ /^\* master$/
|
64
|
+
puts 'You must be on the master branch to release!'
|
65
|
+
exit!
|
66
|
+
end
|
67
|
+
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
68
|
+
sh "git tag v#{version}"
|
69
|
+
sh 'git push origin master'
|
70
|
+
sh "git push origin v#{version}"
|
71
|
+
sh "gem push pkg/#{gem_file}"
|
72
|
+
end
|
73
|
+
|
74
|
+
desc "Build #{gem_file} into the pkg directory"
|
75
|
+
task :build => :gemspec do
|
76
|
+
sh 'mkdir -p pkg'
|
77
|
+
sh "gem build #{gemspec_file}"
|
78
|
+
sh "mv #{gem_file} pkg"
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "Generate #{gemspec_file}"
|
82
|
+
task :gemspec => :validate do
|
83
|
+
# read spec file and split out manifest section
|
84
|
+
spec = File.read(gemspec_file)
|
85
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
86
|
+
|
87
|
+
# replace name, version and date
|
88
|
+
replace_header(head, :name)
|
89
|
+
replace_header(head, :version)
|
90
|
+
replace_header(head, :date)
|
91
|
+
replace_header(head, :rubyforge_project)
|
92
|
+
|
93
|
+
# determine file list from git ls-files
|
94
|
+
files = `git ls-files`.
|
95
|
+
split("\n").
|
96
|
+
sort.
|
97
|
+
reject { |file| file =~ /^\./ }.
|
98
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
99
|
+
map { |file| " #{file}" }.
|
100
|
+
join("\n")
|
101
|
+
|
102
|
+
# piece file back together and write
|
103
|
+
manifest = " s.files = %w(\n#{files}\n )\n"
|
104
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
105
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
106
|
+
puts "Updated #{gemspec_file}"
|
107
|
+
end
|
108
|
+
|
109
|
+
desc "Validate #{gemspec_file}"
|
110
|
+
task :validate do
|
111
|
+
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
112
|
+
unless libfiles.empty?
|
113
|
+
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
114
|
+
exit!
|
115
|
+
end
|
116
|
+
unless Dir['VERSION*'].empty?
|
117
|
+
puts 'A `VERSION` file at root level violates Gem best practices.'
|
118
|
+
exit!
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
data/SPEC.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
ContextIO spec / roadmap
|
2
|
+
========================
|
3
|
+
|
4
|
+
These are things that will be included in the "Usage" section of the README
|
5
|
+
file. Think of this as a roadmap.
|
6
|
+
|
7
|
+
### Getting a list of messages
|
8
|
+
|
9
|
+
Once you have an `Account` object, you can get a list of messages as an array
|
10
|
+
of `Message` objects.
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
account.messages
|
14
|
+
# => [#<ContextIO::Message to: 'me@example.com', ...>, ...]
|
15
|
+
```
|
16
|
+
|
17
|
+
You can also search for messages (see the documentation for
|
18
|
+
ContextIO::Message#find for the full list of attributes you can search for.
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
account.messages(:subject => 'Hello, world!').first
|
22
|
+
# => #<ContextIO::Message subject: 'Hello, world!', ...>
|
23
|
+
```
|
24
|
+
|
25
|
+
### The Message object
|
26
|
+
|
27
|
+
`Message` objects contains information about that message.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
message = account.messages.first
|
31
|
+
|
32
|
+
message.subject
|
33
|
+
# => "Hello, world!"
|
34
|
+
|
35
|
+
message.from
|
36
|
+
# => "John Doe <john.doe@example.com>"
|
37
|
+
|
38
|
+
message.to
|
39
|
+
# => "me@example.com"
|
40
|
+
|
41
|
+
message.date
|
42
|
+
# => Thu Jan 05 23:30:22 +0100 2012
|
43
|
+
|
44
|
+
message.message_id
|
45
|
+
# => "abcdef0123456789"
|
46
|
+
|
47
|
+
message.email_message_id
|
48
|
+
# => "<20120105233022.abcdef0@mta1.mail.example.com>"
|
49
|
+
|
data/context-io.gemspec
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
4
|
+
s.rubygems_version = '1.3.5'
|
5
|
+
|
6
|
+
s.name = 'context-io'
|
7
|
+
s.version = '0.0.1'
|
8
|
+
s.date = '2012-01-26'
|
9
|
+
s.rubyforge_project = 'context-io'
|
10
|
+
|
11
|
+
s.summary = 'Ruby wrapper for the context.io API.'
|
12
|
+
s.description = 'Ruby wrapper for the context.io API.'
|
13
|
+
|
14
|
+
s.authors = ['Henrik Hodne']
|
15
|
+
s.email = 'dvyjones@dvyjones.com'
|
16
|
+
s.homepage = 'https://github.com/dvyjones/context-io'
|
17
|
+
|
18
|
+
s.require_paths = %w(lib)
|
19
|
+
|
20
|
+
s.rdoc_options = ['--charset=UTF-8', '--markup tomdoc', '--main README.md']
|
21
|
+
s.extra_rdoc_files = %w(README.md LICENSE)
|
22
|
+
|
23
|
+
s.add_dependency('faraday', '~> 0.7.5')
|
24
|
+
s.add_dependency('simple_oauth', '~> 0.1.5')
|
25
|
+
s.add_dependency('multi_json', '~> 1.0.0')
|
26
|
+
s.add_dependency('webmock', '~> 1.7.10')
|
27
|
+
|
28
|
+
if RUBY_PLATFORM == 'java'
|
29
|
+
s.add_dependency('jruby-openssl', '>= 0')
|
30
|
+
end
|
31
|
+
|
32
|
+
s.add_development_dependency('rspec', '~> 2.8.0')
|
33
|
+
s.add_development_dependency('rake', '~> 0.9.0')
|
34
|
+
s.add_development_dependency('yard', '~> 0.7.4')
|
35
|
+
s.add_development_dependency('yard-rspec', '~> 0.1')
|
36
|
+
s.add_development_dependency('redcarpet', '~> 2.1.0')
|
37
|
+
s.add_development_dependency('github-markup', '~> 0.7.0')
|
38
|
+
|
39
|
+
# = MANIFEST =
|
40
|
+
s.files = %w(
|
41
|
+
Gemfile
|
42
|
+
LICENSE
|
43
|
+
README.md
|
44
|
+
Rakefile
|
45
|
+
SPEC.md
|
46
|
+
context-io.gemspec
|
47
|
+
lib/context-io.rb
|
48
|
+
lib/context-io/account.rb
|
49
|
+
lib/context-io/authentication.rb
|
50
|
+
lib/context-io/config.rb
|
51
|
+
lib/context-io/connection.rb
|
52
|
+
lib/context-io/core_ext/hash.rb
|
53
|
+
lib/context-io/error.rb
|
54
|
+
lib/context-io/error/bad_request.rb
|
55
|
+
lib/context-io/error/client_error.rb
|
56
|
+
lib/context-io/error/forbidden.rb
|
57
|
+
lib/context-io/error/internal_server_error.rb
|
58
|
+
lib/context-io/error/not_found.rb
|
59
|
+
lib/context-io/error/payment_required.rb
|
60
|
+
lib/context-io/error/server_error.rb
|
61
|
+
lib/context-io/error/service_unavailable.rb
|
62
|
+
lib/context-io/error/unauthorized.rb
|
63
|
+
lib/context-io/file.rb
|
64
|
+
lib/context-io/folder.rb
|
65
|
+
lib/context-io/message.rb
|
66
|
+
lib/context-io/oauth_provider.rb
|
67
|
+
lib/context-io/request.rb
|
68
|
+
lib/context-io/request/oauth.rb
|
69
|
+
lib/context-io/resource.rb
|
70
|
+
lib/context-io/response.rb
|
71
|
+
lib/context-io/response/parse_json.rb
|
72
|
+
lib/context-io/response/raise_client_error.rb
|
73
|
+
lib/context-io/response/raise_server_error.rb
|
74
|
+
lib/context-io/source.rb
|
75
|
+
lib/context-io/version.rb
|
76
|
+
spec/account_spec.rb
|
77
|
+
spec/contextio_spec.rb
|
78
|
+
spec/file_spec.rb
|
79
|
+
spec/fixtures/accounts.json
|
80
|
+
spec/fixtures/files.json
|
81
|
+
spec/fixtures/files_group.json
|
82
|
+
spec/fixtures/folders.json
|
83
|
+
spec/fixtures/messages.json
|
84
|
+
spec/fixtures/oauth_providers.json
|
85
|
+
spec/fixtures/sources.json
|
86
|
+
spec/folder_spec.rb
|
87
|
+
spec/message_spec.rb
|
88
|
+
spec/oauth_provider_spec.rb
|
89
|
+
spec/source_spec.rb
|
90
|
+
spec/spec_helper.rb
|
91
|
+
)
|
92
|
+
# = MANIFEST =
|
93
|
+
|
94
|
+
s.test_files = s.files.select { |path| path =~ /^spec\/spec_.*\.rb/ }
|
95
|
+
end
|
96
|
+
|
data/lib/context-io.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'context-io/config'
|
2
|
+
require 'context-io/authentication'
|
3
|
+
require 'context-io/account'
|
4
|
+
require 'context-io/file'
|
5
|
+
require 'context-io/oauth_provider'
|
6
|
+
require 'context-io/source'
|
7
|
+
require 'context-io/message'
|
8
|
+
require 'context-io/folder'
|
9
|
+
|
10
|
+
# The main ContextIO namespace.
|
11
|
+
module ContextIO
|
12
|
+
extend Config
|
13
|
+
extend Authentication
|
14
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'context-io/resource'
|
4
|
+
|
5
|
+
module ContextIO
|
6
|
+
# An account. Create one of these for every user.
|
7
|
+
#
|
8
|
+
# This does not represent a mail account. An Account can have several mail
|
9
|
+
# accounts attached to it as {Source}s.
|
10
|
+
#
|
11
|
+
# Only the {#first_name} and {#last_name} can be changed after creation.
|
12
|
+
class Account < ContextIO::Resource
|
13
|
+
# @api public
|
14
|
+
# @return [String] The unique ID of the account.
|
15
|
+
attr_reader :id
|
16
|
+
|
17
|
+
# @api public
|
18
|
+
# @return [String] The username of the account.
|
19
|
+
attr_reader :username
|
20
|
+
|
21
|
+
# @api public
|
22
|
+
# @return [Time] When the account was created.
|
23
|
+
attr_reader :created
|
24
|
+
|
25
|
+
# @api public
|
26
|
+
# @return [Time, nil] When the account was suspended, or nil if the account
|
27
|
+
# isn't suspended.
|
28
|
+
attr_reader :suspended
|
29
|
+
|
30
|
+
# @api public
|
31
|
+
# @return [Array<String>] The email addresses associated with the account.
|
32
|
+
attr_reader :email_addresses
|
33
|
+
|
34
|
+
# @api public
|
35
|
+
# @return [String] The first name of the account holder.
|
36
|
+
attr_accessor :first_name
|
37
|
+
|
38
|
+
# @api public
|
39
|
+
# @return [String] The last name of the account holder.
|
40
|
+
attr_accessor :last_name
|
41
|
+
|
42
|
+
# @api public
|
43
|
+
# @return [Time, nil] When the account password expired, or nil if the
|
44
|
+
# password hasn't expired.
|
45
|
+
attr_reader :password_expired
|
46
|
+
|
47
|
+
# @api public
|
48
|
+
# @return [Array<Source>] The sources associated with this account.
|
49
|
+
attr_reader :sources
|
50
|
+
|
51
|
+
# Get all the accounts, optionally filtered with a query
|
52
|
+
#
|
53
|
+
# @api public
|
54
|
+
#
|
55
|
+
# @param [Hash] query The query to filter accounts by. All fields are
|
56
|
+
# optional.
|
57
|
+
# @option query [String] :email Only return accounts associated with this
|
58
|
+
# email address.
|
59
|
+
# @option query [:invalid_credentials, :connection_impossible,
|
60
|
+
# :no_access_to_all_mail, :ok, :temp_disabled, :disabled] :status Only
|
61
|
+
# return accounts with sources whose status is the one given. If an
|
62
|
+
# account has several sources, only those matching the given status will
|
63
|
+
# be included in the response.
|
64
|
+
# @option query [true, false] :status_ok Whether to only return accounts
|
65
|
+
# with sources that are working or not working properly (true/false,
|
66
|
+
# respectively). As with the `:status` filter above, only sources matching
|
67
|
+
# the specific value are included in the response.
|
68
|
+
# @option query [Integer] :limit The maximum number of results to return.
|
69
|
+
# @option query [Integer] :offset The offset to start the list at (0 is no
|
70
|
+
# offset).
|
71
|
+
#
|
72
|
+
# @example Fetch all accounts
|
73
|
+
# ContextIO::Account.all
|
74
|
+
#
|
75
|
+
# @example Fetch all accounts with the email address me@example.com
|
76
|
+
# ContextIO::Account.all(:email => 'me@example.com')
|
77
|
+
#
|
78
|
+
# @return [Array<Account>] The accounts matching the query, or all if no
|
79
|
+
# query is given.
|
80
|
+
def self.all(query={})
|
81
|
+
query[:status] = query[:status].to_s.upcase if query[:status]
|
82
|
+
if query.has_key?(:status_ok)
|
83
|
+
query[:status_ok] = query[:status_ok] ? '1' : '0'
|
84
|
+
end
|
85
|
+
get('/2.0/accounts', query).map do |account|
|
86
|
+
Account.from_json(account)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Find an account given its ID
|
91
|
+
#
|
92
|
+
# @api public
|
93
|
+
#
|
94
|
+
# @param [String] id The ID of the account to look up.
|
95
|
+
#
|
96
|
+
# @example Find the account with the ID 'foobar'
|
97
|
+
# ContextIO::Account.find('foobar')
|
98
|
+
#
|
99
|
+
# @return [Account] The account with the given ID.
|
100
|
+
def self.find(id)
|
101
|
+
Account.from_json(get("/2.0/accounts/#{id}"))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Initialize an Account
|
105
|
+
#
|
106
|
+
# @api public
|
107
|
+
#
|
108
|
+
# @param [Hash] attributes The attributes to set on the account (all values
|
109
|
+
# are optional).
|
110
|
+
# @option attributes [String] :email The primary email address of the
|
111
|
+
# account holder.
|
112
|
+
# @option attributes [String] :first_name The first name of the account
|
113
|
+
# holder.
|
114
|
+
# @option attributes [String] :last_name The last name of the account
|
115
|
+
# holder.
|
116
|
+
#
|
117
|
+
# @example Initialize an account with the email 'me@example.com'
|
118
|
+
# ContextIO::Account.new(:email => 'me@example.com')
|
119
|
+
def initialize(attributes={})
|
120
|
+
@email_addresses = [attributes[:email]] if attributes[:email]
|
121
|
+
@first_name = attributes[:first_name]
|
122
|
+
@last_name = attributes[:last_name]
|
123
|
+
end
|
124
|
+
|
125
|
+
# Send the account info to Context.IO
|
126
|
+
#
|
127
|
+
# If this is the first time the account is sent to Context.IO, the first
|
128
|
+
# email address set will be sent as the primary email address, and the first
|
129
|
+
# and last name will be sent if they are specified. You are required to
|
130
|
+
# specify one email address.
|
131
|
+
#
|
132
|
+
# If the account has been sent to Context.IO before, this will update the
|
133
|
+
# first and last name.
|
134
|
+
#
|
135
|
+
# @api public
|
136
|
+
#
|
137
|
+
# @raise [ArgumentError] If there isn't at least one email address specified
|
138
|
+
# in the {#email_addresses} field.
|
139
|
+
#
|
140
|
+
# @example Create an account
|
141
|
+
# account = ContextIO::Account.new(:email => 'me@example.com')
|
142
|
+
# account.save
|
143
|
+
#
|
144
|
+
# @return [true, false] Whether the save succeeded or not.
|
145
|
+
def save
|
146
|
+
self.id ? update_record : create_record
|
147
|
+
end
|
148
|
+
|
149
|
+
# Update attributes on the account object and then send them to Context.IO
|
150
|
+
#
|
151
|
+
# @api public
|
152
|
+
#
|
153
|
+
# @param [Hash] attributes The attributes to update.
|
154
|
+
# @option attributes [String] :first_name The first name of the account
|
155
|
+
# holder.
|
156
|
+
# @option attributes [String] :last_name The last name of the account
|
157
|
+
# holder.
|
158
|
+
#
|
159
|
+
# @example Update the account holder's name to "John Doe"
|
160
|
+
# account.update_attributes(:first_name => 'John', :last_name => 'Doe')
|
161
|
+
#
|
162
|
+
# @return [true, false] Whether the update succeeded or not.
|
163
|
+
def update_attributes(attributes)
|
164
|
+
@first_name = attributes[:first_name] if attributes[:first_name]
|
165
|
+
@last_name = attributes[:last_name] if attributes[:last_name]
|
166
|
+
|
167
|
+
response = put("/2.0/accounts/#{self.id}", attributes)
|
168
|
+
|
169
|
+
response['success']
|
170
|
+
end
|
171
|
+
|
172
|
+
# Create the account on Context.IO
|
173
|
+
#
|
174
|
+
# @api private
|
175
|
+
#
|
176
|
+
# This will only send the first email address in the email_addresses
|
177
|
+
# attribute (which is required) as well as the first and last name if they
|
178
|
+
# are not-falsey.
|
179
|
+
#
|
180
|
+
# @return [true, false] Whether the creation succeeded or not.
|
181
|
+
def create_record
|
182
|
+
unless self.email_addresses && self.email_addresses.first
|
183
|
+
raise ArgumentError.new('You must specify an email address')
|
184
|
+
end
|
185
|
+
|
186
|
+
attributes = { :email => self.email_addresses.first }
|
187
|
+
attributes[:first_name] = self.first_name if self.first_name
|
188
|
+
attributes[:last_name] = self.last_name if self.last_name
|
189
|
+
|
190
|
+
response = post('/2.0/accounts', attributes)
|
191
|
+
@id = response['id']
|
192
|
+
|
193
|
+
@saved = response['success']
|
194
|
+
end
|
195
|
+
private :create_record
|
196
|
+
|
197
|
+
# Update the account on Context.IO
|
198
|
+
#
|
199
|
+
# Only sends the first and last name, as they are the only attributes the
|
200
|
+
# Context.IO API allows you to update.
|
201
|
+
#
|
202
|
+
# @api private
|
203
|
+
#
|
204
|
+
# @return [true, false] Whether the update succeeded or not.
|
205
|
+
def update_record
|
206
|
+
attributes = {}
|
207
|
+
attributes[:first_name] = self.first_name if self.first_name
|
208
|
+
attributes[:last_name] = self.last_name if self.last_name
|
209
|
+
response = put("/2.0/accounts/#{self.id}", attributes)
|
210
|
+
|
211
|
+
response['success']
|
212
|
+
end
|
213
|
+
private :update_record
|
214
|
+
|
215
|
+
# Create an Account instance from the JSON returned by the Context.IO server
|
216
|
+
#
|
217
|
+
# @api private
|
218
|
+
#
|
219
|
+
# @param [Hash] json The parsed JSON object returned by a Context.IO API
|
220
|
+
# request. See their documentation for what keys are possible.
|
221
|
+
#
|
222
|
+
# @return [Account] An account with the given attributes.
|
223
|
+
def self.from_json(json)
|
224
|
+
account = new
|
225
|
+
account.instance_eval do
|
226
|
+
@id = json['id']
|
227
|
+
@username = json['username']
|
228
|
+
if json['created'] == 0
|
229
|
+
@created = nil
|
230
|
+
else
|
231
|
+
@created = Time.at(json['created'])
|
232
|
+
end
|
233
|
+
if json['suspended'] == 0
|
234
|
+
@suspended = nil
|
235
|
+
else
|
236
|
+
@suspended = Time.at(json['suspended'])
|
237
|
+
end
|
238
|
+
@email_addresses = json['email_addresses']
|
239
|
+
@first_name = json['first_name']
|
240
|
+
@last_name = json['last_name']
|
241
|
+
if json['password_expired'] == 0
|
242
|
+
@password_expired = nil
|
243
|
+
else
|
244
|
+
@password_expired = json['password_expired']
|
245
|
+
end
|
246
|
+
@sources = json['sources'].map do |source|
|
247
|
+
Source.from_json(@id, source)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
account
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|