diff options
-rw-r--r-- | Rakefile | 2 | ||||
-rwxr-xr-x | bin/rbot-remote | 76 | ||||
-rw-r--r-- | data/rbot/plugins/remotectl.rb | 29 | ||||
-rw-r--r-- | lib/rbot/core/remote.rb | 401 | ||||
-rw-r--r-- | man/rbot-remote.xml | 217 | ||||
-rw-r--r-- | rbot.gemspec | 5 |
6 files changed, 3 insertions, 727 deletions
@@ -7,7 +7,7 @@ rule '.1' => ['.xml'] do |t| sh "xsltproc -nonet -o #{t.name} /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl #{t.source}" end -task :manpages => ['man/rbot.1', 'man/rbot-remote.1'] +task :manpages => ['man/rbot.1'] SPECFILE = 'rbot.gemspec' # The Rakefile is also used after installing the gem, to build diff --git a/bin/rbot-remote b/bin/rbot-remote deleted file mode 100755 index 353bb06d..00000000 --- a/bin/rbot-remote +++ /dev/null @@ -1,76 +0,0 @@ -#! /usr/bin/ruby -require 'drb' -require 'optparse' - -#++ -# -# :title: RemoteCtl example script -# -# Author:: jsn (dmitry kim) <dmitry dot kim at gmail dot org> -# Copyright:: (C) 2007 dmitry kim -# License:: in public domain - -user = nil -pw = nil -dst = nil -uri = 'druby://localhost:7268' - -opts = OptionParser.new -opts.on('-u', '--user <user>', "remote user (mandatory)") { |v| user = v } -opts.on('-p', '--password <pw>', "remote user password (mandatory)") { |v| pw = v } -opts.on('-d', '--destination <user or #channel>') { |v| dst = v } -opts.on('-r', '--uri <drb uri>', "rbot url (#{uri})") { |v| uri = v } -opts.on('-h', '--help', "this message") { |v| pw = nil } # sorry! -opts.on('-a', '--about', "what it's all about.") { |v| - puts <<EOF -This is just a proof-of-concept example for rbot druby-based api. This program -reads lines of text from the standard input and sends them to a specified irc -channel or user via rbot. Make sure you have remotectl.rb plugin loaded before -use. - -The necessary setup is: - 1) # create a new rbot user ("rmuser", in this example) with a password - # ("rmpw", in this example). in an open query to rbot: - - <you> user create rmuser rmpw - <rbot> created botuser remote - - 2) # add a remotectl permission to your newly created remote user: - - <you> permissions set +remotectl for rmuser - <rbot> okies! - - 3) # add specific permissions for the commands you want to allow via - # remote interface. for example, in this script we want 'say', - # 'action' and other basic commands to work: - - <you> permissions set +basics::talk::do for rmuser - <rbot> alright - - 4) # run the #{$0} and type something. the message should - # show up on your channel / arrive as an irc private message. - - [you@yourhost ~]$ ./bin/rbot-remote -u rmuser -p rmpw -d '#your-channel' - hello, world! - <Ctrl-D> - [you@yourhost ~]$ -EOF - exit 0 -} -opts.parse! - -if !pw || !user || !dst - puts opts.to_s - exit 0 -end - -rbot = DRbObject.new_with_uri(uri) -id = rbot.delegate(nil, "remote login #{user} #{pw}")[:return] -puts "id is #{id.inspect}" -loop { - s = gets or break - s.chomp! - rv = rbot.delegate(id, "dispatch say #{dst} #{s}") or break - puts "rv is #{rv.inspect}" -} - diff --git a/data/rbot/plugins/remotectl.rb b/data/rbot/plugins/remotectl.rb deleted file mode 100644 index 31d48fe3..00000000 --- a/data/rbot/plugins/remotectl.rb +++ /dev/null @@ -1,29 +0,0 @@ -#-- vim:sw=4:et -#++ -# -# :title: RemoteCtl plugin -# -# Author:: jsn (dmitry kim) <dmitry dot kim at gmail dot org> -# Copyright:: (C) 2007 dmitry kim -# License:: in public domain -# -# Adds druby remote command execution to rbot. See 'bin/rbot-remote' for -# example usage. - -class RemoteCtlPlugin < Plugin - include RemotePlugin - - def remote_command(m, params) - s = params[:string].to_s - u = @bot.server.user("remote:#{m.source.username}") - @bot.auth.login(u, m.source.username, m.source.password) - fake_message(s, :source => u) - end -end - -me = RemoteCtlPlugin.new - -me.remote_map 'dispatch *string', - :action => 'remote_command' - -me.default_auth('*', false) diff --git a/lib/rbot/core/remote.rb b/lib/rbot/core/remote.rb deleted file mode 100644 index d8d43533..00000000 --- a/lib/rbot/core/remote.rb +++ /dev/null @@ -1,401 +0,0 @@ -#-- vim:sw=2:et -#++ -# -# :title: Remote service provider for rbot -# -# Author:: Giuseppe Bilotta (giuseppe.bilotta@gmail.com) -# -# From an idea by halorgium <rbot@spork.in>. -# -# TODO find a way to manage session id (logging out, manually and/or -# automatically) - -require 'drb/drb' - -module ::Irc -class Bot - - module Auth - - # We extend the BotUser class to handle remote logins - # - class BotUser - - # A rather simple method to handle remote logins. Nothing special, just a - # password check. - # - def remote_login(password) - if password == @password - debug "remote login for #{self.inspect} succeeded" - return true - else - return false - end - end - end - - # We extend the ManagerClass to handle remote logins - # - class ManagerClass - - MAX_SESSION_ID = 2**128 - 1 - - # Creates a session id when the given password matches the given - # botusername - # - def remote_login(botusername, pwd) - @remote_users = Hash.new unless defined? @remote_users - n = BotUser.sanitize_username(botusername) - k = n.to_sym - raise "No such BotUser #{n}" unless include?(k) - bu = @allbotusers[k] - if bu.remote_login(pwd) - raise "ran out of session ids!" if @remote_users.length == MAX_SESSION_ID - session_id = rand(MAX_SESSION_ID) - while @remote_users.has_key?(session_id) - session_id = rand(MAX_SESSION_ID) - end - @remote_users[session_id] = bu - return session_id - end - return false - end - - # Returns the botuser associated with the given session id - def remote_user(session_id) - return everyone unless session_id - return nil unless defined? @remote_users - if @remote_users.has_key?(session_id) - return @remote_users[session_id] - else - return nil - end - end - end - - end - - - # A RemoteMessage is similar to a BasicUserMessage - # - class RemoteMessage - # associated bot - attr_reader :bot - - # when the message was received - attr_reader :time - - # remote client that originated the message - attr_reader :source - - # contents of the message - attr_accessor :message - - def initialize(bot, source, message) - @bot = bot - @source = source - @message = message - @time = Time.now - end - - # The target of a RemoteMessage - def target - @bot - end - - # Remote messages are always 'private' - def private? - true - end - end - - # The RemoteDispatcher is a kind of MessageMapper, tuned to handle - # RemoteMessages - # - class RemoteDispatcher < MessageMapper - - # It is initialized by passing it the bot instance - # - def initialize(bot) - super - end - - # The map method for the RemoteDispatcher returns the index of the inserted - # template - # - def map(botmodule, *args) - super - return @templates.length - 1 - end - - # The unmap method for the RemoteDispatcher nils the template at the given index, - # therefore effectively removing the mapping - # - def unmap(botmodule, handle) - tmpl = @templates[handle] - raise "Botmodule #{botmodule.name} tried to unmap #{tmpl.inspect} that was handled by #{tmpl.botmodule}" unless tmpl.botmodule == botmodule.name - debug "Unmapping #{tmpl.inspect}" - @templates[handle] = nil - @templates.clear unless @templates.compact.size > 0 - end - - # We redefine the handle() method from MessageMapper, taking into account - # that @parent is a bot, and that we don't handle fallbacks. - # - # On failure to dispatch anything, the method returns false. If dispatching - # is successfull, the method returns a Hash. - # - # Presently, the hash returned on success has only one key, :return, whose - # value is the actual return value of the successfull dispatch. - # - # TODO this same kind of mechanism could actually be used in MessageMapper - # itself to be able to handle the case of multiple plugins having the same - # 'first word' ... - # - # - def handle(m) - return false if @templates.empty? - failures = [] - @templates.each do |tmpl| - # Skip this element if it was unmapped - next unless tmpl - botmodule = @parent.plugins[tmpl.botmodule] - options = tmpl.recognize(m) - if options.kind_of? Failure - failures << options - else - action = tmpl.options[:action] - unless botmodule.respond_to?(action) - failures << NoActionFailure.new(tmpl, m) - next - end - auth = tmpl.options[:full_auth_path] - debug "checking auth for #{auth}" - # We check for private permission - if m.bot.auth.permit?(m.source, auth, '?') - debug "template match found and auth'd: #{action.inspect} #{options.inspect}" - return :return => botmodule.send(action, m, options) - end - debug "auth failed for #{auth}" - # if it's just an auth failure but otherwise the match is good, - # don't try any more handlers - return false - end - end - failures.each {|r| - debug "#{r.template.inspect} => #{r}" - } - debug "no handler found" - return false - end - - end - - # The Irc::Bot::RemoteObject class represents and object that will take care - # of interfacing with remote clients - # - # Example client session: - # - # require 'drb' - # rbot = DRbObject.new_with_uri('druby://localhost:7268') - # id = rbot.delegate(nil, 'remote login someuser somepass')[:return] - # rbot.delegate(id, 'some secret command') - # - # Of course, the remote login is only neede for commands which may not be available - # to everyone - # - class RemoteObject - - # We don't want this object to be copied clientside, so we make it undumpable - include DRbUndumped - - # Initialization is simple - def initialize(bot) - @bot = bot - end - - # The delegate method. This is the main method used by remote clients to send - # commands to the bot. Most of the time, the method will be called with only - # two parameters (session id and a String), but we allow more parameters - # for future expansions. - # - # The session_id can be nil, meaning that the remote client wants to work as - # an anoynomus botuser. - # - def delegate(session_id, *pars) - warn "Ignoring extra parameters" if pars.length > 1 - cmd = pars.first - client = @bot.auth.remote_user(session_id) - raise "No such session id #{session_id}" unless client - debug "Trying to dispatch command #{cmd.inspect} from #{client.inspect} authorized by #{session_id.inspect}" - m = RemoteMessage.new(@bot, client, cmd) - @bot.remote_dispatcher.handle(m) - end - - private :instance_variables, :instance_variable_get, :instance_variable_set - end - - # The bot also manages a single (for the moment) remote dispatcher. This method - # makes it accessible to the outside world, creating it if necessary. - # - def remote_dispatcher - if defined? @remote_dispatcher - @remote_dispatcher - else - @remote_dispatcher = RemoteDispatcher.new(self) - end - end - - # The bot also manages a single (for the moment) remote object. This method - # makes it accessible to the outside world, creating it if necessary. - # - def remote_object - if defined? @remote_object - @remote_object - else - @remote_object = RemoteObject.new(self) - end - end - - module Plugins - - # We create a new Ruby module that can be included by BotModules that want to - # provide remote interfaces - # - module RemoteBotModule - - # The remote_map acts just like the BotModule#map method, except that - # the map is registered to the @bot's remote_dispatcher. Also, the remote map handle - # is handled for the cleanup management - # - def remote_map(*args) - @remote_maps = Array.new unless defined? @remote_maps - @remote_maps << @bot.remote_dispatcher.map(self, *args) - end - - # Unregister the remote maps. - # - def remote_cleanup - return unless defined? @remote_maps - @remote_maps.each { |h| - @bot.remote_dispatcher.unmap(self, h) - } - @remote_maps.clear - end - - # Redefine the default cleanup method. - # - def cleanup - super - remote_cleanup - end - end - - # And just because I like consistency: - # - module RemoteCoreBotModule - include RemoteBotModule - end - - module RemotePlugin - include RemoteBotModule - end - - end - -end -end - -class RemoteModule < CoreBotModule - - include RemoteCoreBotModule - - Config.register Config::BooleanValue.new('remote.autostart', - :default => false, - :requires_rescan => true, - :desc => "Whether the remote service provider should be started automatically") - - Config.register Config::IntegerValue.new('remote.port', - :default => 7268, # that's 'rbot' - :requires_rescan => true, - :desc => "Port on which the remote interface will be presented") - - Config.register Config::StringValue.new('remote.host', - :default => '127.0.0.1', - :requires_rescan => true, - :desc => "Host on which the remote interface will be presented") - - def initialize - super - @port = @bot.config['remote.port'] - @host = @bot.config['remote.host'] - @drb = nil - begin - start_service if @bot.config['remote.autostart'] - rescue => e - error "couldn't start remote service provider: #{e.inspect}" - end - end - - def start_service - raise "Remote service provider already running" if @drb - @drb = DRb.start_service("druby://#{@host}:#{@port}", @bot.remote_object) - end - - def stop_service - @drb.stop_service if @drb - @drb = nil - end - - def cleanup - stop_service - super - end - - def handle_start(m, params) - if @drb - rep = "remote service provider already running" - rep << " on port #{@port}" if m.private? - else - begin - start_service(@port) - rep = "remote service provider started" - rep << " on port #{@port}" if m.private? - rescue - rep = "couldn't start remote service provider" - end - end - m.reply rep - end - - def remote_test(m, params) - @bot.say params[:channel], "This is a remote test" - end - - def remote_login(m, params) - id = @bot.auth.remote_login(params[:botuser], params[:password]) - raise "login failed" unless id - return id - end - -end - -remote = RemoteModule.new - -remote.map "remote start", - :action => 'handle_start', - :auth_path => ':manage:' - -remote.map "remote stop", - :action => 'handle_stop', - :auth_path => ':manage:' - -remote.default_auth('*', false) - -remote.remote_map "remote test :channel", - :action => 'remote_test' - -remote.remote_map "remote login :botuser :password", - :action => 'remote_login' - -remote.default_auth('login', true) diff --git a/man/rbot-remote.xml b/man/rbot-remote.xml deleted file mode 100644 index b68b4ef0..00000000 --- a/man/rbot-remote.xml +++ /dev/null @@ -1,217 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" -"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ - -<!-- - -Process this file with an XSLT processor: `xsltproc \ --''-nonet /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\ -manpages/docbook.xsl manpage.dbk'. A manual page -<package>.<section> will be generated. You may view the -manual page with: nroff -man <package>.<section> | less'. A -typical entry in a Makefile or Makefile.am is: - -DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\ -manpages/docbook.xsl -XP=xsltproc -''-nonet - -manpage.1: manpage.dbk - $(XP) $(DB2MAN) $< - -The xsltproc binary is found in the xsltproc package. The -XSL files are in docbook-xsl. Please remember that if you -create the nroff version in one of the debian/rules file -targets (such as build), you will need to include xsltproc -and docbook-xsl in your Build-Depends control field. - ---> - - <!-- Fill in your name for FIRSTNAME and SURNAME. --> - <!ENTITY dhfirstname "<firstname>Marc</firstname>"> - <!ENTITY dhsurname "<surname>Dequènes</surname>"> - <!ENTITY gbgname "<firstname>Giuseppe</firstname>"> - <!ENTITY gbfname "<surname>Bilotta</surname>"> - <!-- Please adjust the date whenever revising the manpage. --> - <!ENTITY dhdate "<date>20100701</date>"> - <!-- SECTION should be 1-8, maybe w/ subsection other parameters are - allowed: see man(7), man(1). --> - <!ENTITY dhsection "<manvolnum>1</manvolnum>"> - <!ENTITY dhemail "<email>Duck@DuckCorp.org</email>"> - <!ENTITY gbemail "<email>giuseppe.bilotta@gmail.com</email>"> - <!ENTITY dhusername "Marc Dequènes (Duck)"> - <!ENTITY gbusername "Giuseppe Bilotta"> - <!ENTITY dhucapp "<refentrytitle>RBOT-REMOTE</refentrytitle>"> - <!ENTITY dhapp "rbot-remote"> - <!ENTITY dhpackage "rbot"> - <!ENTITY dhpackageversion "0.9.15"> - - <!ENTITY debian "<productname>Debian</productname>"> - <!ENTITY gnu "<acronym>GNU</acronym>"> - <!ENTITY gpl "&gnu; <acronym>GPL</acronym>"> -]> - -<refentry id="&dhapp;.1"> - - <refentryinfo> - <productname>&dhapp;</productname> - <authorgroup> - <author> - &dhfirstname; - &dhsurname; - &dhemail; - <contrib>&debian; package maintainer</contrib> - </author> - <author> - &gbgname; - &gbfname; - &gbemail; - <contrib>&dhapp; maintainer</contrib> - </author> - </authorgroup> - <copyright> - <year>2004-2009</year> - <holder>&dhusername;</holder> - </copyright> - <copyright> - <year>2010</year> - <holder>&gbusername;</holder> - </copyright> - &dhdate; - </refentryinfo> - - <refmeta> - &dhucapp; - &dhsection; - <refmiscinfo class="manual">&dhapp; man page</refmiscinfo> - <refmiscinfo class="source">&dhpackage;</refmiscinfo> - <refmiscinfo class="version">&dhpackageversion;</refmiscinfo> - </refmeta> - - <refnamediv> - <refname>&dhapp;</refname> - - <refpurpose>IRC bot written in ruby</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis> - <command>&dhapp;</command> - - <group choice="req"> - <group choice="req"> - <arg><option>-u USER</option></arg> - <arg><option>--user USER</option></arg> - </group> - <group choice="req"> - <arg><option>-p PASSWORD</option></arg> - <arg><option>--password PASSWORD</option></arg> - </group> - </group> - <group choice="opt"> - <group choice="req"> - <arg><option>-d DEST</option></arg> - <arg><option>--destination DEST</option></arg> - </group> - <group choice="req"> - <arg><option>-r DRB_URI</option></arg> - <arg><option>--uri DRB_URI</option></arg> - </group> - <group choice="req"> - <arg><option>-h</option></arg> - <arg><option>--help</option></arg> - </group> - <group choice="req"> - <arg><option>-a</option></arg> - <arg><option>--about</option></arg> - </group> - </group> - - </cmdsynopsis> - </refsynopsisdiv> - <refsect1> - <title>DESCRIPTION</title> - - <para><command>&dhapp;</command> is a proof-of-concept example for - rbot druby-based api. This program reads lines of text from the standard - input and sends them to a specified irc channel or user via rbot. - </para> - - <para>Make sure you have the remotectl plugin loaded and assigned the needed - rights to the user before use. - </para> - - </refsect1> - <refsect1> - <title>OPTIONS</title> - - <para>This program follow the usual &gnu; command line syntax, - with long options starting with two dashes (`-'). A summary of - options is included below.</para> - - <variablelist> - <varlistentry> - <term><option>-u <parameter>USER</parameter></option></term> - <term><option>--user <parameter>USER</parameter></option></term> - <listitem> - <para>Remote user.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>-p <parameter>PASSWORD</parameter></option></term> - <term><option>--password <parameter>PASSWORD</parameter></option></term> - <listitem> - <para>Remote user password.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>-d <parameter>DEST</parameter></option></term> - <term><option>--destination <parameter>DEST</parameter></option></term> - <listitem> - <para>Destination for message (user or channel).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>-r <parameter>DRB_URI</parameter></option></term> - <term><option>--uri <parameter>DRB_URI</parameter></option></term> - <listitem> - <para>Rbot url.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>-h</option></term> - <term><option>--help</option></term> - <listitem> - <para>Show summary of options.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>-a</option></term> - <term><option>--about</option></term> - <listitem> - <para>Tell what it's all about.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - <refsect1> - <title>VERSION</title> - - <para>This manual page was written by &dhusername; &dhemail; for - the &debian; system (but may be used by others). Permission is - granted to copy, distribute and/or modify this document under - the terms of the &gnu; General Public License, Version 3 or - any later version published by the Free Software Foundation. - </para> - <para> - On Debian systems, the complete text of the GNU General Public - License can be found in /usr/share/common-licenses/GPL. - </para> - - </refsect1> -</refentry> - diff --git a/rbot.gemspec b/rbot.gemspec index 5d563b53..29d88c1f 100644 --- a/rbot.gemspec +++ b/rbot.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.description = <<-EOF A modular ruby IRC bot specifically designed for ease of extension via plugins. EOF - s.requirements << 'Ruby, version 1.8.0 (or newer)' + s.requirements << 'Ruby, version 1.9.3 (or newer)' s.files = FileList[ 'lib/**/*.rb', @@ -24,7 +24,6 @@ Gem::Specification.new do |s| 'INSTALL', 'Usage_en.txt', 'man/rbot.1', - 'man/rbot-remote.1', 'setup.rb', 'launch_here.rb', 'po/*.pot', @@ -32,7 +31,7 @@ Gem::Specification.new do |s| ] s.bindir = 'bin' - s.executables = ['rbot', 'rbot-remote'] + s.executables = ['rbot', 'rbotdb'] s.default_executable = 'rbot' s.extensions = 'Rakefile' |