Compare commits

...

3 Commits

Author SHA1 Message Date
an 09591b03d1 split quote/fun modules 2019-02-24 06:01:46 -05:00
an 79e6dbd495 change yaml configs to ruby configs 2019-02-24 06:00:41 -05:00
an 8f79a79b4e fix conflation of server and bot 2019-02-24 01:56:59 -05:00
16 changed files with 492 additions and 364 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
*doc
working
*.yml
_config.rb
*.swp
*.vim

View File

@ -1 +1 @@
--protected --private --hide-void-return source/*.rb source/servers/*.rb
--protected --private --hide-void-return source/*.rb source/backends/*.rb

200
source/backends/discord.rb Normal file
View File

@ -0,0 +1,200 @@
# Discord backend.
module Backend_Discord
require 'discordrb'
# Helper for channel permissions handling.
class ChannelPerms
def initialize() @cprm = {} end
# @param chan [Bot_Discord::Channel] the channel for this permission
# @return [Boolean] true if the channel is enabled, false otherwise.
def [](chan) @cprm[chan.name] or @cprm[chan.real.id] end
# Sets a channel's permission on/off.
# @param chan [Bot_Discord::Channel] the channel for this permission
# @param set [Boolean] if this permission should be set
# @return [void]
def []=(chan, set) @cprm[chan] = set end
end
# A Discord user.
class User < Vrobot4::Server::User
attr_reader :real # @return [Discordrb::User] the instance
# @param user [Discordrb::User] the discord user
# @param ops [Array] list of operator role IDs
# @param hop [Array] list of half-operator role IDs
def initialize user, ops, hop
@real = user
@name = user.name
@id = user.id
@roles = "v"
if user.is_a? Discordrb::Member
if user.owner?
@roles += "Ooh"
elsif ops and ops.any? do |role| user.role? role end
@roles += "oh"
elsif hop and hop.any? do |role| user.role? role end
@roles += "h"
end
end
end
end
# A Discord channel.
class Channel < Vrobot4::Server::Channel
attr_reader :real # @return [Discordrb::Channel] the instance
# @param chan [Discordrb::Channel] the discord channel
def initialize chan
@real = chan
@name = ?# + chan.name
@id = chan.id
end
end
# A Discord server.
class Server < Vrobot4::Server::AudioServer
# The server type name.
def self.type() "Discord" end
attr_reader :real # @return [Discordrb::Server] the instance
# (see Vrobot4::Server::Server#initialize)
# @param real [Discordrb::Server] the instance
def initialize info, bot, real
super info, bot
@real = real
@id = real.id
@ops = info[:admins] || []
@hop = info[:halfop] || []
if mods = info[:modules]
for mod in mods
load_mod mod
end
end
end
# (see Vrobot4::Server::AudioServer#voice_quit)
def voice_quit m
@bot.real.voice_destroy m.chan.real.server.id
end
# (see Vrobot4::Server::AudioServer#voice_play)
def voice_play m, fname
vc = @bot.real.voice m.chan.real
raise RuntimeError, "I'm not in a voice channel" unless vc
vc.play_file fname
end
# (see Vrobot4::Server::AudioServer#voice_play_io)
def voice_play_io m, io
vc = @bot.real.voice m.chan.real
raise ArgumentError, "Invalid IO stream" unless io
raise RuntimeError, "I'm not in a voice channel" unless vc
Thread.new do
vc.play_io io
end
# HACK
sleep 1
oldst = nil
while vc.stream_time != oldst
oldst = vc.stream_time
sleep 5
end
end
# (see Vrobot4::Server::Server#flags)
def flags
?A
end
protected
# (see Vrobot4::Server::Server#load_permissions)
def load_permissions pinf
@mprm = {chan: {}, role: {}, glob: {}}
return unless pinf
pinf.each do |pr|
mod = Vrobot4::Module.get_module_type(pr[:module])[:type]
if pr.key? :channel
@mprm[:chan][mod] = ChannelPerms.new unless @mprm[:chan][mod]
@mprm[:chan][mod][pr[:channel]] = true
elsif pr.key? :roles
@mprm[:role][mod] = pr[:roles]
elsif pr.key? :enable
@mprm[:glob][mod] = pr[:enable]
end
end
end
end
# A bot implementation for Discord using discordrb.
class Bot < Vrobot4::Robots::Bot
# The bot type name.
def self.type() "Discord" end
Vrobot4::Robots.add_bot_type self
attr_reader :real
def initialize info
super
@servers = {}
@real = Discordrb::Bot.new \
token: info[:apikey],
client_id: info[:client]
@real.ready do |evt|
for _, serv in evt.bot.servers
add_server serv
end
end
@real.message do |evt|
if evt.server
serv = get_server evt.server
m = Vrobot4::Server::Message.new \
msg: evt.message.content,
user: User.new(evt.user, @ops, @hop),
chan: Channel.new(evt.channel),
serv: serv,
bot: self,
reply: -> (text) {evt.channel.send text},
reply_b: -> (text) {evt.channel.send "```\n#{text}```"}
serv.handle_text_cmd m
end
end
end
# (see Vrobot4::Robots::Bot#connect)
def connect
@real.run
end
protected
# Adds a server to the hash.
# @param serv [Discordrb::Server] server instance
# @return [Server]
def add_server serv
Vrobot4.log :DEBUG, "initializing server #{serv.id}"
@servers[serv.id] = Server.new @info[serv.id] || {}, self, serv
end
# Finds a server in the hash, potentially adding it.
# @param serv [Discordrb::Server] server instance
# @return [Server]
def get_server serv
@servers[serv.id] || add_server(serv)
end
end
end
## EOF

144
source/backends/irc.rb Normal file
View File

@ -0,0 +1,144 @@
# IRC backend.
module Backend_IRC
require 'cinch'
# Helper for channel permissions.
class ChannelPerms
def initialize() @cprm = {} end
# @param chan [Backend_IRC::Channel] the channel for this permission
# @return [Boolean] true if the channel is enabled, false otherwise.
def [](chan) @cprm[chan.name] end
# Sets a channel's permission on/off.
# @param name [String] the channel for this permission
# @param set [Boolean] if this permission should be set
# @return [void]
def []=(name, set) @cprm[name] = set end
end
# An IRC user.
class User < Vrobot4::Server::User
attr_reader :real # The Cinch::User instance.
# @param user [Cinch::User] the irc user
# @param chan [Cinch::Channel] the irc channel this object was made in
def initialize user, chan
@real = user
@name = user.nick
@id = Vrobot4.hash_str user.nick.downcase
if user.oper? then @roles = "Oohv"
elsif chan.opped? user then @roles = "ohv"
elsif chan.half_opped? user then @roles = "hv"
elsif chan.voiced? user then @roles = "v"
else @roles = "" end
end
end
# An IRC channel.
class Channel < Vrobot4::Server::Channel
attr_reader :real # The Cinch::Channel instance.
# @param chan [Cinch::Channel] the irc channel
def initialize chan
@real = chan
@name = chan.name.downcase
@id = Vrobot4.hash_str chan.name.downcase
end
end
# An IRC server.
class Server < Vrobot4::Server::Server
# The server type name.
def self.type() "IRC" end
# (see Vrobot4::Server::Server#initialize)
def initialize info, bot
super
@id = Vrobot4.hash_str info[:server].downcase
for mod in info[:modules] do
load_mod mod
end
end
# (see Vrobot4::Server::Server#flags)
def flags
?L
end
protected
# (see Vrobot4::Server::Server#load_permissions)
def load_permissions pinf
@mprm = {chan: {}, role: {}, glob: {}}
return unless pinf
pinf.each do |pr|
mod = Vrobot4::Module.get_module_type(pr[:module])[:type]
if pr.key? :channel
@mprm[:chan][mod] = ChannelPerms.new unless @mprm[:chan][mod]
@mprm[:chan][mod][pr[:channel].downcase] = true
elsif pr.key? :roles
@mprm[:role][mod] = pr[:roles]
elsif pr.key? :enable
@mprm[:glob][mod] = pr[:enable]
end
end
end
end
# A bot implementation for IRC using cinch.
class Bot < Vrobot4::Robots::Bot
# The bot type name.
def self.type() "IRC" end
Vrobot4::Robots.add_bot_type self
attr_accessor :serv # @return [Vrobot4::Server::Server] the server
# (see Vrobot4::Robots::Bot#initialize)
def initialize info
super
this = self
@bot = Cinch::Bot.new do
configure do |cfg|
cfg.server = info[:server]
cfg.nick = info[:nick] || "vrobot4"
cfg.port = info[:port] if info.key? :port
cfg.password = info[:pass] if info.key? :pass
cfg.modes = info[:modes] if info.key? :modes
cfg.channels = info[:channels] if info.key? :channels
cfg.realname = "vrobot4"
cfg.user = "vrobot4"
cfg.message_split_start = ""
cfg.message_split_end = ""
end
on :message do |evt|
return unless evt.channel
m = Vrobot4::Server::Message.new \
msg: evt.message,
user: User.new(evt.user, evt.channel),
chan: Channel.new(evt.channel),
serv: this.serv,
bot: this,
reply: -> (text) {evt.reply text},
reply_b: -> (text) {evt.reply text}
this.serv.handle_text_cmd m
end
end
@bot.loggers.level = :warn
@serv = Server.new info, self
end
# (see Vrobot4::Robots::Bot#connect)
def connect
@bot.start
end
end
end
## EOF

35
source/config_example.rb Normal file
View File

@ -0,0 +1,35 @@
module Config
def self.get
{
debug: 0,
load: %w[
./backends/discord.rb
./backends/irc.rb
./modules/util.rb
],
bots: [
{
type: "Discord",
client: your_bot_client_id_here,
apikey: your_api_key_here,
admins: [your_personal_client_id_here],
your_server_id_here => {
modules: %w[Utilities],
},
},
{
type: "IRC",
server: your_server_here,
port: 6667,
channels: %w[#my_cool_channel],
modules: %w[Utilities],
}
]
}
end
end
## EOF

View File

@ -1,36 +1,29 @@
require './common.rb'
require './module.rb'
require './server.rb'
require 'yaml'
require './robots.rb'
module Vrobot4
private
# Loads a bot from its configuration +botinfo+.
# @param botinfo [Hash] arbitrary bot information
# Loads a bot from its configuration +info+.
# @param info [Hash] arbitrary bot information
# ["type"] The type by name of the bot.
# @return [Vrobot4::Server] the loaded bot
def self.load_bot botinfo
type = botinfo["type"]
serv = Server::get_server_type(type).new botinfo
for mod in botinfo["modules"] do
serv.load_mod mod
end
serv
# @return [Vrobot4::Robots::Bot] the loaded bot
def self.load_bot info
type = info[:type]
Robots::get_bot_type(type).new info
end
# Runs all bots in +bots+ in separate threads.
# @param bots [Array<Vrobot4::Server>] all bots to run
# @param bots [Array<Vrobot4::Robots::Bot>] all bots to run
# @return [void]
def self.run_bots bots
threads = []
bots.each do |server|
bots.each do |bot|
threads << Thread.new do
server.connect
bot.connect
end
end
@ -42,31 +35,27 @@ module Vrobot4
public
# Runs the program.
# @param cfg [IO] configuration file to read
# @param cfg [String] configuration file to read
# @return [void]
def self.main cfg
Thread.abort_on_exception = true
log :INFO, "vrobot version #{Version}"
begin
cfg = YAML.load cfg.read
rescue
log :ERROR, "error reading bot config: #{$!}"
return
end
load cfg
cfg = Config.get
Vrobot4.set_debug(cfg["debug"] || 0)
Vrobot4.set_debug(cfg[:debug] || 0)
cfg["load"].each do |mod|
cfg[:load].each do |mod|
load mod, true
end
begin
bots = []
cfg["bots"].each do |botinfo|
bots << load_bot(botinfo)
cfg[:bots].each do |info|
bots << load_bot(info)
end
log :DEBUGV, "bots: #{bots.to_s}"

View File

@ -134,11 +134,7 @@ module Vrobot4::Module
check_arg argv[argn], argn, opt[i]
end
else
if opt.length
check_arg argv, 0, opt[0] unless argv.empty?
else
check_arg argv, 0, req[0]
end
check_arg argv, 0, req[0]
end
argv
end

View File

@ -43,9 +43,9 @@ class Mod_Base < Vrobot4::Module::Module
end
def c_modr m, argv
argv = check_args argv.split, "S", "S"
argv = argv.split
m.serv.drop_mod argv[0]
load argv[1], true if argv.length > 1
load argv[1], true if argv[1]
m.serv.load_mod argv[0]
end
@ -59,7 +59,7 @@ class Mod_Base < Vrobot4::Module::Module
def c_dbg m, argv
check_args argv, "N"
Vrobot4.debug = argv.to_i
Vrobot4.set_debug argv.to_i
end
def c_info m, argv

View File

@ -102,8 +102,8 @@ class Mod_DoomRLA < Vrobot4::Module::Module
def reload_info
@winfo = []
@minfo = []
@info["wep_info"].each {|wi| @winfo += JSON.parse(open(wi).read)}
@info["mon_info"].each {|mi| @minfo += JSON.parse(open(mi).read)}
@info[:wep_info].each {|wi| @winfo += JSON.parse(open(wi).read)}
@info[:mon_info].each {|mi| @minfo += JSON.parse(open(mi).read)}
end
end

View File

@ -1,12 +1,7 @@
require 'open-uri'
require 'json'
class Mod_Fun < Vrobot4::Module::Module
def self.type() "Fun" end
Vrobot4::Module.add_module_type self
QDB = "http://greyserv.net/qdb"
def initialize info
super
register :c_carmack, "carmack", "mmmmmmmmmm"
@ -16,7 +11,6 @@ class Mod_Fun < Vrobot4::Module::Module
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_quote, "quote", "Queries the Doominati Quote Database."
register :c_what, "what", "What the fuck did you just fucking say about"
end
@ -40,7 +34,7 @@ class Mod_Fun < Vrobot4::Module::Module
end
def c_marble m, argv
check_args argv, "", "N"
check_args argv, "N"
if argv.empty? then n = 20
else n = argv.to_i end
@ -57,29 +51,6 @@ class Mod_Fun < Vrobot4::Module::Module
m.reply text
end
def c_quote m, argv
if argv.empty?
q, num = nil, nil
max = JSON.parse(open(QDB + "/interface.cgi").read)["numQuotes"]
loop do
num = rand(max) + 1
q = open(QDB + "/q/" + num.to_s).read
break unless m.serv.flags.include? "L" and
(q.lines.count > 4 or q.length > 1000)
end
m.reply_b "Quote %i:\n" % [num] + q
elsif Vrobot4.is_num? argv
m.reply_b open(QDB + "/q/" + argv.to_i.to_s).read
else
raise ArgumentError, "Invalid query" if argv.include? ?&
q = URI.escape argv
info = JSON.parse(open(QDB + "/interface.cgi?query=" + q).read)
raise ArgumentError, "No results" unless info["searchResults"].any?
res = info["searchResults"].sample
m.reply_b "Quote %i:\n" % [res] + open(QDB + "/q/" + res.to_s).read
end
end
def c_what m, argv
if m.serv.flags.include? ?L
m.reply "What the fuck did you just fucking say about me, you little bitch?"

39
source/modules/qdb.rb Normal file
View File

@ -0,0 +1,39 @@
require 'open-uri'
require 'json'
class Mod_QDB < Vrobot4::Module::Module
def self.type() "QDB" end
Vrobot4::Module.add_module_type self
QDB = "http://greyserv.net/qdb"
def initialize info
super
register :c_quote, "quote", "Queries the Doominati Quote Database."
end
def c_quote m, argv
if argv.empty?
q, num = nil, nil
max = JSON.parse(open(QDB + "/interface.cgi").read)["numQuotes"]
loop do
num = rand(max) + 1
q = open(QDB + "/q/" + num.to_s).read
break unless m.serv.flags.include? "L" and
(q.lines.count > 4 or q.length > 1000)
end
m.reply_b "Quote %i:\n" % [num] + q
elsif Vrobot4.is_num? argv
m.reply_b open(QDB + "/q/" + argv.to_i.to_s).read
else
raise ArgumentError, "Invalid query" if argv.include? ?&
q = URI.escape argv
info = JSON.parse(open(QDB + "/interface.cgi?query=" + q).read)
raise ArgumentError, "No results" unless info["searchResults"].any?
res = info["searchResults"].sample
m.reply_b "Quote %i:\n" % [res] + open(QDB + "/q/" + res.to_s).read
end
end
end
## EOF

View File

@ -1,6 +1,6 @@
class Mod_Relay < Vrobot4::Module::Module
def self.type() "Relay" end
Vrobot4::Module.add_module_type self, server: "Discord"
Vrobot4::Module.add_module_type self
def initialize info
super

37
source/robots.rb Normal file
View File

@ -0,0 +1,37 @@
# Module for vrobot4 bot interfaces.
module Vrobot4::Robots
# Generic bot interface.
class Bot
# @param info [Hash] arbitrary extra information for this bot
def initialize info
@info = info
end
# Connect to all servers.
# @abstract
# @return [void]
def connect
raise NotImplementedError, "Bot#connect not implemented"
end
end
# Adds a bot type to the global list.
# @param type [Class] bot type to add
# @return [void]
def self.add_bot_type type
@@bot_types[type.type] = type
Vrobot4.log :INFO, "added bot type: #{type.type}"
end
# Gets a bot type by name from the global list.
# @param name [String] name of the bot type to find
# @return [Class] the bot type
def self.get_bot_type name
@@bot_types[name]
end
# The set of all bot types.
@@bot_types = {}
end
## EOF

View File

@ -21,12 +21,14 @@ module Vrobot4::Server
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
attr_reader :bot # @return [Vrobot4::Robots::Bot] bot this was sent to
# @param info [Hash] A hash containing message info. Keys may be omitted.
# [:msg] Plaintext of message.
# [:user] User that triggered this message.
# [:chan] Channel that this message was sent to.
# [:serv] Server this message was sent to.
# [:bot] Bot this message was sent to.
# [:reply] Method that sends a message to the specified channel.
# [:reply_b] Method that sends a large message to the specified channel.
def initialize(**info)
@ -34,6 +36,7 @@ module Vrobot4::Server
@user = info[:user]
@chan = info[:chan]
@serv = info[:serv]
@bot = info[:bot]
@reply = info[:reply]
@reply_b = info[:reply_b]
end
@ -57,12 +60,15 @@ module Vrobot4::Server
class Server
attr_reader :mprm # @return [Hash] module permissions for this server
attr_reader :id # @return [Integer] unique identifier for the server
attr_reader :bot # @return [Vrobot4::Robots::Bot] the bot we belong to
# @param info [Hash] arbitrary extra information for this server
def initialize info
# @param bot [Vrobot4::Robots::Bot] the bot we belong to
def initialize info, bot
@bot = bot
@info = info
@modules = [Mod_Base.new(nil)]
load_permissions info["permissions"]
load_permissions info[:permissions]
end
# Loads and initializes a module into the load list.
@ -72,9 +78,9 @@ module Vrobot4::Server
mt = Vrobot4::Module.get_module_type(mod)
if mt[:server] and mt[:server] != self.class.type or
mt[:servflags] and mt[:servflags] !~ flags then
raise ArgumentError, "Module " + mod + " not valid for this server"
raise ArgumentError, "Module #{mod} is not valid for this server"
end
@modules << mt[:type].new(@info[mod])
@modules << mt[:type].new(@info[mod.to_sym])
end
# Drops a module from the load list.
@ -188,24 +194,6 @@ module Vrobot4::Server
raise NotImplementedError, "AudioServer#voice_play_io not implemented"
end
end
# Adds a server type to the global list.
# @param type [Class] server type to add
# @return [void]
def self.add_server_type type
@@server_types[type.type] = type
Vrobot4.log :INFO, "added server type: #{type.type}"
end
# Gets a server type by name from the global list.
# @param name [String] name of the server type to find
# @return [Vrobot4::Server::Server] the server type
def self.get_server_type name
@@server_types[name]
end
# The set of all server types.
@@server_types = {}
end
## EOF

View File

@ -1,147 +0,0 @@
require 'discordrb'
# A server implementation for Discord using discordrb.
class Sv_Discord < Vrobot4::Server::AudioServer
# The server type name.
def self.type() "Discord" end
Vrobot4::Server.add_server_type self
attr_reader :bot # The Discordrb::Bot instance.
# (see Vrobot4::Server::Server#initialize)
def initialize info
super
@id = info["client"]
@ops = info["admins"] || []
@hop = info["halfop"] || []
@bot = Discordrb::Bot.new \
token: info["apikey"],
client_id: info["client"]
@bot.message do |evt|
m = Vrobot4::Server::Message.new \
msg: evt.message.content,
user: User.new(evt.user, @ops, @hop),
chan: Channel.new(evt.channel),
serv: self,
reply: -> (text) {evt.respond text},
reply_b: -> (text) {evt.respond "```\n#{text}```"}
handle_text_cmd m
end
end
# (see Vrobot4::Server::AudioServer#voice_quit)
def voice_quit m
@bot.voice_destroy m.chan.real.server.id
end
# (see Vrobot4::Server::AudioServer#voice_play)
def voice_play m, fname
vc = @bot.voice m.chan.real
raise RuntimeError, "I'm not in a voice channel" unless vc
vc.play_file fname
end
# (see Vrobot4::Server::AudioServer#voice_play_io)
def voice_play_io m, io
vc = @bot.voice m.chan.real
raise ArgumentError, "Invalid IO stream" unless io
raise RuntimeError, "I'm not in a voice channel" unless vc
Thread.new do
vc.play_io io
end
# HACK
sleep 1
oldst = nil
while vc.stream_time != oldst
oldst = vc.stream_time
sleep 5
end
end
# (see Vrobot4::Server::Server#connect)
def connect
@bot.run
end
# (see Vrobot4::Server::Server#flags)
def flags
?A
end
protected
# (see Vrobot4::Server::Server#load_permissions)
def load_permissions pinf
@mprm = {chan: {}, role: {}, glob: {}}
pinf.each do |pr|
mod = Vrobot4::Module.get_module_type(pr["module"])[:type]
if pr.key? "channel"
@mprm[:chan][mod] = ChannelPerms.new unless @mprm[:chan].key? mod
@mprm[:chan][mod][pr["channel"]] = true
elsif pr.key? "roles"
@mprm[:role][mod] = pr["roles"]
elsif pr.key? "enable"
@mprm[:glob][mod] = pr["enable"]
end
end if pinf
end
# Helper for channel permissions handling.
class ChannelPerms
def initialize() @cprm = {} end
# @param chan [Sv_Discord::Channel] the channel for this permission
# @return [Boolean] true if the channel is enabled, false otherwise.
def [](chan) @cprm[chan.name] or @cprm[chan.real.id] end
# Sets a channel's permission on/off.
# @param chan [Sv_Discord::Channel] the channel for this permission
# @param set [Boolean] if this permission should be set
# @return [void]
def []=(chan, set) @cprm[chan] = set end
end
private_constant :ChannelPerms
# A Discord user.
class User < Vrobot4::Server::User
attr_reader :real # The Discordrb::User instance.
# @param user [Discordrb::User] the discord user
# @param ops [Array] list of operator role IDs
# @param hop [Array] list of half-operator role IDs
def initialize user, ops, hop
@real = user
@name = user.name
@id = user.id
@roles = "v"
if user.is_a? Discordrb::Member
if user.owner?
@roles += "Ooh"
elsif ops and ops.any? do |role| user.role? role end
@roles += "oh"
elsif hop and hop.any? do |role| user.role? role end
@roles += "h"
end
end
end
end
# A Discord channel.
class Channel < Vrobot4::Server::Channel
attr_reader :real # The Discordrb::Channel instance.
# @param chan [Discordrb::Channel] the discord channel
def initialize chan
@real = chan
@name = ?# + chan.name
@id = chan.id
end
end
end
## EOF

View File

@ -1,124 +0,0 @@
require 'cinch'
# A server implementation for IRC using cinch.
class Sv_IRC < Vrobot4::Server::Server
# The server type name.
def self.type() "IRC" end
Vrobot4::Server.add_server_type self
attr_reader :bot # The Cinch::Bot instance.
# (see Vrobot4::Server::Server#initialize)
def initialize info
super
this = self
@bot = Cinch::Bot.new do
configure do |cfg|
cfg.server = info["server"]
cfg.nick = info["nick"] || "vrobot4"
cfg.port = info["port"] if info.key? "port"
cfg.password = info["pass"] if info.key? "pass"
cfg.modes = info["modes"] if info.key? "modes"
cfg.channels = info["channels"] if info.key? "channels"
cfg.realname = "vrobot4"
cfg.user = "vrobot4"
cfg.message_split_start = ""
cfg.message_split_end = ""
end
on :message do |evt|
return unless evt.channel
m = Vrobot4::Server::Message.new \
msg: evt.message,
user: User.new(evt.user, evt.channel),
chan: Channel.new(evt.channel),
serv: this,
reply: -> (text) {evt.reply text},
reply_b: -> (text) {evt.reply text}
this.handle_text_cmd m
end
end
@bot.loggers.level = :warn
@id = info["server"].downcase.sum
end
# (see Vrobot4::Server::Server#connect)
def connect
@bot.start
end
# (see Vrobot4::Server::Server#flags)
def flags
?L
end
protected
# (see Vrobot4::Server::Server#load_permissions)
def load_permissions pinf
@mprm = {chan: {}, role: {}, glob: {}}
pinf.each do |pr|
mod = Vrobot4::Module.get_module_type(pr["module"])[:type]
if pr.key? "channel"
@mprm[:chan][mod] = ChannelPerms.new unless @mprm[:chan].key? mod
@mprm[:chan][mod][pr["channel"].downcase] = true
elsif pr.key? "roles"
@mprm[:role][mod] = pr["roles"]
elsif pr.key? "enable"
@mprm[:glob][mod] = pr["enable"]
end
end if pinf
end
# Helper for channel permissions.
class ChannelPerms
def initialize() @cprm = {} end
# @param chan [Sv_IRC::Channel] the channel for this permission
# @return [Boolean] true if the channel is enabled, false otherwise.
def [](chan) @cprm[chan.name] end
# Sets a channel's permission on/off.
# @param name [String] the channel for this permission
# @param set [Boolean] if this permission should be set
# @return [void]
def []=(name, set) @cprm[name] = set end
end
private_constant :ChannelPerms
# An IRC user.
class User < Vrobot4::Server::User
attr_reader :real # The Cinch::User instance.
# @param user [Cinch::User] the irc user
# @param chan [Cinch::Channel] the irc channel this object was made in
def initialize user, chan
@real = user
@name = user.nick
@id = user.nick.downcase.sum
if user.oper? then @roles = "Oohv"
elsif chan.opped? user then @roles = "ohv"
elsif chan.half_opped? user then @roles = "hv"
elsif chan.voiced? user then @roles = "v"
else @roles = "" end
end
end
# An IRC channel.
class Channel < Vrobot4::Server::Channel
attr_reader :real # The Cinch::Channel instance.
# @param chan [Cinch::Channel] the irc channel
def initialize chan
@real = chan
@name = chan.name.downcase
@id = chan.name.downcase.sum
end
end
end
## EOF