-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathweb.rb
139 lines (126 loc) · 2.72 KB
/
web.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# coding: utf-8
require 'bundler'
require 'digest/sha1'
require 'json'
require 'igo-ruby'
Dir.chdir File.dirname(__FILE__)
Bundler.require
set :environment, :production
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/momochan.db")
class Momochan
include DataMapper::Resource
property :id, Serial
property :text, String, :length => 4096
property :created_at, DateTime
end
DataMapper.finalize
Momochan.auto_upgrade!
module Splitter
@tagger = Igo::Tagger.new('ipadic')
module_function
def call(str)
['__BEGIN__', *@tagger.wakati(str), '__END__']
end
end
class Markov
def initialize()
@table = {}
end
def study(words)
words.each_cons(3) do |a, b, c|
@table[a] ||= []
@table[a] << [b, c]
end
end
def search1(key)
@table[key].
map {|(b, c)| b }.
sample
end
def search2(key1, key2)
@table[key1].
select {|(b, c)| b == key2 }.
map {|(b, c)| c }.
sample
end
def build
array = []
key1 = '__BEGIN__'
key2 = search1(key1)
return [] unless key2
until key2 == '__END__'
array << key2
key1, key2 = key2, search2(key1, key2)
end
array
end
end
module App
module_function
def momochan(text)
tokens = Splitter.(text)
@markov.study(tokens)
text = 21.times.inject('') {|_, _|
result = @markov.build.join('')
if tokens[1...-1].select {|x| x.size >= 2 && result[x] }.empty?
result
elsif result.size < 140 && /^https?:\/\/\S+$/ !~ result
break result
else
result
end
}
text.gsub(/[“”「」『』【】"]/, '')
end
def momochan_info
{
size: Momochan.all.size,
started_at: @t0,
boot_time: @t1 - @t0,
ready_p: @ready_p
}.to_json
end
@t0 = Time.now
@t1 = @t0
@ready_p = false
@markov = Markov.new
class << self
attr_reader :markov
end
Thread.start do
Momochan.all.each do |m|
#puts m['text']
@markov.study(Splitter.(m['text']))
end
@ready_p = true
@t1 = Time.now
end
end
post '/lingr/' do
json = JSON.parse(request.body.string)
json["events"].map {|e| e['message'] }.compact.map {|message|
text = message['text']
next App.momochan_info if /^#momochan info$/ =~ text
regexp = /#m[aiueo]*m[aiueo]*ch?[aiueo]*n|#amachan/
mcs = text.scan(regexp).map {|_|
App.momochan(text.gsub(regexp, ''))
}
mgs = text.scan(/#momonga/).map {|_|
[*["はい"]*10, "うるさい"].sample
}
reply = [mcs + mgs].join("\n")
if reply.empty?
Momochan.create({:text => text}).update
App.markov.study(Splitter.(text))
""
else
reply
end
}.join.rstrip[0..999]
end
get '/' do
App.momochan('')
end
get '/dev' do
App.momochan_info
end