lita-markov 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/LICENSE +27 -0
- data/README.md +26 -0
- data/Rakefile +6 -0
- data/lib/lita-markov.rb +13 -0
- data/lib/lita/handlers/markov.rb +64 -0
- data/lib/marky_markov/persistent_json_dictionary.rb +34 -0
- data/lita-markov.gemspec +25 -0
- data/locales/en.yml +4 -0
- data/spec/lita/handlers/markov_spec.rb +47 -0
- data/spec/marky_markov/persistent_json_dictionary_spec.rb +28 -0
- data/spec/spec_helper.rb +6 -0
- data/templates/.gitkeep +0 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 80906c8495bb1dcbbc33b970047390e606b429c8
|
4
|
+
data.tar.gz: 85f84a17b45289e6c86334318322eebba6724b8f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f7c18adeba628b7e6cc48a22922fd745595104ce6846c919b773ab475e7c22b4d2e852d747055adadaec74b0dc881cab36254b305ab4c2df179c6a77e1b118e3
|
7
|
+
data.tar.gz: e4fce6fb0f3d70d04d2153fb202d1740c223abadc475a18a6629ba5080f211219dc58a0817bd36d58d6529801b8da7a2eaeb700585b7bb69d7ff1c20daf45145
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2015 Dirk Gadsden
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
* Neither the name of Roost nor the names of its contributors may be used to
|
15
|
+
endorse or promote products derived from this software without specific
|
16
|
+
prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Markov chains for Lita
|
2
|
+
|
3
|
+
Listens to your public chat rooms and generates Markov chain databases
|
4
|
+
for each user.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add `lita-markov` to your Lita instance's Gemfile:
|
9
|
+
|
10
|
+
``` ruby
|
11
|
+
gem 'lita-markov'
|
12
|
+
```
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
The bot will automatically ingest all messages into the Redis-backed Markov
|
17
|
+
chain database. You can then query the bot for a generated chain:
|
18
|
+
|
19
|
+
```
|
20
|
+
user> mybot markov dirk
|
21
|
+
mybot> I love cookies!
|
22
|
+
```
|
23
|
+
|
24
|
+
## License
|
25
|
+
|
26
|
+
Licensed under the 3-clause BSD license. See [LICENSE](LICENSE) for details.
|
data/Rakefile
ADDED
data/lib/lita-markov.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "lita"
|
2
|
+
|
3
|
+
Lita.load_locales Dir[File.expand_path(
|
4
|
+
File.join("..", "..", "locales", "*.yml"), __FILE__
|
5
|
+
)]
|
6
|
+
|
7
|
+
require 'marky_markov/persistent_json_dictionary'
|
8
|
+
require 'lita/handlers/markov'
|
9
|
+
|
10
|
+
# Lita::Handlers::Markov.template_root File.expand_path(
|
11
|
+
# File.join("..", "..", "templates"),
|
12
|
+
# __FILE__
|
13
|
+
# )
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Lita::Handlers
|
2
|
+
class Markov < Lita::Handler
|
3
|
+
Dictionary = MarkyMarkov::PersistentJSONDictionary
|
4
|
+
|
5
|
+
REDIS_KEY_PREFIX = 'lita-markov:'
|
6
|
+
|
7
|
+
route(/.+/, :ingest, command: false)
|
8
|
+
|
9
|
+
route(/markov (.+)/, :generate, command: true, help: {
|
10
|
+
'markov USER' => 'Generate a markov chain from the given user.'
|
11
|
+
})
|
12
|
+
|
13
|
+
def ingest(chat)
|
14
|
+
# Don't ingest messages addressed to ourselves
|
15
|
+
return if chat.command?
|
16
|
+
|
17
|
+
message = chat.matches[0].strip
|
18
|
+
|
19
|
+
# Get the mention name (ie. 'dirk') of the user
|
20
|
+
name = chat.user.mention_name
|
21
|
+
dictionary = dictionary_for_user name
|
22
|
+
|
23
|
+
# Passing `false` to indicate it's a string and not a file name
|
24
|
+
dictionary.parse_source message, false
|
25
|
+
|
26
|
+
save_dictionary name, dictionary
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate(chat)
|
30
|
+
name = chat.matches[0][0].strip
|
31
|
+
|
32
|
+
dictionary = dictionary_for_user name
|
33
|
+
generator = MarkovSentenceGenerator.new dictionary
|
34
|
+
|
35
|
+
begin
|
36
|
+
sentence = generator.generate_sentence 1
|
37
|
+
|
38
|
+
chat.reply sentence
|
39
|
+
rescue EmptyDictionaryError
|
40
|
+
chat.reply "Looks like #{name} hasn't said anything!"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def save_dictionary(name, dictionary)
|
45
|
+
redis.set key_for_user(name), dictionary.to_json
|
46
|
+
end
|
47
|
+
|
48
|
+
def dictionary_for_user(name)
|
49
|
+
key = key_for_user name
|
50
|
+
dictionary = Dictionary.new name
|
51
|
+
json = redis.get key
|
52
|
+
|
53
|
+
dictionary.load_json(json) if json
|
54
|
+
|
55
|
+
dictionary
|
56
|
+
end
|
57
|
+
|
58
|
+
def key_for_user(name)
|
59
|
+
REDIS_KEY_PREFIX+name.downcase
|
60
|
+
end
|
61
|
+
|
62
|
+
Lita.register_handler self
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'marky_markov'
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
module MarkyMarkov
|
5
|
+
class PersistentJSONDictionary < ::PersistentDictionary
|
6
|
+
def initialize(*args)
|
7
|
+
super(*args)
|
8
|
+
|
9
|
+
@dictionary = {}
|
10
|
+
@capitalized_words = []
|
11
|
+
end
|
12
|
+
|
13
|
+
# No-op instead of reading from the filesystem
|
14
|
+
def open_dictionary
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_json(json)
|
19
|
+
data = Oj.load json
|
20
|
+
|
21
|
+
@depth = data['depth']
|
22
|
+
@dictionary = data['dictionary']
|
23
|
+
@capitalized_words = data['capitalized_words']
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_json
|
27
|
+
Oj.dump(
|
28
|
+
'depth' => @depth,
|
29
|
+
'dictionary' => @dictionary,
|
30
|
+
'capitalized_words' => @capitalized_words
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lita-markov.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "lita-markov"
|
3
|
+
spec.version = "0.0.1"
|
4
|
+
spec.authors = ["Dirk Gadsden"]
|
5
|
+
spec.email = ["dirk@dirk.to"]
|
6
|
+
spec.description = "Markov chains for Lita."
|
7
|
+
spec.summary = spec.description
|
8
|
+
spec.homepage = "http://github.com/dirk/lita-markov"
|
9
|
+
spec.metadata = { "lita_plugin_type" => "handler" }
|
10
|
+
|
11
|
+
spec.files = `git ls-files`.split($/)
|
12
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
13
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
|
16
|
+
spec.add_runtime_dependency "lita", ">= 4.6"
|
17
|
+
spec.add_runtime_dependency "marky_markov", "~> 0.3.5"
|
18
|
+
spec.add_runtime_dependency "oj", "~> 2.13.1"
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
21
|
+
spec.add_development_dependency "pry-byebug"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rack-test"
|
24
|
+
spec.add_development_dependency "rspec", ">= 3.0.0"
|
25
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
describe Lita::Handlers::Markov, lita_handler: true do
|
5
|
+
before(:each) do
|
6
|
+
Lita.redis.flushall
|
7
|
+
end
|
8
|
+
|
9
|
+
it "won't call #ingest for non-command messages" do
|
10
|
+
expect(subject).to_not receive(:ingest)
|
11
|
+
|
12
|
+
send_message "#{robot.name} foo"
|
13
|
+
send_command 'bar'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "will ingest a message into that person's dictionary" do
|
17
|
+
send_message 'hello markov world'
|
18
|
+
send_message 'hello markov planet'
|
19
|
+
|
20
|
+
dictionary = subject.dictionary_for_user user.mention_name
|
21
|
+
|
22
|
+
# Check that the messages made it into the dictionary
|
23
|
+
expect(dictionary.dictionary[['hello', 'markov']]).to eql ['world', 'planet']
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'will build a sentence' do
|
27
|
+
send_message 'I love cookies!'
|
28
|
+
send_message 'I love pancakes!'
|
29
|
+
|
30
|
+
send_command "#{robot.name} markov #{user.mention_name}"
|
31
|
+
|
32
|
+
expect(replies.count).to eql 1
|
33
|
+
|
34
|
+
possible_replies = [
|
35
|
+
'I love cookies!',
|
36
|
+
'I love pancakes!'
|
37
|
+
]
|
38
|
+
expect(possible_replies).to include replies[0]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "will complain if the user hasn't said anything" do
|
42
|
+
send_command "#{robot.name} markov #{user.mention_name}"
|
43
|
+
|
44
|
+
expect(replies.count).to eql 1
|
45
|
+
expect(replies[0]).to eql "Looks like Test User hasn't said anything!"
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MarkyMarkov::PersistentJSONDictionary do
|
4
|
+
subject { MarkyMarkov::PersistentJSONDictionary.new 'whoa' }
|
5
|
+
|
6
|
+
it 'initializes with sensible defaults' do
|
7
|
+
expect(subject.dictionary).to eq({})
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'saves a dictionary' do
|
11
|
+
subject.add_word ['a', 'b'], 'c'
|
12
|
+
|
13
|
+
json = subject.to_json
|
14
|
+
|
15
|
+
expect(json).to eql '{"depth":2,"dictionary":{"^#1":[["a","b"],["c"]]},"capitalized_words":[]}'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'saves and loads a dictionary' do
|
19
|
+
subject.add_word ['a', 'b'], 'c'
|
20
|
+
|
21
|
+
json = subject.to_json
|
22
|
+
|
23
|
+
new_dictionary = MarkyMarkov::PersistentJSONDictionary.new 'whoa-another-one'
|
24
|
+
new_dictionary.load_json json
|
25
|
+
|
26
|
+
expect(new_dictionary.dictionary).to eql(['a', 'b'] => ['c'])
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/templates/.gitkeep
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lita-markov
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dirk Gadsden
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: lita
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: marky_markov
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.3.5
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: oj
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.13.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.13.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
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: pry-byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rack-test
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 3.0.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 3.0.0
|
125
|
+
description: Markov chains for Lita.
|
126
|
+
email:
|
127
|
+
- dirk@dirk.to
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- Gemfile
|
134
|
+
- LICENSE
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- lib/lita-markov.rb
|
138
|
+
- lib/lita/handlers/markov.rb
|
139
|
+
- lib/marky_markov/persistent_json_dictionary.rb
|
140
|
+
- lita-markov.gemspec
|
141
|
+
- locales/en.yml
|
142
|
+
- spec/lita/handlers/markov_spec.rb
|
143
|
+
- spec/marky_markov/persistent_json_dictionary_spec.rb
|
144
|
+
- spec/spec_helper.rb
|
145
|
+
- templates/.gitkeep
|
146
|
+
homepage: http://github.com/dirk/lita-markov
|
147
|
+
licenses: []
|
148
|
+
metadata:
|
149
|
+
lita_plugin_type: handler
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 2.4.5.1
|
167
|
+
signing_key:
|
168
|
+
specification_version: 4
|
169
|
+
summary: Markov chains for Lita.
|
170
|
+
test_files:
|
171
|
+
- spec/lita/handlers/markov_spec.rb
|
172
|
+
- spec/marky_markov/persistent_json_dictionary_spec.rb
|
173
|
+
- spec/spec_helper.rb
|