balotelli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 027c995c67a45827bb5fb5731af28403436b9f5e
4
+ data.tar.gz: 53c56b031e08f5ce6c2dbd263483b7abc69b5878
5
+ SHA512:
6
+ metadata.gz: 4e351562adaa6329654db9a343873a0ec729681c798139bfe3bf85eec150986fcc4444103efe71099159b62c01690195dde6477a78bf25bed5332909df6406d0
7
+ data.tar.gz: 748bc1811d9fee418dd31c965e4180bed4d0da28dfd1df7c986fc8adc0529d91697f0802021c675cb74820409f45b73911bea3f0152162943bbf69119653a4a0
data/.codeclimate.yml ADDED
@@ -0,0 +1,4 @@
1
+ languages:
2
+ ruby: true
3
+ exclude_paths:
4
+ "example.rb"
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *logs.txt
2
+ *.log
3
+ tmp
4
+ *.gem
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ - 2.1
5
+ - 2.0
6
+ - jruby-9.0.0.0
7
+ - rbx
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'minitest', '~> 5.8.0'
5
+ gem 'rake', '~> 10.4.2'
6
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,13 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ minitest (5.8.0)
5
+ rake (10.4.2)
6
+
7
+ PLATFORMS
8
+ java
9
+ ruby
10
+
11
+ DEPENDENCIES
12
+ minitest (~> 5.8.0)
13
+ rake (~> 10.4.2)
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # Balotelli [![Build Status](https://travis-ci.org/mhib/balotelli.svg)](https://travis-ci.org/mhib/balotelli)
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "rake/testtask"
2
+ Rake::TestTask.new do |t|
3
+ t.libs.push "test"
4
+ t.test_files = Dir["test/**/*_test.rb"]
5
+ end
6
+
7
+ task :default => :test
data/balotelli.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'balotelli/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "balotelli"
7
+ spec.version = Balotelli::VERSION
8
+ spec.authors = ["Marcin Henryk Bartkowiak"]
9
+ spec.email = ["mhbartkowiak@gmail.com"]
10
+ spec.summary = "Simple IRC bot framework"
11
+ spec.description = ""
12
+ spec.homepage = "https://github.com/mhib/balotelli"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.files.reject! { |file| file.include? 'examples/' }
17
+ #spec.executables = ['path']
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake", '~> 10.4.2'
23
+ spec.add_development_dependency "minitest", '~> 5.8.0'
24
+ end
@@ -0,0 +1,15 @@
1
+ require 'balotelli/base'
2
+
3
+ def Balotelli(server, name, pass, channels, log = false)
4
+ Class.new(Balotelli::Base) do
5
+ Balotelli::Module.constants.each do |c|
6
+ if c != :Base && (m = Balotelli::Module.const_get(c)).is_a?(Module)
7
+ register(m)
8
+ end
9
+ end
10
+ include Balotelli::Core::IrcLogger.new('.', 'logs.log', channels) if log
11
+ end.tap do |c|
12
+ c.configure(*Balotelli::Config.build(server, name, pass))
13
+ c.connect { channels.each(&method(:join)) }
14
+ end
15
+ end
@@ -0,0 +1,155 @@
1
+ require 'balotelli/core/irc'
2
+ require 'balotelli/core/router'
3
+ require 'balotelli/core/priv_msg'
4
+ require 'balotelli/core/join'
5
+ require 'balotelli/core/kick'
6
+ require 'balotelli/core/irc_logger'
7
+ require 'balotelli/core/utils'
8
+ require 'balotelli/config'
9
+
10
+ module Balotelli
11
+ class Base
12
+ def initialize(str, route, block, message, command)
13
+ @str = str
14
+ @message = message
15
+ @block = block
16
+ @route = route
17
+ @command = command
18
+ @matchdata = @command.match(@route)
19
+ end
20
+
21
+ def execute
22
+ instance_exec(@message, @matchdata, &@block)
23
+ end
24
+ private :execute
25
+
26
+ def out(message_string, destination = nil)
27
+ self.class.privmsg((destination || @message.responder), message_string)
28
+ end
29
+
30
+ def kick(params)
31
+ Core::Kick.new(params, self.class).execute!
32
+ end
33
+
34
+ def get_user_list(channel)
35
+ self.class.instance_variable_set(:@to_process, :user_list)
36
+ self.class.names(channel)
37
+ sleep 0.05 while __TO_PROCESS__
38
+ __CACHE__[:user_list][channel]
39
+ end
40
+
41
+ def method_missing(method, *args, **params, &block)
42
+ if method =~ /__([[[:upper:]]_]+)__/
43
+ self.class.instance_variable_get("@#{$1}".downcase)
44
+ else
45
+ super
46
+ end
47
+ end
48
+
49
+ class << self
50
+ include Balotelli::Core::IRC
51
+ include Balotelli::Core::Router
52
+
53
+ def setup
54
+ setup_router
55
+
56
+ @modules = {}
57
+ @cache = Hash.new { |hash, key| hash[key] = {} }
58
+ end
59
+
60
+ def inherited(subclass)
61
+ super
62
+
63
+ subclass.setup
64
+ end
65
+
66
+ def register(mod, namespace = nil)
67
+ if namespace
68
+ mod.instance_variable_set(:@commands_namespace, namespace.intern)
69
+ mod.instance_exec(namespace) do |n|
70
+ define_method(:commands_namespace) { n.intern }
71
+ end
72
+ end
73
+ @modules[mod.commands_namespace] ||= mod
74
+ @cache[:modules] = Hash[@modules.map { |k, v| [k.to_s, v] }]
75
+ end
76
+
77
+ def register_special(mod)
78
+ @routes.merge!(mod.instance_variable_get(:@routes))
79
+ end
80
+
81
+ def mod_match(str, priv = false)
82
+ if str =~ /\A[^a-zA-Z0-9\s]?(\S+) ?(.*)/
83
+ if (mod = @cache[:modules][$1.downcase])
84
+ mod.match($2, priv)
85
+ end
86
+ elsif str == :join
87
+ match = nil
88
+ @modules.each do |_, m|
89
+ if (match = m.match(:join))
90
+ break(match)
91
+ end
92
+ end
93
+ match
94
+ end
95
+ end
96
+
97
+ def run
98
+ @to_process = false
99
+ while (str = sgets)
100
+ process(str)
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def process(str)
107
+ if str =~ /\APING (.*)\z/
108
+ pong $1
109
+ elsif @on_connect && str =~ /End of \/MOTD command/i
110
+ instance_eval(&remove_instance_variable(:@on_connect))
111
+ elsif !(str =~ /(JOIN\s|PRIVMSG\s)/)
112
+ process_table(str)
113
+ else
114
+ Thread.new { process_message(str) }
115
+ end
116
+ end
117
+
118
+ def process_message(str)
119
+ if str =~ Core::Utils::PRIV_MSG_REGEX
120
+ metadata = { user: $1, channel: $2, message: $3 }
121
+ priv = !($2 =~ /#.+/)
122
+ if (match = match(metadata[:message], priv)) ||
123
+ (match = mod_match(metadata[:message], priv))
124
+ new_response(str, match, metadata, Core::PrivMsg, priv)
125
+ end
126
+ elsif str =~ Core::Utils::JOIN_REGEX
127
+ metadata = { user: $1, channel: $2 }
128
+ if (match = match(:join)) || (match = mod_match(:join))
129
+ new_response(str, match, metadata, Core::Join)
130
+ end
131
+ end
132
+ end
133
+
134
+ def new_response(str, match, metadata, klass, priv = nil)
135
+ route, block, mod, command = match.flatten
136
+ responder = klass.new(*[metadata, priv].compact)
137
+ new(str, route, block, responder, command).tap do |response|
138
+ response.extend(mod) if mod.class.to_s == 'Module'
139
+ end.send(:execute)
140
+ end
141
+
142
+ def process_table(string)
143
+ if @to_process && string =~ (regex = Core::Utils.table_regex(@nick))
144
+ metadata = { channel: $2, message: $3 }
145
+ users = @cache[@to_process][metadata[:channel]] = metadata[:message]
146
+ until (str = sgets) =~ /End of \/NAME/i
147
+ users << " #{str.match(regex).captures.first}"
148
+ end
149
+ @cache[@to_process][metadata[:channel]] = users.split(' ')
150
+ @to_process = false
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,15 @@
1
+ module Balotelli
2
+ module Config
3
+ FREENODE = ['chat.freenode.net', 6667]
4
+ QUAKENET = ['irc.quakenet.org', 6667]
5
+ RIZON = ['irc.rizon.net', 6667]
6
+ PIRC = ['irc.pirc.pl', 6667]
7
+ MOZNET = ['irc.mozilla.org', 6667]
8
+
9
+ module_function
10
+
11
+ def build(server, name = ('balotelli%03d' % rand(1000)), pass = nil)
12
+ const_get(server.upcase).dup.push(name, pass)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,62 @@
1
+ require 'socket'
2
+
3
+ module Balotelli
4
+ module Core
5
+ module IRC
6
+ def configure(host, port, nick, pass = nil)
7
+ @host = host
8
+ @port = port
9
+ @nick = nick
10
+ @pass = pass
11
+
12
+ @socket = nil
13
+ @mutex = Mutex.new
14
+ end
15
+
16
+ def connect(&block)
17
+ @socket = TCPSocket.new(@host, @port)
18
+
19
+ sputs("PASS #{@pass}") if @pass
20
+ sputs("NICK #{@nick}")
21
+ sputs("USER #{@nick} 0 * :#{@nick}")
22
+
23
+ if block_given?
24
+ instance_variable_set(:@on_connect, block)
25
+ end
26
+ end
27
+
28
+ def sgets
29
+ str = @socket.gets
30
+ str.chomp! unless str.nil?
31
+
32
+ puts '<< ' + str.inspect
33
+
34
+ str
35
+ end
36
+
37
+ def sputs(str)
38
+ @mutex.synchronize do
39
+ puts '>> ' + str.inspect
40
+
41
+ @socket.puts(str)
42
+ end
43
+ end
44
+
45
+ def pong(message)
46
+ sputs("PONG #{message}")
47
+ end
48
+
49
+ def join(channel, password = nil)
50
+ sputs("JOIN #{channel} #{password}")
51
+ end
52
+
53
+ def privmsg(channel, message)
54
+ sputs("PRIVMSG #{channel} :#{message}")
55
+ end
56
+
57
+ def names(channel)
58
+ sputs("NAMES #{channel}")
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,94 @@
1
+ require 'logger'
2
+ require 'fileutils'
3
+ require 'set'
4
+ module Balotelli
5
+ module Core
6
+ class IrcLogger < Module
7
+ LOG_FORMAT = proc do |_severity, datetime, _progname, msg|
8
+ "#{datetime.utc}: #{msg}\n"
9
+ end
10
+
11
+ attr_reader :log_file, :dir, :channels, :channels_logs
12
+
13
+ def initialize(dir = '', log_name = 'logs.log', channels = [])
14
+ @dir = dir
15
+ check_dir
16
+ @log_file = new_logger(log_name)
17
+ @channels = Set.new channels
18
+ @channels_logs = @channels.each_with_object({}) do |c, o|
19
+ o[c] = new_logger(channel_log_file(c))
20
+ end
21
+ end
22
+
23
+ def included(des)
24
+ super
25
+
26
+ define_log_method
27
+
28
+ des.instance_variable_set(:@log_file, log_file)
29
+ des.instance_variable_set(:@logger, self)
30
+
31
+ class << des
32
+ alias_method :orig_sputs, :sputs
33
+ private :orig_sputs
34
+
35
+ def sputs(str)
36
+ orig_sputs(str)
37
+ to_log = ">>#{str.inspect}\n"
38
+ @log_file.info(to_log)
39
+ if str =~ /\A:?\S+ (#\S+) .*/
40
+ @logger.channel_log($1.downcase, to_log)
41
+ end
42
+ str
43
+ end
44
+
45
+ alias_method :orig_sgets, :sgets
46
+ private :orig_sgets
47
+
48
+ def sgets
49
+ str = orig_sgets
50
+ to_log = "<<#{str.inspect}\n"
51
+ @log_file.info(to_log)
52
+ if str =~ /\A:?\S+ \S+ (#\S+) .*/
53
+ @logger.channel_log($1.downcase, to_log)
54
+ end
55
+ str
56
+ end
57
+ end
58
+ end
59
+
60
+ def channel_log(channel, to_log)
61
+ if (logger = @channels_logs[channel])
62
+ logger.info to_log
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def define_log_method
69
+ define_method :log do |str|
70
+ log_string = "LOG: #{str.inspect}\n"
71
+ __LOG_FILE__.info log_string
72
+ puts log_string
73
+ end
74
+ end
75
+
76
+ def channel_log_file(channel)
77
+ "#{channel.tr('#', '')}_logs.log"
78
+ end
79
+
80
+ def new_logger(file_name)
81
+ Logger.new(File.join(dir, file_name), 0, 1.0 / 0)
82
+ .tap do |l|
83
+ l.formatter = LOG_FORMAT
84
+ end
85
+ end
86
+
87
+ def check_dir
88
+ unless File.file?(dir)
89
+ FileUtils.mkdir_p(dir)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,13 @@
1
+ module Balotelli
2
+ module Core
3
+ class Join
4
+ attr_reader :user, :channel, :user_nick, :responder
5
+ def initialize(metadata)
6
+ @user = metadata[:user]
7
+ @user_nick = Core::Utils.nick_from_user(@user)
8
+ @channel = metadata[:channel]
9
+ @responder = @channel
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module Balotelli
2
+ module Core
3
+ class Kick
4
+ attr_reader :who, :channel, :reason
5
+ def initialize(data, klass)
6
+ @who = data[:who]
7
+ @channel = data[:channel]
8
+ @reason = data[:reason].tr(' ', ' ') # space to nbsp
9
+ @klass = klass
10
+ end
11
+
12
+ def execute!
13
+ @klass.sputs("KICK #{channel} #{who} #{reason}")
14
+ end
15
+
16
+ alias_method :execute, :execute!
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ module Balotelli
2
+ module Core
3
+ class PrivMsg
4
+ attr_reader :user, :channel, :content, :user_nick, :responder
5
+ def initialize(metadata, privacy = false)
6
+ @user = metadata[:user]
7
+ @user_nick = @user.match(/\A(\S+)!.*/)[1]
8
+ @channel = metadata[:channel]
9
+ @content = metadata[:message]
10
+ if privacy
11
+ @responder = @user_nick
12
+ else
13
+ @responder = @channel
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ module Balotelli
2
+ module Core
3
+ module Router
4
+ def setup_router
5
+ @routes = {}
6
+ end
7
+
8
+ def on(route, option = {}, &block)
9
+ fail 'no block given' if block.nil?
10
+
11
+ if !option.key?(:private) || route == :join
12
+ option[:private] = false
13
+ end
14
+
15
+ if option[:private] == :both
16
+ on(route, option.clone.tap { |o| o[:private] = true }, &block)
17
+ on(route, option.clone.tap { |o| o[:private] = false }, &block)
18
+ return
19
+ end
20
+
21
+ @routes[route] ||= {}
22
+
23
+ if @routes[route][option[:private]] && !option[:force]
24
+ fail "Route #{route.inspect}, private: #{option[:private]} already exists"
25
+ end
26
+
27
+ @routes[route][option[:private]] = [block, self]
28
+ end
29
+
30
+ def match?(str, route)
31
+ case route
32
+ when Regexp
33
+ str =~ route
34
+ when String
35
+ str == route
36
+ when Symbol
37
+ str == route
38
+ end
39
+ end
40
+
41
+ def match(str, priv = false)
42
+ if m = @routes.detect { |k, v| match?(str, k) && v[priv] }
43
+ [m[0], m[1][priv], str]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,19 @@
1
+ module Balotelli
2
+ module Core
3
+ module Utils
4
+ NICK_REGEX = /\A(\S+)!.*/.freeze
5
+ PRIV_MSG_REGEX = /\A:?(\S+) PRIVMSG (\S+) :?(.*)/.freeze
6
+ JOIN_REGEX = /\A:?(\S+) JOIN (\S+)/.freeze
7
+
8
+ module_function
9
+
10
+ def nick_from_user(str)
11
+ str.match(NICK_REGEX)[1]
12
+ end
13
+
14
+ def table_regex(nick)
15
+ /\A:?(\S+) \d+ #{nick} \S (#\S+) :?(.*)/.freeze
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ require 'balotelli/core/router'
2
+
3
+ module Balotelli
4
+ module Module
5
+ module Base
6
+ include Balotelli::Core::Router
7
+
8
+ def setup
9
+ setup_router
10
+ end
11
+
12
+ class << self
13
+ def extended(mod)
14
+ super
15
+
16
+ mod.setup
17
+
18
+ mod.instance_eval do
19
+ def commands_namespace
20
+ @commands_namespace ||= name[/[^:]+$/].downcase.intern
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Balotelli
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/balotelli.rb ADDED
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ require 'balotelli/base'
3
+ require 'balotelli/balotelli_helper'
4
+ require 'balotelli/module/base'
5
+ require 'balotelli/version'
6
+ require 'thread'
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+ module Balotelli::Module::Asdf
3
+ extend Balotelli::Module::Base
4
+ end
5
+ module Balotelli::Module::Qwerty
6
+ extend Balotelli::Module::Base
7
+ end
8
+ class BalotelliHelperTest < Minitest::Test
9
+ def setup
10
+ @bot = Balotelli(:freenode, "test", nil, nil)
11
+ end
12
+ def test_that_it_creates_balotelli_class
13
+ assert(Balotelli::Base == @bot.superclass)
14
+ assert(@bot.instance_variable_get(:@nick) == "test")
15
+ end
16
+
17
+ def test_that_it_includes_modules
18
+ assert @bot.instance_variable_get(:@modules)[:qwerty] == Balotelli::Module::Qwerty
19
+ assert @bot.instance_variable_get(:@modules)[:asdf] == Balotelli::Module::Asdf
20
+ end
21
+ end
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+
3
+ class TestBot < Balotelli::Base
4
+ end
5
+
6
+ module Balotelli::Module::Asdf
7
+ extend Balotelli::Module::Base
8
+
9
+ on %r{yes}i do
10
+
11
+ end
12
+ end
13
+
14
+ module Balotelli::Module::Xyz
15
+ extend Balotelli::Module::Base
16
+
17
+ on %r{si}i do
18
+
19
+ end
20
+ end
21
+
22
+ module Balotelli::Module::SpecialOne
23
+ extend Balotelli::Module::Base
24
+ on "asdfg" do
25
+ puts "n"
26
+ end
27
+ end
28
+
29
+ class BaseTest < Minitest::Test
30
+ def test_it_sets_up
31
+ assert TestBot.instance_variable_get(:@routes)
32
+ assert TestBot.instance_variable_get(:@modules)
33
+ assert TestBot.instance_variable_get(:@cache)
34
+ end
35
+
36
+ def test_it_responds_to_run
37
+ assert TestBot.respond_to?(:run)
38
+ end
39
+
40
+ def test_it_registes_module
41
+ TestBot.register(Balotelli::Module::Asdf)
42
+ assert Balotelli::Module::Asdf.commands_namespace == :asdf
43
+ assert TestBot.instance_variable_get(:@modules)[:asdf] == Balotelli::Module::Asdf
44
+ TestBot.register(Balotelli::Module::Xyz, "hoh")
45
+ assert Balotelli::Module::Xyz.commands_namespace == :hoh
46
+ assert TestBot.instance_variable_get(:@modules)[:hoh] == Balotelli::Module::Xyz
47
+ end
48
+
49
+ def test_it_registers_special
50
+ TestBot.register_special(Balotelli::Module::SpecialOne)
51
+ assert TestBot.match("asdfg")
52
+ end
53
+
54
+ #def test_it_matches_module_routes
55
+ #TestBot.register(Balotelli::Module::Asdf)
56
+ #assert_equal TestBot.mod_match("asdf Yes, sir")[0], /yes/i
57
+ #TestBot.register(Balotelli::Module::Xyz, "hoh")
58
+ #assert_equal TestBot.mod_match("!hoh Si si")[0], /si/i
59
+ #end
60
+ end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ class ConfigTest < Minitest::Test
4
+
5
+ def test_it_builds_config
6
+ assert(
7
+ Balotelli::Config.build(:freenode, "test") ==
8
+ ['chat.freenode.net', 6667, "test", nil]
9
+ )
10
+ end
11
+
12
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ class Bot
4
+ include Balotelli::Core::IRC
5
+
6
+ def initialize(*args)
7
+ configure(*args)
8
+ end
9
+ end
10
+
11
+ class IRCTest < Minitest::Test
12
+ def setup
13
+ @bot = Bot.new(*Balotelli::Config.build(:freenode, "test"))
14
+ end
15
+
16
+ def test_it_responds_to_required_messages
17
+ assert @bot.respond_to?(:connect)
18
+ assert @bot.respond_to?(:sgets)
19
+ assert @bot.respond_to?(:sputs)
20
+ assert @bot.respond_to?(:pong)
21
+ assert @bot.respond_to?(:join)
22
+ assert @bot.respond_to?(:privmsg)
23
+ assert @bot.respond_to?(:names)
24
+ end
25
+
26
+ end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class ToRoute
4
+ include Balotelli::Core::Router
5
+
6
+ def initialize
7
+ setup_router
8
+ end
9
+ end
10
+
11
+ class RouterTest < Minitest::Test
12
+ def setup
13
+ @route = ToRoute.new
14
+ end
15
+
16
+ def test_it_has_routes
17
+ assert @route.instance_variable_get(:@routes)
18
+ end
19
+
20
+ def test_it_mathes_routes
21
+ lam = -> { puts 'kk' }
22
+ @route.on %r{ono}i, private: true, &lam
23
+ assert @route.match('onOmatopeja', true) == [%r{ono}i, [lam, @route], 'onOmatopeja']
24
+ refute @route.match('onOmatopeja', false)
25
+ @route.on 'asdf', &lam
26
+ assert @route.match('asdf')
27
+ refute @route.match('asdf', true)
28
+ @route.on %r{hi}i, private: :both, &lam
29
+ assert @route.match('Hi')
30
+ assert @route.match('hI', true)
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ unless Object.const_defined? 'Balotelli'
2
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
3
+ require 'balotelli'
4
+ end
5
+
6
+
7
+ alias :test_puts :puts
8
+ def puts(*args); end
9
+
10
+ require 'minitest/autorun'
11
+ require 'minitest/pride'
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: balotelli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marcin Henryk Bartkowiak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 10.4.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 10.4.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 5.8.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 5.8.0
55
+ description: ''
56
+ email:
57
+ - mhbartkowiak@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".codeclimate.yml"
63
+ - ".gitignore"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - README.md
68
+ - Rakefile
69
+ - balotelli.gemspec
70
+ - lib/balotelli.rb
71
+ - lib/balotelli/balotelli_helper.rb
72
+ - lib/balotelli/base.rb
73
+ - lib/balotelli/config.rb
74
+ - lib/balotelli/core/irc.rb
75
+ - lib/balotelli/core/irc_logger.rb
76
+ - lib/balotelli/core/join.rb
77
+ - lib/balotelli/core/kick.rb
78
+ - lib/balotelli/core/priv_msg.rb
79
+ - lib/balotelli/core/router.rb
80
+ - lib/balotelli/core/utils.rb
81
+ - lib/balotelli/module/base.rb
82
+ - lib/balotelli/version.rb
83
+ - test/lib/balotelli/balotelli_helper_test.rb
84
+ - test/lib/balotelli/base_test.rb
85
+ - test/lib/balotelli/config_test.rb
86
+ - test/lib/balotelli/core/irc_test.rb
87
+ - test/lib/balotelli/core/router_test.rb
88
+ - test/test_helper.rb
89
+ homepage: https://github.com/mhib/balotelli
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.4.8
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Simple IRC bot framework
113
+ test_files:
114
+ - test/lib/balotelli/balotelli_helper_test.rb
115
+ - test/lib/balotelli/base_test.rb
116
+ - test/lib/balotelli/config_test.rb
117
+ - test/lib/balotelli/core/irc_test.rb
118
+ - test/lib/balotelli/core/router_test.rb
119
+ - test/test_helper.rb