syndi 0.1.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.
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: */