rlyeh 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/examples/echo.rb +13 -0
- data/{example → examples}/middleware.rb +3 -1
- data/examples/simple.rb +20 -0
- data/lib/rlyeh/base.rb +14 -11
- data/lib/rlyeh/connection.rb +15 -15
- data/lib/rlyeh/deep_ones/auth.rb +72 -0
- data/lib/rlyeh/deep_ones/builder.rb +37 -0
- data/lib/rlyeh/deep_ones/closer.rb +18 -0
- data/lib/rlyeh/deep_ones/logger.rb +22 -0
- data/lib/rlyeh/deep_ones/parser.rb +21 -0
- data/lib/rlyeh/{middleware → deep_ones}/typablemap.rb +1 -1
- data/lib/rlyeh/deep_ones.rb +9 -0
- data/lib/rlyeh/dispatcher.rb +18 -10
- data/lib/rlyeh/environment.rb +16 -13
- data/lib/rlyeh/filters.rb +91 -0
- data/lib/rlyeh/numeric_reply.rb +206 -0
- data/lib/rlyeh/runner.rb +18 -1
- data/lib/rlyeh/sendable.rb +11 -0
- data/lib/rlyeh/server.rb +6 -9
- data/lib/rlyeh/session.rb +15 -15
- data/lib/rlyeh/settings.rb +35 -0
- data/lib/rlyeh/utils.rb +25 -0
- data/lib/rlyeh/version.rb +1 -1
- data/lib/rlyeh.rb +12 -8
- data/spec/rlyeh/numeric_reply_spec.rb +21 -0
- data/spec/rlyeh/settings_spec.rb +54 -0
- data/spec/spec_helper.rb +1 -1
- metadata +33 -16
- data/example/simple.rb +0 -16
- data/lib/rlyeh/filter.rb +0 -77
- data/lib/rlyeh/middleware/builder.rb +0 -31
data/.gitignore
CHANGED
data/examples/echo.rb
ADDED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# -*- coding: utf-8 -*-
|
3
|
-
$LOAD_PATH.unshift 'lib'
|
3
|
+
$LOAD_PATH.unshift 'lib', '../lib'
|
4
4
|
require 'rlyeh'
|
5
|
+
require 'logger'
|
5
6
|
|
6
7
|
class MyMiddleware
|
7
8
|
include Rlyeh::Dispatcher
|
@@ -21,6 +22,7 @@ class MyMiddleware
|
|
21
22
|
end
|
22
23
|
|
23
24
|
class MyApp < Rlyeh::Base
|
25
|
+
use Rlyeh::DeepOnes::Logger, :level => Logger::DEBUG
|
24
26
|
use MyMiddleware
|
25
27
|
|
26
28
|
on :privmsg do |env|
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
$LOAD_PATH.unshift 'lib', '../lib'
|
4
|
+
require 'rlyeh'
|
5
|
+
|
6
|
+
class MyApp < Rlyeh::Base
|
7
|
+
use Rlyeh::DeepOnes::Logger, :level => 0
|
8
|
+
use Rlyeh::DeepOnes::Auth do |auth|
|
9
|
+
auth.nick if [auth.nick, auth.pass] == ['dankogai', 'kogaidan']
|
10
|
+
end
|
11
|
+
|
12
|
+
set :server_name, 'MyApp'
|
13
|
+
set :server_version, '1.0.0'
|
14
|
+
|
15
|
+
on :privmsg do |env|
|
16
|
+
puts "RECV: #{env.message}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Rlyeh.emerge MyApp, :host => '0.0.0.0'
|
data/lib/rlyeh/base.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
require 'rlyeh/dispatcher'
|
2
|
-
require 'rlyeh/
|
2
|
+
require 'rlyeh/settings'
|
3
|
+
require 'rlyeh/deep_ones/builder'
|
4
|
+
require 'rlyeh/deep_ones/parser'
|
3
5
|
|
4
6
|
module Rlyeh
|
5
7
|
class Base
|
6
8
|
include Rlyeh::Dispatcher
|
9
|
+
include Rlyeh::Settings
|
10
|
+
|
11
|
+
set :server_name, 'Rlyeh'
|
12
|
+
set :server_version, Rlyeh::VERSION
|
7
13
|
|
8
14
|
class << self
|
9
15
|
def middlewares
|
@@ -23,11 +29,9 @@ module Rlyeh
|
|
23
29
|
|
24
30
|
alias new! new unless method_defined? :new!
|
25
31
|
def new(*args, &block)
|
26
|
-
build(Rlyeh::
|
32
|
+
build(Rlyeh::DeepOnes::Builder.new, *args, &block).to_app
|
27
33
|
end
|
28
34
|
|
29
|
-
private
|
30
|
-
|
31
35
|
def build(builder, *args, &block)
|
32
36
|
setup_default_middlewares builder
|
33
37
|
setup_middlewares builder
|
@@ -36,6 +40,8 @@ module Rlyeh
|
|
36
40
|
end
|
37
41
|
|
38
42
|
def setup_default_middlewares(builder)
|
43
|
+
builder.use! Rlyeh::DeepOnes::Closer
|
44
|
+
builder.use! Rlyeh::DeepOnes::Parser
|
39
45
|
end
|
40
46
|
|
41
47
|
def setup_middlewares(builder)
|
@@ -45,23 +51,20 @@ module Rlyeh
|
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
48
|
-
def initialize(app = nil)
|
54
|
+
def initialize(app = nil, options = {})
|
49
55
|
@app = app
|
56
|
+
@options = options
|
50
57
|
yield self if block_given?
|
51
58
|
end
|
52
59
|
|
53
60
|
def call(env)
|
54
61
|
name = env.message.command.to_s.downcase
|
55
62
|
trigger name, env
|
56
|
-
|
57
63
|
@app.call env if @app
|
58
64
|
end
|
59
65
|
|
60
|
-
def
|
61
|
-
|
62
|
-
callbacks.each do |callback|
|
63
|
-
callback.bind(self).call *args, &block
|
64
|
-
end
|
66
|
+
def halt
|
67
|
+
throw :halt
|
65
68
|
end
|
66
69
|
end
|
67
70
|
end
|
data/lib/rlyeh/connection.rb
CHANGED
@@ -1,23 +1,24 @@
|
|
1
|
-
require 'ircp'
|
2
1
|
require 'rlyeh/environment'
|
2
|
+
require 'rlyeh/filters'
|
3
|
+
require 'rlyeh/sendable'
|
3
4
|
|
4
5
|
module Rlyeh
|
5
6
|
class Connection < EventMachine::Connection
|
6
7
|
include EventMachine::Protocols::LineText2
|
8
|
+
include Rlyeh::Sendable
|
7
9
|
|
8
|
-
attr_reader :server, :
|
10
|
+
attr_reader :server, :app_class, :options
|
9
11
|
attr_reader :app, :session
|
10
12
|
|
11
|
-
def initialize(server,
|
13
|
+
def initialize(server, app_class, options)
|
12
14
|
@server = server
|
13
|
-
@
|
15
|
+
@app_class = app_class
|
14
16
|
@options = options
|
15
17
|
set_delimiter "\r\n"
|
16
18
|
end
|
17
19
|
|
18
20
|
def post_init
|
19
|
-
@app =
|
20
|
-
#@app = @app_class.new self, options
|
21
|
+
@app = app_class.new nil, @options
|
21
22
|
end
|
22
23
|
|
23
24
|
def unbind
|
@@ -26,30 +27,29 @@ module Rlyeh
|
|
26
27
|
|
27
28
|
def receive_line(data)
|
28
29
|
env = Rlyeh::Environment.new
|
30
|
+
env.data = data
|
31
|
+
env.server = @server
|
29
32
|
env.connection = self
|
30
|
-
env.
|
33
|
+
env.settings = @app_class.settings
|
31
34
|
|
32
|
-
|
33
|
-
env.message = Ircp.parse data
|
34
|
-
rescue Ircp::ParseError => e
|
35
|
-
p e
|
36
|
-
else
|
35
|
+
catch :halt do
|
37
36
|
@app.call env
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
41
40
|
def attached(session)
|
42
41
|
@session = session
|
43
|
-
#@app.attached session
|
44
42
|
end
|
45
43
|
|
46
|
-
def
|
47
|
-
#@app.detached session
|
44
|
+
def detached(session)
|
48
45
|
@session = nil
|
49
46
|
end
|
50
47
|
|
51
48
|
def attached?
|
52
49
|
!!@session
|
53
50
|
end
|
51
|
+
|
52
|
+
include Rlyeh::Filters
|
53
|
+
define_filters :attached, :detached
|
54
54
|
end
|
55
55
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'rlyeh/dispatcher'
|
3
|
+
|
4
|
+
module Rlyeh
|
5
|
+
module DeepOnes
|
6
|
+
class Auth
|
7
|
+
include Rlyeh::Dispatcher
|
8
|
+
|
9
|
+
attr_reader :nick, :pass, :user, :real, :host
|
10
|
+
|
11
|
+
def initialize(app, &authenticator)
|
12
|
+
@app = app
|
13
|
+
@authenticator = authenticator
|
14
|
+
@authorized = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
dispatch env
|
19
|
+
|
20
|
+
if authorized?
|
21
|
+
env.auth = self
|
22
|
+
@app.call env
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def load_session(env, id)
|
27
|
+
env.server.sessions[id] ||= Rlyeh::Session.new(id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def authorized?
|
31
|
+
@authorized
|
32
|
+
end
|
33
|
+
|
34
|
+
def authorized(env)
|
35
|
+
name = env.settings.server_name
|
36
|
+
version = env.settings.server_version
|
37
|
+
|
38
|
+
env.connection.tap do |conn|
|
39
|
+
conn.send_numeric_reply :welcome, @host, "Welcome to the Internet Relay Network #{@nick}!#{@user}@#{@host}"
|
40
|
+
conn.send_numeric_reply :yourhost, @host, "Your host is #{name}, running version #{version}"
|
41
|
+
conn.send_numeric_reply :created, @host, "This server was created #{Time.now}"
|
42
|
+
conn.send_numeric_reply :myinfo, @host, "#{name} #{version} #{""} #{""}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
on :pass do |env|
|
47
|
+
@pass = env.message.params[0]
|
48
|
+
end
|
49
|
+
|
50
|
+
on :nick do |env|
|
51
|
+
@nick = env.message.params[0]
|
52
|
+
end
|
53
|
+
|
54
|
+
on :user do |env|
|
55
|
+
@user = env.message.params[0]
|
56
|
+
@real = env.message.params[3]
|
57
|
+
port, @host = Socket.unpack_sockaddr_in(env.connection.get_peername)
|
58
|
+
|
59
|
+
session_id = @authenticator.call(self)
|
60
|
+
if session_id.nil?
|
61
|
+
p "Auth error"
|
62
|
+
else
|
63
|
+
@authorized = true
|
64
|
+
session = load_session env, session_id
|
65
|
+
session.attach env.connection
|
66
|
+
authorized env
|
67
|
+
p 'Session attached.'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rlyeh
|
2
|
+
module DeepOnes
|
3
|
+
class Builder
|
4
|
+
def initialize(app = nil, &block)
|
5
|
+
@stack = []
|
6
|
+
@runner = app
|
7
|
+
instance_eval(&block) if block_given?
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.app(app = nil, &block)
|
11
|
+
self.new(app, &block).to_app
|
12
|
+
end
|
13
|
+
|
14
|
+
def use(middleware, *args, &block)
|
15
|
+
@stack << proc { |app| middleware.new(app, *args, &block) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def use!(middleware, *args, &block)
|
19
|
+
@stack.unshift lambda { |app| middleware.new(app, *args, &block) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(app)
|
23
|
+
@runner = app
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_app
|
27
|
+
@stack.reverse.inject(@runner) do |inner, outer|
|
28
|
+
outer.call inner
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(env)
|
33
|
+
to_app.call(env)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rlyeh/dispatcher'
|
2
|
+
|
3
|
+
module Rlyeh
|
4
|
+
module DeepOnes
|
5
|
+
class Closer
|
6
|
+
include Rlyeh::Dispatcher
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
on :quit do |env|
|
13
|
+
env.connection.close_connection_after_writing
|
14
|
+
throw :halt
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Rlyeh
|
4
|
+
module DeepOnes
|
5
|
+
class Logger
|
6
|
+
def initialize(app, options = {})
|
7
|
+
@app = app
|
8
|
+
@logger = options[:logger] || ::Logger.new(STDOUT)
|
9
|
+
@logger.level = options[:level] || ::Logger::INFO
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
write env
|
14
|
+
@app.call env
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(env)
|
18
|
+
@logger.debug env.data
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'ircp'
|
2
|
+
|
3
|
+
module Rlyeh
|
4
|
+
module DeepOnes
|
5
|
+
class Parser
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
begin
|
12
|
+
message = Ircp.parse env.data
|
13
|
+
env.message = message
|
14
|
+
@app.call env
|
15
|
+
rescue Ircp::ParseError => e
|
16
|
+
p e
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Rlyeh
|
2
|
+
module DeepOnes
|
3
|
+
autoload :Parser, 'rlyeh/deep_ones/parser'
|
4
|
+
autoload :Builder, 'rlyeh/deep_ones/builder'
|
5
|
+
autoload :Closer, 'rlyeh/deep_ones/closer'
|
6
|
+
autoload :Logger, 'rlyeh/deep_ones/logger'
|
7
|
+
autoload :Auth, 'rlyeh/deep_ones/auth'
|
8
|
+
end
|
9
|
+
end
|
data/lib/rlyeh/dispatcher.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'rlyeh/utils'
|
2
|
+
|
1
3
|
module Rlyeh
|
2
4
|
module Dispatcher
|
3
5
|
def self.included(base)
|
@@ -7,7 +9,15 @@ module Rlyeh
|
|
7
9
|
module ClassMethods
|
8
10
|
def callbacks(name)
|
9
11
|
@dispatchers ||= {}
|
10
|
-
|
12
|
+
|
13
|
+
callbacks = @dispatchers.select do |key, value|
|
14
|
+
if key.is_a?(Regexp)
|
15
|
+
key =~ name
|
16
|
+
else
|
17
|
+
key == name
|
18
|
+
end
|
19
|
+
end.values.flatten
|
20
|
+
|
11
21
|
if superclass.respond_to?(:callbacks)
|
12
22
|
superclass.callbacks(name) + callbacks
|
13
23
|
else
|
@@ -17,18 +27,16 @@ module Rlyeh
|
|
17
27
|
|
18
28
|
def on(name, &block)
|
19
29
|
@dispatchers ||= {}
|
20
|
-
name = name.to_s
|
30
|
+
name = name.to_s if name.is_a?(Symbol)
|
21
31
|
callbacks = (@dispatchers[name] ||= [])
|
22
|
-
callbacks << generate_method(name,
|
32
|
+
callbacks << Rlyeh::Utils.generate_method(self, "__on_#{name}", block)
|
23
33
|
callbacks.uniq!
|
24
34
|
end
|
35
|
+
end
|
25
36
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
remove_method method_name
|
30
|
-
method
|
31
|
-
end
|
37
|
+
def call(env)
|
38
|
+
dispatch env
|
39
|
+
@app.call env if @app
|
32
40
|
end
|
33
41
|
|
34
42
|
def dispatch(env)
|
@@ -39,7 +47,7 @@ module Rlyeh
|
|
39
47
|
def trigger(name, *args, &block)
|
40
48
|
callbacks = self.class.callbacks name
|
41
49
|
callbacks.each do |callback|
|
42
|
-
callback.bind(self).call
|
50
|
+
break if callback.bind(self).call(*args, &block) == false
|
43
51
|
end
|
44
52
|
end
|
45
53
|
end
|
data/lib/rlyeh/environment.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
module Rlyeh
|
2
2
|
class Environment < ::Hash
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
def respond_to?(method_id, include_private = false)
|
4
|
+
super || respond_to_missing?(method_id, include_private)
|
5
|
+
end
|
6
|
+
|
7
|
+
def respond_to_missing?(method_name, include_private)
|
8
|
+
method_name = method_id.to_s
|
9
|
+
return true if method_name =~ /^(.+)=$/
|
10
|
+
return true if self.key? method_name
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method_id, *args, &block)
|
15
|
+
method_name = method_id.to_s
|
16
|
+
return self[$1] = args.first if method_name =~ /^(.+)=$/
|
17
|
+
return self[method_name] if self.key? method_name
|
18
|
+
super method_id, *args, &block
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'rlyeh/utils'
|
2
|
+
|
3
|
+
module Rlyeh
|
4
|
+
module Filters
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def define_filters(*names, &block)
|
11
|
+
names.each do |name|
|
12
|
+
unless method_defined?("#{name}_with_filters")
|
13
|
+
define_method(:"#{name}_with_filters") do |*args, &block|
|
14
|
+
run_filters name, *args do
|
15
|
+
send(:"#{name}_without_filters", *args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
alias_method :"#{name}_without_filters", :"#{name}"
|
19
|
+
alias_method :"#{name}", :"#{name}_with_filters"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_filters(name, *args, &block)
|
26
|
+
catch :halt do
|
27
|
+
_run_filters name, [:before, :arround], *args
|
28
|
+
result = block.call *args if block
|
29
|
+
_run_filters name, [:arround, :after], *args
|
30
|
+
result
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
[:before, :after, :around].each do |type|
|
35
|
+
define_method(:"#{type}_filter") do |*names, &block|
|
36
|
+
_insert_filter(names, type, block)
|
37
|
+
end
|
38
|
+
alias_method :"append_#{type}_filter", :"#{type}_filter"
|
39
|
+
|
40
|
+
define_method(:"prepend_#{type}_filter") do |*names, &block|
|
41
|
+
_insert_filter(names, type, block, :prepend => true)
|
42
|
+
end
|
43
|
+
|
44
|
+
define_method(:"remove_#{type}_filter") do |*names, &block|
|
45
|
+
_remove_filter(names, type, block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def _filters
|
52
|
+
@_filters ||= {}
|
53
|
+
end
|
54
|
+
|
55
|
+
def _run_filters(name, types, *args, &block)
|
56
|
+
named_filters = _filters[name.to_s] || {}
|
57
|
+
types.each do |type|
|
58
|
+
(named_filters[type.to_s] || []).each do |filter|
|
59
|
+
throw :halt if filter.bind(self).call(*args, &block) == false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def _generate_filter_method(name, type, block)
|
65
|
+
method_name = "__filter_#{type}_#{name}"
|
66
|
+
Rlyeh::Utils.generate_method(Rlyeh::Utils.singleton_class(self), method_name, block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def _insert_filter(names, type, block, options = {})
|
70
|
+
prepend = options[:prepend]
|
71
|
+
names.each do |name|
|
72
|
+
filter = _generate_filter_method name, type, block
|
73
|
+
named_filters = (_filters[name.to_s] ||= {})
|
74
|
+
filters = (named_filters[type.to_s] ||= [])
|
75
|
+
if prepend
|
76
|
+
filters.unshift filter
|
77
|
+
else
|
78
|
+
filters.push filter
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def _remove_filter(names, type, block)
|
84
|
+
names.each do |name|
|
85
|
+
named_filters = (_filters[name.to_s] ||= {})
|
86
|
+
filters = (named_filters[type.to_s] ||= [])
|
87
|
+
filters.delete block
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|