1: <?php
2:
3: namespace Budabot\User\Modules;
4:
5: use Budabot\Core\StopExecutionException;
6:
7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
23: class OnlineController {
24:
25: 26: 27: 28:
29: public $moduleName;
30:
31:
32: public $db;
33:
34:
35: public $chatBot;
36:
37:
38: public $settingManager;
39:
40:
41: public $accessManager;
42:
43:
44: public $buddylistManager;
45:
46:
47: public $altsController;
48:
49:
50: public $text;
51:
52:
53: public $util;
54:
55:
56: public $commandAlias;
57:
58:
59: public $logger;
60:
61: 62: 63:
64: public function setup() {
65: $this->db->loadSQLFile($this->moduleName, "online");
66:
67: $this->settingManager->add($this->moduleName, "online_expire", "How long to wait before clearing online list", "edit", "time", "15m", "2m;5m;10m;15m;20m", '', "mod");
68: $this->settingManager->add($this->moduleName, "online_show_org_guild", "Show org/rank for players in guild channel", "edit", "options", "1", "Show org and rank;Show rank only;Show org only;Show no org info", "2;1;3;0");
69: $this->settingManager->add($this->moduleName, "online_show_org_priv", "Show org/rank for players in private channel", "edit", "options", "2", "Show org and rank;Show rank only;Show org only;Show no org info", "2;1;3;0");
70: $this->settingManager->add($this->moduleName, "online_admin", "Show admin levels in online list", "edit", "options", "0", "true;false", "1;0");
71:
72: $this->commandAlias->register($this->moduleName, "online", "o");
73: $this->commandAlias->register($this->moduleName, "online", "sm");
74: }
75:
76: 77: 78: 79:
80: public function onlineCommand($message, $channel, $sender, $sendto, $args) {
81: $msg = $this->getOnlineList();
82: $sendto->reply($msg);
83: }
84:
85: 86: 87: 88:
89: public function onlineProfCommand($message, $channel, $sender, $sendto, $args) {
90: $profession = $this->util->getProfessionName($args[1]);
91: if (empty($profession)) {
92: return false;
93: }
94:
95: $sql = "
96: SELECT DISTINCT p.*, o.afk, COALESCE(a.main, o.name) AS pmain, (CASE WHEN o2.name IS NULL THEN 0 ELSE 1 END) AS online
97: FROM online o
98: LEFT JOIN alts a ON o.name = a.alt
99: LEFT JOIN alts a2 ON a2.main = COALESCE(a.main, o.name)
100: LEFT JOIN players p ON a2.alt = p.name OR COALESCE(a.main, o.name) = p.name
101: LEFT JOIN online o2 ON p.name = o2.name
102: WHERE p.profession = ?
103: ORDER BY COALESCE(a.main, o.name) ASC";
104: $data = $this->db->query($sql, $profession);
105: $count = count($data);
106: $mainCount = 0;
107: $currentMain = "";
108:
109: if ($count > 0) {
110: forEach ($data as $row) {
111: if ($currentMain != $row->pmain) {
112: $mainCount++;
113: $blob .= "\n<highlight>$row->pmain<end> has\n";
114: $currentMain = $row->pmain;
115: }
116:
117: if ($row->profession === null) {
118: $blob .= "| ($row->name)\n";
119: } else {
120: $prof = $this->util->getProfessionAbbreviation($row->profession);
121: $blob.= "| $row->name - $row->level/<green>$row->ai_level<end> $prof";
122: }
123: if ($row->online == 1) {
124: $blob .= " <green>Online<end>";
125: }
126: $blob .= "\n";
127: }
128: $blob .= "\nWritten by Naturarum (RK2)";
129: $msg = $this->text->makeBlob("$profession Search Results ($mainCount)", $blob);
130: } else {
131: $msg = "$profession Search Results (0)";
132: }
133:
134: $sendto->reply($msg);
135: }
136:
137: 138: 139: 140:
141: public function recordLogonEvent($eventObj) {
142: $sender = $eventObj->sender;
143: if (isset($this->chatBot->guildmembers[$sender])) {
144: $this->addPlayerToOnlineList($sender, $this->chatBot->vars['guild'], 'guild');
145: }
146: }
147:
148: 149: 150: 151:
152: public function recordLogoffEvent($eventObj) {
153: $sender = $eventObj->sender;
154: if (isset($this->chatBot->guildmembers[$sender])) {
155: $this->removePlayerFromOnlineList($sender, 'guild');
156: }
157: }
158:
159: 160: 161: 162:
163: public function showOnlineOnLogonEvent($eventObj) {
164: $sender = $eventObj->sender;
165: if (isset($this->chatBot->guildmembers[$sender]) && $this->chatBot->isReady()) {
166: $msg = $this->getOnlineList();
167: $this->chatBot->sendTell($msg, $sender);
168: }
169: }
170:
171: 172: 173: 174:
175: public function onlineCheckEvent($eventObj) {
176: if ($this->chatBot->isReady()) {
177:
178: $data = $this->db->query("SELECT name, channel_type FROM `online`");
179:
180: $guildArray = array();
181: $privArray = array();
182:
183: forEach ($data as $row) {
184: switch ($row->channel_type) {
185: case 'guild':
186: $guildArray []= $row->name;
187: break;
188: case 'priv':
189: $privArray []= $row->name;
190: break;
191: default:
192: $this->logger->log("WARN", "ONLINE_MODULE", "Unknown channel type: '$row->channel_type'. Expected: 'guild' or 'priv'");
193: }
194: }
195:
196: $time = time();
197:
198: forEach ($this->chatBot->guildmembers as $name => $rank) {
199: if ($this->buddylistManager->isOnline($name)) {
200: if (in_array($name, $guildArray)) {
201: $sql = "UPDATE `online` SET `dt` = ? WHERE `name` = ? AND added_by = '<myname>' AND channel_type = 'guild'";
202: $this->db->exec($sql, $time, $name);
203: } else {
204: $sql = "INSERT INTO `online` (`name`, `channel`, `channel_type`, `added_by`, `dt`) VALUES (?, '<myguild>', 'guild', '<myname>', ?)";
205: $this->db->exec($sql, $name, $time);
206: }
207: }
208: }
209:
210: forEach ($this->chatBot->chatlist as $name => $value) {
211: if (in_array($name, $privArray)) {
212: $sql = "UPDATE `online` SET `dt` = ? WHERE `name` = ? AND added_by = '<myname>' AND channel_type = 'priv'";
213: $this->db->exec($sql, $time, $name);
214: } else {
215: $sql = "INSERT INTO `online` (`name`, `channel`, `channel_type`, `added_by`, `dt`) VALUES (?, '<myguild> Guest', 'priv', '<myname>', ?)";
216: $this->db->exec($sql, $name, $time);
217: }
218: }
219:
220: $sql = "DELETE FROM `online` WHERE (`dt` < ? AND added_by = '<myname>') OR (`dt` < ?)";
221: $this->db->exec($sql, $time, ($time - $this->settingManager->get('online_expire')));
222:
223: }
224: }
225:
226: 227: 228: 229: 230:
231: public function afkCheckPrivateChannelEvent($eventObj) {
232: $this->afkCheck($eventObj->sender, $eventObj->message, $eventObj->type);
233: }
234:
235: 236: 237: 238: 239:
240: public function afkCheckGuildChannelEvent($eventObj) {
241: $this->afkCheck($eventObj->sender, $eventObj->message, $eventObj->type);
242: }
243:
244: 245: 246: 247: 248:
249: public function afkPrivateChannelEvent($eventObj) {
250: $this->afk($eventObj->sender, $eventObj->message, $eventObj->type);
251: }
252:
253: 254: 255: 256: 257:
258: public function afkGuildChannelEvent($eventObj) {
259: $this->afk($eventObj->sender, $eventObj->message, $eventObj->type);
260: }
261:
262: public function afkCheck($sender, $message, $type) {
263:
264: if (!$this->util->isValidSender($sender)) {
265: return;
266: }
267:
268: if (!preg_match("/^.?afk(.*)$/i", $message)) {
269: $row = $this->db->queryRow("SELECT afk FROM online WHERE `name` = ? AND added_by = '<myname>' AND channel_type = ?", $sender, $type);
270:
271: if ($row !== null && $row->afk != '') {
272: list($time, $reason) = explode('|', $row->afk);
273: $timeString = $this->util->unixtimeToReadable(time() - $time);
274:
275: $this->db->exec("UPDATE online SET `afk` = '' WHERE `name` = ? AND added_by = '<myname>' AND channel_type = ?", $sender, $type);
276: $msg = "<highlight>{$sender}<end> is back after $timeString.";
277:
278: if ('priv' == $type) {
279: $this->chatBot->sendPrivate($msg);
280: } else if ('guild' == $type) {
281: $this->chatBot->sendGuild($msg);
282: }
283: }
284: }
285: }
286:
287: public function afk($sender, $message, $type) {
288: if (preg_match("/^.?afk$/i", $message)) {
289: $reason = time();
290: $this->db->exec("UPDATE online SET `afk` = ? WHERE `name` = ? AND added_by = '<myname>' AND channel_type = ?", $reason, $sender, $type);
291: $msg = "<highlight>$sender<end> is now AFK.";
292: } else if (preg_match("/^.?brb(.*)$/i", $message, $arr)) {
293: $msg = trim($arr[1]);
294: $reason = time() . '|brb ' . $msg;
295: $this->db->exec("UPDATE online SET `afk` = ? WHERE `name` = ? AND added_by = '<myname>' AND channel_type = ?", $reason, $sender, $type);
296: $msg = "<highlight>$sender<end> is now AFK.";
297: } else if (preg_match("/^.?afk (.*)$/i", $message, $arr)) {
298: $reason = time() . '|' . $arr[1];
299: $this->db->exec("UPDATE online SET `afk` = ? WHERE `name` = ? AND added_by = '<myname>' AND channel_type = ?", $reason, $sender, $type);
300: $msg = "<highlight>$sender<end> is now AFK.";
301: }
302:
303: if ('' != $msg) {
304: if ('priv' == $type) {
305: $this->chatBot->sendPrivate($msg);
306: } else if ('guild' == $type) {
307: $this->chatBot->sendGuild($msg);
308: }
309:
310:
311:
312: if ($message[0] == $this->settingManager->get('symbol')) {
313: throw new StopExecutionException();
314: }
315: }
316: }
317:
318: public function addPlayerToOnlineList($sender, $channel, $channelType) {
319: $sql = "SELECT name FROM `online` WHERE `name` = ? AND `channel_type` = ? AND added_by = '<myname>'";
320: $data = $this->db->query($sql, $sender, $channelType);
321: if (count($data) == 0) {
322: $sql = "INSERT INTO `online` (`name`, `channel`, `channel_type`, `added_by`, `dt`) VALUES (?, ?, ?, '<myname>', ?)";
323: $this->db->exec($sql, $sender, $channel, $channelType, time());
324: }
325: }
326:
327: public function removePlayerFromOnlineList($sender, $channelType) {
328: $sql = "DELETE FROM `online` WHERE `name` = ? AND `channel_type` = ? AND added_by = '<myname>'";
329: $this->db->exec($sql, $sender, $channelType);
330: }
331:
332: public function getOnlineList() {
333: $orgData = $this->getPlayers('guild');
334: list($orgCount, $orgMain, $orgBlob) = $this->formatData($orgData, $this->settingManager->get("online_show_org_guild"));
335:
336: $privData = $this->getPlayers('priv');
337: list($privCount, $privMain, $privBlob) = $this->formatData($privData, $this->settingManager->get("online_show_org_priv"));
338:
339: $totalCount = $orgCount + $privCount;
340: $totalMain = $orgMain + $privMain;
341:
342: $blob = "\n";
343: if ($orgCount > 0) {
344: $blob .= "<header2>Org Channel ($orgMain)<end>\n";
345: $blob .= $orgBlob;
346: $blob .= "\n\n";
347: }
348: if ($privCount > 0) {
349: $blob .= "<header2>Private Channel ($privMain)<end>\n";
350: $blob .= $privBlob;
351: $blob .= "\n\n";
352: }
353:
354: if ($totalCount > 0) {
355: $blob .= "Written by Naturarum (RK2)";
356: $msg = $this->text->makeBlob("Players Online ($totalMain)", $blob);
357: } else {
358: $msg = "Players Online (0)";
359: }
360: return $msg;
361: }
362:
363: public function getOrgInfo($show_org_info, $fancyColon, $guild, $guild_rank) {
364: switch ($show_org_info) {
365: case 3: return $guild != "" ? " $fancyColon {$guild}":" $fancyColon Not in an org";
366: case 2: return $guild != "" ? " $fancyColon {$guild} ({$guild_rank})":" $fancyColon Not in an org";
367: case 1: return $guild != "" ? " $fancyColon {$guild_rank}":"";
368: default: return "";
369: }
370: }
371:
372: public function getAdminInfo($name, $fancyColon) {
373: if ($this->settingManager->get("online_admin") != 1) {
374: return "";
375: }
376:
377: switch ($this->accessManager->getAccessLevelForCharacter($name)) {
378: case 'superadmin': return " $fancyColon <red>SuperAdmin<end>";
379: case 'admin' : return " $fancyColon <red>Admin<end>";
380: case 'mod' : return " $fancyColon <green>Mod<end>";
381: case 'rl' : return " $fancyColon <orange>RL<end>";
382: }
383: }
384:
385: public function getAfkInfo($afk, $fancyColon) {
386: list($time, $reason) = explode("|", $afk);
387: if (empty($afk)) {
388: return '';
389: } else if (empty($reason)) {
390: $timeString = $this->util->unixtimeToReadable(time() - $time, false);
391: return " $fancyColon <highlight>AFK for $timeString<end>";
392: } else {
393: $timeString = $this->util->unixtimeToReadable(time() - $time, false);
394: return " $fancyColon <highlight>AFK for $timeString: {$reason}<end>";
395: }
396: }
397:
398: public function formatData($data, $showOrgInfo) {
399: $count = count($data);
400: $mainCount = 0;
401: $currentMain = "";
402: $blob = "";
403: $separator = "-";
404:
405: if ($count > 0) {
406: forEach ($data as $row) {
407: if ($currentMain != $row->pmain) {
408: $mainCount++;
409: $blob .= "\n<pagebreak><highlight>$row->pmain<end> on\n";
410: $currentMain = $row->pmain;
411: }
412:
413: $admin = $this->getAdminInfo($row->name, $separator);
414: $afk = $this->getAfkInfo($row->afk, $separator);
415:
416: if ($row->profession === null) {
417: $blob .= "| $row->name$admin$afk\n";
418: } else {
419: $prof = $this->util->getProfessionAbbreviation($row->profession);
420: $orgRank = $this->getOrgInfo($showOrgInfo, $separator, $row->guild, $row->guild_rank);
421: $blob.= "| $row->name - $row->level/<green>$row->ai_level<end> $prof$orgRank$admin$afk\n";
422: }
423: }
424: }
425:
426: return [$count, $mainCount, $blob];
427: }
428:
429: public function getPlayers($channelType) {
430: $sql = "
431: SELECT p.*, o.name, o.afk, COALESCE(a.main, o.name) AS pmain
432: FROM online o
433: LEFT JOIN alts a ON o.name = a.alt
434: LEFT JOIN players p ON o.name = p.name
435: WHERE o.channel_type = ?
436: ORDER BY COALESCE(a.main, o.name) ASC";
437: return $this->db->query($sql, $channelType);
438: }
439: }
440: