ruboty-typetalk 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 178c7d2da07b114597a97c6288f5cbc5d724e9b2
4
+ data.tar.gz: 29cdc58a455c3c2b98e50272055f1765b44fd45a
5
+ SHA512:
6
+ metadata.gz: f5faaf363ae60e8768cac66d2c13b5e3b4fd8f198ae3c77889d140ce54796a4978ef90af16c1d5fcaeff36cbe6a0345bb142976ca8946ca8540d508c4c52247e
7
+ data.tar.gz: 924d8c89d9b4285d957d5397900908b66b088ee3ec1f7c9f775387d38718b25cae569fe33ae21517ff4c5ad4a1d78837ce61c94cd01cd7da168f50a8c6ab3e48
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /vendor
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /bin
@@ -0,0 +1 @@
1
+ inherit_from: .rubocop_todo.yml
@@ -0,0 +1,68 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-04-14 10:05:58 +0900 using RuboCop version 0.54.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: EnforcedStyleAlignWith, AutoCorrect, Severity.
12
+ # SupportedStylesAlignWith: start_of_line, def
13
+ Layout/DefEndAlignment:
14
+ Exclude:
15
+ - 'lib/ruboty/adapters/typetalk.rb'
16
+
17
+ # Offense count: 1
18
+ Lint/UselessAssignment:
19
+ Exclude:
20
+ - 'lib/ruboty/adapters/typetalk.rb'
21
+
22
+ # Offense count: 5
23
+ Metrics/AbcSize:
24
+ Max: 19
25
+
26
+ # Offense count: 1
27
+ # Configuration parameters: CountComments, ExcludedMethods.
28
+ Metrics/BlockLength:
29
+ Max: 72
30
+
31
+ # Offense count: 1
32
+ Metrics/CyclomaticComplexity:
33
+ Max: 9
34
+
35
+ # Offense count: 7
36
+ # Configuration parameters: CountComments.
37
+ Metrics/MethodLength:
38
+ Max: 15
39
+
40
+ # Offense count: 1
41
+ Metrics/PerceivedComplexity:
42
+ Max: 9
43
+
44
+ # Offense count: 2
45
+ Naming/MemoizedInstanceVariableName:
46
+ Exclude:
47
+ - 'lib/ruboty/adapters/typetalk.rb'
48
+
49
+ # Offense count: 3
50
+ Style/Documentation:
51
+ Exclude:
52
+ - 'spec/**/*'
53
+ - 'test/**/*'
54
+ - 'lib/ruboty/adapters/typetalk.rb'
55
+ - 'lib/ruboty/typetalk.rb'
56
+ - 'lib/ruboty/typetalk/client.rb'
57
+
58
+ # Offense count: 2
59
+ # Cop supports --auto-correct.
60
+ Style/IfUnlessModifier:
61
+ Exclude:
62
+ - 'bin/bundle'
63
+
64
+ # Offense count: 26
65
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
66
+ # URISchemes: http, https
67
+ Metrics/LineLength:
68
+ Max: 190
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ruboty-typetalk.gemspec
6
+ gemspec
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ruboty-typetalk (0.1.0)
5
+ faraday (~> 0.14)
6
+ ruboty (>= 1.3)
7
+ websocket-client-simple (~> 0.3.0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activesupport (5.2.0)
13
+ concurrent-ruby (~> 1.0, >= 1.0.2)
14
+ i18n (>= 0.7, < 2)
15
+ minitest (~> 5.1)
16
+ tzinfo (~> 1.1)
17
+ concurrent-ruby (1.0.5)
18
+ dotenv (2.2.2)
19
+ event_emitter (0.2.6)
20
+ faraday (0.14.0)
21
+ multipart-post (>= 1.2, < 3)
22
+ i18n (1.0.0)
23
+ concurrent-ruby (~> 1.0)
24
+ mem (0.1.5)
25
+ minitest (5.11.3)
26
+ multipart-post (2.0.0)
27
+ rake (10.5.0)
28
+ ruboty (1.3.0)
29
+ activesupport
30
+ bundler
31
+ dotenv
32
+ mem
33
+ slop
34
+ slop (4.6.2)
35
+ thread_safe (0.3.6)
36
+ tzinfo (1.2.5)
37
+ thread_safe (~> 0.1)
38
+ websocket (1.2.5)
39
+ websocket-client-simple (0.3.0)
40
+ event_emitter
41
+ websocket
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ bundler (~> 1.16)
48
+ rake (~> 10.0)
49
+ ruboty-typetalk!
50
+
51
+ BUNDLED WITH
52
+ 1.16.1
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2018 pyama86
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,28 @@
1
+ # Ruboty::Typetalk
2
+
3
+ It is [ruboty's](https://github.com/r7kamura/ruboty) typetalk adapter
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ gem 'ruboty-typetalk'
9
+ ```
10
+
11
+ ## ENV
12
+ - `TYPETALK_CLIENT_ID`: 'client id. get one on https://developer.nulab-inc.com/ja/docs/typetalk/
13
+ - `TYPETALK_CLIENT_SECRET`: client secret key
14
+ - `TYPETALK_SPACE_NAME`: your space name(Please set dummy value when not belonging to organization)
15
+ - `TYPETALK_BOT_NAME`: your bot name
16
+
17
+ ## Special thanks
18
+ I refer to [ruboty-slack_rtm](https://github.com/rosylilly/ruboty-slack_rtm) for many codes
19
+
20
+ ## Development
21
+
22
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
23
+
24
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
25
+
26
+ ## Contributing
27
+
28
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/ruboty-typetalk.
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+ task default: :spec
@@ -0,0 +1,142 @@
1
+ # Copyright (c) 2015 Sho Kusano
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.
23
+
24
+ require 'json'
25
+ require 'net/http'
26
+ require 'ruboty/adapters/base'
27
+ require 'faraday'
28
+
29
+ module Ruboty
30
+ module Adapters
31
+ class TypeTalk < Base
32
+ env :TYPETALK_CLIENT_ID, 'ClientID. get one on https://developer.nulab-inc.com/ja/docs/typetalk/'
33
+ env :TYPETALK_CLIENT_SECRET, 'client secret key'
34
+ env :TYPETALK_SPACE_NAME, 'your space name(Please set dummy value when not belonging to organization)'
35
+ env :TYPETALK_BOT_NAME, 'your bot name'
36
+
37
+ def run
38
+ init
39
+ bind
40
+ connect
41
+ end
42
+
43
+ def init
44
+ ENV['RUBOTY_NAME'] = ENV['TYPETALK_BOT_NAME']
45
+ end
46
+
47
+ def say(message)
48
+ channel = resolve_topic_id(message[:to])
49
+ return unless channel
50
+
51
+ m = {
52
+ message: message[:code] ? "```\n#{message[:body]}\n```" : message[:body]
53
+ }
54
+ client.post("/api/v1/topics/#{channel}", m)
55
+ end
56
+
57
+ private
58
+
59
+ def resolve_topic_id(name)
60
+ channel_info.find { |c| c[:name] == name }[:id]
61
+ end
62
+
63
+ def resolve_space_id
64
+ space_info.find {|s| s[:name] == ENV['TYPETALK_SPACE_NAME'] }[:id] rescue nil
65
+ end
66
+
67
+ def channel_info
68
+ @_channel_info ||= begin
69
+ params = resolve_space_id ? { spaceKey: resolve_space_id } : nil
70
+
71
+ body = client.get('api/v2/topics', params)
72
+ body['topics'].map do |t|
73
+ { id: t['topic']['id'], name: t['topic']['name'] }
74
+ end
75
+ end
76
+ end
77
+
78
+ def space_info
79
+ @_space_info ||= begin
80
+ body = client.get('api/v1/spaces')
81
+ body['mySpaces'].map do |t|
82
+ { id: t['space']['key'], name: t['space']['name'] }
83
+ end
84
+ end
85
+ end
86
+
87
+ def bind
88
+ client.on_text do |data|
89
+ method_name = "on_#{data['type'].downcase}".to_sym
90
+ send(method_name, data['data']) if respond_to?(method_name, true)
91
+ end
92
+ end
93
+
94
+ def connect
95
+ Thread.start do
96
+ loop do
97
+ sleep 5
98
+ set_active
99
+ end
100
+ end
101
+
102
+ loop do
103
+ begin
104
+ client.main_loop
105
+ rescue StandardError
106
+ nil
107
+ end
108
+ client(true)
109
+ end
110
+ end
111
+
112
+ def client(renew = nil)
113
+ @_client = ::Ruboty::TypeTalk::Client.new(websocket_url: 'https://typetalk.com/api/v1/streaming') if !@_client || renew
114
+ @_client
115
+ end
116
+
117
+ # event handlers
118
+
119
+ def on_postmessage(data)
120
+ message_info = {
121
+ from: data['topic']['name'],
122
+ from_name: data['post']['account']['name'],
123
+ time: Time.at(data['post']['createdAt'].to_f)
124
+ }
125
+
126
+ body = remove_mention(data['post']['message'])
127
+ mention_to = begin
128
+ data['mentions'].map { |m| m['name'] }
129
+ rescue StandardError
130
+ []
131
+ end
132
+ robot.receive(message_info.merge(body: body, mention_to: mention_to))
133
+ end
134
+
135
+ def remove_mention(text)
136
+ (text || '').gsub(/\<\@(?<uid>[0-9A-Z]+)(?:\|(?<name>[^>]+))?\>/) do |_|
137
+ "@#{Regexp.last_match[:name]}"
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,9 @@
1
+ require 'ruboty/typetalk/version'
2
+ require 'ruboty/adapters/typetalk'
3
+ require 'ruboty/typetalk/client'
4
+
5
+ module Ruboty
6
+ module Typetalk
7
+ # Your code goes here...
8
+ end
9
+ end
@@ -0,0 +1,151 @@
1
+ # Copyright (c) 2015 Sho Kusano
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.
23
+
24
+ require 'json'
25
+ require 'websocket-client-simple'
26
+
27
+ module Ruboty
28
+ module TypeTalk
29
+ class Client
30
+ CONNECTION_CLOSED = Object.new
31
+
32
+ def initialize(websocket_url:)
33
+ @queue = Queue.new
34
+ @stream_client ||= build_stream_client(websocket_url.to_s)
35
+ end
36
+
37
+ def send_message(data)
38
+ data[:id] = (Time.now.to_i * 10 + rand(10)) % (1 << 31)
39
+ @queue.enq(data.to_json)
40
+ end
41
+
42
+ def on_text
43
+ @stream_client.on(:message) do |message|
44
+ case message.type
45
+ when :ping
46
+ Ruboty.logger.debug("#{Client.name}: Received ping message")
47
+ send('', type: 'pong')
48
+ when :pong
49
+ Ruboty.logger.debug("#{Client.name}: Received pong message")
50
+ when :text
51
+ yield(JSON.parse(message.data))
52
+ else
53
+ Ruboty.logger.warn("#{Client.name}: Received unknown message type=#{message.type}: #{message.data}")
54
+ end
55
+ end
56
+ end
57
+
58
+ def main_loop
59
+ keep_connection
60
+
61
+ loop do
62
+ message = @queue.deq
63
+ break if message.equal?(CONNECTION_CLOSED)
64
+ @stream_client.send(message)
65
+ end
66
+ end
67
+
68
+ def post(path, params)
69
+ res = conn.post(path) do |req|
70
+ req.body = params.to_json
71
+ req.headers['Content-Type'] = 'application/json'
72
+ req.headers['Authorization'] = "Bearer #{token}"
73
+ end
74
+
75
+ JSON.parse(res.body)
76
+ request("post", path, params)
77
+ end
78
+
79
+ def get(path, params = {})
80
+ request("get", path, params)
81
+ end
82
+
83
+ private
84
+
85
+ def conn
86
+ @_conn = Faraday.new(url: 'https://typetalk.com') do |faraday|
87
+ faraday.request :url_encoded
88
+ faraday.adapter Faraday.default_adapter
89
+ end
90
+ end
91
+
92
+ def request(method, path, params)
93
+ res = conn.send(method, path, params) do |req|
94
+ req.body = params.to_json
95
+ req.headers['Content-Type'] = 'application/json'
96
+ req.headers['Authorization'] = "Bearer #{token}"
97
+ end
98
+
99
+ JSON.parse(res.body)
100
+ end
101
+
102
+ def token
103
+ if !@_token || @_token.expired?
104
+ @_token = Token.new(conn)
105
+ end
106
+ @_token.value
107
+ end
108
+
109
+ def build_stream_client(url)
110
+ WebSocket::Client::Simple.connect(url, verify_mode: OpenSSL::SSL::VERIFY_PEER, headers: { Authorization: "Bearer #{token}" }).tap do |client|
111
+ client.on(:error) do |err|
112
+ Ruboty.logger.error("#{err.class}: #{err.message}\n#{err.backtrace.join("\n")}")
113
+ end
114
+ queue = @queue
115
+ client.on(:close) do
116
+ Ruboty.logger.info('Disconnected')
117
+ queue.enq(CONNECTION_CLOSED)
118
+ end
119
+ end
120
+ end
121
+
122
+ def keep_connection
123
+ Thread.start do
124
+ loop do
125
+ sleep(30)
126
+ @stream_client.send('', type: 'ping')
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ class Token
133
+ def initialize(conn)
134
+ response = conn.post('/oauth2/access_token', client_id: ENV['TYPETALK_CLIENT_ID'],
135
+ client_secret: ENV['TYPETALK_CLIENT_SECRET'],
136
+ grant_type: 'client_credentials',
137
+ scope: 'my,topic.read,topic.post')
138
+ body = JSON.parse(response.body)
139
+ @_token = { token: body['access_token'], expired_at: Time.now + body['expires_in'] }
140
+ end
141
+
142
+ def expired?
143
+ @_token[:expired_at] < Time.now
144
+ end
145
+
146
+ def value
147
+ @_token[:token]
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,5 @@
1
+ module Ruboty
2
+ module Typetalk
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+
2
+ lib = File.expand_path('lib', __dir__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruboty/typetalk/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ruboty-typetalk'
8
+ spec.version = Ruboty::Typetalk::VERSION
9
+ spec.authors = ['pyama86']
10
+ spec.email = ['pyama@pepabo.com']
11
+
12
+ spec.summary = 'typetalk ruboty adapter.'
13
+ spec.description = 'typetalk rubyty adapter.'
14
+ spec.homepage = 'https://github.com/pyama86/ruboty-typetalk'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.16'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+
26
+ spec.add_dependency 'faraday', '~> 0.14'
27
+ spec.add_dependency 'ruboty', '>= 1.3'
28
+ spec.add_dependency 'websocket-client-simple', '~> 0.3.0'
29
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruboty-typetalk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - pyama86
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-04-17 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.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
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: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.14'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruboty
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: websocket-client-simple
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.3.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.3.0
83
+ description: typetalk rubyty adapter.
84
+ email:
85
+ - pyama@pepabo.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rubocop.yml"
92
+ - ".rubocop_todo.yml"
93
+ - Gemfile
94
+ - Gemfile.lock
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - lib/ruboty/adapters/typetalk.rb
99
+ - lib/ruboty/typetalk.rb
100
+ - lib/ruboty/typetalk/client.rb
101
+ - lib/ruboty/typetalk/version.rb
102
+ - ruboty-typetalk.gemspec
103
+ homepage: https://github.com/pyama86/ruboty-typetalk
104
+ licenses: []
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.6.13
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: typetalk ruboty adapter.
126
+ test_files: []