Document all code with YARDoc
padre
d576bb00f7
commit
e912898dd0
|
@ -1,3 +1,4 @@
|
|||
*doc
|
||||
working
|
||||
*.yml
|
||||
*.swp
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
--protected source/*.rb - README
|
7
README
7
README
|
@ -1 +1,6 @@
|
|||
words
|
||||
Mod_Audio requires:
|
||||
- youtube-dl.rb
|
||||
- streamio-ffmpeg
|
||||
|
||||
Sv_Discord requires:
|
||||
- discordrb
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
# Module for the main vrobot4 program and global info.
|
||||
module Vrobot4
|
||||
# The current program version.
|
||||
Version = "4.00".freeze
|
||||
|
||||
@@debug = 0
|
||||
def self.debug= set; @@debug = set; end
|
||||
def self.debug ; @@debug; end
|
||||
def self.debug=(set) @@debug = set end # Sets the current debug level.
|
||||
def self.debug ( ) @@debug end # Gets the current debug level.
|
||||
|
||||
# Logs to the console.
|
||||
#
|
||||
# @param lv [Symbol]
|
||||
# - If +:DEBUG+, this message will not be printed if the global debug
|
||||
# level is less than 1.
|
||||
# - If +:DEBUGV+, this message will not be printed if the global debug
|
||||
# level is less than 2.
|
||||
# @return [Boolean] true if the message was printed, false otherwise
|
||||
def self.log lv, *text
|
||||
if (lv != :DEBUG || @@debug >= 1) &&
|
||||
(lv != :DEBUGV || @@debug >= 2)
|
||||
|
@ -15,9 +24,14 @@ module Vrobot4
|
|||
end
|
||||
end
|
||||
|
||||
# Checks if the argument +s+ is a numeric string.
|
||||
# @param str [String] the string to check
|
||||
def self.is_num? str
|
||||
/\A[-+]?[0-9]*\.?[0-9]+\Z/ === str
|
||||
end
|
||||
|
||||
private
|
||||
@@debug = 0
|
||||
end
|
||||
|
||||
## EOF
|
||||
|
|
|
@ -5,6 +5,7 @@ require './server.rb'
|
|||
require 'yaml'
|
||||
|
||||
module Vrobot4
|
||||
private
|
||||
def self.loadServer servinfo
|
||||
type = servinfo["type"]
|
||||
|
||||
|
@ -30,6 +31,9 @@ module Vrobot4
|
|||
thrds.each {|th| th.join}
|
||||
end
|
||||
|
||||
public
|
||||
# Runs the program.
|
||||
# @param cfg [IO] configuration file to load
|
||||
def self.main cfg
|
||||
log :INFO, "vrobot version", Version
|
||||
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
# Module for vrobot4 bot modules.
|
||||
module Vrobot4::Module
|
||||
# A command function. Holds extra info for i.e. permissions.
|
||||
class Command
|
||||
attr_reader :help_str
|
||||
attr_reader :help_str # Help string for this command.
|
||||
|
||||
# @param fn [Method] method to be called on run
|
||||
# @param help [String] help string for this command
|
||||
# @param roles [String] list of roles that can use this command
|
||||
def initialize fn, help, roles
|
||||
@function = fn
|
||||
@help_str = help
|
||||
@roles = /[#{roles}]/
|
||||
end
|
||||
|
||||
# Checks if this command is usable in a given context.
|
||||
# @param m [Vrobot4::Server::Message] message for context
|
||||
def usable_in? m
|
||||
type = @function.owner
|
||||
role = m.user.roles
|
||||
|
@ -19,27 +26,33 @@ module Vrobot4::Module
|
|||
role.scan(@roles).any? and (retm or retc or retr)
|
||||
end
|
||||
|
||||
# Calls the method attached to this command.
|
||||
def run m, argv
|
||||
@function.call(m, argv)
|
||||
end
|
||||
end
|
||||
|
||||
# A bot module. Holds commands and callbacks.
|
||||
class Module
|
||||
# @param info [Hash] arbitrary extra information for this module
|
||||
def initialize info
|
||||
@commands = {}
|
||||
@info = info
|
||||
Vrobot4.log :DEBUG, "initialized", self.to_s
|
||||
end
|
||||
|
||||
def register fn, cnam, help = nil, roles: "v"
|
||||
help = "No help available for this command." if help == nil
|
||||
@commands[cnam] = Command.new(self.method(fn), help, roles).freeze
|
||||
end
|
||||
|
||||
# Callback for message receiving.
|
||||
# @param m [Vrobot4::Server::Message] message received
|
||||
# @return [Boolean] if this should block further message callbacks
|
||||
def on_message m
|
||||
false
|
||||
end
|
||||
|
||||
# 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
|
||||
# @return [Boolean] if this should block further command callbacks
|
||||
def on_command m, cnam, argv
|
||||
if (cmd = get_cmd m, cnam)
|
||||
begin; cmd.run(m, argv)
|
||||
|
@ -50,16 +63,48 @@ module Vrobot4::Module
|
|||
end
|
||||
end
|
||||
|
||||
# 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
|
||||
@commands.select {|name, cmd| cmd.usable_in? m}
|
||||
end
|
||||
|
||||
# Gets a command by name in a specified context.
|
||||
# @param m [Vrobot4::Server::Message] message for context
|
||||
# @return [Vrobot4::Module::Command] command if found, nil if not
|
||||
def get_cmd m, name
|
||||
cmds = all_cmds(m)
|
||||
cmds[name] if cmds.key? name
|
||||
end
|
||||
|
||||
protected
|
||||
# Registers a command into this module.
|
||||
# @param fn [Symbol] name of method to add
|
||||
# @param names [String, Array] name(s) to add this command by
|
||||
# @param help [String] help string to use for this command
|
||||
# @param roles [String] roles to allow this command to use
|
||||
# @return [Vrobot4::Module::Command] command added
|
||||
def register fn, names, help = nil, roles: "v"
|
||||
help = "No help available for this command." if help == nil
|
||||
cmd = Command.new(self.method(fn), help, roles).freeze
|
||||
if names.is_a? String
|
||||
@commands[names] = cmd
|
||||
else
|
||||
names.each {|name| @commands[name] = cmd}
|
||||
end
|
||||
cmd
|
||||
end
|
||||
|
||||
# Check argument validity and count.
|
||||
#
|
||||
# Specifiers include:
|
||||
# [N] A number.
|
||||
# [S] An arbitrary string.
|
||||
#
|
||||
# @param argv [Array] array of arguments
|
||||
# @param req [String] specifier string of required arguments
|
||||
# @param opt [String] specifier string of optional arguments
|
||||
def check_args argv, req, opt = ""
|
||||
if argv.length < req.length
|
||||
raise ArgumentError, "Not enough arguments"
|
||||
|
@ -80,15 +125,17 @@ module Vrobot4::Module
|
|||
def check_arg arg, i, req
|
||||
case req
|
||||
when 'N'
|
||||
unless Vrobot4.is_num? arg
|
||||
unless Vrobot4.is_num? arg.strip
|
||||
raise ArgumentError, "Expected a number for arg " + i.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@module_types = {}
|
||||
|
||||
# Adds a module type to the global list.
|
||||
# @param type [Class] module type to add
|
||||
# @param server [String] server type this module is restricted to (or none)
|
||||
# @param servflags [String] flags the server must have to use this (or none)
|
||||
def self.add_module_type type, server: nil, servflags: nil
|
||||
@@module_types[type.type] = {
|
||||
type: type,
|
||||
|
@ -98,9 +145,15 @@ module Vrobot4::Module
|
|||
Vrobot4.log :INFO, "added module type:", type.type
|
||||
end
|
||||
|
||||
def self.get_module_type s
|
||||
@@module_types[s]
|
||||
# Gets a module type by name from the global list.
|
||||
# @param name [String] name of the module type to find
|
||||
# @return [Hash] a hash containing info about the type
|
||||
def self.get_module_type name
|
||||
@@module_types[name]
|
||||
end
|
||||
|
||||
private
|
||||
@@module_types = {}
|
||||
end
|
||||
|
||||
## EOF
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# Module for vrobot4 server interfaces.
|
||||
module Vrobot4::Server
|
||||
class Mod_Base < Vrobot4::Module::Module
|
||||
def initialize info
|
||||
|
@ -10,6 +11,7 @@ module Vrobot4::Server
|
|||
register :c_dbg, "dbg", "Sets the debug level.", roles: "o"
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def c_help m, argv
|
||||
check_args argv, "", "S"
|
||||
if argv.length == 0
|
||||
|
@ -28,6 +30,7 @@ module Vrobot4::Server
|
|||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def c_die m, argv
|
||||
m.serv.voice_quit m if m.serv.flags.include? "A"
|
||||
m.reply \
|
||||
|
@ -42,6 +45,7 @@ module Vrobot4::Server
|
|||
exit
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def c_modr m, argv
|
||||
check_args argv, "S", "S"
|
||||
m.serv.drop_mod argv[0]
|
||||
|
@ -49,38 +53,57 @@ module Vrobot4::Server
|
|||
m.serv.load_mod argv[0]
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def c_modl m, argv
|
||||
check_args argv, "S"
|
||||
m.serv.load_mod argv[0]
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def c_modu m, argv
|
||||
check_args argv, "S"
|
||||
m.serv.drop_mod argv[0]
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def c_dbg m, argv
|
||||
check_args argv, "N"
|
||||
Vrobot4.debug = argv[0].to_i
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def on_command m, cnam, argv
|
||||
Vrobot4.log :DEBUGV, "command", cnam.to_s, argv.to_s
|
||||
super
|
||||
end
|
||||
end
|
||||
private_constant :Mod_Base
|
||||
|
||||
# Generic user information. May be extended.
|
||||
class User
|
||||
attr_reader :name, :roles
|
||||
attr_reader :name # Plaintext name of the user.
|
||||
attr_reader :roles # List of user's roles.
|
||||
end
|
||||
|
||||
# Generic channel information. May be extended.
|
||||
class Channel
|
||||
attr_reader :name
|
||||
attr_reader :name # Plaintext name of the channel.
|
||||
end
|
||||
|
||||
# Generic event information. May not be extended.
|
||||
class Message
|
||||
attr_reader :msg, :user, :chan, :serv
|
||||
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.
|
||||
|
||||
# @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.
|
||||
# [: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)
|
||||
@msg = info[:msg] if info.key? :msg
|
||||
@user = info[:user] if info.key? :user
|
||||
|
@ -90,24 +113,29 @@ module Vrobot4::Server
|
|||
@reply_b = info[:reply_b] if info.key? :reply_b
|
||||
end
|
||||
|
||||
# Sends a message to the channel this message originated from.
|
||||
def reply *args
|
||||
@reply.call args.join(" ")
|
||||
end
|
||||
|
||||
# Sends a large message to the channel this message originated from.
|
||||
def reply_b *args
|
||||
@reply_b.call args.join(" ")
|
||||
end
|
||||
end
|
||||
|
||||
# Generic server interface.
|
||||
class Server
|
||||
attr_reader :mprm
|
||||
attr_reader :mprm # Module permissions for this server.
|
||||
|
||||
# @param info [Hash] arbitrary extra information for this server
|
||||
def initialize info
|
||||
@info = info
|
||||
@modules = [Mod_Base.new(nil)]
|
||||
load_permissions info["permissions"] if info.key? "permissions"
|
||||
end
|
||||
|
||||
# Loads and initializes a module into the load list.
|
||||
def load_mod mod
|
||||
mt = Vrobot4::Module.get_module_type(mod)
|
||||
if mt[:server] and mt[:server] != self.class.type or
|
||||
|
@ -117,6 +145,7 @@ module Vrobot4::Server
|
|||
@modules << mt[:type].new(@info.key?(mod) ? @info[mod] : nil)
|
||||
end
|
||||
|
||||
# Drops a module from the load list.
|
||||
def drop_mod mod
|
||||
mt = Vrobot4::Module.get_module_type(mod)
|
||||
@modules.each_index do |i|
|
||||
|
@ -124,60 +153,86 @@ module Vrobot4::Server
|
|||
end
|
||||
end
|
||||
|
||||
# Yields for every module loaded in the server.
|
||||
def each_mod
|
||||
@modules.each {|mod| yield mod}
|
||||
end
|
||||
|
||||
# (see Vrobot4::Module::Module#on_message)
|
||||
# @note Passes information to all modules.
|
||||
def on_message m
|
||||
@modules.each {|mod| break if mod.on_message m}
|
||||
end
|
||||
|
||||
# (see Vrobot4::Module::Module#on_command)
|
||||
# @note Passes information to all modules.
|
||||
def on_command m, cnam, argv
|
||||
@modules.each {|mod| break if mod.on_command m, cnam, argv}
|
||||
end
|
||||
|
||||
# Connect to the server.
|
||||
def connect
|
||||
raise NotImplementedError, "Server#connect not implemented"
|
||||
end
|
||||
|
||||
# Flags for this server.
|
||||
# @return [String]
|
||||
def flags
|
||||
""
|
||||
end
|
||||
|
||||
protected
|
||||
# Implementation defined permission loader.
|
||||
# Loads information into +@mprm+.
|
||||
def load_permissions pinf
|
||||
raise NotImplementedError, "Server::#load_permissions not implemented"
|
||||
raise NotImplementedError, "Server#load_permissions not implemented"
|
||||
end
|
||||
end
|
||||
|
||||
# Basis for an audio-enabled server interface.
|
||||
class AudioServer < Server
|
||||
# Joins a voice channel, using a message for context.
|
||||
def voice_join m
|
||||
raise NotImplementedError, "AudioServer::#voice_join not implemented"
|
||||
raise NotImplementedError, "AudioServer#voice_join not implemented"
|
||||
end
|
||||
|
||||
# Quits a voice channel, using a message for context.
|
||||
def voice_quit m
|
||||
raise NotImplementedError, "AudioServer::#voice_quit not implemented"
|
||||
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"
|
||||
raise NotImplementedError, "AudioServer#play not implemented"
|
||||
end
|
||||
|
||||
# Check if the bot is playing audio in a given context.
|
||||
def is_playing? m
|
||||
raise NotImplementedError, "AudioServer::#is_playing? not implemented"
|
||||
raise NotImplementedError, "AudioServer#is_playing? not implemented"
|
||||
end
|
||||
|
||||
# (see Vrobot4::Server::Server#flags)
|
||||
def flags
|
||||
"A"
|
||||
end
|
||||
end
|
||||
|
||||
@@server_types = {}
|
||||
|
||||
# Adds a server type to the global list.
|
||||
# @param type [Class] server type to add
|
||||
def self.add_server_type type
|
||||
@@server_types[type.type] = type
|
||||
Vrobot4.log :INFO, "added server type:", type.type
|
||||
end
|
||||
|
||||
def self.get_server_type s
|
||||
@@server_types[s]
|
||||
# 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
|
||||
|
||||
private
|
||||
@@server_types = {}
|
||||
end
|
||||
|
||||
## EOF
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
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
|
||||
attr_reader :bot # The Discordrb::Bot instance.
|
||||
|
||||
# (see Vrobot4::Server::Server#initialize)
|
||||
def initialize info
|
||||
super
|
||||
|
||||
|
@ -41,16 +44,19 @@ class Sv_Discord < Vrobot4::Server::AudioServer
|
|||
end
|
||||
end
|
||||
|
||||
# (see Vrobot4::Server::AudioServer#voice_join)
|
||||
def voice_join m
|
||||
chan = m.user.real.voice_channel
|
||||
raise RuntimeError, "You're not in a voice channel" unless chan
|
||||
@bot.voice_connect chan
|
||||
end
|
||||
|
||||
# (see Vrobot4::Server::AudioServer#voice_join)
|
||||
def voice_quit m
|
||||
@bot.voice_destroy m.chan.real.server.id
|
||||
end
|
||||
|
||||
# (see Vrobot4::Server::AudioServer#play)
|
||||
def play m, io
|
||||
v = @bot.voice(m.chan.real)
|
||||
raise ArgumentError, "Invalid i/o stream" unless io
|
||||
|
@ -58,20 +64,24 @@ class Sv_Discord < Vrobot4::Server::AudioServer
|
|||
v.play_stream io
|
||||
end
|
||||
|
||||
# (see Vrobot4::Server::AudioServer#is_playing?)
|
||||
def is_playing? m
|
||||
v = @bot.voice(m.chan.real)
|
||||
v != nil and v.playing?
|
||||
end
|
||||
|
||||
# (see Vrobot4::Server::Server#connect)
|
||||
def connect
|
||||
@bot.run
|
||||
end
|
||||
|
||||
# (see Vrobot4::Server::Server#flags)
|
||||
def flags
|
||||
"AD"
|
||||
end
|
||||
|
||||
protected
|
||||
# (see Vrobot4::Server::Server#load_permissions)
|
||||
def load_permissions pinf
|
||||
@mprm = {chan: {}, role: {}, glob: {}}
|
||||
pinf.each do |perm|
|
||||
|
@ -92,19 +102,26 @@ class Sv_Discord < Vrobot4::Server::AudioServer
|
|||
@cprm = {}
|
||||
end
|
||||
|
||||
# Returns true if the channel is enabled, false otherwise.
|
||||
def [] chan
|
||||
(@cprm.key? chan.name and @cprm[chan.name]) or
|
||||
(@cprm.key? chan.real.id and @cprm[chan.real.id])
|
||||
end
|
||||
|
||||
# Sets a channel's permission on/off.
|
||||
def []= chan, set
|
||||
@cprm[chan] = set
|
||||
end
|
||||
end
|
||||
private_constant :ChannelPerms
|
||||
|
||||
# A Discord user.
|
||||
class User < Vrobot4::Server::User
|
||||
attr_reader :real
|
||||
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
|
||||
|
@ -121,9 +138,11 @@ class Sv_Discord < Vrobot4::Server::AudioServer
|
|||
end
|
||||
end
|
||||
|
||||
# A Discord channel.
|
||||
class Channel < Vrobot4::Server::Channel
|
||||
attr_reader :real
|
||||
attr_reader :real # The Discordrb::Channel instance.
|
||||
|
||||
# @param chan [Discordrb::Channel] the discord channel
|
||||
def initialize chan
|
||||
@real = chan
|
||||
@name = "#" + chan.name
|
||||
|
|
Cargando…
Referencia en una nueva incidencia