unibanner 0.0.1

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
+ 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
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_PATH: "vendor/bundle"
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ vendor/
2
+ .project
3
+ .vscode/
4
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
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,5 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'unibanner'
4
+ Unibanner::Bots.find_bots
5
+ Unibanner::Bots.start
@@ -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
@@ -0,0 +1,3 @@
1
+ module Unibanner
2
+ VERSION = '0.0.1'
3
+ end
data/lib/unibanner.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'unibanner/bot_class'
2
+
3
+ # vim: ts=2 sw=2
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: []