summaryrefslogtreecommitdiff
path: root/lib/rbot/core/basics.rb
blob: 0473028aceff3899813b029ea60bbd2370367e30 (plain)
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#-- vim:sw=2:et
#++
#
# :title: rbot basic management from IRC
#
# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>

class BasicsModule < CoreBotModule

  Config.register Config::BooleanValue.new('irc.join_after_identify',
    :default => false, :wizard => true, :requires_restart => true,
    :desc => "Should the bot wait until its identification is confirmed before joining any channels?")

  def join_channels
    @bot.config['irc.join_channels'].each { |c|
      debug "autojoining channel #{c}"
      if(c =~ /^(\S+)\s+(\S+)$/i)
        @bot.join $1, $2
      else
        @bot.join c if(c)
      end
    }
  end

  def identified
    join_channels
  end

  # on connect, we join the default channels unless we have to wait for
  # identification. Observe that this means the bot may not connect any channels
  # until the 'identified' method gets delegated
  def connect
    if @bot.config['irc.join_after_identify']
      log "waiting for identififcation before JOINing default channels"
    else
      join_channels
    end
  end

  def ctcp_listen(m)
    who = m.private? ? "me" : m.target
    case m.ctcp.intern
    when :PING
      m.ctcp_reply m.message
    when :TIME
      m.ctcp_reply Time.now.to_s
    end
  end

  def bot_join(m, param)
    if param[:pass]
      @bot.join param[:chan], param[:pass]
    else
      @bot.join param[:chan]
    end
  end

  def invite(m)
    if @bot.auth.allow?(:"basics::move::join", m.source, m.source)
      @bot.join m.channel
    end
  end

  def bot_part(m, param)
    if param[:chan]
      @bot.part param[:chan]
    else
      @bot.part m.target if m.public?
    end
  end

  def bot_channel_list(m, param)
    ret = _('I am in: ')
    # sort the channels by the base name and then map with prefixes for the
    # mode and display.
    ret << @bot.channels.compact.sort { |a,b|
        a.name.downcase <=> b.name.downcase
    }.map { |c|
        c.modes_of(@bot.myself).map{ |mo|
          m.server.prefix_for_mode(mo)
        }.to_s + c.name
    }.join(', ')
    m.reply ret
  end

  def bot_quit(m, param)
    @bot.quit param[:msg].to_s
  end

  def bot_restart(m, param)
    @bot.restart param[:msg].to_s
  end

  def bot_reconnect(m, param)
    @bot.reconnect param[:msg].to_s
  end

  def bot_hide(m, param)
    @bot.join 0
  end

  def bot_say(m, param)
    @bot.say param[:where], param[:what].to_s
  end

  def bot_notify(m, param)
    @bot.notice param[:where], param[:what].to_s
  end

  def bot_action(m, param)
    @bot.action param[:where], param[:what].to_s
  end

  def bot_mode(m, param)
    @bot.mode param[:where], param[:what], param[:who].join(" ")
  end

  def bot_ping(m, param)
    m.reply "pong"
  end

  def bot_quiet(m, param)
    if param.has_key?(:where)
      @bot.set_quiet param[:where].sub(/^here$/, m.target.downcase)
    else
      @bot.set_quiet
    end
    # Make sense when the commmand is given in private or in a non-quieted
    # channel
    m.okay
  end

  def bot_talk(m, param)
    if param.has_key?(:where)
      @bot.reset_quiet param[:where].sub(/^here$/, m.target.downcase)
    else
      @bot.reset_quiet
    end
    # Make sense when the commmand is given in private or in a non-quieted
    # channel
    m.okay
  end

  def bot_help(m, param)
    m.reply @bot.help(param[:topic].join(" "))
  end

  #TODO move these to a "chatback" plugin
  # when (/^(botsnack|ciggie)$/i)
  #   @bot.say m.replyto, @lang.get("thanks_X") % m.sourcenick if(m.public?)
  #   @bot.say m.replyto, @lang.get("thanks") if(m.private?)
  # when (/^#{Regexp.escape(@bot.nick)}!*$/)
  #   @bot.say m.replyto, @lang.get("hello_X") % m.sourcenick

  # handle help requests for "core" topics
  def help(cmd, topic="")
    case cmd
    when "quit"
      _("quit [<message>] => quit IRC with message <message>")
    when "restart"
      _("restart => completely stop and restart the bot (including reconnect)")
    when "reconnect"
      _("reconnect => ask the bot to disconnect and then connect again")
    when "join"
      _("join <channel> [<key>] => join channel <channel> with secret key <key> if specified. #{@bot.myself} also responds to invites if you have the required access level")
    when "part"
      _("part <channel> => part channel <channel>")
    when "hide"
      _("hide => part all channels")
    when "say"
      _("say <channel>|<nick> <message> => say <message> to <channel> or in private message to <nick>")
    when "action"
      _("action <channel>|<nick> <message> => does a /me <message> to <channel> or in private message to <nick>")
    when "quiet"
      _("quiet [in here|<channel>] => with no arguments, stop speaking in all channels, if \"in here\", stop speaking in this channel, or stop speaking in <channel>")
    when "talk"
      _("talk [in here|<channel>] => with no arguments, resume speaking in all channels, if \"in here\", resume speaking in this channel, or resume speaking in <channel>")
    when "ping"
      _("ping => replies with a pong")
    when "mode"
      _("mode <channel> <mode> <nicks> => set channel modes for <nicks> on <channel> to <mode>")
    #     when "botsnack"
    #       return "botsnack => reward #{@bot.myself} for being good"
    #     when "hello"
    #       return "hello|hi|hey|yo [#{@bot.myself}] => greet the bot"
    else
      _("%{name}: quit, restart, join, part, hide, save, say, action, topic, quiet, talk, ping, mode") % {:name=>name}
      #, botsnack, hello
    end
  end
end

basics = BasicsModule.new

basics.map "quit *msg",
  :action => 'bot_quit',
  :defaults => { :msg => nil },
  :auth_path => 'quit'
basics.map "restart *msg",
  :action => 'bot_restart',
  :defaults => { :msg => nil },
  :auth_path => 'quit'
basics.map "reconnect *msg",
  :action => 'bot_reconnect',
  :defaults => { :msg => nil },
  :auth_path => 'quit'

basics.map "quiet [in] [:where]",
  :action => 'bot_quiet',
  :auth_path => 'talk::set'
basics.map "talk [in] [:where]",
  :action => 'bot_talk',
  :auth_path => 'talk::set'

basics.map "say :where *what",
  :action => 'bot_say',
  :auth_path => 'talk::do'
basics.map "notify :where *what",
  :action => 'bot_notify',
  :auth_path => 'talk::do'
basics.map "action :where *what",
  :action => 'bot_action',
  :auth_path => 'talk::do'
basics.map "mode :where :what *who",
  :action => 'bot_mode',
  :auth_path => 'talk::do'

basics.map "join :chan :pass",
  :action => 'bot_join',
  :defaults => {:pass => nil},
  :auth_path => 'move'
basics.map "part :chan",
  :action => 'bot_part',
  :defaults => {:chan => nil},
  :auth_path => 'move'
basics.map "channels",
  :action => 'bot_channel_list',
  :auth_path => 'move'
basics.map "hide",
  :action => 'bot_hide',
  :auth_path => 'move'

basics.map "ping",
  :action => 'bot_ping',
  :auth_path => '!ping!'
basics.map "help *topic",
  :action => 'bot_help',
  :defaults => { :topic => [""] },
  :auth_path => '!help!'

basics.default_auth('*', false)