206 lines
5.7 KiB
Ruby
206 lines
5.7 KiB
Ruby
# 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
|
|
|
|
def send_msg text
|
|
@real.send text
|
|
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
|
|
if serv
|
|
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
|
|
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, or nil.
|
|
# @param serv [Discordrb::Server] server instance
|
|
# @return [Server]
|
|
def get_server serv
|
|
@servers[serv.id]
|
|
end
|
|
end
|
|
end
|
|
|
|
## EOF
|