diff options
author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2014-08-17 23:31:45 -0700 |
---|---|---|
committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2014-08-17 23:31:45 -0700 |
commit | e633d656e00fdac51f077eff827518848235e916 (patch) | |
tree | 0b40a60f95b219545d40fe709e11583ab9e3df6b | |
download | bocelli-e633d656e00fdac51f077eff827518848235e916.tar.gz bocelli-e633d656e00fdac51f077eff827518848235e916.tar.xz |
Initial commit.
-rw-r--r-- | bocelli.rb | 2 | ||||
-rw-r--r-- | bocelli/base.rb | 83 | ||||
-rw-r--r-- | bocelli/core/irc.rb | 53 | ||||
-rw-r--r-- | bocelli/module/base.rb | 25 | ||||
-rw-r--r-- | example.rb | 45 |
5 files changed, 208 insertions, 0 deletions
diff --git a/bocelli.rb b/bocelli.rb new file mode 100644 index 0000000..eaa28e0 --- /dev/null +++ b/bocelli.rb @@ -0,0 +1,2 @@ +require_relative 'bocelli/base' +require_relative 'bocelli/module/base' diff --git a/bocelli/base.rb b/bocelli/base.rb new file mode 100644 index 0000000..dfb7875 --- /dev/null +++ b/bocelli/base.rb @@ -0,0 +1,83 @@ +require_relative 'core/irc' + +module Bocelli + class Base + def initialize(str, route, block, metadata) + @bocelli = { + str: str, + route: route, + block: block, + metadata: metadata + } + end + + def execute + instance_eval(&@bocelli[:block]) + end + + def out(message) + self.class.privmsg(@bocelli[:metadata][:channel], message) + end + + class << self + include Bocelli::Core::IRC + + def setup + @routes = {} + @modules = {} + end + + def inherited(subclass) + super + + subclass.setup + end + + def on(route, &block) + name = "route #{route.inspect}" + + @routes[route] = block + end + + def register(mod) + @modules[mod.name[/[^:]+$/].downcase.intern] ||= mod + end + + def match(str, route) + case route + when Regexp + str =~ route + when String + str == route + end + end + + def process(str) + routes = @modules.inject([]) { |m, (_, v)| m.push(*v.routes) } + routes.push(*@routes) + + if str =~ /(\S+) PRIVMSG (\S+) :?(.*)/ + metadata = { + user: $1, + channel: $2, + message: $3 + } + + if (match = routes.detect { |k, _| match(metadata[:message], k) }) + route, block = match + + new(str, route, block, metadata).execute + end + end + end + + def run + while (str = sgets) + pong($1) if str =~ /\APING (.*)\z/ + + process(str) + end + end + end + end +end diff --git a/bocelli/core/irc.rb b/bocelli/core/irc.rb new file mode 100644 index 0000000..4264e2d --- /dev/null +++ b/bocelli/core/irc.rb @@ -0,0 +1,53 @@ +require 'socket' + +module Bocelli + module Core + module IRC + def configure(host, port, nick, pass = nil) + @host = host + @port = port + @nick = nick + @pass = pass + + @socket = nil + end + + def connect(&block) + @socket = TCPSocket.new(@host, @port) + + sputs("PASS #{@pass}") if @pass + sputs("NICK #{@nick}") + sputs("USER #{@nick} 0 * :#{@nick}") + + instance_eval(&block) if block_given? + end + + def sgets + str = @socket.gets + str.chomp! unless str.nil? + + puts '<< ' + str.inspect + + str + end + + def sputs(str) + puts '>> ' + str.inspect + + @socket.puts(str) + end + + def pong(message) + sputs("PONG #{message}") + end + + def join(channel) + sputs("JOIN #{channel}") + end + + def privmsg(channel, message) + sputs("PRIVMSG #{channel} :#{message}") + end + end + end +end diff --git a/bocelli/module/base.rb b/bocelli/module/base.rb new file mode 100644 index 0000000..1306830 --- /dev/null +++ b/bocelli/module/base.rb @@ -0,0 +1,25 @@ +module Bocelli + module Module + module Base + attr_reader :routes + + def setup + @routes = {} + end + + def on(route, &block) + raise 'no block given' if block.nil? + + @routes[route] = block + end + + class << self + def extended(mod) + super + + mod.setup + end + end + end + end +end diff --git a/example.rb b/example.rb new file mode 100644 index 0000000..cd09859 --- /dev/null +++ b/example.rb @@ -0,0 +1,45 @@ +require_relative 'bocelli' + +module Bocelli::Module::Foo + extend Bocelli::Module::Base + + on 'test' do + out 'this is a test!' + end + + on /^foo/ do + out 'foo' * (rand(5) + 1) + end +end + +module Bocelli::Module::Bar + extend Bocelli::Module::Base + + on /^bar+$/ do + out 'bar' * (rand(5) + 1) + end + + on /^baz+$/i do + out 'baz' * (rand(5) + 1) + end +end + +class TestBot < Bocelli::Base + register Bocelli::Module::Foo + register Bocelli::Module::Bar + + on 'rand' do + out rand(100) + end + + on 'current' do + out '%s %s' % [@bocelli[:str].inspect, @bocelli[:route].inspect] + end +end + +TestBot.configure('chat.freenode.net', 6667, 'bocelli%03d' % rand(1000)) +TestBot.connect do + join '##omp' +end + +TestBot.run |