This repository has been archived by the owner on Sep 12, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathreggie.rb
174 lines (143 loc) · 4.94 KB
/
reggie.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
require 'bundler/setup'
require 'cinch'
require 'configru'
require_relative 'memory'
Configru.load('config.yml') do
option_required :server, String
option :port, Fixnum, 6667
option_required :nick, String
option_array :channels, String
option :max_bangs, Fixnum, 3
end
bot = Cinch::Bot.new do
configure do |c|
c.server = Configru.server
c.port = Configru.port
c.nick = Configru.nick
c.channels = Configru.channels
@max_bangs = Configru.max_bangs
@ch_user_memory = {}
@channel_memory = {}
end
helpers do
def regex_replace(target, match, replace, replace_all, nick)
if target =~ /^\x01ACTION (.*)\x01$/
prefix = "* #{nick} "
target = $1
action = true
else
prefix = "<#{nick}> "
action = false
end
answer = if replace_all
target.gsub(match, replace)
else
target.sub(match, replace)
end
if action
return prefix, answer, "\x01ACTION #{answer}\x01"
else
return prefix, answer, answer
end
end
end
on :channel do |m|
@channel_memory[m.channel.name] ||= Memory.new(@max_bangs)
@ch_user_memory[m.channel.name] ||= {}
@ch_user_memory[m.channel.name][m.user.nick] ||= Memory.new(@max_bangs)
if m.message =~ %r"^(!*)s/((?:[^\\/]|\\.)*)/((?:[^\\/]|\\.)*)/(?:(\S*))?"
bangs = $1
match = $2
replace = $3
flags = $4
# This replaces \/ with / in the replacement part (that is, s//<here>/),
# because / needs to be escaped by users
replace.gsub!(/(?<!\\)((?:\\\\)*)\\\//, '\1/')
if bangs.length > @max_bangs
m.reply("I only support up to #{@max_bangs} !'s.", true)
next
end
extra_slashes = flags.delete!('/')
if flags.include?('?')
snappy_reply = [
"I don't know. Why don't you ask yourself?",
"How should I know?",
"Why would I know that?",
"Yes. Very yes.",
"Are you insane?",
"I don't know. Have you tried asking lazybot??"
].sample
m.reply(snappy_reply, true)
next
end
regex_opts = []
regex_opts << Regexp::IGNORECASE if flags.delete!('i')
regex_opts << Regexp::EXTENDED if flags.delete!('x')
regex_opts << Regexp::MULTILINE if flags.delete!('m')
replace_all = flags.delete!('g')
if flags.size != 0 && extra_slashes
m.reply("Ignoring extra slashes and unrecognized flags: #{flags}", true)
elsif extra_slashes
m.reply("Ignoring extra slashes.", true)
elsif flags.size != 0
m.reply("Ignoring unrecognized flags: #{flags}", true)
end
begin
match = Regexp.new(match, regex_opts.reduce(:|))
rescue RegexpError => err
m.reply(err.message.capitalize, true)
next
end
target = if bangs.length == 0
@channel_memory[m.channel][-1] && @channel_memory[m.channel][-1][1]
else
@ch_user_memory[m.channel][m.user.nick][-bangs.length]
end
if !target
m.reply("My memory doesn't go back that far!", true)
next
end
nick = if bangs.length > 0
m.user.nick
else
@channel_memory[m.channel][-1][0]
end
prefix, answer, new_memory =
regex_replace(target, match, replace, replace_all, nick)
# If s/// doesn't change anything, it will try !s///, !!s///, etc, up
# to the maximum number of exclamation marks. If the last !!!s/// fails,
# it will try to use previous lines from global channel memory.
if bangs.length == 0 && target == answer
nick = m.user.nick
1.upto(@max_bangs) do |i|
target = @ch_user_memory[m.channel][m.user.nick][-i]
break if target.nil?
prefix, answer = regex_replace(target, match, replace, replace_all, nick)
break if answer != target
end
# Try global channel memory.
1.upto(@max_bangs) do |i|
entry = @channel_memory[m.channel][-i]
break if entry.nil?
nick, target = entry
prefix, answer = regex_replace(target, match, replace, replace_all, nick)
break if answer != target
end
end
next if target == answer
# Update the string in @ch_user_memory or @channel_memory.
target.replace(new_memory)
m.reply(prefix + answer)
elsif m.message =~ /^#{Regexp.escape(m.bot.nick)}[:,]\s*help\s*$/
m.reply("I perform Perl-style s/// regex replacements in the channel " \
"using Ruby regex. If you prepend '!', I will only look at " \
"*your* last line. You can use up to #{@max_bangs} '!'s to " \
"look that many lines back. Ruby regex docs at " \
"http://is.gd/rubyregexp", true)
elsif !m.ctcp? || m.ctcp_command == 'ACTION'
@ch_user_memory[m.channel][m.user.nick] << m.message
@channel_memory[m.channel] << [m.user.nick, m.message]
end
end
end
bot.start