Remove automatic argument splitting and add a * arg specifier

master
Marrub 2017-08-12 19:22:31 -04:00
parent f987c780f7
commit e84f48c4a5
9 changed files with 82 additions and 69 deletions

View File

@ -10,8 +10,9 @@ module Vrobot4
type = botinfo["type"]
serv = Server::get_server_type(type).new(botinfo)
botinfo["modules"].each \
{|mod| serv.load_mod mod} if botinfo.key? "modules"
if botinfo.key? "modules" then for mod in botinfo["modules"] do
serv.load_mod mod
end end
serv
end

View File

@ -2,7 +2,7 @@
module Vrobot4::Module
# A command function. Holds extra info for i.e. permissions.
class Command
attr_reader :help_str # Help string for this command.
attr_reader :help_str # @return [String] help string for this command
# @param fn [Method] method to be called on run
# @param help [String] help string for this command
@ -27,6 +27,8 @@ module Vrobot4::Module
end
# Calls the method attached to this command.
# @param m [Vrobot4::Server::Message] message for context
# @param argv [String] argument string
def run m, argv
@function.call(m, argv)
end
@ -51,10 +53,10 @@ module Vrobot4::Module
# Callback for command receiving.
# @param m [Vrobot4::Server::Message] message that triggered this call
# @param cnam [String] name of command to call
# @param argv [Array] array of string arguments
# @param argv [String] array of string arguments
# @return [Boolean] if this should block further command callbacks
def on_command m, cnam, argv
if (cmd = all_cmds(m)[cnam])
if (cmd = cmds(m)[cnam])
begin
cmd.run(m, argv)
rescue
@ -69,7 +71,7 @@ module Vrobot4::Module
# Gets all commands usable in a specified context.
# @param m [Vrobot4::Server::Message] message for context
# @return [Hash] a hash of all commands by name
def all_cmds m
def cmds m
@commands.select {|name, cmd| cmd.usable_in? m}
end
@ -96,24 +98,37 @@ module Vrobot4::Module
# Specifiers include:
# [N] A number.
# [S] An arbitrary string.
# [*] Any amount of arbitrary arguments. Must be the last optional arg.
#
# @param argv [Array] array of arguments
# @param argv [String, Array] array of arguments or a string
# @param req [String] specifier string of required arguments
# @param opt [String] specifier string of optional arguments
# @return argv
def check_args argv, req, opt = ""
if argv.length < req.length
raise ArgumentError, "Not enough arguments"
elsif argv.length > req.length + opt.length
raise ArgumentError, "Too many arguments"
else
(0...req.length).each do |i|
if argv.is_a? Array then
if argv.length < req.length
raise ArgumentError, "Not enough arguments"
elsif opt[-1] != '*' and argv.length > req.length + opt.length
raise ArgumentError, "Too many arguments"
end
for i in (0 ... req.length)
check_arg argv[i], i, req[i]
end
(0...argv.length - req.length).each do |i|
check_arg argv[i + req.length], i + req.length, opt[i]
for i in (0 ... argv.length - req.length)
break if opt[i] == '*'
argn = i + req.length
check_arg argv[argn], argn, opt[i]
end
else
if opt.length
check_arg argv, 0, opt[0] if argv.length
else
check_arg argv, 0, req[0]
end
end
argv
end
private
@ -123,6 +138,9 @@ module Vrobot4::Module
unless Vrobot4.is_num? arg.strip
raise ArgumentError, "Expected a number for arg " + i.to_s
end
when 'S' # Don't need to check anything here.
else
raise ArgumentError, "Invalid argument specifier " + req.to_s
end
end
end

View File

@ -92,7 +92,7 @@ class Mod_Audio < Vrobot4::Module::Module
def push_queue m, argv
m.reply "Queueing '" + uri.to_s + "'..."
uri = URI.parse argv.join(" ")
uri = URI.parse argv
qi = @queue.push QueueItem.new(uri)
m.reply "'" + uri.to_s + "' loaded (%i sec, %i bytes)" %
@ -100,7 +100,7 @@ class Mod_Audio < Vrobot4::Module::Module
end
def start_playback m, qi
m.serv.play m, qi.get_file
m.serv.voice_play m, qi.get_file
end
end

View File

@ -19,7 +19,7 @@ class Mod_Discord < Vrobot4::Module::Module
def c_purge m, argv
check_args argv, "N"
n = argv[0].to_i
n = argv.to_i
n = 2 if n < 2
n = 100 if n > 100
m.chan.real.prune n

