rlyeh 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format d
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rlyeh.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 mashiro
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Rlyeh
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rlyeh'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rlyeh
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task :default => :spec
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ $LOAD_PATH.unshift 'lib'
4
+ require 'rlyeh'
5
+
6
+ class MyMiddleware
7
+ include Rlyeh::Dispatcher
8
+
9
+ on :privmsg do |env|
10
+ p "Middleware: #{env.message}"
11
+ end
12
+
13
+ def initialize(app)
14
+ @app = app
15
+ end
16
+
17
+ def call(env)
18
+ dispatch env
19
+ @app.call env
20
+ end
21
+ end
22
+
23
+ class MyApp < Rlyeh::Base
24
+ use MyMiddleware
25
+
26
+ on :privmsg do |env|
27
+ p "MyApp1: #{env.message}"
28
+ end
29
+
30
+ on :privmsg do |env|
31
+ p "MyApp2: #{env.message}"
32
+ end
33
+ end
34
+
35
+ Rlyeh.run MyApp
data/example/simple.rb ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ $LOAD_PATH.unshift 'lib'
4
+ require 'rlyeh'
5
+
6
+ class MyApp < Rlyeh::Base
7
+ on :privmsg do |env|
8
+ p "MyApp1: #{env.message}"
9
+ end
10
+
11
+ on :privmsg do |env|
12
+ p "MyApp2: #{env.message}"
13
+ end
14
+ end
15
+
16
+ Rlyeh.run MyApp
data/lib/rlyeh/base.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'rlyeh/dispatcher'
2
+ require 'rlyeh/middleware/builder'
3
+
4
+ module Rlyeh
5
+ class Base
6
+ include Rlyeh::Dispatcher
7
+
8
+ class << self
9
+ def middlewares
10
+ @middlewares ||= []
11
+ if superclass.respond_to?(:middlewares)
12
+ superclass.middlewares + @middlewares
13
+ else
14
+ @middlewares
15
+ end
16
+ end
17
+
18
+ def use(name, *args, &block)
19
+ @middlewares ||= []
20
+ @middlewares << [name, args, block]
21
+ @middlewares = @middlewares.uniq
22
+ end
23
+
24
+ alias new! new unless method_defined? :new!
25
+ def new(*args, &block)
26
+ build(Rlyeh::Middleware::Builder.new, *args, &block).to_app
27
+ end
28
+
29
+ private
30
+
31
+ def build(builder, *args, &block)
32
+ setup_default_middlewares builder
33
+ setup_middlewares builder
34
+ builder.run new!(*args, &block)
35
+ builder
36
+ end
37
+
38
+ def setup_default_middlewares(builder)
39
+ end
40
+
41
+ def setup_middlewares(builder)
42
+ middlewares.each do |name, args, block|
43
+ builder.use(name, *args, &block)
44
+ end
45
+ end
46
+ end
47
+
48
+ def initialize(app = nil)
49
+ @app = app
50
+ yield self if block_given?
51
+ end
52
+
53
+ def call(env)
54
+ name = env.message.command.to_s.downcase
55
+ trigger name, env
56
+
57
+ @app.call env if @app
58
+ end
59
+
60
+ def trigger(name, *args, &block)
61
+ callbacks = self.class.callbacks name
62
+ callbacks.each do |callback|
63
+ callback.bind(self).call *args, &block
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,55 @@
1
+ require 'ircp'
2
+ require 'rlyeh/environment'
3
+
4
+ module Rlyeh
5
+ class Connection < EventMachine::Connection
6
+ include EventMachine::Protocols::LineText2
7
+
8
+ attr_reader :server, :klass, :options
9
+ attr_reader :app, :session
10
+
11
+ def initialize(server, klass, options)
12
+ @server = server
13
+ @klass = klass
14
+ @options = options
15
+ set_delimiter "\r\n"
16
+ end
17
+
18
+ def post_init
19
+ @app = klass.new
20
+ #@app = @app_class.new self, options
21
+ end
22
+
23
+ def unbind
24
+ @server.unbind self
25
+ end
26
+
27
+ def receive_line(data)
28
+ env = Rlyeh::Environment.new
29
+ env.connection = self
30
+ env.raw = data
31
+
32
+ begin
33
+ env.message = Ircp.parse data
34
+ rescue Ircp::ParseError => e
35
+ p e
36
+ else
37
+ @app.call env
38
+ end
39
+ end
40
+
41
+ def attached(session)
42
+ @session = session
43
+ #@app.attached session
44
+ end
45
+
46
+ def deatched(session)
47
+ #@app.detached session
48
+ @session = nil
49
+ end
50
+
51
+ def attached?
52
+ !!@session
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ module Rlyeh
2
+ module Dispatcher
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def callbacks(name)
9
+ @dispatchers ||= {}
10
+ callbacks = @dispatchers[name] || []
11
+ if superclass.respond_to?(:callbacks)
12
+ superclass.callbacks(name) + callbacks
13
+ else
14
+ callbacks
15
+ end
16
+ end
17
+
18
+ def on(name, &block)
19
+ @dispatchers ||= {}
20
+ name = name.to_s
21
+ callbacks = (@dispatchers[name] ||= [])
22
+ callbacks << generate_method(name, &block)
23
+ callbacks.uniq!
24
+ end
25
+
26
+ def generate_method(method_name, &block)
27
+ define_method method_name, &block
28
+ method = instance_method method_name
29
+ remove_method method_name
30
+ method
31
+ end
32
+ end
33
+
34
+ def dispatch(env)
35
+ name = env.message.command.to_s.downcase
36
+ trigger name, env
37
+ end
38
+
39
+ def trigger(name, *args, &block)
40
+ callbacks = self.class.callbacks name
41
+ callbacks.each do |callback|
42
+ callback.bind(self).call *args, &block
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ module Rlyeh
2
+ class Environment < ::Hash
3
+ def method_missing(method_id, *args)
4
+ case method_id.to_s
5
+ when /^(.+)=$/
6
+ store $1.to_sym, args.first
7
+ when /^(.+)\?$/
8
+ key? $1.to_sym
9
+ else
10
+ unless key? method_id
11
+ store method_id, Environment.new
12
+ else
13
+ fetch method_id
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,77 @@
1
+ module Rlyeh
2
+ module Filter
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def define_filter(*names, &block)
9
+ names.each do |name|
10
+ unless method_defined?("#{name}_with_filter")
11
+ define_method(:"#{name}_with_filter") do |*args, &block|
12
+ _run_filter_callbacks(:"#{name}", [:before, :around], *args, &block)
13
+ result = send(:"#{name}_without_filter", *args, &block)
14
+ _run_filter_callbacks(:"#{name}", [:around, :after], *args, &block)
15
+ result
16
+ end
17
+ alias_method :"#{name}_without_filter", :"#{name}"
18
+ alias_method :"#{name}", :"#{name}_with_filter"
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def _filter_callbacks
25
+ @_filter_callbacks ||= {}
26
+ end
27
+ private :_filter_callbacks
28
+
29
+ def _run_filter_callbacks(name, types, *args, &block)
30
+ named_filter_callbacks = _filter_callbacks[name] || {}
31
+ types.each do |type|
32
+ (named_filter_callbacks[type] || []).each do |callback|
33
+ callback.call(*args, &block)
34
+ end
35
+ end
36
+ end
37
+ private :_run_filter_callbacks
38
+
39
+ def _insert_filter_callbacks(names, type, block, options = {})
40
+ prepend = options[:prepend]
41
+ names.each do |name|
42
+ named_filter_callbacks = (_filter_callbacks[:"#{name}"] ||= {})
43
+ callbacks = (named_filter_callbacks[type] ||= [])
44
+ if prepend
45
+ callbacks.unshift block
46
+ else
47
+ callbacks.push block
48
+ end
49
+ end
50
+ end
51
+ private :_insert_filter_callbacks
52
+
53
+ def _remove_filter_callbacks(names, type, block)
54
+ names.each do |name|
55
+ named_filter_callbacks = (_filter_callbacks[:"#{name}"] ||= {})
56
+ callbacks = (named_filter_callbacks[type] ||= [])
57
+ callbacks.delete block
58
+ end
59
+ end
60
+ private :_remove_filter_callbacks
61
+
62
+ [:before, :after, :around].each do |type|
63
+ define_method(:"#{type}_filter") do |*names, &block|
64
+ _insert_filter_callbacks(names, type, block)
65
+ end
66
+ alias_method :"append_#{type}_filter", :"#{type}_filter"
67
+
68
+ define_method(:"prepend_#{type}_filter") do |*names, &block|
69
+ _insert_filter_callbacks(names, type, block, :prepend => true)
70
+ end
71
+
72
+ define_method(:"remove_#{type}_filter") do |*names, &block|
73
+ _remove_filter_callbacks(names, type, block)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,31 @@
1
+ module Rlyeh
2
+ module Middleware
3
+ class Builder
4
+ def initialize(&block)
5
+ @ins = []
6
+ instance_eval(&block) if block_given?
7
+ end
8
+
9
+ def self.app(&block)
10
+ self.new(&block).to_app
11
+ end
12
+
13
+ def use(middleware, *args, &block)
14
+ @ins << lambda { |app| middleware.new(app, *args, &block) }
15
+ end
16
+
17
+ def run(app)
18
+ @ins << app #lambda { |nothing| app }
19
+ end
20
+
21
+ def to_app
22
+ inner_app = @ins.last
23
+ @ins[0...-1].reverse.inject(inner_app) { |a, e| e.call(a) }
24
+ end
25
+
26
+ def call(env)
27
+ to_app.call(env)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module Rlyeh
2
+ module Middleware
3
+ class TypableMap
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ @app.call env
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module Rlyeh
2
+ module Runner
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def run(*args, &block)
9
+ starter = proc do
10
+ Server.start *args, &block
11
+ end
12
+
13
+ if EventMachine.reactor_running?
14
+ starter.call
15
+ else
16
+ EventMachine.run &starter
17
+ end
18
+ end
19
+
20
+ def stop
21
+ EventMachine.stop if EventMachine.reactor_running?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,60 @@
1
+ require 'rlyeh/connection'
2
+ require 'rlyeh/utils'
3
+ require 'rlyeh/filter'
4
+
5
+ module Rlyeh
6
+ class Server
7
+ include Rlyeh::Filter
8
+
9
+ attr_reader :options, :host, :port
10
+ attr_reader :app_class, :signature, :connections, :sessions
11
+
12
+ def initialize(*args)
13
+ @options = Rlyeh::Utils.extract_options! args
14
+ @host = @options.delete(:host) || "127.0.0.1"
15
+ @port = @options.delete(:port) || 46667
16
+ @app_class = args.shift
17
+ @signature = nil
18
+ @connections = []
19
+ @sessions = {}
20
+ end
21
+
22
+ def self.start(*args)
23
+ new(*args).start
24
+ end
25
+
26
+ def start
27
+ args = [self, @app_class, options]
28
+ @signature = EventMachine.start_server @host, @port, Rlyeh::Connection, *args do |connection|
29
+ bind connection
30
+ end
31
+ end
32
+
33
+ def stop
34
+ EventMachine.stop_server @signature if @signature
35
+ @signature = nil
36
+ end
37
+
38
+ def bind(connection)
39
+ @connections.push connection
40
+ puts 'bind'
41
+ end
42
+
43
+ def unbind(connection)
44
+ if connection.attached?
45
+ session = connection.session
46
+ session.detach connection
47
+
48
+ if session.empty?
49
+ session.close
50
+ @sessions.delete session
51
+ end
52
+ end
53
+
54
+ @connections.delete connection
55
+ puts 'unbind'
56
+ end
57
+
58
+ define_filter :start, :stop, :bind, :unbind
59
+ end
60
+ end
@@ -0,0 +1,42 @@
1
+ require 'rlyeh/filter'
2
+
3
+ module Rlyeh
4
+ class Session
5
+ include Rlyeh::Filter
6
+
7
+ attr_accessor :channel, :connections
8
+
9
+ def initialize
10
+ @channel = EventMachine::Channel.new
11
+ @subscribers = {}
12
+ end
13
+
14
+ def attach(conn)
15
+ conn.attached self
16
+
17
+ @subscribers[conn] = @channel.subscribe do |msg|
18
+ conn.send_data msg
19
+ end
20
+ end
21
+
22
+ def detach(conn)
23
+ id = @subscribers.delete conn
24
+ @channel.unsubscribe id if id
25
+
26
+ conn.detached self
27
+ end
28
+
29
+ def close
30
+ end
31
+
32
+ def send_data(data)
33
+ @channel.push data
34
+ end
35
+
36
+ def empty?
37
+ @subscribes.empty?
38
+ end
39
+
40
+ define_filter :attach, :detach, :close, :send_data
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module Rlyeh
2
+ module Utils
3
+ class << self
4
+ def extract_options!(args)
5
+ args.last.is_a?(::Hash) ? args.pop : {}
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Rlyeh
2
+ VERSION = "0.0.1"
3
+ end
data/lib/rlyeh.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'eventmachine'
2
+
3
+ module Rlyeh
4
+ autoload :VERSION, 'rlyeh/version'
5
+
6
+ autoload :Server, 'rlyeh/server'
7
+ autoload :Connection, 'rlyeh/connection'
8
+ autoload :Session, 'rlyeh/session'
9
+ autoload :Environment, 'rlyeh/environment'
10
+ autoload :Base, 'rlyeh/base'
11
+
12
+ autoload :Dispatcher, 'rlyeh/dispatcher'
13
+ autoload :Filter, 'rlyeh/filter'
14
+
15
+ require 'rlyeh/runner'
16
+ include Rlyeh::Runner
17
+ end
data/rlyeh.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rlyeh/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["mashiro"]
6
+ gem.email = ["mail@mashiro.org"]
7
+ gem.description = %q{Welcome to the deep sea}
8
+ gem.summary = %q{IRC gateway server framework}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "rlyeh"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Rlyeh::VERSION
17
+
18
+ gem.add_dependency 'ircp'
19
+ gem.add_dependency 'eventmachine'
20
+ gem.add_development_dependency 'rake'
21
+ gem.add_development_dependency 'rspec'
22
+ end
@@ -0,0 +1 @@
1
+ require 'spec_helper'
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'ircp'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rlyeh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - mashiro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-10 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ircp
16
+ requirement: &14960720 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *14960720
25
+ - !ruby/object:Gem::Dependency
26
+ name: eventmachine
27
+ requirement: &14960300 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *14960300
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &14959880 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *14959880
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &15007960 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *15007960
58
+ description: Welcome to the deep sea
59
+ email:
60
+ - mail@mashiro.org
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - .rspec
67
+ - Gemfile
68
+ - LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - example/middleware.rb
72
+ - example/simple.rb
73
+ - lib/rlyeh.rb
74
+ - lib/rlyeh/base.rb
75
+ - lib/rlyeh/connection.rb
76
+ - lib/rlyeh/dispatcher.rb
77
+ - lib/rlyeh/environment.rb
78
+ - lib/rlyeh/filter.rb
79
+ - lib/rlyeh/middleware/builder.rb
80
+ - lib/rlyeh/middleware/typablemap.rb
81
+ - lib/rlyeh/runner.rb
82
+ - lib/rlyeh/server.rb
83
+ - lib/rlyeh/session.rb
84
+ - lib/rlyeh/utils.rb
85
+ - lib/rlyeh/version.rb
86
+ - rlyeh.gemspec
87
+ - spec/rlyeh/server_spec.rb
88
+ - spec/spec_helper.rb
89
+ homepage: ''
90
+ licenses: []
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 1.8.10
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: IRC gateway server framework
113
+ test_files: []