switch to RcB2 build sys
[rofl0r-jsbot.git] / ircbot.js
blob00034c989373ce6eb0b4c95392311e1736ae1f60
1 /* this bot has some privileged commands. in order to authenticate to the bot,
2    send the command ",op" once you brought it online for the first time.
3    it will then write your hostmask into the json savefile and will from then
4    on only accept privileged commands from your hostmask.
5    note: that means you should use a registered account so your hostmask
6    is always the same. */
8 var botname = "";
9 var lastchan = "";
10 var connected = false;
11 var names;
13 var settings = (function() {
14         var tmp = readsettings() ||
15         '{"chans":{"#reaver":{"autojoin":true}},"doAuth":false,"nickservpass":"p4ssw0rd"}';
16         return JSON.parse(tmp);
17 })();
18 function part(chan) {send("PART " + chan);}
19 function join(chan) {send("JOIN " + chan);}
20 function init_chan_settings(chan) {
21         if(!(chan in settings.chans)) settings.chans[chan] = {};
23 function get_chan_setting(chan, setting) {
24         init_chan_settings(chan);
25         return settings.chans[chan][setting];
27 /* this function is the first function called after the bot is
28  * connected. use it to load settings, auth, join channels, etc */
29 function connect() {
30         connected = true;
31         for(var chan in settings.chans) {
32                 if(get_chan_setting(chan, "autojoin")) join(chan);
33         }
36 function save_settings() {writesettings(JSON.stringify(settings, null, "\t"));}
38 function set_global(key, value) {
39         settings[key] = value;
40         save_settings();
42 function set_chan(chan, key, value) {
43         init_chan_settings(chan);
44         settings.chans[chan][key] = value;
45         save_settings();
48 function add_note(chan, mask, rcp, msg) {
49         init_chan_settings(chan);
50         if(!("notes" in settings.chans[chan]))
51                 settings.chans[chan]["notes"] = [];
52         settings.chans[chan]["notes"].push(
53                 {"sender":nick_from_mask(mask), "recipient": rcp, "message":msg});
54         save_settings();
55         return true;
57 function dispatch_note(chan, index) {
58         var note = settings.chans[chan]["notes"].splice(index,1)[0];
59         privmsg(chan, note.recipient + ": " + note.sender + " left the following note for you: " + note.message);
60         save_settings();
62 function check_notes(chan, usr) {
63         if("notes" in settings.chans[chan]) {
64                 for (var i = 0; i < settings.chans[chan]["notes"].length;) {
65                         var note = settings.chans[chan]["notes"][i];
66                         if(note.recipient === usr) dispatch_note(chan, i);
67                         else i++;
68                 }
69         }
72 function botnick(nick) {
73         botname = nick;
75 function selfjoin(chan, nick) {
76 //      privmsg(settings.master, "selfjoin chan " + chan + ", nick "+ nick);
77         botname = nick;
78         lastchan = chan;
79         if(get_chan_setting(chan, "dogreet")) privmsg(chan, "hi " + chan);
81 function has_status_sign(name) {
82         return (name.charAt(0) === '@' || name.charAt(0) === '+');
84 function nameshandler(chan, namelist) {
85         if(typeof names === 'undefined') names = {};
86         var nameblock = namelist.split(" ");
87         if(!(chan in names)) names[chan] = nameblock;
88         else names[chan] = names[chan].concat(nameblock);
90         // remove operator and voice signs
91         for(var i=0; i<names[chan].length;i++) {
92                 if(has_status_sign(names[chan][i]))
93                         names[chan][i] = names[chan][i].substring(1);
94         }
96 function add_name(chan, name) {
97         names[chan].push(name);
99 function remove_name(chan, name) {
100         for(var i = 0; i < names[chan].length; i++)
101                 if(names[chan][i] === name) {
102                         names[chan].splice(i,1);
103                         return;
104                 }
106 function change_name(chan, name, newname) {
107         for(var i = 0; i < names[chan].length; i++)
108                 if(names[chan][i] === name) {
109                         names[chan][i] = newname;
110                         return;
111                 }
113 function remove_name_global(name) {
114         for(var chan in names) {
115                 remove_name(chan, name);
116         }
118 function nickchange(oldnick, newnick) {
119         //privmsg(settings.master, "nickchange " + oldnick + " -> " + newnick);
120         for(var chan in names) {
121                 change_name(chan, oldnick, newnick);
122         }
124 function quithandler(nick, mask, msg) {
125         if(get_chan_setting(lastchan, "dogreet"))
126                 privmsg(lastchan, "hmm. " + nick + " didn't like it here (" + msg + ")");
127         remove_name_global(nick);
129 function joinhandler(chan, nick, mask) {
130         lastchan = chan;
131         if(nick !== botname) {
132                 if(get_chan_setting(chan, "dogreet"))
133                         privmsg(chan, "Hello "+nick+". I am " + settings.master + "'s bot. If you want to talk to him, please be patient and wait here.");
134                 add_name(chan, nick);
135                 check_notes(chan, nick);
136         }
138 function parthandler(chan, nick, mask, msg) {
139         lastchan = chan;
140         if(get_chan_setting(chan, "dogreet"))
141                 privmsg(chan, "oh, "+nick+" left :/ (reason: " + msg + ")");
142         remove_name(chan, nick);
144 function kickhandler(nick, mask, whom, chan, msg) {
145         privmsg(chan, "WOOT! " + nick + " kicked " + whom + "because of " + msg);
148 function nick_from_mask(mask) {
149         return(mask.substring(0, mask.indexOf('!')));
152 function hex2bin(input) {
153         var hextab = "0123456789abcdef";
154         var out = "";
155         for(var i = 0; i < input.length; i+=2) {
156                 var h1 = hextab.indexOf(input.charAt(i));
157                 var h2 = hextab.indexOf(input.charAt(i+1));
158                 out = out + String.fromCharCode((h1 << 4) | h2);
159         }
160         return out;
163 function sanitize_value(v) {
164         if(v=== "false" || v === "0") return false;
165         if(v === "true" || v === "1") return true;
166         return v;
169 function runcmd(chan, mask, cmd, args) {
170         var isop = settings.opmask ? mask.match(RegExp(settings.opmask)) : false;
171         if(0) {
172         } else if(cmd === 'op' && !settings.opmask) {
173                 var a = mask.split("!");
174                 settings.opmask = ".*!" + a[1];
175                 settings.master = a[0];
176                 save_settings();
177                 privmsg(chan, "opmask assigned");
178         } else if(cmd === "reload" && isop) {
179                 if(!reload()) privmsg(chan, "oops. reload failed.");
180                 else privmsg(chan, "reload OK.");
181         } else if(cmd === 'say') {
182                 privmsg(chan, args);
183         } else if(cmd === 'nick') {
184                 privmsg(chan, nick_from_mask(mask));
185         } else if(cmd === 'eval' && isop) {
186                 privmsg(chan, eval(args));
187         } else if(cmd === 'disconnect' && isop) {
188                 connected = false;
189                 names = {};
190                 disconnect();
191         } else if(cmd === 'join' && isop) {
192                 join(args);
193         } else if(cmd == 'note' && isop) {
194                 var x = args.indexOf(' ');
195                 if(x === -1) {
196                         privmsg(chan, "syntax: note recipient message");
197                         return;
198                 }
199                 var rcp = args.substring(0,x);
200                 var msg = args.substring(x+1);
201                 if(add_note(chan, mask, rcp, msg))
202                         privmsg(chan, "your note to " + rcp + " was saved, " + nick_from_mask(mask));
203         } else if((cmd == 'setg' || cmd == 'setc') && isop) {
204                 var x = args.indexOf(' ');
205                 if(x == -1) {
206                         privmsg(chan, "invalid command");
207                         return;
208                 }
209                 var k = args.substring(0,x);
210                 var v = sanitize_value(args.substring(x+1));
211                 if(cmd == 'setg') set_global(k,v);
212                 else set_chan(chan, k, v);
213         } else if(cmd == 'leave' && isop) {
214                 part(chan);
215         } else if(cmd == 'settings' && isop) {
216                 privmsg(chan, JSON.stringify(settings));
217         } else if(cmd == 'hex' && isop) {
218                 // attention, this can be abused to make the bot send raw commands
219                 // for example with 0a51554954
220                 privmsg(chan, hex2bin(args));
221         }
224 function noticehandler(dest, nick, mask, msg) {
225         /*ignore for now
226         if(connected && lastchan && dest.charAt(0) !== '*')
227                 privmsg(master, nick + " noticed " + dest + " of " + msg);
228         */
231 function msghandler(chan, nick, mask, msg) {
232         lastchan = chan;
233         var query = false;
234         if(chan.charAt(0) !== '#') {
235                 query = true;
236                 botname = chan;
237                 chan = nick;
238         }
239         if(nick == botname) return;
240         if(msg.charAt(0) == ',') {
241                 var x = msg.indexOf(' ');
242                 if(x == -1) x = msg.length;
243                 var cmd = msg.substring(1,x);
244                 var args = msg.substring(x+1);
245                 runcmd(chan, mask, cmd, args);
246         }