context-io 0.0.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.
- 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
|
+
[](http://travis-ci.org/dvyjones/context-io)
|
5
|
+
[](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
|