scsi 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +76 -0
- data/bin/scsi-server +20 -0
- data/lib/scsi/config.rb +38 -0
- data/lib/scsi/helper.rb +79 -0
- data/lib/scsi/logger.rb +24 -0
- data/lib/scsi/server.rb +56 -0
- data/lib/scsi/version.rb +5 -0
- data/lib/scsi.rb +3 -0
- data/scsi.gemspec +21 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 72b52c20daefb5e48f29ea7a3669f062b9f2bb7d
|
4
|
+
data.tar.gz: fdcfa0bf71e203f47be2204880242811dedefa6c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 65e4ee49682f37fdd0d15ea7890c80cb4981944b23142b54df3903ad77c22da92545e6db664e5a9d86ce801ad25501c324db21190454bab12b627b63f97aee25
|
7
|
+
data.tar.gz: 5e0acb79d339383eee13ef48d1d3e64c43e5698ef9f6814b314ae1d8fd1556398d26d2bc0cbc6ef0bf3b161818d3f806b484d1d97a2e78f03a917c8a3fb6c496
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Ken J.
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# scsi
|
2
|
+
|
3
|
+
A Ruby server for receiving Slack Slash Command and responding with Slack info.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
- [Ruby](https://www.ruby-lang.org/) 2.1 <=
|
8
|
+
- [Kajiki](https://kenjij.github.io/kajiki/) 1.1 <=
|
9
|
+
- [Sinatra](http://www.sinatrarb.com) 1.4 <=
|
10
|
+
|
11
|
+
## Getting Started
|
12
|
+
|
13
|
+
### Install
|
14
|
+
|
15
|
+
```
|
16
|
+
$ gem install scsi
|
17
|
+
```
|
18
|
+
|
19
|
+
Optionally install [Thin](http://code.macournoyer.com/thin/) for more robustness.
|
20
|
+
|
21
|
+
### Configure
|
22
|
+
|
23
|
+
Optionally, create a configuration file following the example below.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# Configure application logging
|
27
|
+
SCSI.logger = Logger.new(STDOUT)
|
28
|
+
SCSI.logger.level = Logger::DEBUG
|
29
|
+
|
30
|
+
SCSI::Config.setup do |c|
|
31
|
+
# Optional: if any number of strings are set, it will require a matching
|
32
|
+
# "token" parameter in the incoming request (generated by Slack)
|
33
|
+
c.tokens = [
|
34
|
+
'sLaCkG3nEr4TeDt0KeN'
|
35
|
+
]
|
36
|
+
# HTTP server (Sinatra) settings
|
37
|
+
c.dump_errors = true
|
38
|
+
c.logging = true
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
### Run
|
43
|
+
|
44
|
+
In Slack, add a [Slash Command](https://my.slack.com/apps/A0F82E8CA-slash-commands) configuration. Set the URL to wherever you're exposing the SCSI server at. (Hint: setup an SSL front; Slack requires your server to talk HTTPS. E.g., NGINX reverse proxy, [Cloudflare](https://www.cloudflare.com/ssl/).)
|
45
|
+
|
46
|
+
The minimum to start the SCSI server:
|
47
|
+
|
48
|
+
```
|
49
|
+
$ scsi-server start
|
50
|
+
```
|
51
|
+
|
52
|
+
Or, to use your configuration file:
|
53
|
+
|
54
|
+
```
|
55
|
+
$ scsi-server start -c config.rb
|
56
|
+
```
|
57
|
+
|
58
|
+
See help for more options:
|
59
|
+
|
60
|
+
```
|
61
|
+
$ scsi-server -h
|
62
|
+
```
|
63
|
+
|
64
|
+
### Use
|
65
|
+
|
66
|
+
In any Slack channel, type your slash command; e.g., `/slackinfo`. You'll get a response like:
|
67
|
+
|
68
|
+
> BOT 00:00 Only visible to you
|
69
|
+
|
70
|
+
> SCSI: Slash Command Slack Info v0.0.0
|
71
|
+
|
72
|
+
> > **channel_name**
|
73
|
+
> > general
|
74
|
+
|
75
|
+
> > **channel_id**
|
76
|
+
> > C000AAAAA
|
data/bin/scsi-server
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'kajiki'
|
3
|
+
require 'scsi'
|
4
|
+
|
5
|
+
|
6
|
+
opts = Kajiki.preset_options(:server, {config: true})
|
7
|
+
|
8
|
+
Kajiki.run(opts) do |cmd|
|
9
|
+
case cmd
|
10
|
+
when 'start'
|
11
|
+
SCSI::Config.load_config(opts[:config]) if opts[:config]
|
12
|
+
require 'scsi/server'
|
13
|
+
SCSI.logger.warn('SCSI server starting...')
|
14
|
+
Rack::Server.start({
|
15
|
+
app: SCSI::Server.new,
|
16
|
+
Host: opts[:address],
|
17
|
+
Port: opts[:port]
|
18
|
+
})
|
19
|
+
end
|
20
|
+
end
|
data/lib/scsi/config.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module SCSI
|
2
|
+
|
3
|
+
class Config
|
4
|
+
|
5
|
+
# Load Ruby config file
|
6
|
+
# @param path [String] config file
|
7
|
+
def self.load_config(path)
|
8
|
+
raise 'config file missing' unless path
|
9
|
+
SCSI.logger.debug("Loading config file: #{path}")
|
10
|
+
require File.expand_path(path)
|
11
|
+
SCSI.logger.info('Config.load_config done.')
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the shared instance
|
15
|
+
# @return [SCSI::Config]
|
16
|
+
def self.shared
|
17
|
+
@shared_config ||= Config.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Call this from your config file
|
21
|
+
def self.setup
|
22
|
+
yield Config.shared
|
23
|
+
SCSI.logger.debug('Config.setup block executed.')
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_accessor :tokens
|
27
|
+
attr_accessor :dump_errors
|
28
|
+
attr_accessor :logging
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@tokens = []
|
32
|
+
@dump_errors = false
|
33
|
+
@logging = false
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/scsi/helper.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module SCSI
|
5
|
+
|
6
|
+
module Helper
|
7
|
+
|
8
|
+
def slash_keys
|
9
|
+
return [
|
10
|
+
:user_name, :user_id,
|
11
|
+
:channel_name, :channel_id,
|
12
|
+
:team_domain, :team_id
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse_slash(params)
|
17
|
+
return nil unless params.class == Hash
|
18
|
+
info = {}
|
19
|
+
slash_keys.each { |k| info[k] = params[k] }
|
20
|
+
return info
|
21
|
+
end
|
22
|
+
|
23
|
+
def format_info(info)
|
24
|
+
attachments = []
|
25
|
+
i = 0
|
26
|
+
while i < slash_keys.count do
|
27
|
+
a = slash_keys[i]
|
28
|
+
b = slash_keys[i + 1]
|
29
|
+
attachments << {fields: [
|
30
|
+
{title: a, value: info[a], short: true},
|
31
|
+
{title: b, value: info[b], short: true}
|
32
|
+
]}
|
33
|
+
i += 2
|
34
|
+
end
|
35
|
+
return {
|
36
|
+
response_type: "ephemeral",
|
37
|
+
text: "SCSI: Slash Command Slack Info v#{SCSI::Version}",
|
38
|
+
attachments: attachments
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
# Convert object into JSON, optionally pretty-format
|
43
|
+
# @param obj [Object] any Ruby object
|
44
|
+
# @param opts [Hash] any JSON options
|
45
|
+
# @return [String] JSON string
|
46
|
+
def json_with_object(obj, pretty: true, opts: nil)
|
47
|
+
return '{}' if obj.nil?
|
48
|
+
if pretty
|
49
|
+
opts = {
|
50
|
+
indent: ' ',
|
51
|
+
space: ' ',
|
52
|
+
object_nl: "\n",
|
53
|
+
array_nl: "\n"
|
54
|
+
}
|
55
|
+
end
|
56
|
+
JSON.fast_generate(json_format_value(obj), opts)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Return Ruby object/value to JSON standard format
|
60
|
+
# @param val [Object]
|
61
|
+
# @return [Object]
|
62
|
+
def json_format_value(val)
|
63
|
+
case val
|
64
|
+
when Array
|
65
|
+
val.map { |v| json_format_value(v) }
|
66
|
+
when Hash
|
67
|
+
val.reduce({}) { |h, (k, v)| h.merge({k => json_format_value(v)}) }
|
68
|
+
when String
|
69
|
+
val.encode!('UTF-8', {invalid: :replace, undef: :replace})
|
70
|
+
when Time
|
71
|
+
val.utc.iso8601
|
72
|
+
else
|
73
|
+
val
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/lib/scsi/logger.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
|
4
|
+
module SCSI
|
5
|
+
|
6
|
+
def self.logger=(logger)
|
7
|
+
@logger = logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.logger
|
11
|
+
@logger ||= NullLogger.new()
|
12
|
+
end
|
13
|
+
|
14
|
+
class NullLogger < Logger
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(*args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/scsi/server.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'scsi/helper'
|
3
|
+
|
4
|
+
module SCSI
|
5
|
+
|
6
|
+
# The Sinatra server
|
7
|
+
class Server < Sinatra::Base
|
8
|
+
|
9
|
+
helpers Helper
|
10
|
+
|
11
|
+
configure do
|
12
|
+
set :environment, :production
|
13
|
+
disable :static
|
14
|
+
c = Config.shared
|
15
|
+
set :dump_errors, c.dump_errors
|
16
|
+
set :logging, c.logging
|
17
|
+
SCSI.logger.info('Sinatra server configured.')
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
tokens = Config.shared.tokens
|
22
|
+
halt 401 unless tokens.empty? || tokens.include?(params[:token])
|
23
|
+
end
|
24
|
+
|
25
|
+
post '/' do
|
26
|
+
SCSI.logger.info('Incoming request received.')
|
27
|
+
SCSI.logger.debug("Body size: #{request.content_length} bytes")
|
28
|
+
info = parse_slash(params)
|
29
|
+
json_with_object(format_info(info))
|
30
|
+
end
|
31
|
+
|
32
|
+
not_found do
|
33
|
+
SCSI.logger.info('Invalid request.')
|
34
|
+
SCSI.logger.debug("Request method and path: #{request.request_method} #{request.path}")
|
35
|
+
json_with_object({message: 'Huh, nothing here.'})
|
36
|
+
end
|
37
|
+
|
38
|
+
error 401 do
|
39
|
+
SCSI.logger.info(params[:token] ? 'Invalid token provided.' : 'Missing token.')
|
40
|
+
SCSI.logger.debug("Provided auth token: #{params[:auth]}") if params[:auth]
|
41
|
+
json_with_object({message: 'Oops, need a valid auth.'})
|
42
|
+
end
|
43
|
+
|
44
|
+
error do
|
45
|
+
status 500
|
46
|
+
err = env['sinatra.error']
|
47
|
+
SCSI.logger.error "#{err.class.name} - #{err}"
|
48
|
+
json_with_object({message: 'Yikes, internal error.'})
|
49
|
+
end
|
50
|
+
|
51
|
+
after do
|
52
|
+
content_type 'application/json'
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/lib/scsi/version.rb
ADDED
data/lib/scsi.rb
ADDED
data/scsi.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
2
|
+
require 'scsi/version'
|
3
|
+
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'scsi'
|
7
|
+
s.version = SCSI::Version
|
8
|
+
s.authors = ['Ken']
|
9
|
+
s.email = ['ken@propelfuels.com']
|
10
|
+
s.summary = %q{SCSI: Slash Command Slack Info}
|
11
|
+
s.description = %q{A Ruby server for receiving Slack Slash Command and responding with Slack info.}
|
12
|
+
s.homepage = 'https://github.com/propelfuels/scsi'
|
13
|
+
s.license = 'MIT'
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split($/)
|
16
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
|
19
|
+
s.add_runtime_dependency 'kajiki', '~> 1.1'
|
20
|
+
s.add_runtime_dependency 'sinatra', '~> 1.4'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scsi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ken
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kajiki
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.4'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.4'
|
41
|
+
description: A Ruby server for receiving Slack Slash Command and responding with Slack
|
42
|
+
info.
|
43
|
+
email:
|
44
|
+
- ken@propelfuels.com
|
45
|
+
executables:
|
46
|
+
- scsi-server
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- LICENSE
|
51
|
+
- README.md
|
52
|
+
- bin/scsi-server
|
53
|
+
- lib/scsi.rb
|
54
|
+
- lib/scsi/config.rb
|
55
|
+
- lib/scsi/helper.rb
|
56
|
+
- lib/scsi/logger.rb
|
57
|
+
- lib/scsi/server.rb
|
58
|
+
- lib/scsi/version.rb
|
59
|
+
- scsi.gemspec
|
60
|
+
homepage: https://github.com/propelfuels/scsi
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 2.4.8
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: 'SCSI: Slash Command Slack Info'
|
84
|
+
test_files: []
|