Add module functions, permissions, and argument checking

master
Marrub 2017-08-08 04:35:20 -04:00
parent 772c33a956
commit d5329bafdb
9 changed files with 424 additions and 33 deletions

View File

@ -11,6 +11,10 @@ module Vrobot4
puts "[" + lv.to_s.ljust(6) + "] " + text.join(" ")
end
end
def self.is_num? s
/\A[-+]?[0-9]*\.?[0-9]+\Z/ === s
end
end
## EOF

View File

@ -1,6 +1,6 @@
require './common.rb'
require './server.rb'
require './module.rb'
require './server.rb'
require 'yaml'
@ -10,8 +10,8 @@ module Vrobot4
serv = Server::get_server_type(type).new(servinfo)
servinfo.has_key?("modules") && servinfo["modules"].each \
{|mod| serv.loadMod Module::get_module_type(mod).new}
servinfo["modules"].each \
{|mod| serv.load_mod mod} if servinfo.key? "modules"
serv
end
@ -38,7 +38,7 @@ module Vrobot4
begin; cfg = YAML.load IO.read(cfgname)
rescue; log :ERROR, "error reading bot config:", $!; exit; end
Vrobot4.debug = cfg["debug"] if cfg.has_key? "debug"
Vrobot4.debug = cfg["debug"] if cfg.key? "debug"
cfg["loadmods"].each {|mod| load mod, true}

67
source/mod_base.rb Normal file
View File

