Auto 4.0.0.alpha.1-x86-mingw32
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.
- data/.yardopts +7 -0
- data/Gemfile +19 -0
- data/LICENSE.md +31 -0
- data/README.md +109 -0
- data/Rakefile +41 -0
- data/bin/auto +110 -0
- data/bin/auto-conf +45 -0
- data/conf/example.json +100 -0
- data/conf/example.yml +125 -0
- data/docs/Contributing.md +77 -0
- data/docs/Events.md +103 -0
- data/docs/Todo.md +21 -0
- data/docs/Upgrade.md +16 -0
- data/ext/dsl_base.c +49 -0
- data/ext/libauto/auto.h +20 -0
- data/ext/libauto/extconf.rb +16 -0
- data/ext/libauto/libauto.c +29 -0
- data/ext/libauto/libauto.h +28 -0
- data/ext/libauto/logger.c +177 -0
- data/ext/libauto/logger.h +44 -0
- data/lib/auto.rb +43 -0
- data/lib/auto/api.rb +7 -0
- data/lib/auto/api/events.rb +166 -0
- data/lib/auto/api/object.rb +29 -0
- data/lib/auto/api/plugin.rb +155 -0
- data/lib/auto/api/timers.rb +93 -0
- data/lib/auto/bot.rb +338 -0
- data/lib/auto/config.rb +181 -0
- data/lib/auto/configure.rb +410 -0
- data/lib/auto/configure/shell.rb +154 -0
- data/lib/auto/dsl/base.rb +74 -0
- data/lib/auto/dsl/irc.rb +13 -0
- data/lib/auto/irc.rb +8 -0
- data/lib/auto/irc/common.rb +63 -0
- data/lib/auto/irc/library.rb +89 -0
- data/lib/auto/irc/object/channel.rb +21 -0
- data/lib/auto/irc/object/entity.rb +90 -0
- data/lib/auto/irc/object/message.rb +99 -0
- data/lib/auto/irc/object/user.rb +139 -0
- data/lib/auto/irc/protocol.rb +164 -0
- data/lib/auto/irc/protocol/numerics.rb +60 -0
- data/lib/auto/irc/sasl/diffie_hellman.rb +36 -0
- data/lib/auto/irc/sasl/mech.rb +15 -0
- data/lib/auto/irc/sasl/mech/dh_blowfish.rb +83 -0
- data/lib/auto/irc/sasl/mech/plain.rb +39 -0
- data/lib/auto/irc/server.rb +301 -0
- data/lib/auto/irc/state/channel_manager.rb +6 -0
- data/lib/auto/irc/state/support.rb +142 -0
- data/lib/auto/irc/state/user_manager.rb +6 -0
- data/lib/auto/irc/std/commands.rb +99 -0
- data/lib/auto/irc/std/numerics.rb +216 -0
- data/lib/auto/rubyext/integer.rb +25 -0
- data/lib/auto/rubyext/string.rb +10 -0
- data/lib/auto/version.rb +18 -0
- data/lib/libauto.so +0 -0
- data/spec/api_events_spec.rb +68 -0
- data/spec/config_json_spec.rb +116 -0
- data/spec/config_other_spec.rb +29 -0
- data/spec/config_yaml_spec.rb +136 -0
- data/spec/helper.rb +19 -0
- data/spec/irc_object_entity_spec.rb +51 -0
- data/spec/logger_spec.rb +30 -0
- data/spec/plugin_base_spec.rb +35 -0
- data/spec/timers_spec.rb +42 -0
- metadata +238 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2013, Autumn Perrault, et al.
|
3
|
+
* All rights reserved.
|
4
|
+
* This free software is distributed under the FreeBSD license (LICENSE.md).
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
|
8
|
+
#ifndef __LIBAUTO_H__
|
9
|
+
#define __LIBAUTO_H__
|
10
|
+
|
11
|
+
/* SYM(x) returns rb_intern(x) */
|
12
|
+
#define SYM(str) rb_intern(#str)
|
13
|
+
|
14
|
+
/* variable for the Auto module */
|
15
|
+
VALUE mAuto;
|
16
|
+
|
17
|
+
/* Init_libauto prototype */
|
18
|
+
void Init_libauto();
|
19
|
+
|
20
|
+
/* Auto's exceptions */
|
21
|
+
VALUE eLogError;
|
22
|
+
VALUE eConfigError;
|
23
|
+
VALUE eDatabaseError;
|
24
|
+
VALUE ePluginError;
|
25
|
+
|
26
|
+
#endif
|
27
|
+
|
28
|
+
/* vim: set ts=4 sts=4 sw=4 et cindent: */
|
@@ -0,0 +1,177 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2013, Autumn Perrault, et al.
|
3
|
+
* All rights reserved.
|
4
|
+
* This free software is distributed under the FreeBSD license (LICENSE.md).
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
|
8
|
+
// So that the header will be read correctly.
|
9
|
+
#define __LOGGER__
|
10
|
+
|
11
|
+
#include <errno.h>
|
12
|
+
#include <sys/stat.h>
|
13
|
+
#include <string.h>
|
14
|
+
#include <time.h>
|
15
|
+
#include "auto.h"
|
16
|
+
|
17
|
+
/* @overload initialize()
|
18
|
+
* Constructs a new Auto::Logger instance.
|
19
|
+
*
|
20
|
+
* @return [Auto::Logger]
|
21
|
+
*/
|
22
|
+
VALUE logger_init(VALUE self)
|
23
|
+
{
|
24
|
+
rb_iv_set(self, "@status", ID2SYM(SYM(good)));
|
25
|
+
rb_funcall(self, SYM(log_directory_check), 0);
|
26
|
+
return self;
|
27
|
+
}
|
28
|
+
|
29
|
+
/* @overload error(message)
|
30
|
+
* This will log +message+ as an error.
|
31
|
+
*
|
32
|
+
* @param [String] message The error message to be reported.
|
33
|
+
* @return [nil]
|
34
|
+
*/
|
35
|
+
VALUE logger_error(VALUE self, VALUE message)
|
36
|
+
{
|
37
|
+
rb_funcall(self, SYM(log), 2, rb_str_new2("ERROR"), message);
|
38
|
+
return Qnil;
|
39
|
+
}
|
40
|
+
|
41
|
+
/* @overload debug(message)
|
42
|
+
* This will log +message+ as a debug message.
|
43
|
+
*
|
44
|
+
* @param [String] message The debug message to be reported.
|
45
|
+
* @return [nil]
|
46
|
+
*/
|
47
|
+
VALUE logger_debug(VALUE self, VALUE message)
|
48
|
+
{
|
49
|
+
rb_funcall(self, SYM(log), 2, rb_str_new2("DEBUG"), message);
|
50
|
+
return Qnil;
|
51
|
+
}
|
52
|
+
|
53
|
+
/* @overload warning(message)
|
54
|
+
* This will log +message+ as a warning.
|
55
|
+
*
|
56
|
+
* @param [String] message The admonitory message to be reported.
|
57
|
+
* @return [nil]
|
58
|
+
*/
|
59
|
+
VALUE logger_warning(VALUE self, VALUE message)
|
60
|
+
{
|
61
|
+
rb_funcall(self, SYM(log), 2, rb_str_new2("WARNING"), message);
|
62
|
+
return Qnil;
|
63
|
+
}
|
64
|
+
|
65
|
+
/* @overload info(message)
|
66
|
+
* This will log +message+ as an informative message.
|
67
|
+
*
|
68
|
+
* @param [String] message The information to be reported.
|
69
|
+
* @return [nil]
|
70
|
+
*/
|
71
|
+
VALUE logger_info(VALUE self, VALUE message)
|
72
|
+
{
|
73
|
+
rb_funcall(self, SYM(log), 2, rb_str_new2("INFO"), message);
|
74
|
+
return Qnil;
|
75
|
+
}
|
76
|
+
|
77
|
+
/* @overload log(type, message)
|
78
|
+
* This will foremost call {#log_directory_check} to ensure the log directory
|
79
|
+
* exists, and then log the given +message+ as +type+.
|
80
|
+
*
|
81
|
+
* @param [String] type The type; e.g. WARNING, ERROR, etc.
|
82
|
+
* @param [String] message The message to be logged.
|
83
|
+
*
|
84
|
+
* @return [nil]
|
85
|
+
*/
|
86
|
+
VALUE logger_log(VALUE self, VALUE type, VALUE message)
|
87
|
+
{
|
88
|
+
// Declaractions and assignments.
|
89
|
+
char *log_file_name = ALLOCA_N(char, MAX_TIME_STRING_LENGTH + 1);
|
90
|
+
//
|
91
|
+
char *log_time = ALLOCA_N(char, LOG_TIME_FORMAT_LENGTH + 1); // Length of our maximum expected string
|
92
|
+
FILE *log_file;
|
93
|
+
|
94
|
+
/* 8 is The number of extra characters i.e " ", "[]", "\n" */
|
95
|
+
size_t output_string_size = 8 + RSTRING_LEN(type) + RSTRING_LEN(message) + LOG_TIME_FORMAT_LENGTH;
|
96
|
+
|
97
|
+
char *formatted_message = ALLOCA_N(char, ++output_string_size);
|
98
|
+
|
99
|
+
time_t current_time;
|
100
|
+
|
101
|
+
// Ensure we have the directory we need.
|
102
|
+
rb_funcall(self, SYM(log_directory_check), 0);
|
103
|
+
|
104
|
+
// Get the current time
|
105
|
+
time(¤t_time);
|
106
|
+
|
107
|
+
// Create the file name
|
108
|
+
strftime(log_file_name, 100, LOG_FILE_FORMAT, localtime(¤t_time));
|
109
|
+
|
110
|
+
// Open the log file for appending.
|
111
|
+
log_file = fopen(log_file_name, "a+");
|
112
|
+
|
113
|
+
// Make sure we can open the file.
|
114
|
+
if(log_file == NULL)
|
115
|
+
{
|
116
|
+
rb_raise(eLogError, "Could not open logfile %s for reading: %d", log_file_name, errno);
|
117
|
+
return Qnil;
|
118
|
+
}
|
119
|
+
|
120
|
+
// Create the time to log
|
121
|
+
strftime(log_time, 100, "%Y-%M-%d %X %z", localtime(¤t_time));
|
122
|
+
|
123
|
+
|
124
|
+
// Create the string to log
|
125
|
+
sprintf(formatted_message, "[%s] [%s] %s\n", log_time, RSTRING_PTR(type), RSTRING_PTR(message));
|
126
|
+
|
127
|
+
// Write sting to log and close.
|
128
|
+
fputs(formatted_message, log_file);
|
129
|
+
fclose(log_file);
|
130
|
+
|
131
|
+
return Qnil;
|
132
|
+
}
|
133
|
+
|
134
|
+
/* @overload log_directory_check()
|
135
|
+
* @private
|
136
|
+
*
|
137
|
+
* This will check whether the log directory exists, and attempt to create it
|
138
|
+
* in the event that it doesn't.
|
139
|
+
*
|
140
|
+
* @raise [LogError] If directory creation fails.
|
141
|
+
* @return [nil]
|
142
|
+
*/
|
143
|
+
VALUE logger_log_directory_check(VALUE self)
|
144
|
+
{
|
145
|
+
int result;
|
146
|
+
|
147
|
+
#ifdef WIN32
|
148
|
+
result = _mkdir("logs/");
|
149
|
+
#else
|
150
|
+
result = mkdir("logs", S_IRWXU);
|
151
|
+
#endif
|
152
|
+
|
153
|
+
// Only raise an error if we fail to create the directory.
|
154
|
+
if(result != 0 && errno != EEXIST)
|
155
|
+
{
|
156
|
+
int error_number = errno;
|
157
|
+
rb_iv_set(self, "@status", ID2SYM(SYM(bad)));
|
158
|
+
rb_raise(eLogError, "Could not create logs/: %s", strerror(error_number));
|
159
|
+
}
|
160
|
+
|
161
|
+
return Qnil;
|
162
|
+
}
|
163
|
+
|
164
|
+
/* initializes Auto::Logger in Ruby */
|
165
|
+
void init_auto_logger()
|
166
|
+
{
|
167
|
+
cLogger = rb_define_class_under(mAuto, "Logger", rb_cObject);
|
168
|
+
rb_define_method(cLogger, "initialize", logger_init, 0);
|
169
|
+
rb_define_method(cLogger, "error", logger_error, 1);
|
170
|
+
rb_define_method(cLogger, "debug", logger_debug, 1);
|
171
|
+
rb_define_method(cLogger, "warning", logger_warning, 1);
|
172
|
+
rb_define_method(cLogger, "info", logger_info, 1);
|
173
|
+
rb_define_private_method(cLogger, "log_directory_check", logger_log_directory_check, 0);
|
174
|
+
rb_define_private_method(cLogger, "log", logger_log, 2);
|
175
|
+
}
|
176
|
+
|
177
|
+
/* vim: set ts=4 sts=4 sw=4 et cindent: */
|
@@ -0,0 +1,44 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2013, Autumn Perrault, et al.
|
3
|
+
* All rights reserved.
|
4
|
+
* This free software is distributed under the FreeBSD license (LICENSE.md).
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
|
8
|
+
#ifndef __AUTO_LOGGER_H__
|
9
|
+
#define __AUTO_LOGGER_H__
|
10
|
+
|
11
|
+
// Set format based on target OS.
|
12
|
+
#ifdef WIN32
|
13
|
+
#define LOG_FILE_FORMAT "logs\\%Y%m%d.log"
|
14
|
+
#else
|
15
|
+
#define LOG_FILE_FORMAT "logs/%Y%m%d.log"
|
16
|
+
#endif
|
17
|
+
|
18
|
+
// This is based on the desired output give or take a few characters.
|
19
|
+
#define MAX_TIME_STRING_LENGTH 18
|
20
|
+
|
21
|
+
// ("YYYY-MM-DD HH:MM:SS +ZZZZ") "YEAR-MONTH-DAY HOUR:MINUTES:SECONDS UTC_OFFSET"
|
22
|
+
#define LOG_TIME_FORMAT_LENGTH 25
|
23
|
+
|
24
|
+
VALUE cLogger;
|
25
|
+
|
26
|
+
VALUE logger_init(VALUE self);
|
27
|
+
|
28
|
+
VALUE logger_error(VALUE self, VALUE message);
|
29
|
+
|
30
|
+
VALUE logger_debug(VALUE self, VALUE message);
|
31
|
+
|
32
|
+
VALUE logger_warning(VALUE self, VALUE message);
|
33
|
+
|
34
|
+
VALUE logger_info(VALUE self, VALUE message);
|
35
|
+
|
36
|
+
VALUE logger_log(VALUE self, VALUE type, VALUE message);
|
37
|
+
|
38
|
+
VALUE logger_log_directory_check(VALUE self);
|
39
|
+
|
40
|
+
void init_auto_logger();
|
41
|
+
|
42
|
+
|
43
|
+
#endif
|
44
|
+
// __AUTO_LOGGER_H__
|
data/lib/auto.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
|
4
|
+
require 'auto/rubyext/string'
|
5
|
+
require 'auto/version'
|
6
|
+
require 'libauto' # include the native extension
|
7
|
+
require 'auto/bot'
|
8
|
+
|
9
|
+
module Auto
|
10
|
+
|
11
|
+
# @return [Boolean] Whether we're installed as a gem.
|
12
|
+
def self.gem?
|
13
|
+
begin
|
14
|
+
# If we already checked, just return the result of that.
|
15
|
+
return @gem if defined? @gem
|
16
|
+
|
17
|
+
# Otherwise, check.
|
18
|
+
result = Gem.path.each do |gempath|
|
19
|
+
break true if __FILE__ =~ /^#{Regexp.escape gempath}/
|
20
|
+
end
|
21
|
+
@gem = (result == true ? true : false)
|
22
|
+
ensure
|
23
|
+
@gem ||= false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Boolean] Whether we're running on Microsoft Windows.
|
28
|
+
def self.windows?
|
29
|
+
begin
|
30
|
+
return @windows if defined? @windows
|
31
|
+
if ::RbConfig::CONFIG['host_os'] =~ /bccwin|djgpp|mswin|mingw|cygwin|wince/i
|
32
|
+
@windows = true
|
33
|
+
else
|
34
|
+
@windows = false
|
35
|
+
end
|
36
|
+
ensure
|
37
|
+
@windows ||= false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
data/lib/auto/api.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
|
4
|
+
require 'thread'
|
5
|
+
require 'auto/api/object'
|
6
|
+
|
7
|
+
# Entering namespace: Auto
|
8
|
+
module Auto
|
9
|
+
|
10
|
+
# Entering namespace: API
|
11
|
+
module API
|
12
|
+
|
13
|
+
# A class which provides the the fundamental event system, upon which
|
14
|
+
# much of the API is based, and which follows a simple model of broadcasting
|
15
|
+
# and hooking onto such broadcasts.
|
16
|
+
#
|
17
|
+
# Plugin writers may be rather interested in {Auto::DSL::Base}, since that
|
18
|
+
# provides a simpler interface to Auto's instances of this class.
|
19
|
+
#
|
20
|
+
# @api Auto
|
21
|
+
# @since 4.0.0
|
22
|
+
# @author noxgirl
|
23
|
+
#
|
24
|
+
# @see Auto::DSL::Base
|
25
|
+
#
|
26
|
+
# @!attribute [r] threads
|
27
|
+
# @return [Array] An array of threads used by {#call}.
|
28
|
+
class Events < Auto::API::Object
|
29
|
+
|
30
|
+
attr_reader :events, :threads
|
31
|
+
|
32
|
+
# Create a new instance of Auto::API::Events.
|
33
|
+
def initialize
|
34
|
+
@events = {}
|
35
|
+
@threads = []
|
36
|
+
end
|
37
|
+
|
38
|
+
# Listen for (hook onto) an event.
|
39
|
+
#
|
40
|
+
# @param [Symbol] event The name of the event for which to listen.
|
41
|
+
# @param [Integer] priority The priority of the event from 1-5, 1 being utmost priority.
|
42
|
+
#
|
43
|
+
# @yield [...] The arguments that will be yielded to the block vary by event.
|
44
|
+
# Please consult with the {file:docs/Events.md events specification} for details by event.
|
45
|
+
#
|
46
|
+
# @return [Array(Symbol, Integer, String)] Identification data including a unique string. Keep
|
47
|
+
# this if you need to destroy the hook later.
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# events.on :disconnect do |irc|
|
51
|
+
# puts "I'm dying!"
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# @see Auto::DSL::Base#on
|
55
|
+
# @see file:docs/Events.md
|
56
|
+
def on(event, priority=3, &cb)
|
57
|
+
|
58
|
+
# Priority must be in the range of 1-5.
|
59
|
+
unless (1..5).include? priority
|
60
|
+
return 0
|
61
|
+
end
|
62
|
+
|
63
|
+
# If the event does not exist, create it.
|
64
|
+
@events[event] ||= {1 => {}, 2 => {}, 3 => {}, 4 => {}, 5 => {}}
|
65
|
+
|
66
|
+
# Generate a unique pseudorandom ID for this hook.
|
67
|
+
id = ''
|
68
|
+
10.times { id += get_rand_char }
|
69
|
+
while @events[event][priority].has_key? id
|
70
|
+
id = ''
|
71
|
+
10.times { id += get_rand_char }
|
72
|
+
end
|
73
|
+
|
74
|
+
# Create the hook in memory.
|
75
|
+
@events[event][priority][id] = cb
|
76
|
+
|
77
|
+
[event, priority, id]
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# Broadcast an event and associated arguments.
|
82
|
+
#
|
83
|
+
# The arguments are globbed into an array from the list passed to the
|
84
|
+
# method, so be sure to format your call correctly.
|
85
|
+
#
|
86
|
+
# If a hook returns +false+, all subsequent hook executions will be
|
87
|
+
# forestalled from occurring.
|
88
|
+
#
|
89
|
+
# @param [Symbol] event The event being broadcasted.
|
90
|
+
# @param [Array] args A list of arguments which should be passed to
|
91
|
+
# the listeners. (splat)
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# events.call(:cow_moo, "the cows", "go moo", [1, 3, 5])
|
95
|
+
#
|
96
|
+
# @see Auto::DSL::Base#emit
|
97
|
+
def call(event, *args)
|
98
|
+
# Check if any hooks exist for this event.
|
99
|
+
if @events.include? event
|
100
|
+
$m.debug("A thread is spawning for the sake of a broadcast of event {#{event}}.") if $m.opts.verbose?
|
101
|
+
@threads << Thread.new(event) do |evnt|
|
102
|
+
status = nil
|
103
|
+
begin # catch exceptions
|
104
|
+
# Iterate through the hooks.
|
105
|
+
@events[evnt].each_key do |priority|
|
106
|
+
@events[evnt][priority].each_value do |prc|
|
107
|
+
status = prc.call(*args) unless status == false
|
108
|
+
end # each hook
|
109
|
+
end # each priority
|
110
|
+
rescue => e
|
111
|
+
$m.error "An exception occurred inside the thread of #{event}: #{e}", false, e.backtrace
|
112
|
+
$m.error "Said thread has terminated with a backtrace report."
|
113
|
+
end # begin
|
114
|
+
end # thread
|
115
|
+
end # whether this event exists
|
116
|
+
end
|
117
|
+
|
118
|
+
# Delete a hook or listener.
|
119
|
+
#
|
120
|
+
# @param [Array(Symbol, Integer, String)] id The identification data of the hook,
|
121
|
+
# as provided by #on.
|
122
|
+
#
|
123
|
+
# @see Auto::DSL::Base#undo_on
|
124
|
+
def del(id)
|
125
|
+
event, priority, hook = id
|
126
|
+
|
127
|
+
if @events.has_key? event
|
128
|
+
if @events[event][priority].has_key? hook
|
129
|
+
@events[event][priority].delete(hook)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
tidy
|
134
|
+
end
|
135
|
+
|
136
|
+
# Terminate all active threads.
|
137
|
+
def die
|
138
|
+
@threads.each do |thr|
|
139
|
+
thr.kill if thr.active?
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
#######
|
144
|
+
private
|
145
|
+
#######
|
146
|
+
|
147
|
+
# Tidy up.
|
148
|
+
def tidy
|
149
|
+
@events.each do |name, lists|
|
150
|
+
empty = true
|
151
|
+
empty = lists.each_value { |v| break false if not v.empty? }
|
152
|
+
if empty
|
153
|
+
# Drop the event.
|
154
|
+
@events.delete name
|
155
|
+
next
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end # class Events
|
161
|
+
|
162
|
+
end # module API
|
163
|
+
|
164
|
+
end # module Auto
|
165
|
+
|
166
|
+
# vim: set ts=4 sts=2 sw=2 et:
|