kag-gather 1.3.4 → 1.3.5

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.
@@ -0,0 +1,126 @@
1
+ module Cinch
2
+ module Commands
3
+ #
4
+ # @api semipublic
5
+ #
6
+ class Command
7
+
8
+ # Argument formats
9
+ ARG_FORMATS = {
10
+ string: /\S+/,
11
+ integer: /\d+/,
12
+ float: /\d*\.\d+/,
13
+ text: /.+/
14
+ }
15
+
16
+ # Name of the command
17
+ attr_reader :name
18
+
19
+ # Argument names/formats
20
+ attr_reader :arguments
21
+
22
+ # Short summary of the command
23
+ attr_reader :summary
24
+
25
+ # Long description of the command
26
+ attr_reader :description
27
+
28
+ # if admin-only
29
+ attr_reader :admin
30
+
31
+ #
32
+ # Creates a new command.
33
+ #
34
+ # @param [Symbol] name
35
+ # Name of the command.
36
+ #
37
+ # @param [Hash{Symbol => Symbol,Regexp,String,Array}] arguments
38
+ # Arguments names and their formats or possible values.
39
+ #
40
+ # @param [Hash] options
41
+ # Additional options.
42
+ #
43
+ # @option options [Array] :aliases
44
+ # Additiona aliases for the command.
45
+ #
46
+ # @option options [String] :summary
47
+ # Short summary of the command.
48
+ #
49
+ # @option options [String] :description
50
+ # Long description of the command.
51
+ #
52
+ def initialize(name,arguments,options={})
53
+ @name = name.to_s
54
+ @arguments = arguments
55
+ @aliases = options.fetch(:aliases,[]).map(&:to_s)
56
+
57
+ @summary = options[:summary]
58
+ @description = options[:description]
59
+ @admin = options[:admin]
60
+ end
61
+
62
+ #
63
+ # The names for the command.
64
+ #
65
+ # @return [Array<String>]
66
+ # Command names.
67
+ #
68
+ def names
69
+ [@name] + @aliases
70
+ end
71
+
72
+ #
73
+ # Creates a Regular Expression that matches invocations of the command.
74
+ #
75
+ # @return [Regexp]
76
+ # A Regular Expression that matches the command and captures it's
77
+ # arguments.
78
+ #
79
+ def regexp
80
+ pattern = '(?:' + Regexp.union([@name] + @aliases).source + ')'
81
+
82
+ @arguments.each_value do |format|
83
+ arg_regexp = case format
84
+ when Symbol
85
+ ARG_FORMATS.fetch(format)
86
+ when Regexp
87
+ format
88
+ else
89
+ Regexp.union(format)
90
+ end
91
+
92
+ pattern << ' (' << arg_regexp.source << ')'
93
+ end
94
+
95
+ # match the full message
96
+ pattern << '$'
97
+
98
+ Regexp.new(pattern)
99
+ end
100
+
101
+ #
102
+ # The usage string for the command.
103
+ #
104
+ # @return [String]
105
+ # The usage string for the command and it's arguments.
106
+ #
107
+ def usage
108
+ usage = "#{@name}"
109
+
110
+ @arguments.each do |arg,format|
111
+ usage << ' ' << case format
112
+ when Array
113
+ '[' + format.join('|') + ']'
114
+ when String
115
+ format.to_s
116
+ else
117
+ arg.to_s.upcase
118
+ end
119
+ end
120
+
121
+ usage
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,64 @@
1
+ require 'commands/command'
2
+ require 'kag/common'
3
+
4
+ module Cinch
5
+ module Commands
6
+
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ #
13
+ # All registered commands.
14
+ #
15
+ # @return [Array<Command>]
16
+ # The registered commands.
17
+ #
18
+ # @api semipublic
19
+ #
20
+ def commands
21
+ @commands ||= []
22
+ end
23
+
24
+ protected
25
+
26
+ #
27
+ # Registers a command.
28
+ #
29
+ # @param [Symbol] name
30
+ #
31
+ # @param [Hash{Symbol => Symbol,Regexp}] arguments
32
+ #
33
+ # @param [Hash] options
34
+ # Additional options.
35
+ #
36
+ # @option options [String] :summary
37
+ # The short summary for the command.
38
+ #
39
+ # @option options [String] :description
40
+ # The long description for the command.
41
+ #
42
+ # @return [Command]
43
+ # The new command.
44
+ #
45
+ # @example
46
+ # command :grant, {name: :string, :level: :integer},
47
+ # summary: "Grants access",
48
+ # description: %{
49
+ # Grants a certain level of access to the user
50
+ # }
51
+ #
52
+ def command(name,arguments={},options={})
53
+ new_command = Command.new(name,arguments,options)
54
+
55
+ m = options.key?(:method) ? options[:method] : name
56
+ match(new_command.regexp, method: m)
57
+
58
+ commands << new_command
59
+ new_command
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,101 @@
1
+ require 'commands/commands'
2
+ require 'cinch/plugin'
3
+ require 'kag/common'
4
+
5
+ module Cinch
6
+ module Commands
7
+ #
8
+ # Generic `!help` command that lists all commands.
9
+ #
10
+ class Help
11
+ include Cinch::Plugin
12
+ include Cinch::Commands
13
+ include KAG::Common
14
+
15
+ command :help, {command: :string},
16
+ summary: %{Displays help information for the COMMAND},
17
+ description: %{Finds the COMMAND and prints the usage and description for the COMMAND.}
18
+
19
+ command :help, {},
20
+ summary: "Lists available commands",
21
+ description: %{If no COMMAND argument is given, then all commands will be listed.}
22
+
23
+ #
24
+ # Displays a list of commands or the help information for a specific
25
+ # command.
26
+ #
27
+ # @param [Cinch::Message]
28
+ # The message that invoked `!help`.
29
+ #
30
+ # @param [String] command
31
+ # The specific command to list help information for.
32
+ #
33
+ def help(m,command=nil)
34
+ if command
35
+ found = commands_named(command)
36
+
37
+ if found.empty?
38
+ m.reply "help: Unknown command #{command.dump}"
39
+ else
40
+ return if found.first.admin and !is_admin(m.user)
41
+
42
+ msg = []
43
+ # print all usages
44
+ found.each do |cmd|
45
+ msg << cmd.usage
46
+ end
47
+ # print the description of the first command
48
+ desc = found.first.description.to_s
49
+ msg = "\x0302#{msg.join(", ")}\x0314"+(desc != "" ? " - #{desc}" : " - #{found.first.summary.to_s}")
50
+ User(m.user.nick).send(msg)
51
+ end
52
+ else
53
+ msg = []
54
+ each_command do |cmd|
55
+ #msg << "\x0302#{cmd.usage}\x0314: #{cmd.summary}" unless (cmd.admin and !is_admin(m.user))
56
+ msg << "!"+cmd.usage
57
+ end
58
+ User(m.user.nick).send(msg.join ", ")
59
+ end
60
+ end
61
+
62
+ protected
63
+
64
+ #
65
+ # Enumerates over every command.
66
+ #
67
+ # @yield [command]
68
+ # The given block will be passed every command.
69
+ #
70
+ # @yieldparam [Command] command
71
+ # A command.
72
+ #
73
+ # @return [Enumerator]
74
+ # If no block is given, an Enumerator will be returned.
75
+ #
76
+ def each_command(&block)
77
+ return enum_for(__method__) unless block_given?
78
+
79
+ bot.config.plugins.plugins.each do |plugin|
80
+ if plugin < Cinch::Commands
81
+ plugin.commands.each(&block)
82
+ end
83
+ end
84
+ end
85
+
86
+ #
87
+ # Finds all commands with a similar name.
88
+ #
89
+ # @param [String] name
90
+ # The name to search for.
91
+ #
92
+ # @return [Array<Command>]
93
+ # The commands with the matching name.
94
+ #
95
+ def commands_named(name)
96
+ each_command.select { |command| command.name == name }
97
+ end
98
+
99
+ end
100
+ end
101
+ end
data/lib/gather.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'patches'
2
- require 'kag/gather'
1
+ require 'kag/bot/bot'
3
2
 
