scsi 0.1.0

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 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
1
+ module SCSI
2
+
3
+ Version = '0.1.0'
4
+
5
+ end
data/lib/scsi.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'scsi/version'
2
+ require 'scsi/logger'
3
+ require 'scsi/config'
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: []