View File

@ -1,7 +1,7 @@
require 'open-uri'
require 'json'
#
#--
# ===== WARNING =====
#
# !!! INCOMING SPAGHETTI !!!
@ -31,8 +31,7 @@ class Mod_DoomRLA < Vrobot4::Module::Module
end
def c_weaponinfo m, argv
name = argv.join(" ")
w = @winfo.select {|wep| wep if wep["Name"].casecmp? name}[0]
w = @winfo.select {|wep| wep if wep["Name"].casecmp? argv}[0]
raise ArgumentError, "Weapon not found" if w == nil
t = "%s %s damage\n" % [w["Damage"], w["DamageType"]]
t << "%s shots\n" % [w["Shots"]] if w["Shots"].to_i > 1
@ -53,10 +52,9 @@ class Mod_DoomRLA < Vrobot4::Module::Module
end
def c_monsterinfo m, argv
name = argv.join(" ")
mi = @minfo.select do |mon|
mon if mon["Name"].casecmp? name or
mon["Tags"].split(", ").include? name
mon if mon["Name"].casecmp? argv or
mon["Tags"].split(", ").include? argv
end
raise ArgumentError, "No monsters found" if mi == nil
mi.first(3).each do |w|
@ -78,7 +76,7 @@ class Mod_DoomRLA < Vrobot4::Module::Module
embed.title = "[%s] %s" % [w["Difficulty"], w["Name"]]
embed.title << " %s" % [w["Weapon"]] if w["Weapon"]
embed.image = Discordrb::Webhooks::EmbedImage.new \
url: w["Sprite"] if w.key? "Sprite"
url: w["Sprite"] if w["Sprite"]
embed.description = t
end
end

View File

@ -29,15 +29,12 @@ class Mod_Fun < Vrobot4::Module::Module
def c_nyan (m, argv) m.reply "nyan " * (rand(10) + 1) + "~" end
def c_box m, argv
str = argv.join(" ")
text = str + "\n"
raise ArgumentError, "String too long" if str.length > 30
if str.length > 2
for i in (1..str.length - 2)
text << str[i] + " " * (str.length - 2) + str.reverse[i] + "\n"
end
end
text << str.reverse
text = argv + "\n"
raise ArgumentError, "String too long" if argv.length > 30
if argv.length > 2 then for i in (1..argv.length - 2)
text << argv[i] + " " * (argv.length - 2) + argv.reverse[i] + "\n"
end end
text << argv.reverse
m.reply_b text
end
@ -48,8 +45,8 @@ class Mod_Fun < Vrobot4::Module::Module
def c_marble m, argv
check_args argv, "", "N"
if argv.length == 0 then n = 20
else n = argv[0].to_i end
if argv.empty? then n = 20
else n = argv.to_i end
if m.serv.flags.include? "L" and n > 200 then n = 200
elsif n > 1000 then n = 1000 end
@ -64,8 +61,7 @@ class Mod_Fun < Vrobot4::Module::Module
end
def c_quote m, argv
argv = argv.join(" ")
if argv.length == 0
if argv.empty?
q, num = nil, nil
max = JSON.parse(open(QDB + "/interface.cgi").read)["numQuotes"]
loop do

View File

@ -14,7 +14,7 @@ class Mod_Util < Vrobot4::Module::Module
end
def c_rand m, argv
check_args argv, "N", "N"
argv = check_args argv.split, "N", "N"
min, max = 0, argv[0].to_f
min, max = max, argv[1].to_f if argv.length >= 2
max, min = min, max if max < min
@ -23,7 +23,7 @@ class Mod_Util < Vrobot4::Module::Module
end
def c_decide m, argv
argv = argv.join(" ").split(",").each {|arg| arg.chomp!}
argv = check_args argv.split(/\s*,\s*/), "S", "*"
m.reply argv.sample
end

View File

