-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtutorial.jsmod
More file actions
239 lines (164 loc) · 8.76 KB
/
Copy pathtutorial.jsmod
File metadata and controls
239 lines (164 loc) · 8.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/* ***** BEGIN LICENSE BLOCK *****
* Version: GNU GPL 3.0
*
* The contents of this file are subject to the
* GNU General Public License Version 3.0; you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
* http://www.gnu.org/licenses/gpl.html
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* ***** END LICENSE BLOCK ***** */
// This is a module constructor ( in JavaScript, a constructor is like a OOP class )
// $D is initialized to core data structure.
// Data is not reachable directly, you need to use getData,
// setData, hasData API to handle data ( see dataObject.js )
// $A contains the common API and the exported module API ( defined in moduleApi )
// This API is a mix between core function exported to modules and modules function exported to modules.
// $S is the core state object.
// The state object allows to be aware of what happen in the bot.
(function TutorialModule($D, $A, $S) {
// This avoid the module to be loaded.
// Usualy, this line does not appears or disable is set to false ( result is the same ).
this.disabled = true;
// first, the module has to define it's name, usualy, it is the name of the constructor function ( "BlankModule" here )
// but you are free to use the name you want.
this.name = this.constructor.name;
// $MD is just a simple shortcut link to the core data.
// This allows an easy access to the module's part of the configuration ( see configuration.js )
var $MD = $D[this.name];
// AsyncProcHelper helps us to manage (start/stop) the procedure easily,
// else, we have to deal with: new Procedure(...) / StartAsyncProc / StopAsyncProc.
var sendTheDateEveryMinute = new AsyncProcHelper(
// The following function is an aynchronous procedure. At the application level,
// it is quite similar to a working thread without any need of synchronization.
// BEWARE: the function must contain at least one yield instruction to work,
// else JavaScript engine will threat it as a simple function.
// Each time a yield instruction is encounter, the procesure is stopped until the result is received.
// While the function is stopped, the bot continue to run.
function( channel ) {
// this is a procedure that never ends unless you use a function like StopAsyncProc, in witch case, the finally section will be called
try {
for (;;) {
// Use Privmsg function from the common API ($A) to send a message to the channel.
$A.Privmsg( channel, new Date() );
// Sleep one minute.
// NOTICE: the following code is equivalent to:
// yield function(callback) io.AddTimeout( delay, callback );
yield AsyncSleep( 1*MINUTE );
}
} finally {
$A.Privmsg( channel, 'Bye, now you have to get the time by yourself' );
}
}
);
// This is another asynchronus procedure.
// The difference with the previous one is that this procedure do not run forever and may be executed several times.
function AskANumber(nick) {
var number;
do {
// Prompt function is defined by the module CommandEventModule and is used to ask something to someone.
var [status, message] = yield function(callback) $A.Prompt(nick, 'Please give me a number', callback );
if ( status != OK )
return;
number = parseInt(message);
if ( number == NaN )
$A.Privmsg( nick, 'Hey, this is not a number !' );
} while ( number == NaN );
$A.Privmsg( nick, 'Good, '+number+' this is a number. Bye!' );
}
// this.moduleListener is a tree where the leafs are functions, each tree level is an argument value of the final function.
// In the following case, ircMsg is at the first level of the tree and is a filter to the first argument of the function.
// Only 'ircMsg' messages will fire the function.
// NOTE: the following syntax that is used to create this.messageListener is called "Object Initializer"
// see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Creating_New_Objects:Using_Object_Initializers
// moduleListener is used to listen events dispatched by other modules
this.moduleListener = {
ircMsg: {
// This function is called each time a PRIVMSG command is received from the server.
// command argument is the name of the command itself ( PRIVMSG here ).
// from argument is who sent the message.
// to argument contains the destination of the message ( channel or a nickname )
PRIVMSG: function( command, from, to, msg ) {
// IsBotOp is an AIP function defined in the operator module ( operator.jsmod )
if ( !$A.IsBotOp(from) )
return;
// this function is often used to extract the nickname from the 'from' argument that looks like "nickName!hostname.com"
var nick = StrBefore(from, '!');
var replyTo = to[0] == '#' ? to : nick;
// call Privmsg (defined in default.jsmod ) to send data to a user or a channel
$A.Privmsg( replyTo, 'listening' );
}
},
// botcmd messages are sent by bodCmd.jsmod module and allow you to manage commands like: !echo test
botcmd: {
// the following function is called when someone type !help
help: function( modCmd, cmdName, cmdData, command, from, to, msg ) {
// if the !help command has only to be used in a channel context, not with a private message then use this:
if ( to[0] != '#' )
return;
// if you want to restrict this command to one channel only, you have to do this:
if ( $A.NormalizeChannelName(to) != '#jsircbot' )
return;
$A.Privmsg( to, 'listening' );
},
num: function( modCmd, cmdName, cmdData, command, from, to, msg ) {
// again, replyTo contains either a nickname or a channel name
var replyTo = to[0] == '#' ? to : StrBefore(from, '!');
// the argument cmdData is the string that cames just after the botcommand name ( !<botCmd> <cmdData> )
if ( cmdData ) {
StartAsyncProc( AskANumber(cmdData) );
} else {
// if !num is called without arguments, display some help
$A.Privmsg( replyTo, 'type !num <nick name>' );
}
},
date: function( modCmd, cmdName, cmdData, command, from, to, msg ) {
if ( to[0] != '#' )
return;
// because the "sendTheDateEveryMinute" procedure accepts a channel name on start,
// it is impossible to use the Toggle function.
if ( sendTheDateEveryMinute.running ) {
// Stop the running procedure.
// BEWARE: This call will failed if the procedure is not started.
sendTheDateEveryMinute.Stop();
} else {
// Start the 'sendTheDateEveryMinute' procedure with the channel name as argument.
// BEWARE: It is up to you to check the that procedure is not already running.
sendTheDateEveryMinute.Start(to);
}
}
}
}
// The following object contains some API functions that the module wants to export to other modules.
// When the module is unloaded, this object is used to remove its API from the common API ( alias $A )
this.moduleApi = {
// This API function can be used in any module.
// BEWARE: Because module loading is asynchronous, You have to ensure that the API is defined before using it.
// Because messageListener and moduleListener calls are enclosed by a try..catch, even if the API is not defined,
// the bot will not crash.
// In this case, if the default module is not yet loaded, SayHello says nothing.
SayHello: function(to) {
$A.Privmsg && $A.Privmsg( to, 'Hello' );
}
}
// the state listener is used to be aware of any state changes ( eg. connecting state to connected state, ... )
// stateListener is an array of objects.
// When module is loaded ( module loading may be assynchronous ), its name is used as a state,
// then you can know when a module is loaded or unloaded.
this.stateListener = [
{
// set is a function that returns true or false. It contains the condition required to call the trigger function.
// in this case, trigger is call (with polarity=true) if the bot is in STATE_IRC_INTERACTIVE state and the default module is loaded
set: function(s) s.STATE_IRC_INTERACTIVE && s.DefaultModule,
// reset give the condition to to call the trigger function with false as argument
reset: function(s) !s.STATE_IRC_INTERACTIVE || !s.DefaultModule,
// the trigger function is only call on state transition
trigger: function(polarity) {
//
}
}
];
})