lita-elasticsearch-indexer 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 11fd7fd834da4c9ca3378b5b3fe9c9176c33fa10
4
+ data.tar.gz: d6ded8af78eac2d21bc3ef1899c6c1170f74f29e
5
+ SHA512:
6
+ metadata.gz: 66d84027258f128f8f49cb76c7a57b903ead954522f48fdd52b80a2ad0c0d1aeb8ea1f81962cf45f1d84ea047006006f5804068614091330855bc2977a0bf9b8
7
+ data.tar.gz: 1019e35ce7fd1e357d52e25b7c0629a8c7c3e40c6f15b6f37bafe491452b4e1aac99449a9de0d3348d9c2d488f33dba63264f214d1d716f92e0a9a4e81ec4dbc
@@ -0,0 +1,56 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # This is only used for development
14
+ docker-compose.override.yml
15
+
16
+ # lita.env contains secrets
17
+ /lita.env
18
+
19
+ # Used by dotenv library to load environment variables.
20
+ # .env
21
+
22
+ ## Specific to RubyMotion:
23
+ .dat*
24
+ .repl_history
25
+ build/
26
+ *.bridgesupport
27
+ build-iPhoneOS/
28
+ build-iPhoneSimulator/
29
+
30
+ ## Specific to RubyMotion (use of CocoaPods):
31
+ #
32
+ # We recommend against adding the Pods directory to your .gitignore. However
33
+ # you should judge for yourself, the pros and cons are mentioned at:
34
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
35
+ #
36
+ # vendor/Pods/
37
+
38
+ ## Documentation cache and generated files:
39
+ /.yardoc/
40
+ /_yardoc/
41
+ /doc/
42
+ /rdoc/
43
+
44
+ ## Environment normalization:
45
+ /.bundle/
46
+ /vendor/bundle
47
+ /lib/bundler/man/
48
+
49
+ # for a library or gem, you might want to ignore these files since the code is
50
+ # intended to run in multiple environments; otherwise, check them in:
51
+ Gemfile.lock
52
+ # .ruby-version
53
+ # .ruby-gemset
54
+
55
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
56
+ .rvmrc
@@ -0,0 +1,323 @@
1
+ Development with Docker
2
+ ===
3
+ We use [Docker](https://www.docker.com/) to run, test, and debug our application.
4
+ The following documents how to install and use Docker on a Mac. There are
5
+ [instructions](https://docs.docker.com/installation) for installing and using
6
+ docker on other operating systems.
7
+
8
+ On the mac, we use [docker for mac](https://docs.docker.com/engine/installation/mac/#/docker-for-mac).
9
+
10
+ We use [docker-compose](https://docs.docker.com/compose/) to automate most of
11
+ our interactions with the application.
12
+
13
+ Table of Contents
14
+ ===
15
+ * [Installation and Upgrade](#installation-and-upgrade)
16
+ * [Launching the Application](#launching-the-application)
17
+ * [Docker Compose](#docker-compose)
18
+ * [Dockerfile](#dockerfile)
19
+ * [Useful Docker Commands](#useful-docker-commands)
20
+ * [Bash Profile](#bash-profile)
21
+
22
+ Installation and Upgrade
23
+ ===
24
+ Docker makes it easy to install docker for mac, which includes docker, and docker-compose
25
+ on your mac, and keep them upgraded in sync. Follow the instructions
26
+ to install [Docker 4 Mac]((https://docs.docker.com/engine/installation/mac/#/docker-for-mac).
27
+
28
+ Once you have docker running, you can run any of the following commands to test
29
+ that docker is working:
30
+ ```
31
+ docker ps
32
+ ```
33
+ This should always return a table with the following headers, and 0 or more
34
+ entries:
35
+
36
+ `CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES`
37
+
38
+ ```
39
+ docker images
40
+ ```
41
+ Similar to above, it should always return a table with the following headers, and
42
+ 0 or more entries:
43
+
44
+ `REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE`
45
+
46
+ Launching the Application
47
+ ===
48
+
49
+ Create lita.env in the Application root, using lita.env.example. If you are using
50
+ slack, you will need to create a [Slack API Token](https://my.slack.com/services/new/lita)
51
+ and add it to the LITA_SLACK_TOKEN variable.
52
+
53
+ In the Application root, run the following:
54
+ ```bash
55
+ touch Gemfile.lock
56
+ docker-compose up -d
57
+ ```
58
+
59
+ Docker Compose
60
+ ===
61
+
62
+ Once you have docker installed, you can use docker-compose to run all of the
63
+ commands that you would normally run when developing and testing the application.
64
+ Docker Compose uses one or more yml files to specify everything required to build
65
+ and run the application and any other support application (databases, volume
66
+ containers, etc.) it requires. There are multiple docker-compose yml files in
67
+ the Application Root, explained below.
68
+
69
+ docker-compose.yml
70
+ ---
71
+ This is the base docker-compose file used to manage the server.
72
+
73
+ Anyone with docker and docker-compose can run the following command from within
74
+ the Application Root (where this file you are reading resides), to build the server
75
+ image (You must be connected to the internet so that docker can
76
+ pull down any base docker images, or package/gem installs, for this to work).
77
+
78
+ ```
79
+ docker-compose build
80
+ ```
81
+ Once you have built the images, you can launch containers of all services
82
+ required by the app (docker calls a running instance of a docker image a docker
83
+ container):
84
+ ```
85
+ docker-compose up -d
86
+ ```
87
+
88
+ The docker-compose definition for the 'server' service mounts the Application
89
+ Root as /var/www/app in the server docker container. Since the Dockerfile specifies
90
+ /var/www/app as its default WORKDIR, this allows you to make changes to the files
91
+ on your machine and see them reflected live in the running server (although see
92
+ [below](#dockerfile) for **important information about modifying the Gemfile**).
93
+
94
+ The Dockerfile hosts the application on port 3000 inside the container,
95
+ and the docker-compose service definition attaches this to port 3000 on the
96
+ host machine (this will fail if you have another service of any kind attached to
97
+ port 3000 on the same host).
98
+ To connect to this host you can use curl, or your browser to connect to
99
+ http://localhost:3000/api/v1/app/status to check the status of
100
+ the application. All other parts of the application are served at
101
+ http://localhost:3000.
102
+
103
+ docker-compose.dev.yml
104
+ ---
105
+ This file extends docker-compose.yml to add service definitions to make it possible
106
+ to easily run things like bundle, rspec, rails, rake, etc (see below for more).
107
+
108
+ You can use this by adding the -f docker-compose.yml -f docker-compose.dev.yml flag
109
+ to all of your docker-compose commands, e.g.
110
+ ```
111
+ docker-compose -f docker-compose.yml -f docker-compose.dev.yml run rails c
112
+ ```
113
+
114
+ Alternatively, you can use the fact that docker-compose looks for both docker-compose.yml
115
+ and docker-compose.override.yml by default, and create a symlink from docker-compose.dev.yml
116
+ to docker-compose.override.yml that will make docker-compose use both by default, without
117
+ any of the extra -f flags.
118
+ ```
119
+ ln -s docker-compose.dev.yml docker-compose.override.yml
120
+ ```
121
+ Note, you should add docker-compose.override.yml to your .gitignore, so it will
122
+ never be committed to the repo. This ensures that the default behavior for those
123
+ not wishing to use the extra functionality in docker-compose.dev.yml is preserved.
124
+
125
+ You should always specify the exact service (e.g. top level key
126
+ in the docker-compose.dev.yml file) when running docker-compose commands using this
127
+ docker-compose.dev.yml file. Otherwise, docker-compose will try to run all services,
128
+ which will cause things to run that do not need to run (such as bundle).
129
+
130
+ default docker-compose commands
131
+ ---
132
+ Using just the docker-compose.yml, e.g. docker-compose.override.yml file/symlink
133
+ is not present:
134
+
135
+ Launch the server to interact with the application:
136
+ ```
137
+ docker-compose up -d server
138
+ ```
139
+ Docker-compose is smart enough to realize all of the linked services required,
140
+ and spin them up in order. This will not launch a swift service.
141
+
142
+ Bring down and delete running containers:
143
+ ```
144
+ docker-compose down
145
+ ```
146
+
147
+ docker-compose.dev.yml docker-compose commands
148
+ ---
149
+ Either use -f docker-compose.yml -f docker-compose.dev.yml, like so:
150
+ Run rspec
151
+ ```
152
+ docker-compose -f docker-compose.yml -f docker-compose.dev.yml run rspec
153
+ docker-compose -f docker-compose.yml -f docker-compose.dev.yml run rspec spec/requests
154
+ ```
155
+
156
+ Or create a symlink from docker-compose.dev.yml to docker-compose.override.yml.
157
+ This is the recommended way to use docker-compose.dev.yml, as it will be more
158
+ permanent between invocations of the shell terminal.
159
+ ```
160
+ ln -s docker-compose.dev.yml docker-compose.override.yml
161
+ ```
162
+
163
+ Then you can run services like rspec without the extra -f flags:
164
+ ```
165
+ docker-compose run rspec
166
+ docker-compose run rspec spec/requests
167
+ ```
168
+
169
+ The following commands assume the symlink exists.
170
+ Run bundle (see
171
+ [below](#dockerfile) for **important information about modifying the Gemfile**)):
172
+ ```
173
+ docker-compose run bundle
174
+ ```
175
+
176
+ Run rake commands (default RAILS_ENV=development):
177
+ ```
178
+ docker-compose run rake db:migrate
179
+ docker-compose run rake db:seed
180
+ docker-compose run rake db:migrate RAILS_ENV=test
181
+ ```
182
+
183
+ Run rails commands (default RAILS_ENV=docker):
184
+ ```
185
+ docker-compose run rails c
186
+ docker-compose run rails c RAILS_ENV=test
187
+ ```
188
+
189
+ **Note about docker-compose down**
190
+ You should run docker-compose down using the same docker-compose yml file context,
191
+ e.g. with COMPOSE_FILE set, or the docker-compose.override.yml file in existence,
192
+ or using the -f flags for all docker-compose yml files. Otherwise, services defined
193
+ in the missing docker-compose.yml file will not be shut down and removed, and a warning
194
+ may come up in your output that says containers were 'orphaned'.
195
+
196
+ Dockerfile
197
+ ===
198
+ Docker uses a [Dockerfile](https://docs.docker.com/reference/builder/) to
199
+ specify how to build an image to host an application. We have created a
200
+ Dockerfile in the Application Root. This Dockerfile:
201
+ * installs required libraries for ruby, rails, node, etc.
202
+ * installs specific versions of ruby
203
+ * installs the sqlite client libraries
204
+ * creates /var/www/app and sets this to the default working directory
205
+ * adds Gemfile and Gemfile.lock (see below)
206
+ * bundles to install required gems into the image
207
+ * exposes 3000
208
+ * sets up to run the rails server to host the service by default
209
+
210
+ **Important information about modifying the Gemfile**
211
+ When you need to add a gem to your Gemfile, you will also need to rebuild
212
+ the server. This will permenently install the new gem into the server image.
213
+
214
+ ```
215
+ docker-compose build server
216
+ ```
217
+ You then need to run bundle, which will update Gemfile.lock in the Application
218
+ Root
219
+ ```
220
+ docker-compose -f docker-compose.yml -f docker-compose.dev.yml run bundle
221
+ ```
222
+ You should then commit and push the new Gemfile and Gemfile.lock to the repository.
223
+
224
+ Docker basics
225
+ ===
226
+
227
+ To stop all running docker containers (you must stop a container before you can
228
+ remove it or its image):
229
+ ```
230
+ docker-compose stop
231
+ ```
232
+
233
+ To stop and/or remove all containers, use the following:
234
+ ```
235
+ docker-compose down
236
+ ```
237
+
238
+ When a docker container stops for any reason, docker keeps it around in its
239
+ system. There are ways you can start and attach to a stopped container, but
240
+ in many cases this is not useful. You should remove containers on a regular basis.
241
+ When you start up the machines from scratch, you will need to run rake db:migrate,
242
+ etc. to get the database ready.
243
+
244
+ You can list all running containers using the following command:
245
+ ```
246
+ docker ps
247
+ ```
248
+ You can list all containers (both running and stopped):
249
+ ```
250
+ docker ps -a
251
+ ```
252
+
253
+ Each docker container is given a long UUID by docker (called the CONTAINERID).
254
+ You can use this UUID (or even the first 4 or more characters) to stop
255
+ and remove a container using the docker commandline instead of
256
+ using docker-compose (see Docker [commandline documentation](https://docs.docker.com/engine/reference/commandline)
257
+ for other things you can find out about a running container using the docker command):
258
+ ```
259
+ docker stop UUID
260
+ docker rm -v UUID
261
+ ```
262
+
263
+ Sometimes docker will leave files from a container on the host, which can build
264
+ up over time and cause your VM to become sluggish or behave strangely. We
265
+ recommend adding the -v (volumes) flag to docker rm commands to make sure these
266
+ files are cleaned up appropriately. Also, docker ps allows you to pass the -q
267
+ flag, and get only the UUID of the containers it lists. Using the following
268
+ command, you can easily stop all running containers:
269
+ ```
270
+ docker stop $(docker ps -q)
271
+ ```
272
+
273
+ Similarly, to remove all stopped containers (this will skip running containers, but
274
+ print a warning for each):
275
+ ```
276
+ docker rm -v $(docker ps -aq)
277
+ ```
278
+
279
+ You may also need to check for volumes that have been left behind when containers
280
+ were removed without explicitly using docker rm -v, such as when docker-compose down
281
+ is run. To list all volumes on the docker host:
282
+ ```
283
+ docker volume ls
284
+ ```
285
+
286
+ The output from this is very similar to all other docker outputs. Each volume is
287
+ assigned a UUID. You can remove a specific volume with:
288
+ ```
289
+ docker volume rm UUID
290
+ ```
291
+
292
+ You can remove all volumes using the -q pattern used in other docker commands
293
+ ```
294
+ docker volume rm $(docker volume ls -q)
295
+ ```
296
+
297
+ We recommend running some of these frequently to clean up containers and volumes that
298
+ build up over time. Sometimes, when running a combination docker rm $(docker ls -q)
299
+ pattern command when there is nothing to remove, docker will print a warning that
300
+ it requires 1 or more arguments, but this is ok. It can be useful to put some or
301
+ all of these in your Bash Profile.
302
+
303
+ Bash Profile
304
+ ===
305
+ The following can be placed in the .bash_profile file located in your
306
+ HOME directory (e.g. ~/.bash_profile)
307
+
308
+ ```bash_profile
309
+ # Docker configurations and helpers
310
+ alias docker_stop_all='docker stop $(docker ps -q)'
311
+ alias docker_cleanup='docker rm -v $(docker ps -aq)'
312
+ alias docker_images_cleanup='docker rmi $(docker images -f dangling=true -q)'
313
+ alias docker_volume_cleanup='docker volume rm $(docker volume ls -q)'
314
+
315
+ # fake rake/rails/rspec using docker under the hood
316
+ # this depends on either a docker-compose.override.yml, or COMPOSE_FILE
317
+ # environment variable
318
+ alias rails="docker-compose run rails"
319
+ alias rake="docker-compose run rake"
320
+ alias rspec="docker-compose run rspec"
321
+ alias bundle="docker-compose run bundle"
322
+ alias dcdown="docker-compose down"
323
+ ```
@@ -0,0 +1,15 @@
1
+ FROM ruby:2.3
2
+ MAINTAINER Darin London <darin.london@duke.edu>
3
+ RUN gem install -N bundler lita
4
+
5
+ #miscellaneous
6
+ RUN ["mkdir","-p","/var/www"]
7
+ WORKDIR /var/www/app
8
+ ADD Gemfile /var/www/app/Gemfile
9
+ ADD Gemfile.lock /var/www/app/Gemfile.lock
10
+ ADD lita-elasticsearch-indexer.gemspec /var/www/app/lita-elasticsearch-indexer.gemspec
11
+
12
+ RUN ["bundle", "install", "--jobs=4"]
13
+
14
+ # run the app by defualt
15
+ CMD ["lita"]
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "lita-slack"
6
+ gem "faye-websocket", "0.10.2"
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Research Application Development Group
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.
@@ -0,0 +1,46 @@
1
+ # lita-elasticsearch-indexer
2
+
3
+ A [Lita](https://www.lita.io/) handler plugin that indexes messages to
4
+ [Elasticsearch](https://www.elastic.co/).
5
+
6
+ ## Installation
7
+
8
+ Add lita-elasticsearch-indexer to your Lita instance's Gemfile:
9
+
10
+ ``` ruby
11
+ gem "lita-elasticsearch-indexer"
12
+ ```
13
+
14
+ ## Configuration
15
+
16
+ ### Required
17
+ * `elasticsearch_url` (String) - Host url for the Elasticsearch instance
18
+ * `elasticsearch_index_name` (String) - The name of the Elasticsearch index
19
+
20
+ ### Optional
21
+ * `elasticsearch_index_type` (String) - The
22
+ Elasticsearch document type. (default: 'message')
23
+ * `elasticsearch_index_options` (Proc) - A ruby `Proc` or `lambda` used to set index parameters or override the index body.
24
+
25
+ ## Usage
26
+
27
+ lita-elasticsearch-indexer is a lurker-bot that silently indexes all messages posted
28
+ by all users in any room to which it has been invited. It can also index
29
+ private messages sent directly to the bot. The bot will not index any messages
30
+ posted to rooms to which it has not been invited.
31
+
32
+ ### Setting elasticsearch index options with a Proc
33
+
34
+ Any of the optional arguments for [Elasticsearch::API::Actions index](http://www.rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions#index-instance_method) can be set via `elasticsearch_index_options` by creating a Proc
35
+ (or lambda) that returns a Hash. The hash will be merged with the required
36
+ parameters and passed directly to the elasticsearch client index method.
37
+
38
+ ```
39
+ config.handlers.elasticsearch_indexer.elasticsearch_index_options = lambda {|response|
40
+ options = {}
41
+ if response.message.extensions[:slack]
42
+ options[:id] = response.room.id + '-' + response.message.extensions[:slack][:timestamp]
43
+ end
44
+ options
45
+ }
46
+ ```
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,24 @@
1
+ version: '2'
2
+ services:
3
+ bundle:
4
+ image: "lita-elasticsearch-indexer_server"
5
+ volumes_from:
6
+ - workdir
7
+ entrypoint: ['bundle']
8
+ rake:
9
+ image: "lita-elasticsearch-indexer_server"
10
+ volumes_from:
11
+ - workdir
12
+ entrypoint: ['rake']
13
+ rspec:
14
+ image: "lita-elasticsearch-indexer_server"
15
+ environment:
16
+ - LITA_REDIS_HOST=redis
17
+ - LITA_ELASTICSEARCH_URL=elastic.local:9200
18
+ volumes_from:
19
+ - workdir
20
+ links:
21
+ - redis
22
+ - elasticsearch:elastic.local
23
+ entrypoint: ['rspec']
24
+ command: spec
@@ -0,0 +1,28 @@
1
+ version: '2'
2
+ services:
3
+ workdir:
4
+ image: ruby:2.3 # Reducing footprint by matching image to Dockerfile FROM
5
+ command: ['df'] # Just a quick command that exits. Mount info is a bonus.
6
+ volumes:
7
+ - .:/var/www/app
8
+ lita:
9
+ build: .
10
+ image: lita-elasticsearch-indexer_server
11
+ volumes_from:
12
+ - workdir
13
+ restart: always
14
+ links:
15
+ - redis
16
+ - elasticsearch:elastic.local
17
+ ports:
18
+ - 8080:8080
19
+ env_file:
20
+ - lita.env
21
+ redis:
22
+ image: redis
23
+ volumes:
24
+ - ./redis:/var/lib/redis
25
+ elasticsearch:
26
+ image: elasticsearch:2.2.2
27
+ ports:
28
+ - 9200
@@ -0,0 +1,12 @@
1
+ require "lita"
2
+
3
+ Lita.load_locales Dir[File.expand_path(
4
+ File.join("..", "..", "locales", "*.yml"), __FILE__
5
+ )]
6
+
7
+ require "lita/handlers/elasticsearch_indexer"
8
+
9
+ Lita::Handlers::ElasticsearchIndexer.template_root File.expand_path(
10
+ File.join("..", "..", "templates"),
11
+ __FILE__
12
+ )
@@ -0,0 +1,55 @@
1
+ require 'elasticsearch'
2
+ module Lita
3
+ module Handlers
4
+ class ElasticsearchIndexer < Handler
5
+ config :elasticsearch_url, type: String, required: true
6
+ config :elasticsearch_index_name, type: String, required: true
7
+ config :elasticsearch_index_type, type: String, default: "message"
8
+ config :elasticsearch_index_options, type: Proc
9
+
10
+ route(/^(.+)/,
11
+ :index_conversation,
12
+ help: { "info" =>
13
+ "Stores conversations in elasticsearch"
14
+ })
15
+
16
+ def elasticsearch_client
17
+ @@elasticsearch_client ||= Elasticsearch::Client.new(
18
+ urls: config.elasticsearch_url
19
+ )
20
+ end
21
+
22
+ def index_conversation(response)
23
+ user = response.user
24
+ message = response.message
25
+ room = message.room_object
26
+ index_body = {
27
+ user: {id: user.id, name: user.name},
28
+ message: {
29
+ private: message.private_message?,
30
+ body: message.body
31
+ }
32
+ }
33
+ index_body[:room] = {id: room.id, name: room.name} if room
34
+ index_params = {
35
+ body: index_body
36
+ }.merge(elasticsearch_index_options(response))
37
+ index_params[:index] = config.elasticsearch_index_name
38
+ index_params[:type] = config.elasticsearch_index_type
39
+ index = elasticsearch_client.index(index_params)
40
+ end
41
+
42
+ Lita.register_handler(self)
43
+
44
+ private
45
+
46
+ def elasticsearch_index_options(response)
47
+ if config.elasticsearch_index_options
48
+ config.elasticsearch_index_options.call(response)
49
+ else
50
+ {}
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,31 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "lita-elasticsearch-indexer"
3
+ spec.version = "0.1.1"
4
+ spec.authors = ["Darrin Mann", "Darin London"]
5
+ spec.email = ["darrin.mann@duke.edu", "darin.london@duke.edu"]
6
+ spec.description = <<-EOF
7
+ lita-elasticsearch-indexer is a lurker-bot that silently indexes all messages posted
8
+ by all users in any room to which it has been invited. It can also index
9
+ private messages sent directly to the bot. The bot will not index any messages
10
+ posted to rooms to which it has not been invited.
11
+ EOF
12
+ spec.summary = "Listens to channel conversations and stores them to elasticsearch"
13
+ spec.homepage = "https://github.com/ORI-RAD/lita-elasticsearch-indexer"
14
+ spec.license = "MIT"
15
+ spec.metadata = { "lita_plugin_type" => "handler" }
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "lita", ">= 4.7"
23
+ spec.add_runtime_dependency "elasticsearch"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "pry-byebug"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "rack-test"
29
+ spec.add_development_dependency "rspec", ">= 3.0.0"
30
+ spec.add_development_dependency "faker"
31
+ end
@@ -0,0 +1,11 @@
1
+ #----------------------------------------------------------------------
2
+ # Copy this file to lita.env and configure lita secrets there.
3
+ # DO NOT ADD SECRETS TO THIS [lita.env.example] FILE!
4
+ #----------------------------------------------------------------------
5
+
6
+ # Slack API token for the bot. For more information, see:
7
+ # https://github.com/litaio/lita-slack#configuration
8
+ LITA_SLACK_TOKEN=REPLACE-THIS-WITH-YOUR-API-TOKEN
9
+ LITA_ELASTICSEARCH_URL=elastic.local:9200
10
+ LITA_ELASTICSEARCH_INDEX_NAME=rad-chats
11
+ LITA_REDIS_HOST=redis
@@ -0,0 +1,43 @@
1
+ Lita.configure do |config|
2
+ # The name your robot will use.
3
+ # config.robot.name = "Lita"
4
+
5
+ # The locale code for the language to use.
6
+ # config.robot.locale = :en
7
+
8
+ # The severity of messages to log. Options are:
9
+ # :debug, :info, :warn, :error, :fatal
10
+ # Messages at the selected level and above will be logged.
11
+ config.robot.log_level = :debug
12
+
13
+ # An array of user IDs that are considered administrators. These users
14
+ # the ability to add and remove other users from authorization groups.
15
+ # What is considered a user ID will change depending on which adapter you use.
16
+ # config.robot.admins = ["1", "2"]
17
+
18
+ # The adapter you want to connect with. Make sure you've added the
19
+ # appropriate gem to the Gemfile.
20
+ config.robot.adapter = :slack
21
+ config.adapters.slack.token = ENV['LITA_SLACK_TOKEN']
22
+
23
+ ## Example: Set options for the chosen adapter.
24
+ # config.adapter.username = "myname"
25
+ # config.adapter.password = "secret"
26
+
27
+ ## Example: Set options for the Redis connection.
28
+ config.redis[:host] = ENV['LITA_REDIS_HOST']
29
+ # config.redis.port = 1234
30
+
31
+ ## Example: Set configuration for any loaded handlers. See the handler's
32
+ ## documentation for options.
33
+ # config.handlers.some_handler.some_config_key = "value"
34
+ config.handlers.elasticsearch_indexer.elasticsearch_url = ENV['LITA_ELASTICSEARCH_URL']
35
+ config.handlers.elasticsearch_indexer.elasticsearch_index_name = ENV['LITA_ELASTICSEARCH_INDEX_NAME']
36
+ config.handlers.elasticsearch_indexer.elasticsearch_index_options = lambda {|response|
37
+ options = {}
38
+ if response.message.extensions[:slack]
39
+ options[:id] = response.room.id + '-' + response.message.extensions[:slack][:timestamp]
40
+ end
41
+ options
42
+ }
43
+ end
@@ -0,0 +1,4 @@
1
+ en:
2
+ lita:
3
+ handlers:
4
+ elasticsearch_indexer:
@@ -0,0 +1,116 @@
1
+ require "spec_helper"
2
+ require "faker"
3
+
4
+ describe Lita::Handlers::ElasticsearchIndexer, lita_handler: true do
5
+ describe 'config' do
6
+ let(:config) { Hash[described_class.configuration_builder.children.collect {|x| [x.name, x]}] }
7
+ # Elasticsearch::Transport Client setting hosts documentation:
8
+ # http://www.rubydoc.info/gems/elasticsearch-transport/file/README.md#Setting_Hosts
9
+ it { expect(config).to have_key(:elasticsearch_url) }
10
+ it { expect(config[:elasticsearch_url]).to be_required }
11
+ it { expect(config[:elasticsearch_url].types).to contain_exactly(String) }
12
+
13
+ # Elasticsearch::API::Actions#index documentation:
14
+ # http://www.rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions#index-instance_method
15
+ it { expect(config).to have_key(:elasticsearch_index_name) }
16
+ it { expect(config[:elasticsearch_index_name]).to be_required }
17
+ it { expect(config[:elasticsearch_index_name].types).to contain_exactly(String) }
18
+
19
+ it { expect(config).to have_key(:elasticsearch_index_type) }
20
+ it { expect(config[:elasticsearch_index_type]).not_to be_required }
21
+ it { expect(config[:elasticsearch_index_type].types).to contain_exactly(String) }
22
+
23
+ it { expect(config).to have_key(:elasticsearch_index_options) }
24
+ it { expect(config[:elasticsearch_index_options]).not_to be_required }
25
+ it { expect(config[:elasticsearch_index_options].types).to contain_exactly(Proc) }
26
+ end
27
+
28
+ describe '#index_conversation' do
29
+ it { is_expected.to respond_to(:index_conversation).with(1).argument }
30
+
31
+ context 'with a non-empty message' do
32
+ let(:message) { Faker::Hacker.say_something_smart }
33
+ let(:room_id) { Faker::Internet.slug }
34
+ let(:private_message) { false }
35
+
36
+ it { is_expected.to route(message).to(:index_conversation) }
37
+
38
+ context 'send_message' do
39
+ let(:method) { send_message(message, from: room_id, privately: private_message) }
40
+ let(:registry_config) { registry.config.handlers.elasticsearch_indexer }
41
+ let(:index_name) { "test-#{Faker::Internet.slug}" }
42
+ let(:index_type) { "test-#{Faker::Internet.slug}" }
43
+ let(:index_body) { {
44
+ "user" => {
45
+ "id" => user.id,
46
+ "name" => user.name
47
+ },
48
+ "message" => {
49
+ "private" => private_message,
50
+ "body" => message
51
+ }
52
+ } }
53
+ let(:elasticsearch_url) { ENV['LITA_ELASTICSEARCH_URL'] }
54
+
55
+ before do
56
+ registry_config.elasticsearch_url = elasticsearch_url
57
+ registry_config.elasticsearch_index_name = index_name
58
+ registry_config.elasticsearch_index_type = index_type
59
+
60
+ expect(registry_config.elasticsearch_url).not_to be_nil
61
+ end
62
+
63
+ it 'does not send a reply' do
64
+ expect{ method }.not_to raise_error
65
+ expect(replies).to be_empty
66
+ end
67
+
68
+ it_behaves_like 'an elasticsearch indexer' do
69
+ include_context 'with a single document indexed'
70
+
71
+ it { expect(document["_index"]).to eq(index_name) }
72
+ it { expect(document["_type"]).to eq(index_type) }
73
+ it { expect(document["_source"]).to include(index_body) }
74
+ end
75
+
76
+ context 'when elasticsearch_index_options' do
77
+ let(:id) { Faker::Internet.slug }
78
+ before do
79
+ expect {
80
+ registry_config.elasticsearch_index_options = index_options
81
+ }.not_to raise_error
82
+ end
83
+ context 'is a Proc' do
84
+ let(:index_options) {
85
+ Proc.new { |response|
86
+ {id: id}
87
+ }
88
+ }
89
+ it_behaves_like 'an elasticsearch indexer' do
90
+ include_context 'with a single document indexed'
91
+
92
+ it { expect(document["_id"]).to eq(id) }
93
+ end
94
+ end
95
+
96
+ context 'is a lambda' do
97
+ let(:index_options) {
98
+ lambda { |response|
99
+ {id: id}
100
+ }
101
+ }
102
+ it_behaves_like 'an elasticsearch indexer' do
103
+ include_context 'with a single document indexed'
104
+
105
+ it { expect(document["_id"]).to eq(id) }
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'with an empty message' do
113
+ it { is_expected.not_to route('').to(:index_conversation) }
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,14 @@
1
+ require "lita-elasticsearch-indexer"
2
+ require "lita/rspec"
3
+
4
+ # loading shared examples
5
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
6
+
7
+ # A compatibility mode is provided for older plugins upgrading from Lita 3. Since this plugin
8
+ # was generated with Lita 4, the compatibility mode should be left disabled.
9
+ Lita.version_3_compatibility_mode = false
10
+
11
+ Lita.configure do |config|
12
+ config.redis[:host] = ENV['LITA_REDIS_HOST']
13
+ # config.redis.port = 1234
14
+ end
@@ -0,0 +1,31 @@
1
+ shared_examples 'an elasticsearch indexer' do |method_sym: :method, elasticsearch_url_sym: :elasticsearch_url|
2
+ let(:elasticsearch_client) {
3
+ Elasticsearch::Client.new(urls: send(elasticsearch_url_sym))
4
+ }
5
+ let(:existing_documents) { elasticsearch_client.search["hits"]["hits"] }
6
+ let(:new_documents) { elasticsearch_client.search["hits"]["hits"] - existing_documents }
7
+ before do
8
+ expect{ existing_documents }.not_to raise_error
9
+ expect{ send(method_sym) }.not_to raise_error
10
+ expect{ elasticsearch_client.indices.flush }.not_to raise_error
11
+ expect{ new_documents }.not_to raise_error
12
+ expect(new_documents).not_to be_empty
13
+ end
14
+ after do
15
+ new_documents.each do |d|
16
+ elasticsearch_client.delete(
17
+ id: d["_id"],
18
+ index: d["_index"],
19
+ type: d["_type"]
20
+ )
21
+ end
22
+ end
23
+ end
24
+
25
+ shared_context 'with a single document indexed' do
26
+ let(:document) { new_documents.first }
27
+ before do
28
+ expect(new_documents.length).to eq(1)
29
+ expect(document).not_to be_nil
30
+ end
31
+ end
File without changes
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lita-elasticsearch-indexer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Darrin Mann
8
+ - Darin London
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-01-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: lita
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '4.7'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '4.7'
28
+ - !ruby/object:Gem::Dependency
29
+ name: elasticsearch
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: bundler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '1.3'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '1.3'
56
+ - !ruby/object:Gem::Dependency
57
+ name: pry-byebug
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rack-test
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: 3.0.0
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: 3.0.0
112
+ - !ruby/object:Gem::Dependency
113
+ name: faker
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: |2
127
+ lita-elasticsearch-indexer is a lurker-bot that silently indexes all messages posted
128
+ by all users in any room to which it has been invited. It can also index
129
+ private messages sent directly to the bot. The bot will not index any messages
130
+ posted to rooms to which it has not been invited.
131
+ email:
132
+ - darrin.mann@duke.edu
133
+ - darin.london@duke.edu
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - .gitignore
139
+ - Docker.README.md
140
+ - Dockerfile
141
+ - Gemfile
142
+ - LICENSE
143
+ - README.md
144
+ - Rakefile
145
+ - docker-compose.dev.yml
146
+ - docker-compose.yml
147
+ - lib/lita-elasticsearch-indexer.rb
148
+ - lib/lita/handlers/elasticsearch_indexer.rb
149
+ - lita-elasticsearch-indexer.gemspec
150
+ - lita.env.example
151
+ - lita_config.rb
152
+ - locales/en.yml
153
+ - spec/lita/handlers/elasticsearch_indexer_spec.rb
154
+ - spec/spec_helper.rb
155
+ - spec/support/elasticsearch_shared_examples.rb
156
+ - templates/.gitkeep
157
+ homepage: https://github.com/ORI-RAD/lita-elasticsearch-indexer
158
+ licenses:
159
+ - MIT
160
+ metadata:
161
+ lita_plugin_type: handler
162
+ post_install_message:
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - '>='
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - '>='
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubyforge_project:
178
+ rubygems_version: 2.0.14.1
179
+ signing_key:
180
+ specification_version: 4
181
+ summary: Listens to channel conversations and stores them to elasticsearch
182
+ test_files:
183
+ - spec/lita/handlers/elasticsearch_indexer_spec.rb
184
+ - spec/spec_helper.rb
185
+ - spec/support/elasticsearch_shared_examples.rb