@ -13,20 +13,18 @@ module Vrobot4::Server
# @!visibility private
def c_help m, argv
check_args argv, "", "S"
if argv.length == 0
if argv.empty?
cmds = []
m.serv.each_mod {|mod| cmds << mod.all_cmds(m).keys.join(", ")}
m.serv.each_mod {|mod| cmds << mod.cmds(m).keys.join(", ")}
cmds.delete ""
m.reply "Commands:", cmds.join(", ")
else
name = argv[0]
m.serv.each_mod do |mod|
if (cmd = mod.get_cmd m, name)
return m.reply name + ":", cmd.help_str
if (cmd = mod.cmds(m)[argv])
return m.reply argv + ":", cmd.help_str
end
end
m.reply "Command not found:", name
m.reply "Command not found:", argv
end
end
@ -47,7 +45,7 @@ module Vrobot4::Server
# @!visibility private
def c_modr m, argv
check_args argv, "S", "S"
argv = check_args argv.split, "S", "S"
m.serv.drop_mod argv[0]
load argv[1], true if argv.length > 1
m.serv.load_mod argv[0]
@ -55,25 +53,23 @@ module Vrobot4::Server
# @!visibility private
def c_modl m, argv
check_args argv, "S"
m.serv.load_mod argv[0]
m.serv.load_mod argv
end
# @!visibility private
def c_modu m, argv
check_args argv, "S"
m.serv.drop_mod argv[0]
m.serv.drop_mod argv
end
# @!visibility private
def c_dbg m, argv
check_args argv, "N"
Vrobot4.debug = argv[0].to_i
Vrobot4.debug = argv.to_i
end
# @!visibility private
def on_command m, cnam, argv
Vrobot4.log :DEBUGV, "command", cnam.to_s, argv.to_s
Vrobot4.log :DEBUGV, "command", cnam.to_s, argv
super
end
end
@ -81,21 +77,21 @@ module Vrobot4::Server
# Generic user information. May be extended.
class User
attr_reader :name # Plaintext name of the user.
attr_reader :roles # List of user's roles.
attr_reader :name # @return [String] plaintext name of the user
attr_reader :roles # @return [String] list of user's roles
end
# Generic channel information. May be extended.
class Channel
attr_reader :name # Plaintext name of the channel.
attr_reader :name # @return [String] plaintext name of the channel
end
# Generic event information. May not be extended.
class Message
attr_reader :msg # Plaintext of message (if any.)
attr_reader :user # User that triggered this message (if any.)
attr_reader :chan # Channel this message was sent to (if any.)
attr_reader :serv # Server this message was sent to.
attr_reader :msg # @return [String] plaintext of message
attr_reader :user # @return [User] user that triggered this message
attr_reader :chan # @return [Channel] channel this message was sent to
attr_reader :serv # @return [Server] server this message was sent to
# @param info [Hash] A hash containing message info. Keys may be omitted.
# [:msg] Plaintext of message.
@ -126,7 +122,7 @@ module Vrobot4::Server
# Generic server interface.
class Server
attr_reader :mprm # Module permissions for this server.
attr_reader :mprm # @return [Hash] module permissions for this server
# @param info [Hash] arbitrary extra information for this server
def initialize info
@ -195,21 +191,26 @@ module Vrobot4::Server
# Basis for an audio-enabled server interface.
class AudioServer < Server
# Joins a voice channel, using a message for context.
# @param m [Vrobot4::Server::Message] message for context
def voice_join m
raise NotImplementedError, "AudioServer#voice_join not implemented"
end
# Quits a voice channel, using a message for context.
# @param m [Vrobot4::Server::Message] message for context
def voice_quit m
raise NotImplementedError, "AudioServer#voice_quit not implemented"
end
# Plays an arbitrary audio file in a given context.
def play m, io
raise NotImplementedError, "AudioServer#play not implemented"
# @param m [Vrobot4::Server::Message] message for context
# @param io [IO] audio stream to play
def voice_play m, io
raise NotImplementedError, "AudioServer#voice_play not implemented"
end
# Check if the bot is playing audio in a given context.
# @param m [Vrobot4::Server::Message] message for context
def is_playing? m
raise NotImplementedError, "AudioServer#is_playing? not implemented"
end

View File

@ -32,9 +32,8 @@ class Sv_Discord < Vrobot4::Server::AudioServer
reply_b: -> (text) {evt.respond "```\n" + text + "```"}
if m.msg.start_with? '.'
argv = m.msg.split
cnam = argv.shift[1..-1]
on_command m, cnam, argv
arg = m.msg.split(' ', 2)
on_command m, arg[0][1..-1], (arg[1] or "")
else
on_message m
end
@ -53,8 +52,8 @@ class Sv_Discord < Vrobot4::Server::AudioServer
@bot.voice_destroy m.chan.real.server.id
end
# (see Vrobot4::Server::AudioServer#play)
def play m, io
# (see Vrobot4::Server::AudioServer#voice_play)
def voice_play m, io
v = @bot.voice(m.chan.real)
raise ArgumentError, "Invalid i/o stream" unless io
raise RuntimeError, "I'm not in a voice channel" unless v