workxp 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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ODg5YTkzY2JmNGI3YmVkNzllZGZlYTlmMWVlNGRlNzA3MTAzMDA2Yg==
5
+ data.tar.gz: !binary |-
6
+ OGQ0YTYxZjAwYWIwZmE3ODI5MzYzNTNmMjUxYzcwYmMyMjk4YjEwMQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NGM2NWI4Y2QzZTNjODE2OTFhOGZlNzdhM2VlODVlODMzMTRkOWFiODhhNDg3
10
+ ZTEyMDAzNzA5NGNkZjU2ZDkxMTRmMTg1NTA5Mzc0OWNlNjUyNzhmYjZkNGVl
11
+ YTMwNmI3OTZkM2ZmMTdhMzNiYjYyMmFkNWFhMDQ2ZDg1YzQxZmY=
12
+ data.tar.gz: !binary |-
13
+ YjQwZjgxM2IyNzFiYmViYTEzMGIyMjY2MDYzZWM2YmVlYTA4NmExMTUwNDJm
14
+ OGIxZTNlNjNhYzUwZGEzMDY2ODljYTM2ZDU4NjE5MjcxNzljYzM0N2FmY2Vm
15
+ MDAxYjljMTFhZDJkZGFhMTNmN2Y3ODFiMTdlNjcyMmFlNDU2ZTI=
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in workxp.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Yuan Ping
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,101 @@
1
+ # Workxp
2
+
3
+ A Ruby interface to the [WorkXP API](https://github.com/yuanping/workxp-api).
4
+
5
+ 在OAuth2::Client的基础上封装了WorkXP API,使用OAuth2的Token创建Workxp::Client,返回Hash或Array。
6
+ 获取OAuth2 Token可以使用 [omniauth-workxp](https://github.com/liuqi1024/omniauth-workxp) Gem。
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'workxp'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install workxp
21
+
22
+ ## Usage
23
+
24
+ ```shell
25
+ client = Workxp::Client.new token: 'oauth2 token',
26
+ refresh_token: 'oauth2 refresh token',
27
+ expires_at: 1.month.from_now,
28
+ sub_domain: 'your subdomain',
29
+ app_key: 'app key',
30
+ app_secret: 'app secret',
31
+ user_agent: 'WorkXP iOS客户端'
32
+
33
+ ```
34
+
35
+ 获得所有联系人,以Hash的方式传参数
36
+
37
+ client.contacts #=> [{"id": 37, name: 'YuanPing', ...}]
38
+ client.contacts "begin" => '2014-06-01T10:00:00+0800', "end" => '2014-07-01T10:00:00+0800', "page" => 2
39
+
40
+ 通过ID取某一个联系人信息
41
+
42
+ client.contact '37' #=> {"id": 37, name: 'YuanPing', ...}
43
+
44
+ 创建、更新一个联系人
45
+
46
+ contact_hash = {name: 'Pan', type: 'Person', contact_methods: [{type: 'ContactPhone', key: 'mobile', value: '13800138000'}]}
47
+ client.create_contact contact_hash.to_json
48
+ #=> {"id": 38, name: 'Pan', ...}
49
+
50
+ client.update_contact '38', contact_hash.to_json
51
+
52
+ 删除联系人
53
+
54
+ client.delete_contact '38'
55
+
56
+ ## API List
57
+ 联系人
58
+ ```shell
59
+ contacts(opts={})
60
+ contact(id)
61
+ create_contact(json)
62
+ update_contact(id, json)
63
+ delete_contact(id)
64
+ ```
65
+
66
+ 机会
67
+ ```shell
68
+ deals(opts={})
69
+ deal(id)
70
+ create_deal(json)
71
+ update_deal(id, json)
72
+ delete_deal(id)
73
+ ```
74
+
75
+ 项目(kase) 账户信息(account) 分类(category) 任务(task) 事件(note) 的接口与联系人与机会接口的命名规则相同。
76
+
77
+ 其它接口:
78
+ ```shell
79
+ deletions(opts={})
80
+
81
+ task_categories(opts={})
82
+ groups
83
+ tags
84
+
85
+ # create_attachment '/path/file.png', 'image/png'
86
+ create_attachment(file_path, file_type)
87
+
88
+ # search_activities term: 'test'
89
+ search_activities(opts={})
90
+
91
+ activities(opts={})
92
+
93
+ ```
94
+
95
+ ## Contributing
96
+
97
+ 1. Fork it
98
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
99
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
100
+ 4. Push to the branch (`git push origin my-new-feature`)
101
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,6 @@
1
+ require "workxp/version"
2
+ require 'workxp/client'
3
+
4
+ module Workxp
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,124 @@
1
+ require "workxp/restfulable"
2
+
3
+ module Workxp
4
+ class Client
5
+
6
+ delegate :delete, :get, :post, :put, :request, to: :valid_token
7
+
8
+ WORKXP_SITE = "https://workxp.info"
9
+
10
+ include Workxp::Restfulable
11
+
12
+ # OAuth2::AccessToken
13
+ #
14
+ # Store authorized infos
15
+ attr_accessor :access_token
16
+
17
+ # WorkXP product's subdomain. subdomain is your product's identify.
18
+ # Your can set different subdomain for fetch different product's data.
19
+ # @example
20
+ # https://ruby.workxp.info 'ruby' is subdomain
21
+ attr_accessor :sub_domain
22
+
23
+ # @param [Hash] opts the options to create WorkXP Client.
24
+ # @option opts [String] :app_key <required>
25
+ # @option opts [String] :app_secret <required>
26
+ # @option opts [String] :token oauth2 access token. <required>
27
+ # @option opts [String] :refresh_token <optional>
28
+ # @option opts [DateTime] :expires_at <optional>
29
+ # @option opts [String] :workxp_site <optional>
30
+ # @option opts [String] :sub_domain <optional>
31
+ # @option opts [String] :user_agent <optional> App name of client
32
+ def initialize(opts={})
33
+ @app_key = opts.delete :app_key
34
+ @app_secret = opts.delete :app_secret
35
+ @workxp_site = opts.delete(:workxp_site) || WORKXP_SITE
36
+ @user_agent = opts.delete(:user_agent)
37
+ self.sub_domain = opts.delete :sub_domain
38
+
39
+ self.access_token = OAuth2::AccessToken.new(self.oauth_client, opts[:token], opts)
40
+ end
41
+
42
+ # OAuth2::Client instance with WorkxP OAuth
43
+ def oauth_client
44
+ @oauth_client ||= OAuth2::Client.new @app_key, @app_secret, site: @workxp_site do |stack|
45
+ stack.request :multipart
46
+ stack.request :url_encoded
47
+ stack.adapter :net_http
48
+ end
49
+ end
50
+
51
+ def valid_token
52
+ if access_token.expired?
53
+ self.access_token = access_token.refresh!
54
+ end
55
+ self.access_token
56
+ end
57
+
58
+ # @param [Hash] opts the request parameters
59
+ # @option opts [String] :group_id Filter by group_id
60
+ def users(opts={})
61
+ valid_token.get('/api/users.json', params: opts, headers: domain_hash).parsed
62
+ end
63
+
64
+ def user(id)
65
+ valid_token.get("/api/users/#{id}.json", headers: domain_hash).parsed
66
+ end
67
+
68
+ def accounts
69
+ valid_token.get("/api/accounts.json", )
70
+ end
71
+
72
+ def activities(opts={})
73
+ valid_token.get('/api/activities.json', params: opts, headers: domain_hash).parsed
74
+ end
75
+
76
+ def search_activities(opts={})
77
+ valid_token.get('/api/activities/search.json', params: opts, headers: domain_hash).parsed
78
+ end
79
+
80
+ def activity(id)
81
+ valid_token.get("/api/activities/#{id}.json", headers: domain_hash).parsed
82
+ end
83
+
84
+ # @param [String] file_path 'path/avatar.png'
85
+ # @param [String] file_type 'image/png'
86
+ # @return [Hash] {"token"=>"1578a2cd0682359935ae03826fb892701f7c5120"}
87
+ def create_attachment(file_path, file_type)
88
+ payload = {file: Faraday::UploadIO.new(file_path, file_type)}
89
+ valid_token.post("/api/attachments.json", body: payload, headers: {:'Sub-Domain' => sub_domain}).parsed
90
+ end
91
+
92
+ def tags
93
+ valid_token.get('/api/tags.json', headers: domain_hash).parsed
94
+ end
95
+
96
+ def groups
97
+ valid_token.get('/api/groups.json', headers: domain_hash).parsed
98
+ end
99
+
100
+ def deletions(opts={})
101
+ valid_token.get('/api/deletions.json', params: opts, headers: domain_hash).parsed
102
+ end
103
+
104
+
105
+ restful_api "account"
106
+ restful_api "contact"
107
+ restful_api "task"
108
+ restful_api "note"
109
+ restful_api "deal"
110
+ restful_api "kase"
111
+ restful_api "category"
112
+
113
+ def task_categories
114
+ categories.select {|obj| obj['type'] == 'TaskCategory'}
115
+ end
116
+
117
+ private
118
+ def domain_hash
119
+ raise(ArgumentError, "WorkXP Subdomain required.") if sub_domain.nil?
120
+ {:'Sub-Domain' => sub_domain, :'Content-Type' => 'application/json', :'User-Agent' => (@user_agent || 'WorkXP Client')}
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,34 @@
1
+ module Workxp::Restfulable
2
+
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def restful_api(name)
10
+ names = name.pluralize
11
+ define_method "#{names}" do |*args|
12
+ opts = args.first || Hash.new
13
+ valid_token.get("/api/#{names}.json", params: opts, headers: domain_hash).parsed
14
+ end
15
+
16
+ define_method name do |id|
17
+ valid_token.get("/api/tasks/#{id}.json", headers: domain_hash).parsed
18
+ end
19
+
20
+ define_method "create_#{name}" do |json|
21
+ valid_token.post("/api/#{names}.json", body: json, headers: domain_hash).parsed
22
+ end
23
+
24
+ define_method "update_#{name}" do |id, json|
25
+ valid_token.put("/api/#{names}/#{id}.json", body: json, headers: domain_hash).parsed
26
+ end
27
+
28
+ define_method "delete_#{name}" do |id|
29
+ valid_token.delete("/api/#{names}/#{id}.json", headers: domain_hash).parsed
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Workxp
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'workxp/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "workxp"
8
+ spec.version = Workxp::VERSION
9
+ spec.authors = ["Yuan Ping"]
10
+ spec.email = ["yp.xjgz@gmail.com"]
11
+ spec.description = %q{A Ruby interface to the WorkXP API.}
12
+ spec.summary = %q{A Ruby interface to the WorkXP API.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_dependency "oauth2"
25
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: workxp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuan Ping
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: oauth2
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A Ruby interface to the WorkXP API.
56
+ email:
57
+ - yp.xjgz@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/workxp.rb
68
+ - lib/workxp/client.rb
69
+ - lib/workxp/restfulable.rb
70
+ - lib/workxp/version.rb
71
+ - workxp.gemspec
72
+ homepage: ''
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.1.11
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: A Ruby interface to the WorkXP API.
96
+ test_files: []