syndi 0.1.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +12 -0
  3. data/CHANGELOG.md +0 -0
  4. data/Gemfile +8 -0
  5. data/LICENSE +28 -0
  6. data/README.md +104 -0
  7. data/Rakefile +30 -0
  8. data/WINDOWS.md +64 -0
  9. data/bin/syndi +102 -0
  10. data/bin/syndi-conf +47 -0
  11. data/conf/example.yml +101 -0
  12. data/docs/Events.md +103 -0
  13. data/docs/Upgrade.md +16 -0
  14. data/ext/csyndi/events.c +50 -0
  15. data/ext/csyndi/extconf.rb +20 -0
  16. data/ext/csyndi/integer.c +53 -0
  17. data/ext/csyndi/libauto.c +37 -0
  18. data/ext/csyndi/logger.c +229 -0
  19. data/include/syndi.h +22 -0
  20. data/include/syndi/csyndi.h +38 -0
  21. data/include/syndi/events.h +19 -0
  22. data/include/syndi/integer.h +17 -0
  23. data/include/syndi/logger.h +56 -0
  24. data/lib/csyndi.so +0 -0
  25. data/lib/syndi.rb +137 -0
  26. data/lib/syndi/actress.rb +12 -0
  27. data/lib/syndi/api.rb +7 -0
  28. data/lib/syndi/api/object.rb +29 -0
  29. data/lib/syndi/bot.rb +266 -0
  30. data/lib/syndi/config.rb +113 -0
  31. data/lib/syndi/dsl/base.rb +74 -0
  32. data/lib/syndi/dsl/irc.rb +13 -0
  33. data/lib/syndi/events.rb +130 -0
  34. data/lib/syndi/irc.rb +8 -0
  35. data/lib/syndi/irc/common.rb +63 -0
  36. data/lib/syndi/irc/library.rb +89 -0
  37. data/lib/syndi/irc/object/channel.rb +21 -0
  38. data/lib/syndi/irc/object/entity.rb +90 -0
  39. data/lib/syndi/irc/object/message.rb +99 -0
  40. data/lib/syndi/irc/object/user.rb +139 -0
  41. data/lib/syndi/irc/protocol.rb +161 -0
  42. data/lib/syndi/irc/protocol/numerics.rb +60 -0
  43. data/lib/syndi/irc/sasl/diffie_hellman.rb +36 -0
  44. data/lib/syndi/irc/sasl/mech.rb +7 -0
  45. data/lib/syndi/irc/sasl/mech/dh_blowfish.rb +83 -0
  46. data/lib/syndi/irc/sasl/mech/plain.rb +39 -0
  47. data/lib/syndi/irc/server.rb +301 -0
  48. data/lib/syndi/irc/state/channel_manager.rb +6 -0
  49. data/lib/syndi/irc/state/support.rb +142 -0
  50. data/lib/syndi/irc/state/user_manager.rb +6 -0
  51. data/lib/syndi/irc/std/commands.rb +99 -0
  52. data/lib/syndi/irc/std/numerics.rb +216 -0
  53. data/lib/syndi/jewel.rb +5 -0
  54. data/lib/syndi/jewel/specification.rb +121 -0
  55. data/lib/syndi/jewel/util.rb +27 -0
  56. data/lib/syndi/rubyext/string.rb +10 -0
  57. data/lib/syndi/verbosity.rb +10 -0
  58. data/lib/syndi/version.rb +38 -0
  59. data/spec/helper.rb +37 -0
  60. data/spec/syndi/events_spec.rb +89 -0
  61. data/tasks/compile.rake +15 -0
  62. data/tasks/install.rake +10 -0
  63. data/tasks/package.rake +13 -0
  64. data/tasks/spec.rake +12 -0
  65. metadata +243 -0
