Project

General

Profile

« Previous | Next » 

Revision ecdabe95

Added by Marc Dequènes over 13 years ago

  • ID ecdabe959057281f9350bbcd0735c9639206244f

[evol] uncomplete MapMaker bot implementation (global cyborg classes, use of EventMachine with UNIX socket backend, configuration adjustments, ...) (refs #31)

View differences:

lib/cyborghood/cyborg.rb
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
require 'xmpp4r'
require 'xmpp4r/presence'
require 'xmpp4r/version/iq/version'
require 'xmpp4r/version/helper/simpleresponder'
require 'xmpp4r/caps'
require 'xmpp4r/discovery'
#require 'xmpp4r/vcard/helper/vcard'
require 'xmpp4r/muc/helper/mucbrowser'
require 'xmpp4r/muc/helper/simplemucclient'
require 'cyborghood'
require 'cyborghood/cyborg/server'
module CyborgHood
class Cyborg
attr_reader :jid, :room_jid, :chat_jid
include I18nTranslation
bindtextdomain("cyborghood", {:path => Config::L10N_DIR, :charset => "UTF-8"})
FEATURE_NS = 'http://duckcorp.org/protocol/cyborghood'
def initialize()
def initialize
# load config
Config.load(self.human_name.downcase)
Config.load(self.human_name)
@config = Config.instance
# setup logs
unless @config.log.nil?
logger.output_level(@config.log.console_level) unless @config.log.console_level.nil?
logger.log_to_file(@config.log.file) unless @config.log.file.nil?
end
# prepare
clear
@jid = Jabber::JID.new(@config.xmpp.jid)
@room_jid = Jabber::JID.new(@config.xmpp.muc).bare
yield if block_given?
logger.info "Bot '#{self.human_name}' loaded"
end
def run
logger.info "Initializing bot..."
begin
@cl = Jabber::Client.new(@jid)
@cl.allow_tls = true
@cl.ssl_capath = @config.xmpp.ssl_capath unless @config.xmpp.ssl_capath.nil?
reconnect
rescue Jabber::ServerError => e
if e.error.type == :cancel and e.error.code == 409
if @nick_index < 100
retry
unless @config.log.path.nil?
if File.directory? @config.log.path
logger.log_to_file(File.join(@config.log.path, "ch_#{self.class.human_name}.log"))
else
logger.fatal "Cannot connect to CyborgHood HeadQuarters because my Nickname range is full (maybe a security problem)"
quit(true)
logger.fatal "Log path does not exist or is not a directory, exiting"
exit 1
end
else
logger.fatal "Cannot connect to CyborgHood HeadQuarters: " + e.error.text
quit(true)
end
end
@cl.on_exception { sleep 5; reconnect }
logger.info "Bot ready for work"
@run_thread = Thread.new { yield }
@run_thread.join
logger.info "Bot work is finished, going to sleep..."
quit
end
def ask_to_stop
@should_stop = true
@run_thread.wakeup if @run_thread.stop?
end
protected
def quit(fatal = false)
if @cl
@muc.exit if @muc and @muc.active?
@cl.close
end
clear
exit 1 if fatal
end
def advertise_presence(available)
show = (available ? :chat : :dnd)
@cl.send(Jabber::Presence.new.set_show(show))
end
def advertise_presence_in_room(available)
show = (available ? :chat : :dnd)
stanza = Jabber::Presence.new.set_show(show)
stanza.from = @jid.to_s
stanza.to = @chat_jid.to_s
@cl.send(stanza)
end
def discover_features(jid)
result = discover(jid)
result.nil? ? [] : result.features
end
def room_members
@muc.roster.keys.sort
end
def unnormalize_message(msg)
msg2 = msg.dup
REXML::DocType::DEFAULT_ENTITIES.each_value do |entity|
msg2.gsub!("&#{entity.name};", entity.value)
end
msg2.gsub!( '&amp;', '&' )
return msg2
end
private
def reconnect
logger.debug "Connecting to the XMPP server..."
@cl.connect
@cl.auth(@config.xmpp.passwd)
unless @cl.is_tls?
logger.fatal "Connection to CyborgHood HeadQuarters is not encrypted; please configure TLS support !"
quit(true)
end
# initial presence before being ready
logger.debug "Advertising unavailable status"
advertise_presence(false)
# version
logger.debug "Starting version responder"
Jabber::Version::SimpleResponder.new(@cl, PRODUCT, VERSION, "")
# advertise discovery info
logger.debug "Starting capabilities responder"
Jabber::Caps::Helper.new(@cl,
[Jabber::Discovery::Identity.new('client', self.human_name, 'bot')],
[Jabber::Discovery::Feature.new(FEATURE_NS)]
)
# enter MUC room
knock_at_room_door unless @in_room
enter_room
# presence
logger.debug "Advertising available status"
advertise_presence(true)
end
def knock_at_room_door
end
def enter_room
logger.debug "Discovering room component features"
unless discover_features(@room_jid).include?(Jabber::MUC::XMUC.new.namespace)
logger.fatal "CyborgHood HeadQuarters has no MUC support"
quit(true)
end
logger.debug "Fetching room list"
@muc_br = Jabber::MUC::MUCBrowser.new(@cl)
room_list = @muc_br.muc_rooms(@room_jid.domain)
@chat_jid = @room_jid.dup
@chat_jid.resource = generate_available_nick()
@server = BotServer.build
logger.debug "Joining room '#{@room_jid}' as '#{@chat_jid.resource}'..."
@muc = Jabber::MUC::SimpleMUCClient.new(@cl)
register_room_callbacks
@muc.join(@chat_jid)
if room_list.keys.include?(@room_jid.to_s)
on_existing_room()
else
on_missing_room()
end
# presence
logger.debug "Advertising available status in room"
advertise_presence_in_room(true)
@in_room = true
end
def on_missing_room
logger.fatal "CyborgHood HeadQuarters has no meeting room"
quit(true)
end
def on_existing_room
end
def register_room_callbacks
end
def discover(jid, node = nil)
iq = Jabber::Iq.new(:get, jid.domain)
iq.query = Jabber::Discovery::IqQueryDiscoInfo.new
iq.query.node = node unless node.nil?
result = nil
@cl.send_with_id(iq) {|reply|
result = reply.query
}
return result
logger.info "Bot '#{self.human_name}' loaded"
end
def generate_available_nick
@nick_index += 1
self.human_name + "-" + @nick_index.to_s.rjust(2, "0")
def run
logger.info "Bot starting"
@server.run
end
def clear
@cl = nil
@muc_br = nil
@muc = nil
@chat_jid = nil
@nick_index = 0
@in_room = false
@should_stop = false
def ask_to_stop
@server.stop
logger.info "Bot was asked to stop..."
end
end
end

Also available in: Unified diff