4
- KAG::Bot.new
3
+ KAG::Bot::Bot.new
@@ -0,0 +1,93 @@
1
+ require 'cinch'
2
+ require 'kag/common'
3
+ require 'commands/help'
4
+
5
+ module KAG
6
+ module Bans
7
+ class Plugin
8
+ include Cinch::Plugin
9
+ include Cinch::Commands
10
+ include KAG::Common
11
+
12
+ command :report,{nick: :string},
13
+ summary: "Report a user the bot"
14
+ def report(m,nick)
15
+ unless is_banned?(m.user)
16
+ u = User(nick)
17
+ if u and !u.unknown
18
+ KAG::Bans::Report.new(self,m,u)
19
+ else
20
+ reply m,"User #{nick} not found!"
21
+ end
22
+ end
23
+ end
24
+
25
+ command :reports,{nick: :string},
26
+ summary: "Show the number of reports for a given user"
27
+ def reports(m,nick)
28
+ user = User(nick)
29
+ if user and !user.unknown
30
+ count = KAG::Bans::Report.reports(user)
31
+ if count
32
+ reply m,"User has been reported #{count.to_s} times."
33
+ else
34
+ reply m,"User has not been reported."
35
+ end
36
+ else
37
+ reply m,"Could not find user #{nick}"
38
+ end
39
+ end
40
+
41
+ command :reported,{},
42
+ summary: "Show a list of reported users"
43
+ def reported(m)
44
+ unless is_banned?(m.user)
45
+ KAG::Bans::Report.list
46
+ end
47
+ end
48
+
49
+ command :unreport,{nick: :string},
50
+ summary: "Clear all reports for a given user",
51
+ admin: true
52
+ def unreport(m,nick)
53
+ if is_admin(m.user)
54
+ user = User(nick)
55
+ if user and !user.unknown
56
+ KAG::Bans::Report.remove(self,m,user)
57
+ else
58
+ reply m,"Could not find user #{nick}"
59
+ end
60
+ end
61
+ end
62
+
63
+ command :ignore,{nick: :string},
64
+ summary: "Ignore (Ban) a user",
65
+ admin: true
66
+ def ignore(m,nick)
67
+ if is_admin(m.user)
68
+ user = User(nick)
69
+ if user and !user.unknown
70
+ KAG::Bans::Report.ignore(self,m,user)
71
+ else
72
+ reply m,"Could not find user #{nick}"
73
+ end
74
+ end
75
+ end
76
+
77
+ command :unignore,{nick: :string},
78
+ summary: "Unignore (Unban) a user",
79
+ admin: true
80
+ def unignore(m,nick)
81
+ if is_admin(m.user)
82
+ user = User(nick)
83
+ if user and !user.unknown
84
+ KAG::Bans::Report.unignore(self,m,user)
85
+ else
86
+ reply m,"Could not find user #{nick}"
87
+ end
88
+ end
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,172 @@
1
+ require 'symboltable'
2
+ require 'kag/data'
3
+ require 'kag/config'
4
+
5
+ module KAG
6
+ module Bans
7
+ class Report < SymbolTable
8
+ def initialize(gather,m,user)
9
+ hash = {
10
+ :nick => user.nick,
11
+ :authname => user.authname,
12
+ :host => user.host,
13
+ :realname => user.realname,
14
+ :gather => gather,
15
+ :message => m,
16
+ :count => 1
17
+ }
18
+ super(hash)
19
+ _ensure_data
20
+ if reported?
21
+ if can_report?
22
+ if past_threshold?
23
+ ignore
24
+ else
25
+ up_report_count
26
+ end
27
+ else
28
+ self.gather.reply self.message,"You have already reported #{self[:nick]}. You can only report a user once."
29
+ end
30
+ else
31
+ report
32
+ end
33
+ end
34
+
35
+ def can_report?
36
+ r = _report
37
+ if r and r[:reporters]
38
+ !r[:reporters].include?(self.message.user.authname)
39
+ else
40
+ true
41
+ end
42
+ end
43
+
44
+ def _ensure_data
45
+ data[:reported] = {} unless data[:reported]
46
+ data[:ignored] = {} unless data[:ignored]
47
+ end
48
+
49
+ def reported?
50
+ data[:reported].key?(self[:authname].to_sym)
51
+ end
52
+
53
+ def report
54
+ puts self.message.inspect
55
+ c = self.dup
56
+ c.delete(:gather)
57
+ c.delete(:message)
58
+ c[:reporters] = [self.message.user.authname]
59
+ data[:reported][self[:authname].to_sym] = c
60
+ data.save
61
+
62
+ self.gather.reply self.message,"User #{self[:nick]} reported." if self.gather.class == KAG::Gather
63
+ end
64
+
65
+ def ignore
66
+ c = self.clone
67
+ c.delete(:gather)
68
+ c.delete(:message)
69
+ data[:ignored][self[:authname].to_sym] = c
70
+ data.save
71
+ self.gather.reply self.message,"User #{self[:nick]} ignored." if self.gather.class == KAG::Gather
72
+ end
73
+
74
+ def past_threshold?
75
+ _report[:count].to_i > KAG::Config.instance[:report_threshold].to_i
76
+ end
77
+
78
+ def up_report_count
79
+ _report[:count] = _report[:count].to_i + 1
80
+ _report[:reporters] = [] unless _report[:reporters]
81
+ _report[:reporters] << self.message.user.authname
82
+ data.save
83
+
84
+ self.gather.reply message,"User #{self[:nick]} reported. #{self[:nick]} has now been reported #{data[:reported][self[:authname].to_sym][:count]} times." if self.gather.class == KAG::Gather
85
+ end
86
+
87
+ def self.ignore(gather,message,user)
88
+ KAG::Config.data[:ignored] = {} unless KAG::Config.data[:ignored]
89
+ if KAG::Config.data[:ignored] and !KAG::Config.data[:ignored].key?(user.authname.to_sym)
90
+ c = SymbolTable.new({
91
+ :nick => user.nick,
92
+ :authname => user.authname,
93
+ :host => user.host,
94
+ :realname => user.realname,
95
+ :gather => gather,
96
+ :message => message,
97
+ :reporters => [message.user.authname]
98
+ })
99
+ KAG::Config.data[:ignored][user.authname.to_sym] = c
100
+ KAG::Config.data.save
101
+
102
+ gather.reply message,"User #{user.nick} added to ignore list." if gather.class == KAG::Gather
103
+ true
104
+ else
105
+ gather.reply message,"User #{user.nick} already in ignore list!" if gather.class == KAG::Gather
106
+ false
107
+ end
108
+ end
109
+
110
+ def self.remove(gather,message,user)
111
+ if KAG::Config.data[:reported] and KAG::Config.data[:reported].key?(user.authname.to_sym)
112
+ KAG::Config.data[:reported].delete(user.authname.to_sym)
113
+ KAG::Config.data.save
114
+
115
+ gather.reply message,"User #{user.nick} removed from report list." if gather.class == KAG::Gather
116
+ true
117
+ else
118
+ gather.reply message,"User #{user.nick} not in report list!" if gather.class == KAG::Gather
119
+ false
120
+ end
121
+ end
122
+
123
+ def self.unignore(gather,message,user)
124
+ if KAG::Config.data[:ignored] and KAG::Config.data[:ignored].key?(user.authname.to_sym)
125
+ KAG::Config.data[:ignored].delete(user.authname.to_sym)
126
+ KAG::Config.data.save
127
+
128
+ gather.reply message,"User #{user.nick} removed from ignore list." if gather.class == KAG::Gather
129
+ true
130
+ else
131
+ gather.reply message,"User #{user.nick} not in ignore list!" if gather.class == KAG::Gather
132
+ false
133
+ end
134
+ end
135
+
136
+ def self.reports(user)
137
+ if KAG::Config.data[:reported] and KAG::Config.data[:reported].key?(user.authname.to_sym)
138
+ KAG::Config.data[:reported][user.authname.to_sym][:count]
139
+ else
140
+ false
141
+ end
142
+ end
143
+
144
+ def self.is_banned?(user)
145
+ KAG::Config.data[:ignored] = {} unless KAG::Config.data[:ignored]
146
+ begin
147
+ KAG::Config.data[:ignored].key?(user.authname.to_sym)
148
+ rescue Exception => e
149
+ puts e.message
150
+ end
151
+ end
152
+
153
+ def self.list
154
+ if KAG::Config.data[:ignored]
155
+ KAG::Config.data[:ignored].keys
156
+ else
157
+ []
158
+ end
159
+ end
160
+
161
+ protected
162
+
163
+ def data
164
+ KAG::Config.data
165
+ end
166
+
167
+ def _report
168
+ data[:reported][self[:authname].to_sym]
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,42 @@
1
+ require 'patches'
2
+ require 'cinch'
3
+ require 'kag/config'
4
+ require 'kag/data'
5
+ require 'kag/gather/plugin'
6
+ require 'kag/bans/plugin'
7
+ require 'kag/irc/plugin'
8
+ require 'kag/bot/plugin'
9
+ require 'commands/help'
10
+
11
+ module KAG
12
+ module Bot
13
+ class Bot
14
+ def initialize
15
+ config = self.config
16
+ bot = Cinch::Bot.new do
17
+ configure do |c|
18
+ c.server = config[:server]
19
+ c.channels = config[:channels]
20
+ c.port = config[:port].to_i > 0 ? config[:port] : 6667
21
+ #c.ssl = config[:ssl]
22
+ c.nick = config[:nick].to_s != "" ? config[:nick] : "KAGatherer"
23
+ c.realname = config[:realname].to_s != "" ? config[:realname] : "KAG Gatherer"
24
+ c.messages_per_second = 1
25
+ c.server_queue_size = 1
26
+ c.plugins.plugins = [Cinch::Commands::Help,KAG::Bot::Plugin,KAG::Gather::Plugin,KAG::Bans::Plugin,KAG::IRC::Plugin]
27
+ if config[:sasl]
28
+ c.sasl.username = config[:sasl][:username]
29
+ c.sasl.password = config[:sasl][:password]
30
+ end
31
+ end
32
+ end
33
+
34
+ bot.start
35
+ end
36
+
37
+ def config
38
+ KAG::Config.instance
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,56 @@
1
+ require 'cinch'
2
+ require 'kag/common'
3
+ require 'commands/help'
4
+
5
+ module KAG
6
+ module Bot
7
+ class Plugin
8
+ include Cinch::Plugin
9
+ include Cinch::Commands
10
+ include KAG::Common
11
+
12
+ command :quit,{},
13
+ summary: "Quit the bot",
14
+ admin: true
15
+ def quit(m)
16
+ if is_admin(m.user)
17
+ m.bot.quit("Shutting down...")
18
+ end
19
+ end
20
+
21
+ command :restart,{},
22
+ summary: "Restart the bot",
23
+ admin: true
24
+ def restart(m)
25
+ if is_admin(m.user)
26
+ cmd = (KAG::Config.instance[:restart_method] or "nohup sh gather.sh &")
27
+ debug cmd
28
+ pid = spawn cmd
29
+ debug "Restarting bot, new process ID is #{pid.to_s} ..."
30
+ exit
31
+ end
32
+ end
33
+
34
+ command :is_an_admin,{nick: :string},
35
+ summary: "See if the specified user is an Admin"
36
+ def is_an_admin(m,nick)
37
+ u = User(nick)
38
+ if is_admin(u)
39
+ reply m,"Yes, #{nick} is an admin!"
40
+ else
41
+ reply m,"No, #{nick} is not an admin."
42
+ end
43
+ end
44
+
45
+ command :reload_config,{},
46
+ summary: "Reload the configuration file",
47
+ admin: true
48
+ def reload_config(m)
49
+ if is_admin(m.user)
50
+ KAG::Config.instance.reload
51
+ m.reply "Configuration reloaded."
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
data/lib/kag/common.rb ADDED
@@ -0,0 +1,34 @@
1
+
2
+ module KAG
3
+ module Common
4
+ include Cinch::Plugin
5
+
6
+ def reply(message,text,colorize = true)
7
+ text = Format(:grey,text) if colorize
8
+ message.reply text
9
+ end
10
+
11
+ def send_channels_msg(msg,colorize = true)
12
+ KAG::Config.instance[:channels].each do |c|
13
+ msg = Format(:grey,msg) if colorize
14
+ Channel(c).send(msg)
15
+ end
16
+ end
17
+
18
+ def is_banned?(user)
19
+ KAG::Bans::Report.is_banned?(user)
20
+ end
21
+
22
+ def debug(msg)
23
+ if KAG::Config.instance[:debug]
24
+ puts msg
25
+ end
26
+ end
27
+
28
+ def is_admin(user)
29
+ user.refresh
30
+ o = (KAG::Config.instance[:owners] or [])
31
+ o.include?(user.authname)
32
+ end
33
+ end
34
+ end