Add module functions, permissions, and argument checking
parent
772c33a956
commit
d5329bafdb
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue