hiptail 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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/examples/integrate_sinatra/Gemfile +5 -0
- data/examples/integrate_sinatra/README.md +9 -0
- data/examples/integrate_sinatra/app.rb +58 -0
- data/examples/simple_rack_app_1/Gemfile +4 -0
- data/examples/simple_rack_app_1/README.md +9 -0
- data/examples/simple_rack_app_1/config.ru +56 -0
- data/examples/simple_rack_app_2/Gemfile +4 -0
- data/examples/simple_rack_app_2/README.md +9 -0
- data/examples/simple_rack_app_2/app.rb +42 -0
- data/examples/simple_rack_app_2/config.ru +4 -0
- data/hiptail.gemspec +53 -0
- data/lib/hiptail/atom.rb +303 -0
- data/lib/hiptail/authority/provider.rb +65 -0
- data/lib/hiptail/authority/sqlite3_provider.rb +85 -0
- data/lib/hiptail/authority.rb +258 -0
- data/lib/hiptail/event.rb +108 -0
- data/lib/hiptail/manager.rb +234 -0
- data/lib/hiptail/util.rb +78 -0
- data/lib/hiptail/version.rb +3 -0
- data/lib/hiptail/web/handler.rb +99 -0
- data/lib/hiptail/web/rack_app.rb +100 -0
- data/lib/hiptail.rb +9 -0
- metadata +126 -0
data/lib/hiptail/util.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
module HipTail
|
2
|
+
module Util
|
3
|
+
# Build capability object.
|
4
|
+
# @param [Hash] params
|
5
|
+
# @option params [String] :key Identical key for add-on
|
6
|
+
# @option params [String] :name Add-on name
|
7
|
+
# @option params [String] :base_url Base URL for add-on
|
8
|
+
# @option params [String] :capability_url URL for capability
|
9
|
+
# @option params [String] :webhook_url URL for event webhook
|
10
|
+
# @option params [String] :installed_url URL for installed / uninstalled event webhook
|
11
|
+
# @option params [String] :description (same as :name) Add-on description (optional)
|
12
|
+
# @option params [String] :vendor_name (same as :name) Vendor name (optional)
|
13
|
+
# @option params [String] :vendor_url (same as :base_url) Vendor URL (optional)
|
14
|
+
# @option params [String] :homepage_url (same as :base_url) Homepage (optional)
|
15
|
+
# @option params [String] :sender_name (same as :name) Name of notification sender (optional)
|
16
|
+
# @option params [String] :allow_global (true) Allow global installation (optional)
|
17
|
+
# @option params [String] :allow_room (true) Allow room installation (optional)
|
18
|
+
# @option params [String] :message_filter Room message filter regexp (optional)
|
19
|
+
def create_capability(params)
|
20
|
+
requireds = %w( key name
|
21
|
+
base_url capability_url webhook_url installed_url )
|
22
|
+
missings = requireds.select { |k| ! params.include?(k.to_sym) }
|
23
|
+
if missings.length > 0
|
24
|
+
raise "missing parameters: " + missings.join(%q{, })
|
25
|
+
end
|
26
|
+
|
27
|
+
capability = {
|
28
|
+
key: params[:key],
|
29
|
+
name: params[:name],
|
30
|
+
description: params[:description] || params[:name],
|
31
|
+
vendor: {
|
32
|
+
name: params[:vendor_name] || params[:name],
|
33
|
+
url: (params[:vendor_url] || params[:base_url]).to_s,
|
34
|
+
},
|
35
|
+
links: {
|
36
|
+
self: params[:capability_url].to_s,
|
37
|
+
homepage: (params[:homepage_url] || params[:base_url]).to_s,
|
38
|
+
},
|
39
|
+
capabilities: {
|
40
|
+
webhook: [],
|
41
|
+
hipchatApiConsumer: {
|
42
|
+
scopes: %w( send_notification send_message admin_room view_group ),
|
43
|
+
fromName: params[:sender_name] || params[:name],
|
44
|
+
},
|
45
|
+
installable: {
|
46
|
+
allowGlobal: params.include?(:allow_global) ? params[:allow_global] : true,
|
47
|
+
allowRoom: params.include?(:allow_room) ? params[:allow_room] : true,
|
48
|
+
callbackUrl: params[:installed_url].to_s,
|
49
|
+
}
|
50
|
+
},
|
51
|
+
}
|
52
|
+
|
53
|
+
event_names = %w( room_notification room_topic_change
|
54
|
+
room_enter room_exit )
|
55
|
+
webhook_url = params[:webhook_url].to_s
|
56
|
+
|
57
|
+
capability[:capabilities][:webhook] = event_names.map { |key|
|
58
|
+
{
|
59
|
+
name: key,
|
60
|
+
event: key,
|
61
|
+
url: webhook_url,
|
62
|
+
}
|
63
|
+
}
|
64
|
+
message_webhook = {
|
65
|
+
name: 'room_message',
|
66
|
+
event: 'room_message',
|
67
|
+
url: webhook_url,
|
68
|
+
}
|
69
|
+
if params[:message_filter]
|
70
|
+
message_webhook[:pattern] = params[:message_filter].to_s
|
71
|
+
end
|
72
|
+
capability[:capabilities][:webhook] << message_webhook
|
73
|
+
|
74
|
+
capability
|
75
|
+
end
|
76
|
+
module_function :create_capability
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'uri'
|
3
|
+
require 'hiptail/util'
|
4
|
+
|
5
|
+
module HipTail
|
6
|
+
module Web; end
|
7
|
+
|
8
|
+
class Web::Handler
|
9
|
+
# @return [HipTail::Manager] Returns HipTail::Manager.
|
10
|
+
attr_reader :manager
|
11
|
+
|
12
|
+
# @param [HipTail::Manager] manager
|
13
|
+
def initialize(manager)
|
14
|
+
@manager = manager
|
15
|
+
end
|
16
|
+
|
17
|
+
# Handles installing request.
|
18
|
+
# @param [Rack::Request] request
|
19
|
+
# @return [Array] Rack response.
|
20
|
+
def handle_install(request)
|
21
|
+
request.body.rewind
|
22
|
+
@manager.handle_install(JSON.parse(request.body.read))
|
23
|
+
create_response({})
|
24
|
+
end
|
25
|
+
|
26
|
+
# Handles uninstalling request.
|
27
|
+
# @note Uninstall event will be fired after uninstallation on the server.
|
28
|
+
# So you cannot use oauth information to do something (e.g. sending notification) on uninstallation phase.
|
29
|
+
# @param [Rack::Request] request
|
30
|
+
# @param [String] oauth_id Corresponding OAuth ID
|
31
|
+
# @return [Array] Rack response.
|
32
|
+
def handle_uninstall(request, oauth_id)
|
33
|
+
@manager.handle_uninstall(oauth_id)
|
34
|
+
create_response({})
|
35
|
+
end
|
36
|
+
|
37
|
+
# Handles events (room_message, room_enter, etc.).
|
38
|
+
# @param [Rack::Request] request
|
39
|
+
# @return [Array] Rack response.
|
40
|
+
def handle_event(request)
|
41
|
+
request.body.rewind
|
42
|
+
@manager.handle_event(JSON.parse(request.body.read))
|
43
|
+
create_response({})
|
44
|
+
end
|
45
|
+
|
46
|
+
# Handles retrieving capability request.
|
47
|
+
# @param [Rack::Request] request
|
48
|
+
# @param [Hash] params Capability parameters
|
49
|
+
# @option params [String] :key Identical key for add-on
|
50
|
+
# @option params [String] :name Add-on name
|
51
|
+
# @option params [String] :base_url Base URL for add-on
|
52
|
+
# @option params [String] :capability_url URL for capability
|
53
|
+
# @option params [String] :webhook_url URL for event webhook
|
54
|
+
# @option params [String] :installed_url URL for installed / uninstalled event webhook
|
55
|
+
# @option params [String] :description (same as :name) Add-on description (optional)
|
56
|
+
# @option params [String] :vendor_name (same as :name) Vendor name (optional)
|
57
|
+
# @option params [String] :vendor_url (same as :base_url) Vendor URL (optional)
|
58
|
+
# @option params [String] :homepage_url (same as :base_url) Homepage (optional)
|
59
|
+
# @option params [String] :sender_name (same as :name) Name of notification sender (optional)
|
60
|
+
# @option params [String] :allow_global (true) Allow global installation (optional)
|
61
|
+
# @option params [String] :allow_room (true) Allow room installation (optional)
|
62
|
+
# @option params [String] :message_filter Room message filter regexp (optional)
|
63
|
+
# @return [Array] Rack response.
|
64
|
+
def handle_capability(request, params)
|
65
|
+
requireds = %w( key name
|
66
|
+
webhook_path installed_path )
|
67
|
+
missings = requireds.select { |k| ! params.include?(k.to_sym) }
|
68
|
+
if missings.length > 0
|
69
|
+
raise "missing parameters: " + missings.join(%q{, })
|
70
|
+
end
|
71
|
+
params = params.dup
|
72
|
+
|
73
|
+
params[:capability_url] = request.url.to_s
|
74
|
+
|
75
|
+
base_url = URI.parse(request.url).merge(params[:base_path] || '/')
|
76
|
+
params[:base_url] = base_url.to_s
|
77
|
+
|
78
|
+
params[:webhook_url] = base_url.merge('./' + params[:webhook_path])
|
79
|
+
params[:installed_url] = base_url.merge('./' + params[:installed_path])
|
80
|
+
|
81
|
+
capability = HipTail::Util::create_capability(params)
|
82
|
+
create_response(capability)
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param [Hash] data
|
86
|
+
# @param [Integer] status (200)
|
87
|
+
def create_response(data, status = 200)
|
88
|
+
body = JSON.generate(data)
|
89
|
+
|
90
|
+
body.gsub!(/[\u{007f}-\u{10ffff}]+/) { |match| match.unpack("U*").map! { |i| "\\u#{i.to_s(16)}" }.join }
|
91
|
+
|
92
|
+
headers = {
|
93
|
+
'Content-Type' => 'application/json; charset=UTF-8',
|
94
|
+
'Content-Length' => body.bytesize.to_s,
|
95
|
+
}
|
96
|
+
return [ status, headers, [ body ] ]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
require 'hiptail/web/handler'
|
5
|
+
|
6
|
+
module HipTail
|
7
|
+
module Web; end
|
8
|
+
|
9
|
+
class Web::RackApp
|
10
|
+
# @return [HipTail::Manager] Returns HipTail::Manager.
|
11
|
+
attr_reader :manager
|
12
|
+
|
13
|
+
# @param [Hash] params Capability parameters (and manager)
|
14
|
+
# @option params [HipTail::Manager] :manager HipTail::Manager instance (optional)
|
15
|
+
# @option params [String] :key Identical key for add-on
|
16
|
+
# @option params [String] :name Add-on name
|
17
|
+
# @option params [String] :base_url Base URL for add-on
|
18
|
+
# @option params [String] :capability_url URL for capability
|
19
|
+
# @option params [String] :webhook_url URL for event webhook
|
20
|
+
# @option params [String] :installed_url URL for installed / uninstalled event webhook
|
21
|
+
# @option params [String] :description (same as :name) Add-on description (optional)
|
22
|
+
# @option params [String] :vendor_name (same as :name) Vendor name (optional)
|
23
|
+
# @option params [String] :vendor_url (same as :base_url) Vendor URL (optional)
|
24
|
+
# @option params [String] :homepage_url (same as :base_url) Homepage (optional)
|
25
|
+
# @option params [String] :sender_name (same as :name) Name of notification sender (optional)
|
26
|
+
# @option params [String] :allow_global (true) Allow global installation (optional)
|
27
|
+
# @option params [String] :allow_room (true) Allow room installation (optional)
|
28
|
+
# @option params [String] :message_filter Room message filter regexp (optional)
|
29
|
+
def initialize(params)
|
30
|
+
params = params.dup
|
31
|
+
@manager = params.delete(:manager) || Manager.new
|
32
|
+
@handler = Web::Handler.new(@manager)
|
33
|
+
|
34
|
+
params[:base_path] ||= '/'
|
35
|
+
params[:webhook_path] ||= '/event'
|
36
|
+
params[:installed_path] ||= '/install'
|
37
|
+
params[:capability_path] ||= '/cap'
|
38
|
+
@capability_params = params
|
39
|
+
|
40
|
+
base_url = URI.parse('http://example.com/').merge(params[:base_path])
|
41
|
+
path = {
|
42
|
+
:base => base_url.request_uri,
|
43
|
+
}
|
44
|
+
[ :webhook, :installed, :capability ].each do |key|
|
45
|
+
path[key] = base_url.merge('./' + params["#{key}_path".to_sym]).request_uri
|
46
|
+
end
|
47
|
+
|
48
|
+
@regex = {}
|
49
|
+
@regex[:capability] = %r{\A #{Regexp.escape(path[:capability])} \z}xm
|
50
|
+
@regex[:event] = %r{\A #{Regexp.escape(path[:webhook])} \z}xm
|
51
|
+
|
52
|
+
@regex[:install] = %r{\A #{Regexp.escape(path[:installed])} \z}xm
|
53
|
+
@regex[:uninstall] = %r{\A #{Regexp.escape(path[:installed])} / ([-0-9a-fA-F]+) \z}xm
|
54
|
+
end
|
55
|
+
|
56
|
+
def call(env)
|
57
|
+
req = Rack::Request.new(env)
|
58
|
+
|
59
|
+
case req.path_info
|
60
|
+
when @regex[:capability]
|
61
|
+
if req.get?
|
62
|
+
return on_capability(req)
|
63
|
+
end
|
64
|
+
when @regex[:event]
|
65
|
+
if req.post?
|
66
|
+
return on_event(req)
|
67
|
+
end
|
68
|
+
when @regex[:install]
|
69
|
+
if req.post?
|
70
|
+
return on_install(req)
|
71
|
+
end
|
72
|
+
when @regex[:uninstall]
|
73
|
+
if req.delete?
|
74
|
+
return on_uninstall(req, $1)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
return @handler.create_response({}, 404)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def on_capability(request)
|
84
|
+
@capability_cached ||= @handler.handle_capability(request, @capability_params)
|
85
|
+
@capability_cached
|
86
|
+
end
|
87
|
+
|
88
|
+
def on_event(request)
|
89
|
+
@handler.handle_event(request)
|
90
|
+
end
|
91
|
+
|
92
|
+
def on_install(request)
|
93
|
+
@handler.handle_install(request)
|
94
|
+
end
|
95
|
+
|
96
|
+
def on_uninstall(request, oauth_id)
|
97
|
+
@handler.handle_uninstall(request, oauth_id)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/hiptail.rb
ADDED
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hiptail
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ITO Nobuaki
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: oauth2
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
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: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
description: HipChat Add-on Framework
|
70
|
+
email:
|
71
|
+
- daydream.trippers@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- Gemfile
|
77
|
+
- LICENSE.txt
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- examples/integrate_sinatra/Gemfile
|
81
|
+
- examples/integrate_sinatra/README.md
|
82
|
+
- examples/integrate_sinatra/app.rb
|
83
|
+
- examples/simple_rack_app_1/Gemfile
|
84
|
+
- examples/simple_rack_app_1/README.md
|
85
|
+
- examples/simple_rack_app_1/config.ru
|
86
|
+
- examples/simple_rack_app_2/Gemfile
|
87
|
+
- examples/simple_rack_app_2/README.md
|
88
|
+
- examples/simple_rack_app_2/app.rb
|
89
|
+
- examples/simple_rack_app_2/config.ru
|
90
|
+
- hiptail.gemspec
|
91
|
+
- lib/hiptail.rb
|
92
|
+
- lib/hiptail/atom.rb
|
93
|
+
- lib/hiptail/authority.rb
|
94
|
+
- lib/hiptail/authority/provider.rb
|
95
|
+
- lib/hiptail/authority/sqlite3_provider.rb
|
96
|
+
- lib/hiptail/event.rb
|
97
|
+
- lib/hiptail/manager.rb
|
98
|
+
- lib/hiptail/util.rb
|
99
|
+
- lib/hiptail/version.rb
|
100
|
+
- lib/hiptail/web/handler.rb
|
101
|
+
- lib/hiptail/web/rack_app.rb
|
102
|
+
homepage: https://github.com/dayflower/hiptail
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.2.2
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: HipChat Add-on Framework
|
126
|
+
test_files: []
|