unibanner 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.
- checksums.yaml +7 -0
- data/.bundle/config +2 -0
- data/.gitignore +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +57 -0
- data/bin/unibanner +5 -0
- data/lib/unibanner/bot_class.rb +163 -0
- data/lib/unibanner/functions.rb +22 -0
- data/lib/unibanner/logger.rb +63 -0
- data/lib/unibanner/version.rb +3 -0
- data/lib/unibanner.rb +3 -0
- data/unibanner.gemspec +48 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a987a90282931e2839767ae60f520bcca07c7635f3e66f2481c4e2ce8bae9f59
|
4
|
+
data.tar.gz: 7804309c159b11547855b6cbc3e1083b05c0e6ca1a2914344079c58c0d99f176
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d6e62892ca52da8cca98641430088d06233fc6b9e4739f6dfbff3686a9c11ef9e4404dea3f759f72fefc7be01cfc6a34a1eddf09255086c6a04e60fb7cd467a2
|
7
|
+
data.tar.gz: 7d32bb8ce10aa2351bf336407030e2c9734624eba46aac6f2bca675b36cb7b6d0ef884cca002d2783ba96f3d6916abff4c3093745ba0aaaf7571de36060e1c57
|
data/.bundle/config
ADDED
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
unibanner (0.0.0)
|
5
|
+
irc_socket (~> 1.0, >= 1)
|
6
|
+
logging (~> 2.2.2)
|
7
|
+
paint (~> 2.0.1)
|
8
|
+
parseconfig (~> 1.0.8)
|
9
|
+
pry
|
10
|
+
unirest (~> 1.1.2)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
addressable (2.3.8)
|
16
|
+
ansi (1.5.0)
|
17
|
+
builder (3.2.3)
|
18
|
+
coderay (1.1.2)
|
19
|
+
irc_socket (1.0.7)
|
20
|
+
json (1.8.6)
|
21
|
+
little-plugger (1.1.4)
|
22
|
+
logging (2.2.2)
|
23
|
+
little-plugger (~> 1.1)
|
24
|
+
multi_json (~> 1.10)
|
25
|
+
method_source (0.9.1)
|
26
|
+
mime-types (1.25.1)
|
27
|
+
minitest (5.11.3)
|
28
|
+
minitest-reporters (1.3.5)
|
29
|
+
ansi
|
30
|
+
builder
|
31
|
+
minitest (>= 5.0)
|
32
|
+
ruby-progressbar
|
33
|
+
multi_json (1.13.1)
|
34
|
+
paint (2.0.1)
|
35
|
+
parseconfig (1.0.8)
|
36
|
+
pry (0.12.0)
|
37
|
+
coderay (~> 1.1.0)
|
38
|
+
method_source (~> 0.9.0)
|
39
|
+
rest-client (1.6.9)
|
40
|
+
mime-types (~> 1.16)
|
41
|
+
ruby-progressbar (1.10.0)
|
42
|
+
unirest (1.1.2)
|
43
|
+
addressable (~> 2.3.5)
|
44
|
+
json (~> 1.8.1)
|
45
|
+
rest-client (~> 1.6.7)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
bundler (~> 1.16)
|
52
|
+
minitest (~> 5)
|
53
|
+
minitest-reporters (~> 1.1)
|
54
|
+
unibanner!
|
55
|
+
|
56
|
+
BUNDLED WITH
|
57
|
+
1.16.4
|
data/bin/unibanner
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require "logging"
|
2
|
+
require "irc_socket"
|
3
|
+
require "yaml"
|
4
|
+
require "unibanner/logger"
|
5
|
+
|
6
|
+
module Unibanner
|
7
|
+
# class containing all the bot instances and methods to act on them.
|
8
|
+
class Bots
|
9
|
+
@@bots = {}
|
10
|
+
@@threads = []
|
11
|
+
Unibanner::Logger.new(self)
|
12
|
+
@@log = Unibanner::Logger[self]
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@log = @@log
|
16
|
+
end
|
17
|
+
|
18
|
+
# Find all bots existing in configuration
|
19
|
+
def self.find_bots
|
20
|
+
cfg = YAML::load_file(Pathname(Dir.home).join(".unibanner").join("config"))
|
21
|
+
cfg["networks"].each do |network, hsh|
|
22
|
+
@@log.debug "bot = Unibanner::Bot.new(#{network}, #{hsh})"
|
23
|
+
bot = Unibanner::Bot.new(network, hsh)
|
24
|
+
@@log.debug "Unibanner::Bots.add_bot(#{bot})"
|
25
|
+
Unibanner::Bots.add_bot(bot)
|
26
|
+
@@log.debug "Unibanner::Bot.find_bots ... done."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add a bot into the Bots list
|
31
|
+
# @param [Unibanner::Bot] bot Unibanner::Bot object
|
32
|
+
def self.add_bot(bot)
|
33
|
+
@@bots[bot.network] = bot
|
34
|
+
end
|
35
|
+
|
36
|
+
# return list of bots
|
37
|
+
# @return [Array] bots list
|
38
|
+
def self.bots
|
39
|
+
@@bots
|
40
|
+
end
|
41
|
+
|
42
|
+
# Start all bots found via Bots#find_bots
|
43
|
+
def self.start
|
44
|
+
@@bots.each do |network, bot|
|
45
|
+
thr = Thread.new do
|
46
|
+
Thread.current.name = "#{bot.nick}@#{network}[#{bot.server}:#{bot.ssl == true ? '+' : ''}#{bot.port}]"
|
47
|
+
bot.start
|
48
|
+
end
|
49
|
+
@@threads << thr
|
50
|
+
@@threads.each(&:join)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Cause all bots to die/quit
|
55
|
+
# @overload self.die(msg)
|
56
|
+
# Quits all bots with 'msg'
|
57
|
+
# and all threads are exited.
|
58
|
+
# @param [String] msg quit msg to use
|
59
|
+
# @overload self.die(msg, threads)
|
60
|
+
# Quits all bots with 'msg'
|
61
|
+
# and threads determines if threads are killed
|
62
|
+
# @param [String] msg quit msg to use
|
63
|
+
# @param [Boolean] threads whether to kill/exit threads
|
64
|
+
def self.die(msg, threads = true)
|
65
|
+
@@bots.each do |network, bot|
|
66
|
+
@@log.info "Quitting off #{network}."
|
67
|
+
bot.quit(msg)
|
68
|
+
end
|
69
|
+
if threads
|
70
|
+
@@threads.each do |thr|
|
71
|
+
@@log.info "Exiting from '#{thr.name}' thread."
|
72
|
+
thr.exit
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class Bot
|
79
|
+
attr_accessor :irc, :sock
|
80
|
+
attr_reader :server, :port, :ssl, :network, :local_host, :nick, :geckos, :prefix, :oper_name
|
81
|
+
attr :log, :log_level
|
82
|
+
|
83
|
+
# Create a new bot
|
84
|
+
# @param [String] network The network name
|
85
|
+
# @param [Hash] hsh hash full of network options
|
86
|
+
def initialize(network, hsh)
|
87
|
+
@network = group
|
88
|
+
@server = hsh["server"] # network::server: irc.server.tld
|
89
|
+
@ssl = hsh["ssl"] # network::ssl: true/false
|
90
|
+
@port = hsh["port"] # network::port: 0000
|
91
|
+
@local_host = hsh["local_host"] # network::local_host: 0.0.0.0
|
92
|
+
@nick = hsh["nick"] # network::nick: nickname
|
93
|
+
@geckos = hsh["geckos"] # network::geckos: Real Name
|
94
|
+
@prefix = hsh["prefix"] # network::prefix: !
|
95
|
+
@oper_name = hsh["oper_name"] # network::oper_name: opername
|
96
|
+
@oper_pass = hsh["oper_pass"] # network::oper_pass: PASSWORD
|
97
|
+
@channels = hsh["channels"] # network::channels: [channel1,channel2]
|
98
|
+
|
99
|
+
Unibanner::Logger.new(self)
|
100
|
+
@log = Unibanner::Logger[self]
|
101
|
+
@log_level = hsh["log_level"]
|
102
|
+
@log.level = @log_level
|
103
|
+
@irc = IRCSocket.new(@server, @port, @ssl)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Allow Bot.quit(msg) to actually cause the irc connection to /quit
|
107
|
+
# @param [String] msg Quit msg to use
|
108
|
+
def quit(msg)
|
109
|
+
@irc.quit(msg)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Start the IRC connection
|
113
|
+
# @return [nil]
|
114
|
+
def start
|
115
|
+
@irc.connect
|
116
|
+
if @irc.connected?
|
117
|
+
@irc.nick "#{@nick}"
|
118
|
+
@irc.user "#{@nick}", 0, "*", "#{@geckos}"
|
119
|
+
while line = irc.read
|
120
|
+
@log.incoming line
|
121
|
+
# Join Channels after MOTD
|
122
|
+
if line.split[1] == "376"
|
123
|
+
Thread.new {
|
124
|
+
@irc.oper @oper_name, @oper_pass
|
125
|
+
@channels.each do |channel|
|
126
|
+
@irc.join channel
|
127
|
+
end
|
128
|
+
}
|
129
|
+
end
|
130
|
+
# 0 1 2 ------------------3-------------------
|
131
|
+
# :kojo.electrocode.net 340 unibanner :ephemer0l_=+~ephemer0l_@196.27.72.156
|
132
|
+
|
133
|
+
if line.split[1] == "340"
|
134
|
+
user_ip = line.split[3].gsub(/:.*@(.*)/, '\1')
|
135
|
+
@log.info "Got #{user_ip} back from /USERIP. Submitting to blacklist."
|
136
|
+
#reply = SendToBlacklist(user_ip)
|
137
|
+
@log.debug "send2BL(#{user_ip}) returned '#{reply}'"
|
138
|
+
#ircZLine(user_ip)
|
139
|
+
end
|
140
|
+
if line.split[1] == '433'
|
141
|
+
@log.error "#{self.network}: 433, Nickname in use, can't connect"
|
142
|
+
::Unibanner::Bots.die("Nickname in use, Can't connect")
|
143
|
+
end
|
144
|
+
# unicode characters used by the spammers
|
145
|
+
# spam_pattern = /(\uFE13|\u04BB|\u0501|\u0D20|\u222A|\u217E|\u1EFF){1,}/
|
146
|
+
spam_pattern = Regexp.new('(\ufe68|\u205f|\u0422|\u2009|\u04bb|\u1952|\u217c|\u2004|\u217f|\u1d20|\u03bf|\u0456|\u217d|\u2c9f|\u2024|\u0435|\uff03|\uff0f|\u03f3|\ufe57|\u2216|\u2170|\u1959|\u13df|\u0251|\u222a|\u0441|\u0430|\u2001|\u200a|\u217e|\u0443|\u2005|\u2002|\u0455|\u2000|\u2215|\u2044|\u03f2|\u043e|\u0d20|\u0261|\u1971|\u0501|\u2007|\u0392|\uff0e|\u13a1|\u0458|\u202f|\ufe55|\u15b4|\u1d21|\u2006|\u2cad|\u0440|\u2574|\u16ec|\u13da|\u13a2)')
|
147
|
+
# message pattern
|
148
|
+
nick_pattern = Regexp.new(':(?<nick>.*)!(?<user>.+)\@(?<host>\S+) PRIVMSG (?<channel>\#\S+) :(?<msg>.*)')
|
149
|
+
# Run a /USERIP on the nick that matched the spam text
|
150
|
+
if line =~ nick_pattern
|
151
|
+
@log.info "matched on nick pattern"
|
152
|
+
irc_msg = Regexp.last_match
|
153
|
+
if irc_msg["msg"] =~ spam_pattern
|
154
|
+
@log.info "matched on spam pattern"
|
155
|
+
@irc.userip(irc_msg["nick"])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
return nil
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Unibanner
|
2
|
+
# A group of functions to help with unibanner
|
3
|
+
# @attr [String] key DNSBL.im key file contents
|
4
|
+
class Functions
|
5
|
+
# Send an IP to the blacklist
|
6
|
+
# A bit longer description.
|
7
|
+
#
|
8
|
+
# @param [String] ip IP sending to blacklist
|
9
|
+
# @returns [True,False]
|
10
|
+
def send2BL(ip)
|
11
|
+
url = 'https://api.dnsbl.im/import'
|
12
|
+
payload = {
|
13
|
+
key: File.open('/home/ken/.dnsblim-key', 'r').read.chomp!,
|
14
|
+
addresses: [
|
15
|
+
{type: '5,6', ip: ip, reason: 'fngate and/or unicode spam'}
|
16
|
+
]
|
17
|
+
}
|
18
|
+
r = Unirest.post(url, parameters: payload.to_json)
|
19
|
+
r.body
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "logging"
|
2
|
+
require 'paint'
|
3
|
+
module Logging
|
4
|
+
class Logger
|
5
|
+
|
6
|
+
def incoming?( ); true; end
|
7
|
+
def incoming( data = nil )
|
8
|
+
data = yield if block_given?
|
9
|
+
log_event(::Logging::LogEvent.new(@name, 1, " #{Paint['->', 'green']} #{data}", @caller_tracing))
|
10
|
+
true
|
11
|
+
end
|
12
|
+
def outgoing?( ); true; end
|
13
|
+
def outgoing( data = nil )
|
14
|
+
data = yield if block_given?
|
15
|
+
log_event(::Logging::LogEvent.new(@name, 1, " #{Paint['<-', 'red']} #{data}", @caller_tracing))
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
Logging.color_scheme("bright",
|
21
|
+
:levels => {
|
22
|
+
:info => :green,
|
23
|
+
:warn => :yellow,
|
24
|
+
:error => :red,
|
25
|
+
:fatal => [:white, :on_red],
|
26
|
+
},
|
27
|
+
:date => :blue,
|
28
|
+
:logger => :cyan,
|
29
|
+
:message => :white)
|
30
|
+
|
31
|
+
Logging.appenders.stdout(
|
32
|
+
"stdout",
|
33
|
+
:layout => Logging.layouts.pattern(
|
34
|
+
:pattern => '[%d] %-5l %c: %m\n',
|
35
|
+
:color_scheme => "bright",
|
36
|
+
),
|
37
|
+
)
|
38
|
+
Logging.logger.root.appenders = Logging.appenders.stdout
|
39
|
+
Logging.logger.root.level = :info
|
40
|
+
|
41
|
+
module Unibanner
|
42
|
+
LOGGER = Logging.logger[self]
|
43
|
+
class Logger
|
44
|
+
@@loggers = {}
|
45
|
+
@@loggers['Unibanner'] = Logging.logger['Unibanner']
|
46
|
+
@@loggers[self] = Logging.logger[self]
|
47
|
+
@@instance = Logging::Repository.instance
|
48
|
+
|
49
|
+
def initialize(name)
|
50
|
+
@@loggers[name] = Logging.logger[name]
|
51
|
+
end
|
52
|
+
|
53
|
+
def update
|
54
|
+
@@instance = Logging::Repository.instance
|
55
|
+
end
|
56
|
+
def loggers
|
57
|
+
@@loggers
|
58
|
+
end
|
59
|
+
def self.[](key)
|
60
|
+
@@loggers[key]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/unibanner.rb
ADDED
data/unibanner.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'unibanner/version'
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'unibanner'
|
6
|
+
s.version = Unibanner::VERSION
|
7
|
+
s.authors = ['Ken Spencer']
|
8
|
+
s.email = 'me@iotaspencer.me'
|
9
|
+
s.summary = 'A simpleish bot made to ban and blacklist unicode spamming bots.'
|
10
|
+
s.description = 'A simple bot made to ban and blacklist unicode spamming bots on IRC. Use only in channels where such unicode is not commonplace.'
|
11
|
+
s.homepage = 'https://iotaspencer.me/projects/unibanner'
|
12
|
+
s.license = 'MIT'
|
13
|
+
|
14
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
15
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
16
|
+
if s.respond_to?(:metadata)
|
17
|
+
s.metadata = {
|
18
|
+
'github_repo' => 'https://git.lasershark.army/IotaSpencer/unibanner',
|
19
|
+
'bug_tracker_uri' => 'https://git.lasershark.army/IotaSpencer/unibanner/issues',
|
20
|
+
# 'documentation_uri' => 'https://rubydoc.info/gems/unibanner',
|
21
|
+
'homepage_uri' => 'https://iotaspencer.me/projects/unibanner',
|
22
|
+
'source_code_uri' => 'https://git.lasershark.army/IotaSpencer/unibanner',
|
23
|
+
'wiki_uri' => 'https://git.lasershark.army/IotaSpencer/unibanner/wiki'
|
24
|
+
}
|
25
|
+
else
|
26
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
27
|
+
'public gem pushes.'
|
28
|
+
end
|
29
|
+
|
30
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
31
|
+
f.match(%r{^(test)/})
|
32
|
+
end
|
33
|
+
s.required_ruby_version = '~> 2'
|
34
|
+
s.bindir = 'bin'
|
35
|
+
s.executables << 'unibanner'
|
36
|
+
s.require_paths = ['lib']
|
37
|
+
|
38
|
+
s.add_runtime_dependency 'irc_socket', '~> 1.0', '>= 1'
|
39
|
+
s.add_runtime_dependency 'logging', '~> 2.2.2'
|
40
|
+
s.add_runtime_dependency 'paint', '~> 2.0.1'
|
41
|
+
s.add_runtime_dependency 'parseconfig', '~> 1.0.8'
|
42
|
+
s.add_runtime_dependency 'pry'
|
43
|
+
s.add_runtime_dependency 'unirest', '~> 1.1.2'
|
44
|
+
s.add_development_dependency 'bundler', '~> 1.16'
|
45
|
+
s.add_development_dependency 'minitest', '~> 5'
|
46
|
+
s.add_development_dependency 'minitest-reporters', '~> 1.1'
|
47
|
+
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: unibanner
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ken Spencer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: irc_socket
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: logging
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 2.2.2
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.2.2
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: paint
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.0.1
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 2.0.1
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: parseconfig
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.0.8
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.0.8
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: pry
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: unirest
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 1.1.2
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.1.2
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: bundler
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.16'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '1.16'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: minitest
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '5'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '5'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: minitest-reporters
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '1.1'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '1.1'
|
145
|
+
description: A simple bot made to ban and blacklist unicode spamming bots on IRC.
|
146
|
+
Use only in channels where such unicode is not commonplace.
|
147
|
+
email: me@iotaspencer.me
|
148
|
+
executables:
|
149
|
+
- unibanner
|
150
|
+
extensions: []
|
151
|
+
extra_rdoc_files: []
|
152
|
+
files:
|
153
|
+
- ".bundle/config"
|
154
|
+
- ".gitignore"
|
155
|
+
- Gemfile
|
156
|
+
- Gemfile.lock
|
157
|
+
- bin/unibanner
|
158
|
+
- lib/unibanner.rb
|
159
|
+
- lib/unibanner/bot_class.rb
|
160
|
+
- lib/unibanner/functions.rb
|
161
|
+
- lib/unibanner/logger.rb
|
162
|
+
- lib/unibanner/version.rb
|
163
|
+
- unibanner.gemspec
|
164
|
+
homepage: https://iotaspencer.me/projects/unibanner
|
165
|
+
licenses:
|
166
|
+
- MIT
|
167
|
+
metadata:
|
168
|
+
github_repo: https://git.lasershark.army/IotaSpencer/unibanner
|
169
|
+
bug_tracker_uri: https://git.lasershark.army/IotaSpencer/unibanner/issues
|
170
|
+
homepage_uri: https://iotaspencer.me/projects/unibanner
|
171
|
+
source_code_uri: https://git.lasershark.army/IotaSpencer/unibanner
|
172
|
+
wiki_uri: https://git.lasershark.army/IotaSpencer/unibanner/wiki
|
173
|
+
post_install_message:
|
174
|
+
rdoc_options: []
|
175
|
+
require_paths:
|
176
|
+
- lib
|
177
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - "~>"
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '2'
|
182
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
187
|
+
requirements: []
|
188
|
+
rubyforge_project:
|
189
|
+
rubygems_version: 2.7.6
|
190
|
+
signing_key:
|
191
|
+
specification_version: 4
|
192
|
+
summary: A simpleish bot made to ban and blacklist unicode spamming bots.
|
193
|
+
test_files: []
|