@ -0,0 +1,67 @@
module Vrobot4::Server
class Mod_Base < Vrobot4::Module::Module
def initialize
super
register :c_help, "help", "Prints documentation for commands."
register :c_die, "die", "Kills all bot instances.", roles: "o"
register :c_modr, "modr", "Reloads a module.", roles: "o"
register :c_modl, "modl", "Loads a module.", roles: "o"
register :c_modu, "modu", "Unloads a module.", roles: "o"
register :c_dbg, "dbg", "Sets the debug level.", roles: "o"
end
def c_help m, argv
check_args argv, "", "S"
if argv.length == 0
cmds = []
m.serv.each_mod {|mod| cmds << mod.all_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
end
end
m.reply "Command not found:", name
end
end
def c_die m, argv
m.reply \
["STATUS: DYING",
"ded",
"proceeding to die",
"bye",
"dedededed"].sample
exit
end
def c_modr m, argv
check_args argv, "S"
m.serv.drop_mod argv[0]
m.serv.load_mod argv[0]
end
def c_modl m, argv
check_args argv, "S"
m.serv.load_mod argv[0]
end
def c_modu m, argv
check_args argv, "S"
m.serv.drop_mod argv[0]
end
def c_dbg m, argv
check_args argv, "N"
Vrobot4.debug = argv[0].to_i
end
def onCommand m, cnam, argv
Vrobot4.log :DEBUG, "command", cnam.to_s, argv.to_s
super
end
end
end

25
source/mod_discord.rb Normal file
View File

@ -0,0 +1,25 @@
class Mod_Discord < Vrobot4::Module::Module
Vrobot4::Module.add_module_type self, "Discord", server: "Discord"
def initialize
super
register :c_roles, "roles", "Gets a list of roles on your user."
register :c_purge, "purge", "Prunes messages from a channel.", roles: "o"
end
def c_roles m, argv
roles = []
m.user.real.roles.each {|role| roles << role.name + ":" + role.id.to_s}
m.reply roles.join("\n")
end
def c_purge m, argv
check_args argv, "N"
n = argv[0].to_i
n = 2 if n < 2
n = 100 if n > 100
m.chan.real.prune n
end
end
## EOF

58
source/mod_fun.rb Normal file
View File

@ -0,0 +1,58 @@
class Mod_Fun < Vrobot4::Module::Module
Vrobot4::Module.add_module_type self, "Fun"
def initialize
super
register :c_carmack, "carmack", "mmmmmmmmmm"
register :c_revenant, "revenant", "AAAAAAAAA"
register :c_wan, "wan", "wan!"
register :c_nyan, "nyan", "nyan~"
register :c_box, "box", "S H I T P O S T I N G"
register :c_zdoom, "zdoom", "ZDoom™"
register :c_marble, "marble", "mararuaruaruaruarb"
register :c_what, "what", "What the fuck did you just fucking say about"
end
def c_carmack m, argv; m.reply "m" * (rand(24) + 5) ; end
def c_revenant m, argv; m.reply "A" * (rand(24) + 3) ; end
def c_wan m, argv; m.reply "wan! " * (rand(10) + 1) ; end
def c_nyan m, argv; m.reply "nyan " * (rand(10) + 1) + "~"; end
def c_box m, argv
str = argv.join(" ")
text = str + "\n"
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
m.reply_spaced text
end
def c_zdoom m, argv
m.reply "ZDoom" + "" * (rand(15) + 1)
end
def c_marble m, argv
check_args argv, "", "N"
if argv.length == 0; n = 20
else; n = argv[0].to_i; end
n = 1000 if n > 1000
text = "m"
for i in (0..rand(n) + 1)
text << ["a", "r", "u"].sample
end
text << "b"
m.reply text
end
def c_what m, argv
m.reply "What the fuck did you just fucking say about me, you little bitch? I'll have you know I graduated top of my class in the Navy Seals, and I've been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the fuck out with precision the likes of which has never been seen before on this Earth, mark my fucking words. You think you can get away with saying that shit to me over the Internet? Think again, fucker. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You're fucking dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that's just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little \"clever\" comment was about to bring down upon you, maybe you would have held your fucking tongue. But you couldn't, you didn't, and now you're paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You're fucking dead, kiddo."
end
end
## EOF

View File

@ -2,12 +2,93 @@ class Mod_Util < Vrobot4::Module::Module
Vrobot4::Module.add_module_type self, "Utilities"
def initialize
super()
register :testf, "Test function."
super
register :c_rand, "rand", "Returns a random number. Example: .rand 500"
register :c_decide, "decide", "Decides between one or more choices."
register :c_eightball, "eightball", "Peer into the magic 8-ball."
register :c_mystery, "mystery", "it is a mystery"
end
def testf m, argv
puts "test function run", m, argv
def c_rand m, argv
check_args argv, "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
n = rand(max - min) + min
m.reply n.round
end
def c_decide m, argv
argv = argv.join(" ").split(",").each {|arg| arg.chomp!}
m.reply argv.sample
end
def c_eightball m, argv
m.reply \
["Yes.",
"No.",
"Try again later.",
"Reply hazy.",
"Perhaps...",
"Maybe not...",
"Definitely.",
"Never.",
"system error [0xfded] try again later",
"Can you repeat the question?",
"Most certainly.",
"Nope.",
"Without a doubt.",
"Not at all.",
"Better not tell you now.",
"Concentrate and ask again.",
"It is decidedly so.",
"My reply is \"no\".",
"You may rely on it.",
"Don't count on it.",
"The answer is uncertain.",
"Sorry, I wasn't paying attention. What'd you say?",
"As I see it, yes.",
"My sources say \"no\".",
"Most likely.",
"Very doubtful.",
"I don't know. Ask your mom.",
"The demon runes are quaking again. One moment.",
"Outlook good.",
"Outlook is not so good.",
"Indeed.",
"Absolutely not.",
"Yeah, we'll go with that.",
"That works.",
"Of course. What are you, stupid?",
"No. Hell no.",
"Signs say yes.",
"Aren't you a little too old to be believing that?",
"Looks good to me.",
"Sure, why not?",
"It is certain.",
"Please no. Please no. Please no.",
"Yes, please.",
"Nah.",
"Go for it!",
"Negative.",
"Obviously, dumbass.",
"I doubt it.",
"Eeeh...it's likely?",
"Forget about it.",
"Chances aren't good.",
"Ahahahahahahaha no.",
"Maybe? I think.",
"No. Die.",
"Huh? Oh, sure.",
"Yeah, right...",
"How about no.",
"Doesn't look good to me.",
"Probably.",
"Obviously not, dumbass.",
"#<Enumerator:0x000000028a49c0>"].sample
end
def c_mystery m, argv
end
end

View File

@ -2,9 +2,23 @@ module Vrobot4::Module
class Command
attr_reader :help_str
def initialize fn, help
def initialize fn, help, roles
@function = fn
@help_str = help
@roles = /[#{roles}]/
end
def usable_in? m, type
chan = m.chan.name
role = m.user.roles
mprm = m.serv.mprm
retm = true
retc = false
retr = false
retm = mprm[:glob][type] if mprm[:glob].key? type
retc = mprm[:chan][type].key? chan if mprm[:chan].key? type
retr = mprm[:role][type].scan /[#{role}]/ if mprm[:role].key? type
role.scan(@roles).any? && (retm || retc || retr)
end
def run m, argv
@ -15,25 +29,68 @@ module Vrobot4::Module
class Module
def initialize
@commands = {}
Vrobot4.log :DEBUG, "initialized", self.to_s
end
def register fn, help
@commands[fn.to_s] = Command.new(self.method(fn), help)
def register fn, cnam, help, roles: "v"
@commands[cnam] = Command.new(self.method(fn), help, roles).freeze
end
def eachCmd
@commands.each {|cmd| yield cmd}
def onMessage m
false
end
def onCommand m, cnam, argv
@commands[cnam].run(m, argv) if @commands.has_key? cnam
if (cmd = get_cmd m, cnam)
begin; cmd.run(m, argv)
rescue; m.reply "error:", $!.to_s; end
return true
else
return false
end
end
def all_cmds m
@commands.select {|name, cmd| cmd.usable_in? m, self.class}
end
def get_cmd m, name
cmds = all_cmds(m)
cmds[name] if cmds.key? name
end
protected
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|
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]
end
end
end
private
def check_arg arg, i, req
case req
when 'N'
unless Vrobot4.is_num? arg
raise ArgumentError, "expected a number for arg " + i.to_s
end
end
end
end
@@module_types = {}
def self.add_module_type t, name
@@module_types[name] = t
def self.add_module_type t, name, server: nil
@@module_types[name] = {:type => t, :server => server}
Vrobot4.log :INFO, "added module type:", name
end

View File

@ -1,34 +1,95 @@
require './mod_base.rb'
module Vrobot4::Server
class User
end
class Message
attr_reader :msg
def initialize msg
@msg = msg
end
attr_reader :name, :roles
end
class Channel
attr_reader :name
end
class Message
attr_reader :msg, :user, :chan, :serv
def initialize(
msg: nil,
user: nil,
chan: nil,
serv: nil,
reply: nil,
reply_spaced: nil)
@msg = msg
@user = user
@chan = chan
@serv = serv
@reply = reply
@reply_spaced = reply_spaced
end
def reply *args
@reply.call args.join(" ")
end
def reply_spaced *args
@reply_spaced.call args.join(" ")
end
end
class Server
def initialize
@modules = []
attr_reader :mprm
def initialize info
@modules = [Mod_Base.new]
load_permissions info["permissions"] if info.key? "permissions"
end
def loadMod mod
@modules << mod
def load_mod mod
mt = Vrobot4::Module.get_module_type(mod)
if mt[:server] and mt[:server] != type
raise ArgumentError, "Module " + mod + " not valid for this server"
end
@modules << mt[:type].new
end
def drop_mod mod
mt = Vrobot4::Module.get_module_type(mod)
@modules.each_index do |i|
@modules.delete_at i if @modules[i].is_a? mt[:type]
end
end
def each_mod
@modules.each {|mod| yield mod}
end
def onMessage m
Vrobot4.log :DEBUG, "message:", m.to_s
@modules.each {|mod| break if mod.onMessage m}
end
def onCommand m, cnam, argv
Vrobot4.log :DEBUG, "command:", m.to_s, cnam.to_s, argv.to_s
@modules.each {|mod| mod.onCommand m, cnam, argv}
@modules.each {|mod| break if mod.onCommand m, cnam, argv}
end
def type
"Unknown"
end
private
def load_permissions pinf
@mprm = {:chan => {}, :role => {}, :glob => {}}
pinf.each do |perm|
mod = Vrobot4::Module.get_module_type(perm["module"])[:type]
if perm.key? "channel"
chan = perm["channel"]
@mprm[:chan][mod] = {} unless @mprm[:chan].key? chan
@mprm[:chan][mod][chan] = true
elsif perm.key? "roles"
@mprm[:role][mod] = perm["roles"]
else
@mprm[:glob][mod] = perm["enable"]
end
end
end
end

View File

@ -3,14 +3,48 @@ require 'discordrb'
class Sv_Discord < Vrobot4::Server::Server
Vrobot4::Server.add_server_type self, "Discord"
attr_reader :bot
class User < Vrobot4::Server::User
attr_reader :real
def initialize user, admins
@real = user
@name = user.name
@roles = "v"
@roles += "o" if admins.select {|role| user.role? role}.any?
@roles += "O" if user.owner?
end
end
class Channel < Vrobot4::Server::Channel
attr_reader :real
def initialize chan
@real = chan
@name = "#" + chan.name
end
end
def initialize info
super()
super
if info.key? "admins"; @admins = info["admins"]
else; @admins = []; end
@bot = Discordrb::Bot.new \
token: info["apikey"],
client_id: info["client"]
@bot.message do |evt|
m = Vrobot4::Server::Message.new(evt.message.content)
m = Vrobot4::Server::Message.new \
msg: evt.message.content,
user: User.new(evt.user, @admins),
chan: Channel.new(evt.channel),
serv: self,
reply: -> (text) {evt.respond text},
reply_spaced: -> (text) {evt.respond "```\n" + text + "```"}
if m.msg.start_with? '.'
argv = m.msg.split
cnam = argv.shift[1..-1]
@ -24,6 +58,10 @@ class Sv_Discord < Vrobot4::Server::Server
def connect
@bot.run
end
def type
"Discord"
end
end
## EOF