1: <?php
2:
3: namespace Budabot\Core;
4:
5: use ReflectionAnnotatedClass;
6: use stdClass;
7: use DefineCommand;
8:
9: require_once 'AOChat.class.php';
10:
11: 12: 13:
14: class Budabot extends AOChat {
15:
16:
17: public $db;
18:
19:
20: public $commandManager;
21:
22:
23: public $subcommandManager;
24:
25:
26: public $commandAlias;
27:
28:
29: public $eventManager;
30:
31:
32: public $helpManager;
33:
34:
35: public $settingManager;
36:
37:
38: public $banController;
39:
40:
41: public $text;
42:
43:
44: public $util;
45:
46:
47: public $limitsController;
48:
49:
50: public $buddylistManager;
51:
52:
53: public $relayController;
54:
55:
56: public $setting;
57:
58:
59: public $logger;
60:
61: public $ready = false;
62:
63: public $chatlist = array();
64: public $guildmembers = array();
65: public $vars;
66:
67: private $buddyListSize = 0;
68:
69:
70: public $channelsToIgnore = array("", 'IRRK News Wire', 'OT OOC', 'OT Newbie OOC', 'OT shopping 11-50',
71: 'Tour Announcements', 'Neu. Newbie OOC', 'Neu. shopping 11-50', 'Neu. OOC', 'Clan OOC',
72: 'Clan Newbie OOC', 'Clan shopping 11-50', 'OT German OOC', 'Clan German OOC', 'Neu. German OOC');
73:
74: public function init(&$vars) {
75: $this->vars = $vars;
76:
77:
78: $this->vars["startup"] = time();
79:
80: $this->logger->log('DEBUG', 'Initializing bot');
81:
82:
83: $this->db->exec("CREATE TABLE IF NOT EXISTS cmdcfg_<myname> (`module` VARCHAR(50), `cmdevent` VARCHAR(6), `type` VARCHAR(18), `file` TEXT, `cmd` VARCHAR(50), `admin` VARCHAR(10), `description` VARCHAR(75) DEFAULT 'none', `verify` INT DEFAULT '0', `status` INT DEFAULT '0', `dependson` VARCHAR(25) DEFAULT 'none', `help` VARCHAR(255))");
84: $this->db->exec("CREATE TABLE IF NOT EXISTS eventcfg_<myname> (`module` VARCHAR(50), `type` VARCHAR(18), `file` VARCHAR(255), `description` VARCHAR(75) DEFAULT 'none', `verify` INT DEFAULT '0', `status` INT DEFAULT '0', `help` VARCHAR(255))");
85: $this->db->exec("CREATE TABLE IF NOT EXISTS settings_<myname> (`name` VARCHAR(50) NOT NULL, `module` VARCHAR(50), `type` VARCHAR(30), `mode` VARCHAR(10), `value` VARCHAR(255) DEFAULT '0', `options` VARCHAR(255) DEFAULT '0', `intoptions` VARCHAR(50) DEFAULT '0', `description` VARCHAR(75), `source` VARCHAR(5), `admin` VARCHAR(25), `verify` INT DEFAULT '0', `help` VARCHAR(255))");
86: $this->db->exec("CREATE TABLE IF NOT EXISTS hlpcfg_<myname> (`name` VARCHAR(25) NOT NULL, `module` VARCHAR(50), `file` VARCHAR(255), `description` VARCHAR(75), `admin` VARCHAR(10), `verify` INT DEFAULT '0')");
87: $this->db->exec("CREATE TABLE IF NOT EXISTS cmd_alias_<myname> (`cmd` VARCHAR(255) NOT NULL, `module` VARCHAR(50), `alias` VARCHAR(25) NOT NULL, `status` INT DEFAULT '0')");
88:
89:
90: $this->db->exec("UPDATE cmdcfg_<myname> SET `verify` = 0");
91: $this->db->exec("UPDATE eventcfg_<myname> SET `verify` = 0");
92: $this->db->exec("UPDATE settings_<myname> SET `verify` = 0");
93: $this->db->exec("UPDATE hlpcfg_<myname> SET `verify` = 0");
94: $this->db->exec("UPDATE eventcfg_<myname> SET `status` = 1 WHERE `type` = 'setup'");
95:
96:
97: $data = $this->db->query("SELECT * FROM cmdcfg_<myname> WHERE `cmdevent` = 'subcmd'");
98: forEach ($data as $row) {
99: $this->existing_subcmds[$row->type][$row->cmd] = true;
100: }
101:
102: $data = $this->db->query("SELECT * FROM eventcfg_<myname>");
103: forEach ($data as $row) {
104: $this->existing_events[$row->type][$row->file] = true;
105: }
106:
107: $data = $this->db->query("SELECT * FROM hlpcfg_<myname>");
108: forEach ($data as $row) {
109: $this->existing_helps[$row->name] = true;
110: }
111:
112: $data = $this->db->query("SELECT * FROM settings_<myname>");
113: forEach ($data as $row) {
114: $this->existing_settings[$row->name] = true;
115: }
116:
117: $this->db->beginTransaction();
118: forEach (Registry::getAllInstances() as $name => $instance) {
119: if (isset($instance->moduleName)) {
120: $this->registerInstance($name, $instance);
121: } else {
122: $this->callSetupMethod($name, $instance);
123: }
124: }
125: $this->db->commit();
126:
127:
128: unset($this->existing_events);
129: unset($this->existing_subcmds);
130: unset($this->existing_settings);
131: unset($this->existing_helps);
132:
133:
134: $this->db->exec("DELETE FROM cmdcfg_<myname> WHERE `verify` = 0");
135: $this->db->exec("DELETE FROM eventcfg_<myname> WHERE `verify` = 0");
136: $this->db->exec("DELETE FROM settings_<myname> WHERE `verify` = 0");
137: $this->db->exec("DELETE FROM hlpcfg_<myname> WHERE `verify` = 0");
138:
139: $this->commandManager->loadCommands();
140: $this->subcommandManager->loadSubcommands();
141: $this->commandAlias->load();
142: $this->eventManager->loadEvents();
143: }
144:
145: 146: 147: 148:
149: function connectAO($login, $password, $server, $port) {
150:
151: $this->logger->log('INFO', "Connecting to AO Server...({$server}:{$port})");
152: if (false === $this->connect($server, $port)) {
153: $this->logger->log('ERROR', "Connection failed! Please check your Internet connection and firewall.");
154: sleep(10);
155: die();
156: }
157:
158: $this->logger->log('INFO', "Authenticate login data...");
159: if (false === $this->authenticate($login, $password)) {
160: $this->logger->log('ERROR', "Authentication failed! Invalid username or password.");
161: sleep(10);
162: die();
163: }
164:
165: $this->logger->log('INFO', "Logging in {$this->vars["name"]}...");
166: if (false === $this->login($this->vars["name"])) {
167: $this->logger->log('ERROR', "Character selection failed! Could not login on as character '{$this->vars["name"]}'.");
168: sleep(10);
169: die();
170: }
171:
172: $this->buddyListSize += 1000;
173: $this->logger->log('INFO', "All Systems ready!");
174: }
175:
176: public function run() {
177: $loop = new EventLoop();
178: Registry::injectDependencies($loop);
179: while (true) {
180: $loop->execSingleLoop();
181: }
182: }
183:
184: public function processAllPackets() {
185: while ($this->processNextPacket()) {
186:
187: }
188: }
189:
190: public function processNextPacket() {
191:
192:
193:
194: $packet = $this->wait_for_packet($this->isReady() ? 0 : 1);
195: if ($packet) {
196: $this->process_packet($packet);
197: return true;
198: } else {
199: $this->ready = true;
200: return false;
201: }
202: }
203:
204: public function sendPrivate($message, $disable_relay = false, $group = null) {
205:
206: if (is_array($message)) {
207: forEach ($message as $page) {
208: $this->sendPrivate($page, $disable_relay, $group);
209: }
210: return;
211: }
212:
213: if ($group == null) {
214: $group = $this->setting->default_private_channel;
215: }
216:
217: $message = $this->text->formatMessage($message);
218: $senderLink = $this->text->makeUserlink($this->vars['name']);
219: $guildNameForRelay = $this->relayController->getGuildAbbreviation();
220: $guestColorChannel = $this->settingManager->get('guest_color_channel');
221: $privColor = $this->settingManager->get('default_priv_color');
222:
223: $this->send_privgroup($group, $privColor.$message);
224: if ($this->isDefaultPrivateChannel($group)) {
225:
226: if (!$disable_relay && $this->settingManager->get('guild_channel_status') == 1 && $this->settingManager->get("guest_relay") == 1 && $this->settingManager->get("guest_relay_commands") == 1) {
227: $this->send_guild("</font>{$guestColorChannel}[Guest]</font> {$senderLink}: {$privColor}$message</font>", "\0");
228: }
229:
230:
231: if (!$disable_relay && $this->settingManager->get("relaybot") != "Off" && $this->settingManager->get("bot_relay_commands") == 1) {
232: $this->relayController->sendMessageToRelay("grc [{$guildNameForRelay}] [Guest] {$senderLink}: $message");
233: }
234: }
235: }
236:
237: public function sendGuild($message, $disable_relay = false, $priority = null) {
238: if ($this->settingManager->get('guild_channel_status') != 1) {
239: return;
240: }
241:
242:
243: if (is_array($message)) {
244: forEach ($message as $page) {
245: $this->sendGuild($page, $disable_relay, $priority);
246: }
247: return;
248: }
249:
250: if ($priority == null) {
251: $priority = AOC_PRIORITY_MED;
252: }
253:
254: $message = $this->text->formatMessage($message);
255: $senderLink = $this->text->makeUserlink($this->vars['name']);
256: $guildNameForRelay = $this->relayController->getGuildAbbreviation();
257: $guestColorChannel = $this->settingManager->get('guest_color_channel');
258: $guildColor = $this->settingManager->get("default_guild_color");
259:
260: $this->send_guild($guildColor.$message, "\0", $priority);
261:
262:
263: if (!$disable_relay && $this->settingManager->get("guest_relay") == 1 && $this->settingManager->get("guest_relay_commands") == 1) {
264: $this->send_privgroup($this->setting->default_private_channel, "</font>{$guestColorChannel}[{$guildNameForRelay}]</font> {$senderLink}: {$guildColor}$message</font>");
265: }
266:
267:
268: if (!$disable_relay && $this->settingManager->get("relaybot") != "Off" && $this->settingManager->get("bot_relay_commands") == 1) {
269: $this->relayController->sendMessageToRelay("grc [{$guildNameForRelay}] {$senderLink}: $message");
270: }
271: }
272:
273: public function sendTell($message, $character, $priority = null, $formatMessage = true) {
274:
275: if (is_array($message)) {
276: forEach ($message as $page) {
277: $this->sendTell($page, $character, $priority);
278: }
279: return;
280: }
281:
282: if ($priority == null) {
283: $priority = AOC_PRIORITY_MED;
284: }
285:
286: if ($formatMessage) {
287: $message = $this->text->formatMessage($message);
288: $tellColor = $this->settingManager->get("default_tell_color");
289: }
290:
291: $this->logger->logChat("Out. Msg.", $character, $message);
292: $this->send_tell($character, $tellColor.$message, "\0", $priority);
293: }
294:
295: public function sendPublic($message, $channel, $priority = null) {
296:
297: if (is_array($message)) {
298: forEach ($message as $page) {
299: $this->sendPublic($page, $channel, $priority);
300: }
301: return;
302: }
303:
304: if ($priority == null) {
305: $priority = AOC_PRIORITY_MED;
306: }
307:
308: $message = $this->text->formatMessage($message);
309: $guildColor = $this->settingManager->get("default_guild_color");
310:
311: $this->send_group($channel, $guildColor.$message, "\0", $priority);
312: }
313:
314: 315: 316: 317:
318: function processCommandArgs(&$type, &$admin) {
319: if ($type == "") {
320: $type = array("msg", "priv", "guild");
321: } else {
322: $type = explode(' ', $type);
323: }
324:
325: $admin = explode(' ', $admin);
326: if (count($admin) == 1) {
327: $admin = array_fill(0, count($type), $admin[0]);
328: } else if (count($admin) != count($type)) {
329: $this->logger->log('ERROR', "The number of type arguments does not equal the number of admin arguments for command/subcommand registration");
330: return false;
331: }
332: return true;
333: }
334:
335: 336: 337: 338:
339: function process_packet($packet) {
340: try {
341: $this->process_all_packets($packet);
342:
343:
344: switch ($packet->type){
345: case AOCP_LOGIN_OK:
346: $this->buddyListSize += 1000;
347: break;
348: case AOCP_GROUP_ANNOUNCE:
349: $this->process_group_announce($packet->args);
350: break;
351: case AOCP_PRIVGRP_CLIJOIN:
352: $this->process_private_channel_join($packet->args);
353: break;
354: case AOCP_PRIVGRP_CLIPART:
355: $this->process_private_channel_leave($packet->args);
356: break;
357: case AOCP_BUDDY_ADD:
358: $this->process_buddy_update($packet->args);
359: break;
360: case AOCP_BUDDY_REMOVE:
361: $this->process_buddy_removed($packet->args);
362: break;
363: case AOCP_MSG_PRIVATE:
364: $this->process_private_message($packet->args);
365: break;
366: case AOCP_PRIVGRP_MESSAGE:
367: $this->process_private_channel_message($packet->args);
368: break;
369: case AOCP_GROUP_MESSAGE:
370: $this->process_public_channel_message($packet->args);
371: break;
372: case AOCP_PRIVGRP_INVITE:
373: $this->process_private_channel_invite($packet->args);
374: break;
375: }
376: } catch (StopExecutionException $e) {
377: $this->logger->log('DEBUG', 'Execution stopped prematurely', $e);
378: }
379: }
380:
381: function process_all_packets($packet) {
382:
383: $eventObj = new stdClass;
384: $eventObj->type = "packet({$packet->type})";
385: $eventObj->packet = $packet;
386: $this->eventManager->fireEvent($eventObj);
387: }
388:
389: function process_group_announce($args) {
390: $orgId = $this->getOrgId($args[0]);
391: $this->logger->log('DEBUG', "AOCP_GROUP_ANNOUNCE => name: '$args[1]'");
392: if ($orgId) {
393: $this->vars["my_guild_id"] = $orgId;
394:
395: }
396: }
397:
398: function process_private_channel_join($args) {
399: $eventObj = new stdClass;
400: $channel = $this->lookup_user($args[0]);
401: $charId = $args[1];
402: $sender = $this->lookup_user($charId);
403: $eventObj->channel = $channel;
404: $eventObj->sender = $sender;
405:
406: $this->logger->log('DEBUG', "AOCP_PRIVGRP_CLIJOIN => channel: '$channel' sender: '$sender'");
407:
408: if ($this->isDefaultPrivateChannel($channel)) {
409: $eventObj->type = "joinpriv";
410:
411: $this->logger->logChat("Priv Group", -1, "$sender joined the channel.");
412:
413:
414: if ($this->banController->isBanned($charId)){
415: $this->privategroup_kick($sender);
416: return;
417: }
418:
419:
420: $this->chatlist[$sender] = true;
421:
422: $this->eventManager->fireEvent($eventObj);
423: }
424: }
425:
426: function process_private_channel_leave($args) {
427: $eventObj = new stdClass;
428: $channel = $this->lookup_user($args[0]);
429: $sender = $this->lookup_user($args[1]);
430: $eventObj->channel = $channel;
431: $eventObj->sender = $sender;
432:
433: $this->logger->log('DEBUG', "AOCP_PRIVGRP_CLIPART => channel: '$channel' sender: '$sender'");
434:
435: if ($this->isDefaultPrivateChannel($channel)) {
436: $eventObj->type = "leavepriv";
437:
438: $this->logger->logChat("Priv Group", -1, "$sender left the channel.");
439:
440:
441: unset($this->chatlist[$sender]);
442:
443: $this->eventManager->fireEvent($eventObj);
444: }
445: }
446:
447: function process_buddy_update($args) {
448: $sender = $this->lookup_user($args[0]);
449: $status = 0 + $args[1];
450:
451: $eventObj = new stdClass;
452: $eventObj->sender = $sender;
453:
454: $this->logger->log('DEBUG', "AOCP_BUDDY_ADD => sender: '$sender' status: '$status'");
455:
456: $this->buddylistManager->update($args);
457:
458:
459: if ($sender == "") {
460: return;
461: }
462:
463:
464: if ($status == 0) {
465: $eventObj->type = "logoff";
466:
467: $this->logger->log('DEBUG', "$sender logged off");
468:
469: $this->eventManager->fireEvent($eventObj);
470: } else if ($status == 1) {
471: $eventObj->type = "logon";
472:
473: $this->logger->log('DEBUG', "$sender logged on");
474:
475: $this->eventManager->fireEvent($eventObj);
476: }
477: }
478:
479: function process_buddy_removed($args) {
480: $sender = $this->lookup_user($args[0]);
481:
482: $this->logger->log('DEBUG', "AOCP_BUDDY_REMOVE => sender: '$sender'");
483:
484: $this->buddylistManager->updateRemoved($args);
485: }
486:
487: function process_private_message($args) {
488: $type = "msg";
489: $charId = $args[0];
490: $sender = $this->lookup_user($charId);
491:
492: $this->logger->log('DEBUG', "AOCP_MSG_PRIVATE => sender: '$sender' message: '$args[1]'");
493:
494:
495: if (preg_match("/^<font color='#([0-9a-f]+)'>(.+)$/si", $args[1], $arr)) {
496: $message = $arr[2];
497: } else {
498: $message = $args[1];
499: }
500:
501: $eventObj = new stdClass;
502: $eventObj->sender = $sender;
503: $eventObj->type = $type;
504: $eventObj->message = $message;
505:
506: $this->logger->logChat("Inc. Msg.", $sender, $message);
507:
508:
509: if (preg_match("|$sender is AFK|si", $message)) {
510: return;
511: } else if (preg_match("|I am away from my keyboard right now|si", $message)) {
512: return;
513: } else if (preg_match("|Unknown command or access denied!|si", $message)) {
514: return;
515: } else if (preg_match("|I am responding|si", $message)) {
516: return;
517: } else if (preg_match("|I only listen|si", $message)) {
518: return;
519: } else if (preg_match("|Error!|si", $message)) {
520: return;
521: } else if (preg_match("|Unknown command input|si", $message)) {
522: return;
523: } else if (preg_match("|/tell $sender !help|i", $message)) {
524: return;
525: }
526:
527: if ($this->banController->isBanned($charId)) {
528: return;
529: }
530:
531: $this->eventManager->fireEvent($eventObj);
532:
533:
534: if ($message[0] == $this->settingManager->get("symbol") && strlen($message) > 1) {
535: $message = substr($message, 1);
536: }
537:
538:
539: if (!$this->limitsController->check($sender, $message)) {
540: return;
541: }
542:
543: $sendto = new PrivateMessageCommandReply($this, $sender);
544: $this->commandManager->process($type, $message, $sender, $sendto);
545: }
546:
547: function process_private_channel_message($args) {
548: $charId = $args[1];
549: $sender = $this->lookup_user($charId);
550: $channel = $this->lookup_user($args[0]);
551: $message = $args[2];
552:
553: $eventObj = new stdClass;
554: $eventObj->sender = $sender;
555: $eventObj->channel = $channel;
556: $eventObj->message = $message;
557:
558: $this->logger->log('DEBUG', "AOCP_PRIVGRP_MESSAGE => sender: '$sender' channel: '$channel' message: '$message'");
559: $this->logger->logChat($channel, $sender, $message);
560:
561: if ($sender == $this->vars["name"] || $this->banController->isBanned($charId)) {
562: return;
563: }
564:
565: if ($this->isDefaultPrivateChannel($channel)) {
566: $type = "priv";
567: $eventObj->type = $type;
568:
569: $this->eventManager->fireEvent($eventObj);
570:
571: if ($message[0] == $this->settingManager->get("symbol") && strlen($message) > 1) {
572: $message = substr($message, 1);
573: $sendto = new PrivateChannelCommandReply($this, $channel);
574: $this->commandManager->process($type, $message, $sender, $sendto);
575: }
576: } else {
577: $type = "extpriv";
578: $eventObj->type = $type;
579:
580: $this->eventManager->fireEvent($eventObj);
581: }
582: }
583:
584: function process_public_channel_message($args) {
585: $charId = $args[1];
586: $sender = $this->lookup_user($charId);
587: $message = $args[2];
588: $channel = $this->get_gname($args[0]);
589:
590: $eventObj = new stdClass;
591: $eventObj->sender = $sender;
592: $eventObj->channel = $channel;
593: $eventObj->message = $message;
594:
595: $this->logger->log('DEBUG', "AOCP_GROUP_MESSAGE => sender: '$sender' channel: '$channel' message: '$message'");
596:
597: if (in_array($channel, $this->channelsToIgnore)) {
598: return;
599: }
600:
601: $orgId = $this->getOrgId($args[0]);
602:
603:
604: if ($channel != "All Towers" && $channel != "Tower Battle Outcome" && (!$orgId || $this->settingManager->get('guild_channel_status') == 1)) {
605: $this->logger->logChat($channel, $sender, $message);
606: } else {
607: $this->logger->log('DEBUG', "[" . $channel . "]: " . $message);
608: }
609:
610: if ($this->util->isValidSender($sender)) {
611:
612: if ($sender == $this->vars["name"]) {
613: return;
614: }
615: if ($this->banController->isBanned($charId)) {
616: return;
617: }
618: }
619:
620: if ($channel == "All Towers" || $channel == "Tower Battle Outcome") {
621: $eventObj->type = "towers";
622:
623: $this->eventManager->fireEvent($eventObj);
624: } else if ($channel == "Org Msg"){
625: $eventObj->type = "orgmsg";
626:
627: $this->eventManager->fireEvent($eventObj);
628: } else if ($orgId && $this->settingManager->get('guild_channel_status') == 1) {
629: $type = "guild";
630: $sendto = 'guild';
631:
632: $eventObj->type = $type;
633:
634: $this->eventManager->fireEvent($eventObj);
635:
636: if ($message[0] == $this->settingManager->get("symbol") && strlen($message) > 1) {
637: $message = substr($message, 1);
638: $sendto = new GuildChannelCommandReply($this);
639: $this->commandManager->process($type, $message, $sender, $sendto);
640: }
641: }
642: }
643:
644: function process_private_channel_invite($args) {
645: $type = "extjoinprivrequest";
646: $uid = $args[0];
647: $sender = $this->lookup_user($uid);
648:
649: $eventObj = new stdClass;
650: $eventObj->sender = $sender;
651: $eventObj->type = $type;
652:
653: $this->logger->log('DEBUG', "AOCP_PRIVGRP_INVITE => sender: '$sender'");
654:
655: $this->logger->logChat("Priv Channel Invitation", -1, "$sender channel invited.");
656:
657: $this->eventManager->fireEvent($eventObj);
658: }
659:
660: public function registerInstance($name, $obj) {
661: $this->logger->log('DEBUG', "Registering instance name '$name' for module '$moduleName'");
662: $moduleName = $obj->moduleName;
663:
664:
665: $reflection = new ReflectionAnnotatedClass($obj);
666: forEach ($reflection->getProperties() as $property) {
667: if ($property->hasAnnotation('Setting')) {
668: $this->settingManager->add(
669: $moduleName,
670: $property->getAnnotation('Setting')->value,
671: $property->getAnnotation('Description')->value,
672: $property->getAnnotation('Visibility')->value,
673: $property->getAnnotation('Type')->value,
674: $obj->{$property->name},
675: @$property->getAnnotation('Options')->value,
676: @$property->getAnnotation('Intoptions')->value,
677: @$property->getAnnotation('AccessLevel')->value,
678: @$property->getAnnotation('Help')->value
679: );
680: }
681: }
682:
683:
684: $commands = array();
685: $subcommands = array();
686: forEach ($reflection->getAllAnnotations() as $annotation) {
687: if ($annotation instanceof DefineCommand) {
688: if (!$annotation->command) {
689: $this->logger->log('WARN', "Cannot parse @DefineCommand annotation in '$name'.");
690: }
691: $command = $annotation->command;
692: $definition = array(
693: 'channels' => $annotation->channels,
694: 'defaultStatus' => $annotation->defaultStatus,
695: 'accessLevel' => $annotation->accessLevel,
696: 'description' => $annotation->description,
697: 'help' => $annotation->help,
698: 'handlers' => array()
699: );
700: list($parentCommand, $subCommand) = explode(" ", $command, 2);
701: if ($subCommand) {
702: $definition['parentCommand'] = $parentCommand;
703: $subcommands[$command] = $definition;
704: } else {
705: $commands[$command] = $definition;
706: }
707:
708: if ($annotation->alias) {
709: $this->commandAlias->register($moduleName, $command, $annotation->alias);
710: }
711: }
712: }
713:
714: forEach ($reflection->getMethods() as $method) {
715: if ($method->hasAnnotation('Setup')) {
716: if (call_user_func(array($obj, $method->name)) === false) {
717: $this->logger->log('ERROR', "Failed to call setup handler for '$name'");
718: }
719: } else if ($method->hasAnnotation('HandlesCommand')) {
720: $commandName = $method->getAnnotation('HandlesCommand')->value;
721: $methodName = $method->name;
722: $handlerName = "{$name}.{$method->name}";
723: if (isset($commands[$commandName])) {
724: $commands[$commandName]['handlers'][] = $handlerName;
725: } else if (isset($subcommands[$commandName])) {
726: $subcommands[$commandName]['handlers'][] = $handlerName;
727: } else {
728: $this->logger->log('WARN', "Cannot handle command '$commandName' as it is not defined with @DefineCommand in '$name'.");
729: }
730: } else if ($method->hasAnnotation('Event')) {
731: forEach ($method->getAllAnnotations('Event') as $eventAnnotation) {
732: $this->eventManager->register(
733: $moduleName,
734: $eventAnnotation->value,
735: $name . '.' . $method->name,
736: @$method->getAnnotation('Description')->value,
737: @$method->getAnnotation('Help')->value,
738: @$method->getAnnotation('DefaultStatus')->value
739: );
740: }
741: }
742: }
743:
744: forEach ($commands as $command => $definition) {
745: if (count($definition['handlers']) == 0) {
746: $this->logger->log('ERROR', "No handlers defined for command '$command' in module '$moduleName'.");
747: continue;
748: }
749: $this->commandManager->register(
750: $moduleName,
751: $definition['channels'],
752: implode(',', $definition['handlers']),
753: $command,
754: $definition['accessLevel'],
755: $definition['description'],
756: $definition['help'],
757: $definition['defaultStatus']
758: );
759: }
760:
761: forEach ($subcommands as $subcommand => $definition) {
762: if (count($definition['handlers']) == 0) {
763: $this->logger->log('ERROR', "No handlers defined for subcommand '$subcommand' in module '$moduleName'.");
764: continue;
765: }
766: $this->subcommandManager->register(
767: $moduleName,
768: $definition['channels'],
769: implode(',', $definition['handlers']),
770: $subcommand,
771: $definition['accessLevel'],
772: $definition['parentCommand'],
773: $definition['description'],
774: $definition['help'],
775: $definition['defaultStatus']
776: );
777: }
778: }
779:
780: public function callSetupMethod($name, $obj) {
781: $reflection = new ReflectionAnnotatedClass($obj);
782: forEach ($reflection->getMethods() as $method) {
783: if ($method->hasAnnotation('Setup')) {
784: if (call_user_func(array($obj, $method->name)) === false) {
785: $this->logger->log('ERROR', "Failed to call setup handler for '$name'");
786: }
787: }
788: }
789: }
790:
791: public function getBuddyListSize() {
792: return $this->buddyListSize;
793: }
794:
795: public function getOrgId($channelId) {
796: $b = unpack("C*", $channelId);
797: if ($b[1] == 3) {
798: return ($b[2] << 24) + ($b[3] << 16) + ($b[4] << 8) + ($b[5]);
799: } else {
800: return false;
801: }
802: }
803:
804: 805: 806: 807:
808: public function isReady() {
809: return $this->ready;
810: }
811:
812: public function isDefaultPrivateChannel($channel) {
813: return $channel == $this->setting->default_private_channel;
814: }
815: }
816: