balotelli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +4 -0
- data/.gitignore +4 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +13 -0
- data/README.md +1 -0
- data/Rakefile +7 -0
- data/balotelli.gemspec +24 -0
- data/lib/balotelli/balotelli_helper.rb +15 -0
- data/lib/balotelli/base.rb +155 -0
- data/lib/balotelli/config.rb +15 -0
- data/lib/balotelli/core/irc.rb +62 -0
- data/lib/balotelli/core/irc_logger.rb +94 -0
- data/lib/balotelli/core/join.rb +13 -0
- data/lib/balotelli/core/kick.rb +19 -0
- data/lib/balotelli/core/priv_msg.rb +18 -0
- data/lib/balotelli/core/router.rb +48 -0
- data/lib/balotelli/core/utils.rb +19 -0
- data/lib/balotelli/module/base.rb +27 -0
- data/lib/balotelli/version.rb +3 -0
- data/lib/balotelli.rb +6 -0
- data/test/lib/balotelli/balotelli_helper_test.rb +21 -0
- data/test/lib/balotelli/base_test.rb +60 -0
- data/test/lib/balotelli/config_test.rb +12 -0
- data/test/lib/balotelli/core/irc_test.rb +26 -0
- data/test/lib/balotelli/core/router_test.rb +32 -0
- data/test/test_helper.rb +11 -0
- metadata +119 -0
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
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
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
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
|
data/lib/balotelli.rb
ADDED
@@ -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,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
|
data/test/test_helper.rb
ADDED
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
|