data/docs/Events.md ADDED
@@ -0,0 +1,103 @@
1
+ # @title Specification of Events
2
+
3
+ Specification of Events
4
+ =======================
5
+
6
+ **Events** are managed by Syndi's event systems, each of which is an instance
7
+ of {Syndi::API::Events}.
8
+
9
+ `$m.events` manages the **Syndi** events, which is to say the central events,
10
+ while libraries have their own individual events systems.
11
+
12
+ {Syndi::DSL::Base} provides `#on`, `#emit`, `#undo_on`, etc., which all provide
13
+ easy distinction between the individual event systems. `:syndi`, for example,
14
+ indicates the central system, whereas `:irc` indicates the IRC event system.
15
+
16
+ :syndi
17
+ -----
18
+
19
+ ### :start
20
+
21
+ This event occurs when Syndi is starting, and each library is expected to await
22
+ this event and upon its occurrence, initiate any of their processes.
23
+
24
+ ### :die `|reason|`
25
+
26
+ **reason** (_String_): The reason for termination.
27
+
28
+ This occurs when Syndi is terminating.
29
+
30
+ ### :net_receive `|socket_object|`
31
+
32
+ **socket_object** (_Object_): The object with which the socket (`.socket`) is
33
+ associated.
34
+
35
+ This occurs when the socket associated with `socket_object` has data waiting to
36
+ be read (as determined by `select()`).
37
+
38
+ ### :rehash
39
+
40
+ This event occurs when the configuration file is successfully reprocessed and
41
+ reloaded.
42
+
43
+ :irc
44
+ ----
45
+
46
+ ### :preconnect |irc|
47
+
48
+ **irc** (_Syndi::IRC::Server_): The IRC connection.
49
+
50
+ This event occurs when we are about to register (i.e., send `USER`, `CAP LS`)
51
+ on the server and initiate connection.
52
+
53
+ ### :receive |irc, data|
54
+
55
+ **irc** (_Syndi::IRC::Server_): The IRC connection.
56
+ **data** (_String_): The line of data.
57
+
58
+ This event occurs when data has been removed from the receive queue and is ready
59
+ for processing, with newlines and carriage returns stripped.
60
+
61
+ ### :connected |irc|
62
+
63
+ **irc** (_Syndi::IRC::Server_): The IRC connection.
64
+
65
+ This event occurs after ISUPPORT has been received and processed, and the
66
+ connection is fully established.
67
+
68
+ Typically, at this point, any traditional service identification and syndijoining
69
+ occurs.
70
+
71
+ ### :disconnect |irc, reason|
72
+
73
+ **irc** (_Syndi::IRC::Server_): The IRC connection.
74
+ **reason** (_String_): The reason for which we are disconnecting.
75
+
76
+ This event occurs when we're about to disconnect from the given server.
77
+
78
+ ### :send_join |irc, channel, key|
79
+
80
+ **irc** (_Syndi::IRC::Server_): The IRC connection.
81
+ **channel** (_String_): The channel which we are attempting to join.
82
+ **key** (_String_ or _nil_): The key, if provided.
83
+
84
+ This event occurs when we try to join a channel.
85
+
86
+ ### :send_nick |irc, nickname|
87
+
88
+ **irc** (_Syndi::IRC::Server_): The IRC connection.
89
+ **nickname** (_String_): The nickname we are trying to use.
90
+
91
+ This occurs when we try to change our nickname with /NICK.
92
+
93
+ ### :self_who |irc|
94
+
95
+ **irc** (_Syndi::IRC::Server_): The IRC connection.
96
+
97
+ This occurs when we send a /WHO on ourselves.
98
+
99
+ ### irc:onWhoReply `[all strs](irc*, nick, username, host, realname, awaystatus, server)`
100
+
101
+ This event occurs when the bot receives **RPL_WHOREPLY** (numeric 352) in response to a /WHO. Note that
102
+ `awaystatus =~ /H/` will be true if the user is not away, while `awaystatus =~ /G/` will be true if the
103
+ user is away (`H` meaning _here_, `G` meaning _gone_).
data/docs/Upgrade.md ADDED
@@ -0,0 +1,16 @@
1
+ # @title Upgrade Syndi 3 to 4
2
+
3
+ Upgrade Syndi 3 to 4
4
+ ===================
5
+
6
+ Summary
7
+ -----------
8
+ Syndi 3 was a comprehensive release of Syndi, and is currently available from
9
+ [Arinity](https://github.com/arinity/Syndi). As all things should hopefully improve
10
+ however, this fourth major revision was begun.
11
+
12
+ Nonetheless, we recognize that it is essential that we provide a means by which
13
+ Syndi users may upgrade their old configuration files and databases to function
14
+ with Syndi 4.
15
+
16
+ We intend to address this matter when Syndi 4 is nearer stability.
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Copyright (c) 2013, Autumn Perrault, et al.
3
+ * All rights reserved.
4
+ * This free software is distributed under the FreeBSD license (see LICENSE).
5
+ *
6
+ */
7
+
8
+ #include "syndi.h"
9
+
10
+ VALUE cEvents;
11
+
12
+ static VALUE events_initialize(VALUE self)
13
+ {
14
+ rb_iv_set(self, "@events", rb_hash_new());
15
+ rb_iv_set(self, "@threads", rb_ary_new());
16
+ return self;
17
+ }
18
+
19
+ static VALUE events_on(VALUE self, VALUE event, VALUE rbpriority, VALUE prc)
20
+ {
21
+ int i, priority;
22
+
23
+ // convert the priority to an integer
24
+ priority = FIX2INT(rbpriority);
25
+
26
+ // priority must be 1-5
27
+ if (priority <= 1 || priority >= 5)
28
+ return Qnil;
29
+
30
+ // if the event does not exist, create it
31
+ if (rb_hash_aref(rb_iv_get(self, "@events"), event) == Qnil) {
32
+ rb_hash_aset(rb_iv_get(self, "@events"), event, rb_hash_new());
33
+ for (i = 1; i <= 5; ++i)
34
+ rb_hash_aset(rb_hash_aref(rb_iv_get(self, "@events"), event), INT2FIX(i), rb_hash_new());
35
+ }
36
+
37
+
38
+
39
+ return Qnil;
40
+ }
41
+
42
+ /* initialize Syndi::Events */
43
+ static void init_events()
44
+ {
45
+ cEvents = rb_define_class_under(mSyndi, "Events", SYM(Syndi::API::Object));
46
+ rb_define_method(cEvents, "initialize", events_initialize, 0);
47
+ rb_define_method(cEvents, "on", events_on, 3);
48
+ }
49
+
50
+ /* vim: set ts=4 sts=4 sw=4 et cindent: */
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
3
+ # This free software is distributed under the FreeBSD license (see LICENSE).
4
+
5
+ require 'mkmf'
6
+
7
+ EXT = 'csyndi'
8
+
9
+ LIBSYNDI_DIR = File.expand_path(File.join('..', '..', '..', 'include'), __FILE__)
10
+ unless Dir.exists? LIBSYNDI_DIR
11
+ STDERR.puts "csyndi headers are missing; your copy of Syndi is most probably broken."
12
+ exit 1
13
+ end
14
+
15
+ $CFLAGS << " -Wno-unused-function"
16
+ $CFLAGS << " -I#{LIBSYNDI_DIR}"
17
+
18
+ create_makefile EXT
19
+
20
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,53 @@
1
+ /*
2
+ * Copyright (c) 2013, Autumn Perrault, et al.
3
+ * All rights reserved.
4
+ * This free software is distributed under the FreeBSD license (see LICENSE).
5
+ *
6
+ */
7
+
8
+ #include "syndi.h"
9
+
10
+ /* SWAR algorithm for finding the number of set bits. */
11
+ VALUE swar_bits_set(VALUE self)
12
+ {
13
+ long long l = NUM2LONG(self);
14
+ l -= ((l >> 1) & 0x55555555);
15
+ l = (l & 0x33333333) + ((l >> 2) & 0x33333333);
16
+ return INT2FIX((((l + (l >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
17
+ }
18
+
19
+ /* c = PI(n-1, i=0, (b^2^i)) % m */
20
+ VALUE modular_power(VALUE self, VALUE exponent, VALUE modulus)
21
+ {
22
+ VALUE result = INT2FIX(1);
23
+ VALUE base = self;
24
+
25
+ int exp = NUM2INT(exponent);
26
+
27
+ if( (modulus << 1) == 0 )
28
+ {
29
+ // Avoid divide by zero
30
+ return Qnil;
31
+ }
32
+
33
+ while(exp > 0)
34
+ {
35
+ if(exp & 1)
36
+ result = rb_funcall(rb_funcall(result, SYM(*), 1, base), SYM(%), 1, modulus);
37
+ exp >>= 1;
38
+ base = rb_funcall(rb_funcall(base, SYM(*), 1, base), SYM(%), 1, modulus);
39
+ }
40
+
41
+ // If the numbers become an issue we will switch to INT2NUM to allow for Bignums
42
+ return result;
43
+ }
44
+
45
+ /* initialize extension of Ruby stdlib Integer */
46
+ void init_integer()
47
+ {
48
+ rb_define_method(rb_cInteger, "bits_set", swar_bits_set, 0);
49
+ rb_define_method(rb_cInteger, "mod_exp", modular_power, 2);
50
+ }
51
+
52
+ /* vim: set ts=4 sts=4 sw=4 et cindent: */
53
+
@@ -0,0 +1,37 @@
1
+ /*
2
+ * Copyright (c) 2013, Autumn Perrault, et al.
3
+ * All rights reserved.
4
+ * This free software is distributed under the FreeBSD license (see LICENSE).
5
+ *
6
+ */
7
+
8
+ #include "syndi.h"
9
+
10
+ VALUE mSyndi;
11
+ VALUE eLogError;
12
+ VALUE ePluginError;
13
+ VALUE eConfigError;
14
+ VALUE eDatabaseError;
15
+
16
+ /* initialize exceptions */
17
+ void initialize_exceptions()
18
+ {
19
+ eLogError = rb_define_class_under(mSyndi, "LogError", rb_eStandardError);
20
+ ePluginError = rb_define_class_under(mSyndi, "PluginError", rb_eStandardError);
21
+ eConfigError = rb_define_class_under(mSyndi, "ConfigError", rb_eStandardError);
22
+ eDatabaseError = rb_define_class_under(mSyndi, "DatabaseError", rb_eStandardError);
23
+ }
24
+
25
+ /* initialize Syndi module */
26
+ void Init_csyndi()
27
+ {
28
+ mSyndi = rb_define_module("Syndi");
29
+ /* initialize exceptions */
30
+ initialize_exceptions();
31
+ /* initialize Syndi::Logger */
32
+ init_syndi_logger();
33
+ /* extend Ruby stdlib Integer */
34
+ init_integer();
35
+ }
36
+
37
+ /* vim: set ts=4 sts=4 sw=4 et cindent: */
@@ -0,0 +1,229 @@
1
+ /*
2
+ * Copyright (c) 2013, Autumn Perrault, et al.
3
+ * All rights reserved.
4
+ * This free software is distributed under the FreeBSD license (see LICENSE).
5
+ *
6
+ */
7
+
8
+ #include "syndi.h"
9
+
10
+ VALUE cLogger;
11
+
12
+ /* This will print a verbose message to STDOUT if the level of verbosity specified does
13
+ * not exceed the runtime verbosity.
14
+ */
15
+ static void log_out2scrn(int type, const char *message, int level)
16
+ {
17
+ char *real_type = ALLOCA_N(char, 12);
18
+
19
+ if (FIX2INT(rb_gv_get("$VERBOSITY")) < level)
20
+ return;
21
+
22
+ switch (type) {
23
+ case TYPE_FATAL:
24
+ real_type = RSTRING_PTR(rb_funcall(rb_str_new2("FATAL ERROR:"), SYM(red), 0));
25
+ break;
26
+ case TYPE_ERROR:
27
+ real_type = RSTRING_PTR(rb_funcall(rb_str_new2("ERROR:"), SYM(red), 0));
28
+ break;
29
+ case TYPE_WARNING:
30
+ real_type = RSTRING_PTR(rb_funcall(rb_str_new2("WARNING:"), SYM(red), 0));
31
+ break;
32
+ case TYPE_INFO:
33
+ real_type = RSTRING_PTR(rb_funcall(rb_str_new2("***"), SYM(green), 0));
34
+ break;
35
+ case TYPE_DEBUG:
36
+ real_type = RSTRING_PTR(rb_funcall(rb_str_new2("==>"), SYM(magenta), 0));
37
+ break;
38
+ }
39
+
40
+ printf("%s %s%s", real_type, message, OS_LINE_TERM);
41
+ }
42
+
43
+ /* This will foremost call log_dircheck() to ensure the presence of the log
44
+ * directory, and then it will output the message to today's logfile.
45
+ */
46
+ static void log_out2file(const char *type, const char *message)
47
+ {
48
+ char *log_file_name = ALLOCA_N(char, MAX_TIME_STRING_LENGTH + 1);
49
+ char *log_time = ALLOCA_N(char, LOG_TIME_FORMAT_LENGTH + 1);
50
+ FILE *log_file;
51
+
52
+ /* 8 is the number of extra characters i.e " ", "[]", "\n" */
53
+ size_t output_string_size = 8 + strlen(type) + strlen(message) + LOG_TIME_FORMAT_LENGTH;
54
+ char *formatted_message = ALLOCA_N(char, ++output_string_size);
55
+ time_t current_time;
56
+
57
+ /* Ensure the log directory's existence. */
58
+ log_dircheck();
59
+
60
+ time(&current_time);
61
+
62
+ strftime(log_file_name, 100, LOG_FILE_FORMAT, localtime(&current_time));
63
+
64
+ log_file = fopen(log_file_name, "a+");
65
+ if (log_file == NULL)
66
+ {
67
+ rb_raise(eLogError, "Could not open logfile %s for reading: %d", log_file_name, errno);
68
+ return;
69
+ }
70
+
71
+ /* Fetch the current time and format the message. */
72
+ strftime(log_time, 100, "%Y-%M-%d %X %z", localtime(&current_time));
73
+ sprintf(formatted_message, "[%s] [%s] %s%s", log_time, type, message, OS_LINE_TERM);
74
+
75
+ /* Write to file. */
76
+ fputs(formatted_message, log_file);
77
+ fclose(log_file);
78
+ }
79
+
80
+ /* Ensure the existence of the log directory. */
81
+ static void log_dircheck()
82
+ {
83
+ int result;
84
+ char *dir = ALLOCA_N(char, strlen(SYNDI_DIR) + 5);
85
+
86
+ #ifdef _WIN32
87
+ sprintf(dir, "%s\\logs", SYNDI_DIR);
88
+ result = _mkdir(dir);
89
+ #else
90
+ sprintf(dir, "%s/logs", SYNDI_DIR);
91
+ result = mkdir(dir, S_IRWXU);
92
+ #endif
93
+
94
+ // Only raise an error if we fail to create the directory.
95
+ if (result != 0 && errno != EEXIST)
96
+ {
97
+ int error_number = errno;
98
+ rb_raise(eLogError, "Could not create %s: %s", dir, strerror(error_number));
99
+ }
100
+ }
101
+
102
+ /* @overload initialize()
103
+ * Constructs a new Syndi::Logger instance.
104
+ *
105
+ * @return [Syndi::Logger]
106
+ */
107
+ VALUE logger_init(VALUE self)
108
+ {
109
+ log_dircheck();
110
+ return self;
111
+ }
112
+
113
+ /* @overload fatal(message)
114
+ * This will log +message+ as a fatal error, as well as kill the program.
115
+ *
116
+ * @param [String] message The fatal error message to be reported.
117
+ * @return [nil]
118
+ */
119
+ VALUE logger_fatal(VALUE self, VALUE message)
120
+ {
121
+ char *msg = RSTRING_PTR(message);
122
+ log_out2file("FATAL ERROR", msg);
123
+ log_out2scrn(TYPE_FATAL, msg, 0);
124
+ rb_exit(1);
125
+ return Qnil;
126
+ }
127
+
128
+ /* @overload error(message)
129
+ * This will log +message+ as an error, optionally also outputting +backtrace+,
130
+ * the data for which shall be obtained from Kernel#caller.
131
+ *
132
+ * @param [String] message The error message to be reported.
133
+ * @param [Boolean] backtrace Whether to output a backtrace.
134
+ * @return [nil]
135
+ */
136
+ VALUE logger_error(int argc, VALUE *argv, VALUE self)
137
+ {
138
+ VALUE message;
139
+ VALUE backtrace;
140
+ VALUE bt_bool;
141
+ char *msg;
142
+
143
+ rb_scan_args(argc, argv, "11", &message, &bt_bool);
144
+
145
+ msg = RSTRING_PTR(message);
146
+ log_out2file("ERROR", msg);
147
+ log_out2scrn(TYPE_ERROR, msg, 0);
148
+
149
+ if (bt_bool == Qtrue)
150
+ {
151
+ backtrace = rb_funcall(rb_cObject, SYM(caller), 0);
152
+ fprintf(stderr, "Backtrace:%s", OS_LINE_TERM);
153
+ rb_funcall(rb_stderr, SYM(puts), 1, backtrace);
154
+ }
155
+
156
+ return Qnil;
157
+ }
158
+
159
+ /* @overload warn(message)
160
+ * This will log +message+ as a warning.
161
+ *
162
+ * @param [String] message The admonitory message to be reported.
163
+ * @return [nil]
164
+ */
165
+ VALUE logger_warn(VALUE self, VALUE message)
166
+ {
167
+ char *msg = RSTRING_PTR(message);
168
+ log_out2file("WARNING", msg);
169
+ log_out2scrn(TYPE_WARNING, msg, 0);
170
+ return Qnil;
171
+ }
172
+
173
+ /* @overload info(message)
174
+ * This will log +message+ as an informative message.
175
+ *
176
+ * @param [String] message The information to be reported.
177
+ * @return [nil]
178
+ */
179
+ VALUE logger_info(VALUE self, VALUE message)
180
+ {
181
+ char *msg = RSTRING_PTR(message);
182
+ log_out2file("INFO", msg);
183
+ log_out2scrn(TYPE_INFO, msg, 0);
184
+ return Qnil;
185
+ }
186
+
187
+ /* @overload verbose(message, level)
188
+ * Yield a message of verbosity magic. This will execute any block it is
189
+ * passed (*implicit!*).
190
+ *
191
+ * @param [String] message The message to be reported.
192
+ * @param [Integer] level The level of verbosity. We recommend +VSIMPLE+,
193
+ * +VUSEFUL+, or +VNOISY+.
194
+ *
195
+ * @return [nil]
196
+ */
197
+ VALUE logger_verbose(VALUE self, VALUE message, VALUE level)
198
+ {
199
+ char *msg = RSTRING_PTR(message);
200
+ int vrb = FIX2INT(level);
201
+
202
+ /* check verbosity */
203
+ if (FIX2INT(rb_gv_get("$VERBOSITY")) < vrb)
204
+ return Qnil;
205
+
206
+ /* log */
207
+ log_out2file("DEBUG", msg);
208
+ log_out2scrn(TYPE_DEBUG, msg, vrb);
209
+
210
+ /* execute the block */
211
+ if (rb_block_given_p())
212
+ rb_yield(Qnil);
213
+
214
+ return Qnil;
215
+ }
216
+
217
+ /* initializes Syndi::Logger in Ruby */
218
+ void init_syndi_logger()
219
+ {
220
+ cLogger = rb_define_class_under(mSyndi, "Logger", rb_cObject);
221
+ rb_define_method(cLogger, "initialize", logger_init, 0);
222
+ rb_define_method(cLogger, "fatal", logger_fatal, 1);
223
+ rb_define_method(cLogger, "error", logger_error, -1);
224
+ rb_define_method(cLogger, "verbose", logger_verbose, 2);
225
+ rb_define_method(cLogger, "warn", logger_warn, 1);
226
+ rb_define_method(cLogger, "info", logger_info, 1);
227
+ }
228
+
229
+ /* vim: set ts=4 sts=4 sw=4 et cindent: */