zetabot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +281 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/Zeta.gemspec +74 -0
- data/bin/console +14 -0
- data/bin/setup +13 -0
- data/bin/zeta +9 -0
- data/bin/zeta-setup +13 -0
- data/lib/Zeta.rb +13 -0
- data/lib/Zeta/access.rb +84 -0
- data/lib/Zeta/admin.rb +10 -0
- data/lib/Zeta/admin/autojoin.rb +25 -0
- data/lib/Zeta/admin/bot.rb +43 -0
- data/lib/Zeta/admin/channels.rb +36 -0
- data/lib/Zeta/admin/eval.rb +43 -0
- data/lib/Zeta/admin/fifo.rb +45 -0
- data/lib/Zeta/admin/ignore.rb +112 -0
- data/lib/Zeta/admin/oper.rb +50 -0
- data/lib/Zeta/admin/plugins.rb +109 -0
- data/lib/Zeta/admin/users.rb +5 -0
- data/lib/Zeta/blacklist.rb +25 -0
- data/lib/Zeta/cache.rb +0 -0
- data/lib/Zeta/cinch.rb +35 -0
- data/lib/Zeta/config.rb +42 -0
- data/lib/Zeta/gems.rb +0 -0
- data/lib/Zeta/locale.rb +4 -0
- data/lib/Zeta/log.rb +2 -0
- data/lib/Zeta/models.rb +5 -0
- data/lib/Zeta/models/channel.rb +3 -0
- data/lib/Zeta/models/plugin.rb +3 -0
- data/lib/Zeta/models/user.rb +3 -0
- data/lib/Zeta/plugins.rb +27 -0
- data/lib/Zeta/plugins/attack.rb +61 -0
- data/lib/Zeta/plugins/botinfo.rb +83 -0
- data/lib/Zeta/plugins/darkscience.rb +215 -0
- data/lib/Zeta/plugins/dbz.rb +31 -0
- data/lib/Zeta/plugins/dcc.rb +25 -0
- data/lib/Zeta/plugins/dnsbl.rb +36 -0
- data/lib/Zeta/plugins/echo.rb +15 -0
- data/lib/Zeta/plugins/eightball.rb +53 -0
- data/lib/Zeta/plugins/fml.rb +35 -0
- data/lib/Zeta/plugins/fnord.rb +329 -0
- data/lib/Zeta/plugins/gem.rb +0 -0
- data/lib/Zeta/plugins/gif.rb +73 -0
- data/lib/Zeta/plugins/help.rb +32 -0
- data/lib/Zeta/plugins/libsecure.rb +34 -0
- data/lib/Zeta/plugins/macros.rb +124 -0
- data/lib/Zeta/plugins/movie.rb +67 -0
- data/lib/Zeta/plugins/pdfinfo.rb +69 -0
- data/lib/Zeta/plugins/rainbow.rb +65 -0
- data/lib/Zeta/plugins/russian_roulette.rb +90 -0
- data/lib/Zeta/plugins/seen.rb +77 -0
- data/lib/Zeta/plugins/silly.rb +183 -0
- data/lib/Zeta/plugins/snooper.rb +146 -0
- data/lib/Zeta/plugins/urban.rb +60 -0
- data/lib/Zeta/plugins/weather.rb +203 -0
- data/lib/Zeta/plugins/whois.rb +25 -0
- data/lib/Zeta/plugins/wiki.rb +75 -0
- data/lib/Zeta/plugins/wolfram.rb +46 -0
- data/lib/Zeta/tasks/db.rb +0 -0
- data/lib/Zeta/version.rb +3 -0
- data/lib/generators/config/config.rb +0 -0
- data/lib/generators/plugin/new_plugin.rb +0 -0
- data/locale/en/8ball.yml +0 -0
- data/locale/en/attack.yml +148 -0
- data/locale/en/dbz.yml +10 -0
- data/locale/en/ircop.yml +5 -0
- data/locale/en/macros.yml +98 -0
- data/locale/en/meme.yml +27 -0
- metadata +636 -0
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "zeta"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
set -vx
|
5
|
+
|
6
|
+
bundle install
|
7
|
+
|
8
|
+
# Do any other automated setup that you need to do here
|
9
|
+
mkdir -p ~/.zeta/cache
|
10
|
+
|
11
|
+
end
|
12
|
+
Dir.mkdir( File.join(Dir.home, ".zeta"), 0700)
|
13
|
+
Dir.mkdir(File.join(Dir.home, ".zeta", 'cache'), 0700)
|
data/bin/zeta
ADDED
data/bin/zeta-setup
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
Puts 'Setting up ZetaBot'
|
3
|
+
puts 'Checking if .zeta is in your home directory'
|
4
|
+
unless Dir.exists? File.join(Dir.home, '.zeta')
|
5
|
+
puts 'Creating .zeta/'
|
6
|
+
Dir.mkdir( File.join(Dir.home, ".zeta"), 0700)
|
7
|
+
puts 'Creating .zeta/cache/'
|
8
|
+
Dir.mkdir(File.join(Dir.home, ".zeta", 'cache'), 0700)
|
9
|
+
puts 'Creating .zeta/db/'
|
10
|
+
Dir.mkdir(File.join(Dir.home, ".zeta", 'db'), 0700)
|
11
|
+
puts 'Creating .zeta/log/'
|
12
|
+
Dir.mkdir(File.join(Dir.home, ".zeta", 'log'), 0700)
|
13
|
+
end
|
data/lib/Zeta.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Zeta; end
|
2
|
+
|
3
|
+
require 'Zeta/version'
|
4
|
+
require 'Zeta/cache'
|
5
|
+
require 'Zeta/config'
|
6
|
+
require 'Zeta/access'
|
7
|
+
require 'Zeta/blacklist'
|
8
|
+
require 'Zeta/cinch'
|
9
|
+
require 'Zeta/models'
|
10
|
+
require 'Zeta/admin'
|
11
|
+
require 'Zeta/locale'
|
12
|
+
require 'Zeta/plugins'
|
13
|
+
require 'Zeta/log'
|
data/lib/Zeta/access.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
module Cinch
|
2
|
+
module Plugin
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def enable_acl(lvl= :nobody, secure_chan=false)
|
6
|
+
hook(:pre, :for => [:match], :method => lambda { |m| check?(m,lvl,secure_chan) })
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def check?(m, lvl, secure_chan)
|
11
|
+
# Make sure we are actually getting a channel object
|
12
|
+
if m.class == Cinch::Channel
|
13
|
+
channel = m
|
14
|
+
elsif m.class == Cinch::Message
|
15
|
+
channel = m.channel
|
16
|
+
else
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get User
|
21
|
+
if m.class == Cinch::User
|
22
|
+
user = m
|
23
|
+
elsif m.class == Cinch::Message
|
24
|
+
user = m.user
|
25
|
+
else
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
|
29
|
+
# Oper Overide
|
30
|
+
if Config.oper_overide
|
31
|
+
return true if user.oper
|
32
|
+
end
|
33
|
+
|
34
|
+
# Check Channel status
|
35
|
+
return false if Blacklist.channels.include? channel.to_s
|
36
|
+
|
37
|
+
# Check Ignore status
|
38
|
+
return false if Blacklist.users.include? user.to_s
|
39
|
+
|
40
|
+
# Only check if user has permission in the secure channel
|
41
|
+
channel = Channel(Config.secure_channel.to_s) if secure_chan
|
42
|
+
|
43
|
+
# Authorization method
|
44
|
+
if Config.secure_mode == 'channel'
|
45
|
+
# Check lvl privilege
|
46
|
+
case lvl
|
47
|
+
when :O, :oper
|
48
|
+
return true if user.oper
|
49
|
+
false
|
50
|
+
when :q, :owner # Owner
|
51
|
+
return true if channel.owners.include? user
|
52
|
+
false
|
53
|
+
when :a, :admin # Admin
|
54
|
+
return true if channel.admins.include? user
|
55
|
+
false
|
56
|
+
when :o, :op # Op
|
57
|
+
return true if channel.ops.include? user
|
58
|
+
false
|
59
|
+
when :h, :halfop # Half-Op
|
60
|
+
return true if channel.half_ops.include? user
|
61
|
+
false
|
62
|
+
when :v, :voice # Voice
|
63
|
+
return true if channel.voiced.include? user
|
64
|
+
false
|
65
|
+
when :nobody
|
66
|
+
return true
|
67
|
+
else
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
elsif Config.secure_mode == 'identify'
|
71
|
+
# TODO
|
72
|
+
# Require you to identify with bot before usage
|
73
|
+
elsif Config.secure_mode == 'hostmask'
|
74
|
+
# TODO
|
75
|
+
# Require hostmask
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def log2chan(msg, level=:notice)
|
80
|
+
Channel(Config.log_channel.to_s).send "[#{level.to_s}] #{msg}"
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
data/lib/Zeta/admin.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Admin; end
|
2
|
+
require 'Zeta/admin/channels'
|
3
|
+
require 'Zeta/admin/eval'
|
4
|
+
require 'Zeta/admin/fifo'
|
5
|
+
require 'Zeta/admin/oper'
|
6
|
+
require 'Zeta/admin/plugins'
|
7
|
+
require 'Zeta/admin/users'
|
8
|
+
require 'Zeta/admin/autojoin'
|
9
|
+
require 'Zeta/admin/ignore'
|
10
|
+
require 'Zeta/admin/bot'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Admin
|
2
|
+
class Autojoin
|
3
|
+
include Cinch::Plugin
|
4
|
+
include Cinch::Helpers
|
5
|
+
|
6
|
+
# Listeners
|
7
|
+
listen_to :invite, method: :invited
|
8
|
+
|
9
|
+
# Methods
|
10
|
+
def invited(m)
|
11
|
+
puts "triggered"
|
12
|
+
if Config.options.dig :join_on_invite
|
13
|
+
return false if Blacklist.users.include? m.user.nick.to_s
|
14
|
+
return false if Blacklist.channels.include? m.channel.to_s
|
15
|
+
|
16
|
+
log2chan("#{m.user.nick} has requested me join #{m.channel}", :notice)
|
17
|
+
|
18
|
+
Channel(m.channel).join
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# AutoLoad
|
25
|
+
Bot.config.plugins.plugins.push Admin::Autojoin
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Admin
|
2
|
+
class Bot
|
3
|
+
include Cinch::Plugin
|
4
|
+
include Cinch::Helpers
|
5
|
+
|
6
|
+
enable_acl(:oper)
|
7
|
+
|
8
|
+
set(
|
9
|
+
plugin_name: "BotAdmin",
|
10
|
+
help: "Bot administrator-only private commands.\nUsage: `~nick [channel]`;",
|
11
|
+
)
|
12
|
+
|
13
|
+
# Regex
|
14
|
+
match /set nick (.+)/, method: :nick
|
15
|
+
match /set mode (.+)/, method: :mode
|
16
|
+
match /die(?: (.+))?/, method: :quit, group: :quit
|
17
|
+
|
18
|
+
# Methods
|
19
|
+
def nick(m, nick)
|
20
|
+
bot.nick = nick
|
21
|
+
synchronize(:nickchange) do
|
22
|
+
@bot.handlers.dispatch :admin, m, "My nick got changed from #{@bot.last_nick} to #{@bot.nick} by #{m.user.nick}", m.target
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def mode(m, nick)
|
27
|
+
bot.modes = m
|
28
|
+
end
|
29
|
+
|
30
|
+
def quit(m, msg=nil)
|
31
|
+
msg ||= m.user.nick
|
32
|
+
@bot.handlers.dispatch :admin, m, "I am being shut down NOW!#{" - Reason: " + msg unless msg.nil?}", m.target
|
33
|
+
sleep 2
|
34
|
+
bot.quit(msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# AutoLoad
|
43
|
+
Bot.config.plugins.plugins.push Admin::Bot
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Admin
|
2
|
+
class Channels
|
3
|
+
include Cinch::Plugin
|
4
|
+
include Cinch::Helpers
|
5
|
+
|
6
|
+
enable_acl(:operator, true)
|
7
|
+
|
8
|
+
set(
|
9
|
+
plugin_name: 'ChannelAdmin',
|
10
|
+
help: "Bot administrator-only private commands.\nUsage: `?join [channel]`; `?part [channel] <reason>`; `?quit [reason]`;",
|
11
|
+
)
|
12
|
+
|
13
|
+
# Regex
|
14
|
+
match /join (.+)/, method: :join
|
15
|
+
match /part(?: (\S+))?(?: (.+))?/, method: :part, group: :part
|
16
|
+
|
17
|
+
def join(m, channel)
|
18
|
+
channel.split(", ").each {|ch|
|
19
|
+
Channel(ch).join
|
20
|
+
@bot.handlers.dispatch :admin, m, "Attempt to join #{ch.split[0]} by #{m.user.nick}...", m.target
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def part(m, channel=nil, msg=nil)
|
25
|
+
channel ||= m.channel.name
|
26
|
+
msg ||= m.user.nick
|
27
|
+
Channel(channel).part(msg) if channel
|
28
|
+
@bot.handlers.dispatch :admin, m, "Parted #{channel}#{" - #{msg}" unless msg.nil?}", m.target
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# AutoLoad
|
36
|
+
Bot.config.plugins.plugins.push Admin::Channels
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Admin
|
2
|
+
class Eval
|
3
|
+
include Cinch::Plugin
|
4
|
+
|
5
|
+
enable_acl(:oper)
|
6
|
+
|
7
|
+
set(
|
8
|
+
plugin_name: "Bot_Eval",
|
9
|
+
help: "Bot administrator-only private commands.\nUsage: `?er <code>`;",
|
10
|
+
)
|
11
|
+
|
12
|
+
# Regex
|
13
|
+
match /e (.+)/, method: :boteval
|
14
|
+
match /eval (.+)/, method: :boteval
|
15
|
+
match /ereturn (.+)/, method: :botevalreturn
|
16
|
+
match /er (.+)/, method: :botevalreturn
|
17
|
+
match /evalmsg (.+)/, method: :botevalmsg
|
18
|
+
match /em (.+)/, method: :botevalmsg
|
19
|
+
|
20
|
+
def boteval(m, s)
|
21
|
+
eval(s)
|
22
|
+
rescue => e
|
23
|
+
m.user.send "eval error: %s\n- %s (%s)" % [s, e.message, e.class.name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def botevalreturn(m, s)
|
27
|
+
return m.reply eval(s)
|
28
|
+
rescue => e
|
29
|
+
m.user.send "eval error: %s\n- %s (%s)" % [s, e.message, e.class.name]
|
30
|
+
end
|
31
|
+
|
32
|
+
def botevalmsg(m, s)
|
33
|
+
return m.user.msg eval(s)
|
34
|
+
rescue => e
|
35
|
+
m.user.send "eval error: %s\n- %s (%s)" % [s, e.message, e.class.name]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# AutoLoad
|
43
|
+
Bot.config.plugins.plugins.push Admin::Eval
|
@@ -0,0 +1,45 @@
|
|
1
|
+
unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
2
|
+
require 'mkfifo'
|
3
|
+
end
|
4
|
+
|
5
|
+
# Named pipe plugin for Cinch.
|
6
|
+
module Admin
|
7
|
+
class Fifo
|
8
|
+
include Cinch::Plugin
|
9
|
+
listen_to :connect, :method => :open_fifo
|
10
|
+
listen_to :disconnect, :method => :close_fifo
|
11
|
+
|
12
|
+
def open_fifo(m)
|
13
|
+
# Sometimes FiFo is left open on crash, remove old fifo
|
14
|
+
if File.exists?(File.join(Dir.home, '.zeta', 'zeta.io'))
|
15
|
+
File.delete(File.join(Dir.home, '.zeta', 'zeta.io'))
|
16
|
+
end
|
17
|
+
|
18
|
+
File.mkfifo(File.join(Dir.home, '.zeta', 'zeta.io') || raise(ArgumentError, "No FIFO path given!"))
|
19
|
+
File.chmod(0660, File.join(Dir.home, '.zeta', 'zeta.io'))
|
20
|
+
|
21
|
+
File.open(File.join(Dir.home, '.zeta', 'zeta.io'), "r+") do |fifo|
|
22
|
+
bot.info "Opened named pipe (FIFO) at #{File.join(Dir.home, '.zeta', 'zeta.io')}"
|
23
|
+
|
24
|
+
fifo.each_line do |line|
|
25
|
+
msg = line.strip
|
26
|
+
bot.debug "Got message from the FIFO: #{msg}"
|
27
|
+
bot.irc.send msg
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def close_fifo(msg)
|
34
|
+
File.delete(File.join(Dir.home, '.zeta', 'zeta.io'))
|
35
|
+
bot.info "Deleted named pipe #{File.join(Dir.home, '.zeta', 'zeta.io')}"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# AutoLoad if Not Jruby
|
43
|
+
unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
44
|
+
Bot.config.plugins.plugins.push Admin::Fifo
|
45
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Admin
|
2
|
+
class Ignore
|
3
|
+
include Cinch::Plugin
|
4
|
+
include Cinch::Helpers
|
5
|
+
|
6
|
+
enable_acl(:operator, true)
|
7
|
+
|
8
|
+
set(
|
9
|
+
plugin_name: "BotAdmin",
|
10
|
+
help: "Bot administrator-only private commands.\nUsage: `~nick [channel]`;",
|
11
|
+
)
|
12
|
+
|
13
|
+
# Regex
|
14
|
+
match /ignore (.+)/, method: :ignore_user
|
15
|
+
match /unignore (.+)/, method: :unignore_user
|
16
|
+
|
17
|
+
match /disable (.+)/, method: :disable_channel
|
18
|
+
match /enable (.+)/, method: :enable_channel
|
19
|
+
match 'disable', method: :disable_channel
|
20
|
+
match 'enable', method: :enable_channel
|
21
|
+
|
22
|
+
match 'ignorelist', method: :ignore_list
|
23
|
+
|
24
|
+
match 'sync', method: :sync
|
25
|
+
|
26
|
+
def finalize
|
27
|
+
save_blacklist()
|
28
|
+
end
|
29
|
+
|
30
|
+
# Methods
|
31
|
+
def ignore_user(m, nickname)
|
32
|
+
nickname.rstrip!
|
33
|
+
return m.reply("You can't ignore yourself") if m.user.nick == nickname
|
34
|
+
u = User(nickname)
|
35
|
+
if m.channel.users.member?(u)
|
36
|
+
if Blacklist.users.include? u
|
37
|
+
m.reply("#{nickname} is already being ignored")
|
38
|
+
else
|
39
|
+
Blacklist.users << u.to_s
|
40
|
+
m.action_reply "is now ignoring #{nickname}"
|
41
|
+
end
|
42
|
+
else
|
43
|
+
m.reply "#{nickname} isn't currently in channel"
|
44
|
+
end
|
45
|
+
save_blacklist()
|
46
|
+
end
|
47
|
+
|
48
|
+
def unignore_user(m, nickname)
|
49
|
+
nickname.rstrip!
|
50
|
+
u = User(nickname)
|
51
|
+
if Blacklist.users.include?(u.to_s)
|
52
|
+
Blacklist.users.delete(u.to_s)
|
53
|
+
m.action_reply "is no longer ignoring #{nickname}"
|
54
|
+
else
|
55
|
+
m.reply "#{nickname} isn't on the ignore list"
|
56
|
+
end
|
57
|
+
save_blacklist()
|
58
|
+
end
|
59
|
+
|
60
|
+
def disable_channel(m, channel=nil)
|
61
|
+
if channel
|
62
|
+
if Blacklist.channels.include?(channel.to_s)
|
63
|
+
m.reply('Channel is currently disabled')
|
64
|
+
else
|
65
|
+
Blacklist.channels << channel.to_s
|
66
|
+
m.action_reply "has disabled #{channel} buffer"
|
67
|
+
end
|
68
|
+
else
|
69
|
+
if Blacklist.channels.include?(m.channel.to_s)
|
70
|
+
m.reply('Channel is currently disabled')
|
71
|
+
else
|
72
|
+
Blacklist.channels << m.channel.to_s.to_s
|
73
|
+
m.action_reply "has disabled #{m.channel.to_s} buffer"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
save_blacklist()
|
77
|
+
end
|
78
|
+
|
79
|
+
def enable_channel(m, channel=nil)
|
80
|
+
if channel
|
81
|
+
if Blacklist.channels.include?(channel.to_s)
|
82
|
+
Blacklist.channels.delete(channel.to_s)
|
83
|
+
m.action_reply "has enabled #{channel} buffer"
|
84
|
+
else
|
85
|
+
m.reply('Channel is currently enabled')
|
86
|
+
end
|
87
|
+
else
|
88
|
+
if Blacklist.channels.include?(m.channel.to_s)
|
89
|
+
Blacklist.channels.delete(m.channel.to_s)
|
90
|
+
m.action_reply "has enabled #{m.channel.to_s} buffer"
|
91
|
+
else
|
92
|
+
m.reply('Channel is currently enabled')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
save_blacklist()
|
96
|
+
end
|
97
|
+
|
98
|
+
def ignore_list(m)
|
99
|
+
m.reply "Currently ignored users are: #{Blacklist.users.join(', ')}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def sync(m)
|
103
|
+
save_blacklist()
|
104
|
+
m.action_reply 'is now synced!'
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# AutoLoad
|
112
|
+
Bot.config.plugins.plugins.push Admin::Ignore
|