embulk-input-slack_channel_messages 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5d70c06c882e105c8b5729d24ad6e3d244d1f9f7048586b1da4039954cf63800
4
+ data.tar.gz: ba6594949b3ba80bfb9555b6ef09502d9dfa29e92ee81a9d6ce9c61c3021b1c1
5
+ SHA512:
6
+ metadata.gz: 9d469dee6d30a5eb141ddebe98a97fc5c88283b57eaa51a0633c172e1a5dc64d3413b008db2884d8c0b364cb2fbd9c093ea3848dfc08b7350daa22f3d3f63e5a
7
+ data.tar.gz: b734b76cadf28c24f55aac1642fc3f7ea344e531f2695b38b3a744d9f54b7695688a1de6b5c1c865b3b86dd708c30c6892e0a49977700ffa0bf587104992204c
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *~
2
+ /pkg/
3
+ /tmp/
4
+ /.bundle/
5
+ /.ruby-version
6
+ /Gemfile.lock
7
+ /spec/lib/embulk/input/slack/config.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org/'
2
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+
2
+ MIT License
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Slack Channel Messages input plugin for Embulk
2
+
3
+ input all messages from slack public channels
4
+
5
+ ## Overview
6
+
7
+ **Plugin type**: input
8
+
9
+ ## Configuration
10
+
11
+ | name | type | requirement | default | description |
12
+ | ----------- | ------ | ----------- | ------- | ------------------------ |
13
+ | token | string |   required | | slack api token |
14
+ | channel_ids | array | required | | slack public channel ids |
15
+
16
+ using slack apis below
17
+
18
+ - auth.test
19
+ - users.list
20
+ - conversations.history
21
+ - conversations.info
22
+
23
+ **We must add an OAuth scopes for using these apis.**
24
+
25
+ ## Example
26
+
27
+ ```yaml
28
+ in:
29
+ type: slack_channel_messages
30
+ token: <slack api token>
31
+ channel_ids:
32
+ - <public channel id 1>
33
+ - <public channel id 2>
34
+ ```
35
+
36
+ ## Build
37
+
38
+ ```
39
+ $ rake
40
+ ```
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task default: :build
@@ -0,0 +1,21 @@
1
+
2
+ Gem::Specification.new do |spec|
3
+ spec.name = "embulk-input-slack_channel_messages"
4
+ spec.version = "0.1.0"
5
+ spec.authors = ["Sasaki1994"]
6
+ spec.summary = "Slack Channel Messages input plugin for Embulk"
7
+ spec.description = "Loads slack channel messages using slack API."
8
+ spec.email = ["b.92421933411@gmail.com"]
9
+ spec.licenses = ["MIT"]
10
+ spec.homepage = "https://github.com/Sasaki1994/embulk-input-slack_channel_messages"
11
+
12
+ spec.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
13
+ spec.test_files = spec.files.grep(%r{^(test|spec)/})
14
+ spec.require_paths = ["lib"]
15
+
16
+ #spec.add_dependency 'YOUR_GEM_DEPENDENCY', ['~> YOUR_GEM_DEPENDENCY_VERSION']
17
+ # spec.add_development_dependency 'embulk', ['>= 0.9.23']
18
+ spec.add_development_dependency 'bundler', ['>= 1.10.6']
19
+ spec.add_development_dependency 'rake', ['>= 10.0']
20
+ spec.add_development_dependency 'rspec'
21
+ end
@@ -0,0 +1,118 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+
5
+ module Slack
6
+ class Client
7
+ attr_reader :token
8
+
9
+ def initialize(token)
10
+ @token = token
11
+ end
12
+
13
+ def ch_messages(channel_id)
14
+ """
15
+ Get all channel messages by channel_id using conversations.history api.
16
+ This API can only retrieve up to 1000 at a time, so we use 'next_cusor' to retrieve them recursively.
17
+
18
+ conversations.history api
19
+ https://api.slack.com/methods/conversations.history
20
+
21
+ params: slack public channel id (string)
22
+ return: all channel messages with datetime and user id (Array[Array])
23
+ """
24
+ messages = []
25
+ cursor = nil
26
+ begin
27
+ res = JSON.parse(get('conversations.history', {channel: channel_id, limit: 1000, cursor: cursor}))
28
+
29
+ messages += res['messages'].select{ |message| message['type'] == 'message' }.map do |message|
30
+ {
31
+ 'timestamp' => message['ts'],
32
+ 'user_id' => message['user'],
33
+ 'text' => message['text']
34
+ }
35
+ end
36
+
37
+ cursor = res['response_metadata']&.[]('next_cursor') || ''
38
+ end until cursor == ''
39
+ messages
40
+ end
41
+
42
+ def members
43
+ """
44
+ Get all members using users.list api.
45
+ This API is limited at a time, so we use 'next_cusor' to retrieve them recursively.
46
+
47
+ users.list api
48
+ https://api.slack.com/methods/users.list
49
+
50
+ return: all user id(key) and name(value) store (Hash)
51
+ """
52
+ members = {}
53
+ cursor = nil
54
+ begin
55
+ res = JSON.parse(get('users.list', {limit: 1000, cursor: cursor}))
56
+ raise "Error '#{res['error']}'" unless res['ok']
57
+
58
+ res['members'].each do |member|
59
+ members[member['id']] = member['profile']['display_name']
60
+ end
61
+
62
+ cursor = res['response_metadata']&.[]('next_cursor') || ''
63
+ end until cursor == ''
64
+ members
65
+ end
66
+
67
+ def channel_by_id!(ch_id)
68
+ """
69
+ Get channel information by channel_id using conversations.info api.
70
+
71
+ conversations.info api
72
+ https://api.slack.com/methods/conversations.info
73
+
74
+ params: slack public channel id (string)
75
+ return: channel object (hash)
76
+ """
77
+ res = JSON.parse(get('conversations.info', {channel: ch_id}))
78
+ raise "Error #{res['error']} channel id = #{ch_id}" unless res['ok']
79
+ res['channel']
80
+ end
81
+
82
+ def channel_by_id(ch_id)
83
+ res = JSON.parse(get('conversations.info', {channel: ch_id}))
84
+ return nil unless res['ok']
85
+ res['channel']
86
+ end
87
+
88
+ def auth_check
89
+ """
90
+ Do auth check test using auth.test api.
91
+
92
+ auth.test api
93
+ https://api.slack.com/methods/auth.test
94
+
95
+ return: is successed to api request with @token auth (bool)
96
+ """
97
+ res = JSON.parse(post('auth.test'))
98
+ raise 'Slack API Server Error' unless res.has_key?("ok")
99
+ res["ok"]
100
+ end
101
+
102
+ private
103
+ def slack_uri(api, params=nil)
104
+ uri = URI.parse("https://slack.com/api/#{api}")
105
+ uri.query = URI.encode_www_form(params) if params
106
+ uri
107
+ end
108
+
109
+ def get(api, options = {})
110
+ Net::HTTP.get(slack_uri(api, options.merge(token: token)))
111
+ end
112
+
113
+ def post(api, options = {})
114
+ Net::HTTP.post_form(slack_uri(api), options.merge(token: token)).body
115
+ end
116
+ end
117
+ end
118
+
@@ -0,0 +1,58 @@
1
+ require_relative 'client'
2
+ module Slack
3
+ class Service
4
+ attr_reader :token
5
+
6
+ def initialize(token)
7
+ @token = token
8
+ @client = Client.new(@token)
9
+ end
10
+
11
+ def compose_record(channel_id, &block)
12
+ """
13
+ Compose embulk insert record.
14
+
15
+ params:
16
+ slack public channel id (string)
17
+ embulk insert method (block)
18
+ """
19
+ members = get_members
20
+ channel = get_channel(channel_id)
21
+ messages = get_messages(channel_id)
22
+
23
+ messages.each do |message|
24
+ record = {
25
+ 'id' => "#{channel_id}-#{message['timestamp'].to_i}-#{message['user_id']}",
26
+ 'post_at' => Time.at(message['timestamp'].to_i),
27
+ 'slack_user_id' => message['user_id'],
28
+ 'slack_username' => members[message['user_id']],
29
+ 'slack_channel_name' => channel['name'],
30
+ 'message_text' => message['text']
31
+ }
32
+ block.call(record)
33
+ end
34
+ end
35
+
36
+ def get_members
37
+ @client.members
38
+ end
39
+
40
+ def get_channel(channel_id)
41
+ @client.channel_by_id!(channel_id)
42
+ end
43
+
44
+ def get_messages(channel_id)
45
+ @client.ch_messages(channel_id)
46
+ end
47
+
48
+ def check_token
49
+ raise 'Error token is invalid' unless @client.auth_check
50
+ end
51
+
52
+ def check_channels(channel_ids)
53
+ channel_ids.each do |ch_id|
54
+ @client.channel_by_id!(ch_id)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,70 @@
1
+ require_relative 'slack/service'
2
+
3
+ module Embulk
4
+ module Input
5
+
6
+ class SlackChannelMessages < InputPlugin
7
+ Plugin.register_input("slack_channel_messages", self)
8
+
9
+ @@columns = [
10
+ ["id", :string],
11
+ ["post_at", :timestamp],
12
+ ["slack_user_id", :string],
13
+ ["slack_username", :string],
14
+ ["slack_channel_name", :string],
15
+ ["message_text", :string],
16
+ ]
17
+
18
+ def self.transaction(config, &control)
19
+ # configuration code:
20
+ task = {
21
+ "token" => config.param("token", :string),
22
+ "channel_ids" => config.param("channel_ids", :array),
23
+ }
24
+
25
+ columns = @@columns.map.with_index{ |column, index| Column.new(index, *column) }
26
+
27
+ resume(task, columns, 1, &control)
28
+ end
29
+
30
+ def self.resume(task, columns, count, &control)
31
+ task_reports = yield(task, columns, count)
32
+
33
+ next_config_diff = {}
34
+ return next_config_diff
35
+ end
36
+
37
+ # TODO
38
+ # def self.guess(config)
39
+ # sample_records = [
40
+ # {"example"=>"a", "column"=>1, "value"=>0.1},
41
+ # {"example"=>"a", "column"=>2, "value"=>0.2},
42
+ # ]
43
+ # columns = Guess::SchemaGuess.from_hash_records(sample_records)
44
+ # return {"columns" => columns}
45
+ # end
46
+
47
+ def init
48
+ @token = task["token"]
49
+ @channel_ids = task["channel_ids"]
50
+ @service = Slack::Service.new(@token)
51
+ end
52
+
53
+ def run
54
+ @service.check_token
55
+ @service.check_channels(@channel_ids)
56
+ @channel_ids.each do |channel_id|
57
+ @service.compose_record(channel_id) do |record|
58
+ # ex) page_builder.add([<col1>, <col2>, <col3> ...])
59
+ page_builder.add(@@columns.map{|col| record[col[0]]})
60
+ end
61
+ end
62
+ page_builder.finish
63
+
64
+ task_report = {}
65
+ return task_report
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,77 @@
1
+ require 'embulk/input/slack/client'
2
+ require_relative 'config'
3
+
4
+ RSpec.describe do
5
+
6
+ let!(:client) {Slack::Client.new(config[:token])}
7
+
8
+ describe '#ch_messages' do
9
+ let(:messages) {client.ch_messages(config[:channel])}
10
+
11
+ it 'is hash of array' do
12
+ expect(messages).to be_an_instance_of(Array)
13
+ expect(messages[0]).to be_an_instance_of(Hash)
14
+ end
15
+
16
+ it 'has expected keys' do
17
+ expect(messages[0].keys).to include("timestamp", "user_id", "text")
18
+ end
19
+ end
20
+
21
+ describe '#members' do
22
+ let(:members) {client.members}
23
+
24
+ it 'is hash' do
25
+ expect(members).to be_an_instance_of(Hash)
26
+ end
27
+ end
28
+
29
+ describe '#channel_by_id!' do
30
+ let(:channel) {client.channel_by_id!(config[:channel])}
31
+
32
+ it 'is hash' do
33
+ expect(channel).to be_an_instance_of(Hash)
34
+ end
35
+
36
+ it 'has "name" key' do
37
+ expect(channel.keys).to include("name")
38
+ end
39
+
40
+ context 'not found channel id' do
41
+ it 'occurs error' do
42
+ expect{client.channel_by_id!('no_id')}.to raise_error('Error channel_not_found channel id = no_id')
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '#channel_by_id' do
48
+ let(:channel) {client.channel_by_id(config[:channel])}
49
+
50
+ it 'is hash' do
51
+ expect(channel).to be_an_instance_of(Hash)
52
+ end
53
+
54
+ it 'has "name" key' do
55
+ expect(channel.keys).to include("name")
56
+ end
57
+
58
+ context 'not found channel id' do
59
+ it 'returns nil' do
60
+ expect(client.channel_by_id('no_id')).to eq nil
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#auth_check' do
66
+ it 'returns true' do
67
+ expect(client.auth_check).to eq true
68
+ end
69
+
70
+ context 'token is invalid' do
71
+ it 'returns false' do
72
+ client = Slack::Client.new("invalid token")
73
+ expect(client.auth_check).to eq false
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,30 @@
1
+ require 'embulk/input/slack/service'
2
+
3
+ RSpec.describe do
4
+
5
+ describe '#compose_record' do
6
+ it 'A record is correct hash' do
7
+ service = Slack::Service.new("token")
8
+ allow(service).to receive(:get_members).and_return({"A00AAA00" => "sample_user"})
9
+ allow(service).to receive(:get_channel).and_return({"name" => "sample_channel"})
10
+ allow(service).to receive(:get_messages).and_return([{
11
+ 'timestamp' => 111111.1111,
12
+ 'user_id' => "A00AAA00",
13
+ 'text' => "sample message"
14
+ }])
15
+
16
+ ex_record = {
17
+ 'id' => "channel_id-111111-A00AAA00",
18
+ 'post_at' => Time.at(111111),
19
+ 'slack_user_id' => "A00AAA00",
20
+ 'slack_username' => "sample_user",
21
+ 'slack_channel_name' => "sample_channel",
22
+ 'message_text' => "sample message"
23
+ }
24
+
25
+ service.compose_record("channel_id") do |record|
26
+ expect(record).to eq ex_record
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,100 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ RSpec.configure do |config|
17
+ # rspec-expectations config goes here. You can use an alternate
18
+ # assertion/expectation library such as wrong or the stdlib/minitest
19
+ # assertions if you prefer.
20
+ config.expect_with :rspec do |expectations|
21
+ # This option will default to `true` in RSpec 4. It makes the `description`
22
+ # and `failure_message` of custom matchers include text for helper methods
23
+ # defined using `chain`, e.g.:
24
+ # be_bigger_than(2).and_smaller_than(4).description
25
+ # # => "be bigger than 2 and smaller than 4"
26
+ # ...rather than:
27
+ # # => "be bigger than 2"
28
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
29
+ end
30
+
31
+ # rspec-mocks config goes here. You can use an alternate test double
32
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
33
+ config.mock_with :rspec do |mocks|
34
+ # Prevents you from mocking or stubbing a method that does not exist on
35
+ # a real object. This is generally recommended, and will default to
36
+ # `true` in RSpec 4.
37
+ mocks.verify_partial_doubles = true
38
+ end
39
+
40
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
41
+ # have no way to turn it off -- the option exists only for backwards
42
+ # compatibility in RSpec 3). It causes shared context metadata to be
43
+ # inherited by the metadata hash of host groups and examples, rather than
44
+ # triggering implicit auto-inclusion in groups with matching metadata.
45
+ config.shared_context_metadata_behavior = :apply_to_host_groups
46
+
47
+ # The settings below are suggested to provide a good initial experience
48
+ # with RSpec, but feel free to customize to your heart's content.
49
+ =begin
50
+ # This allows you to limit a spec run to individual examples or groups
51
+ # you care about by tagging them with `:focus` metadata. When nothing
52
+ # is tagged with `:focus`, all examples get run. RSpec also provides
53
+ # aliases for `it`, `describe`, and `context` that include `:focus`
54
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
55
+ config.filter_run_when_matching :focus
56
+
57
+ # Allows RSpec to persist some state between runs in order to support
58
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
59
+ # you configure your source control system to ignore this file.
60
+ config.example_status_persistence_file_path = "spec/examples.txt"
61
+
62
+ # Limits the available syntax to the non-monkey patched syntax that is
63
+ # recommended. For more details, see:
64
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
65
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
66
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
67
+ config.disable_monkey_patching!
68
+
69
+ # This setting enables warnings. It's recommended, but in some cases may
70
+ # be too noisy due to issues in dependencies.
71
+ config.warnings = true
72
+
73
+ # Many RSpec users commonly either run the entire suite or an individual
74
+ # file, and it's useful to allow more verbose output when running an
75
+ # individual spec file.
76
+ if config.files_to_run.one?
77
+ # Use the documentation formatter for detailed output,
78
+ # unless a formatter has already been configured
79
+ # (e.g. via a command-line flag).
80
+ config.default_formatter = "doc"
81
+ end
82
+
83
+ # Print the 10 slowest examples and example groups at the
84
+ # end of the spec run, to help surface which specs are running
85
+ # particularly slow.
86
+ config.profile_examples = 10
87
+
88
+ # Run specs in random order to surface order dependencies. If you find an
89
+ # order dependency and want to debug it, you can fix the order by providing
90
+ # the seed, which is printed after each run.
91
+ # --seed 1234
92
+ config.order = :random
93
+
94
+ # Seed global randomization in this process using the `--seed` CLI option.
95
+ # Setting this allows you to use `--seed` to deterministically reproduce
96
+ # test failures related to randomization by passing the same `--seed` value
97
+ # as the one that triggered the failure.
98
+ Kernel.srand config.seed
99
+ =end
100
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: embulk-input-slack_channel_messages
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sasaki1994
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-02-14 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.10.6
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.10.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Loads slack channel messages using slack API.
56
+ email:
57
+ - b.92421933411@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - embulk-input-slack_channel_messages.gemspec
69
+ - lib/embulk/input/slack/client.rb
70
+ - lib/embulk/input/slack/service.rb
71
+ - lib/embulk/input/slack_channel_messages.rb
72
+ - spec/lib/embulk/input/slack/client_spec.rb
73
+ - spec/lib/embulk/input/slack/service_spec.rb
74
+ - spec/spec_helper.rb
75
+ homepage: https://github.com/Sasaki1994/embulk-input-slack_channel_messages
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubygems_version: 3.1.2
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Slack Channel Messages input plugin for Embulk
98
+ test_files:
99
+ - spec/lib/embulk/input/slack/client_spec.rb
100
+ - spec/lib/embulk/input/slack/service_spec.rb
101
+ - spec/spec_helper.rb