1: <?php
2:
3: namespace Budabot\User\Modules;
4:
5: use stdClass;
6:
7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22: class VoteController {
23:
24: 25: 26: 27:
28: public $moduleName;
29:
30:
31: public $text;
32:
33:
34: public $db;
35:
36:
37: public $chatBot;
38:
39:
40: public $util;
41:
42:
43: public $settingManager;
44:
45:
46: public $accessManager;
47:
48: private $votes = array();
49: private $delimiter = "|";
50: private $table = "vote_<myname>";
51:
52:
53: const STATUS_CREATED = 0;
54: const STATUS_STARTED = 1;
55: const STATUS_60_MINUTES_LEFT = 2;
56: const STATUS_15_MINUTES_LEFT = 3;
57: const STATUS_60_SECONDS_LEFT = 4;
58: const STATUS_ENDED = 9;
59:
60: 61: 62: 63:
64: public function setup() {
65: $this->db->loadSQLFile($this->moduleName, 'vote');
66:
67: $this->settingManager->add($this->moduleName, "vote_channel_spam", "Showing Vote status messages in", "edit", "options", "2", "Private Channel;Guild;Private Channel and Guild;Neither", "0;1;2;3", "mod", "votesettings.txt");
68:
69: $data = $this->db->query("SELECT * FROM vote_<myname> WHERE `status` <> ? AND `duration` IS NOT NULL", self::STATUS_ENDED);
70: forEach ($data as $row) {
71: $this->votes[$row->question] = $row;
72: }
73: }
74:
75: 76: 77: 78: 79: 80:
81: public function checkVote($eventObj) {
82: if (count($this->votes) == 0) {
83: return;
84: }
85:
86: forEach ($this->votes as $key => $row) {
87: $author = $row->author;
88: $question = $row->question;
89: $started = $row->started;
90: $duration = $row->duration;
91: $answer = $row->answer;
92: $status = $row->status;
93:
94: $timeleft = $started + $duration - time();
95:
96: if ($timeleft <= 0) {
97: $title = "Finished Vote: $question";
98: $this->db->exec("UPDATE $this->table SET `status` = ? WHERE `duration` = ? AND `question` = ?", self::STATUS_ENDED, $duration, $question);
99: unset($this->votes[$key]);
100: } else if ($status == self::STATUS_CREATED) {
101: $title = "Vote: $question";
102:
103: if ($timeleft > 3600) {
104: $mstatus = self::STATUS_STARTED;
105: } else if ($timeleft > 900) {
106: $mstatus = self::STATUS_60_MINUTES_LEFT;
107: } else if ($timeleft > 60) {
108: $mstatus = self::STATUS_15_MINUTES_LEFT;
109: } else {
110: $mstatus = self::STATUS_60_SECONDS_LEFT;
111: }
112: $this->votes[$key]->status = $mstatus;
113: } else if ($timeleft <= 60 && $timeleft > 0 && $status != self::STATUS_60_SECONDS_LEFT) {
114: $title = "60 seconds left: $question";
115: $this->votes[$key]->status = self::STATUS_60_SECONDS_LEFT;
116: } else if ($timeleft <= 900 && $timeleft > 60 && $status != self::STATUS_15_MINUTES_LEFT) {
117: $title = "15 minutes left: $question";
118: $this->votes[$key]->status = self::STATUS_15_MINUTES_LEFT;
119: } else if ($timeleft <= 3600 && $timeleft > 900 && $status != self::STATUS_60_MINUTES_LEFT) {
120: $title = "60 minutes left: $question";
121: $this->votes[$key]->status = self::STATUS_60_MINUTES_LEFT;
122: } else {
123: $title = "";
124: }
125:
126: if ($title != "") {
127:
128: $blob = $this->getVoteBlob($question);
129:
130: $msg = $this->text->makeBlob($title, $blob);
131:
132: if ($this->settingManager->get("vote_channel_spam") == 0 || $this->settingManager->get("vote_channel_spam") == 2) {
133: $this->chatBot->sendGuild($msg, true);
134: }
135: if ($this->settingManager->get("vote_channel_spam") == 1 || $this->settingManager->get("vote_channel_spam") == 2) {
136: $this->chatBot->sendPrivate($msg, true);
137: }
138: }
139: }
140: }
141:
142: 143: 144: 145: 146: 147:
148: public function voteCommand($message, $channel, $sender, $sendto, $args) {
149: $data = $this->db->query("SELECT * FROM $this->table WHERE `duration` IS NOT NULL ORDER BY `started`");
150: if (count($data) > 0) {
151: forEach ($data as $row) {
152: $question = $row->question;
153: $started = $row->started;
154: $duration = $row->duration;
155: $line = "<tab>" . $this->text->makeChatcmd($question, "/tell <myname> vote show $question");
156:
157: $timeleft = $started + $duration - time();
158: if ($timeleft>0) {
159: $running .= $line . "\n(" . $this->util->unixtimeToReadable($timeleft) . " left)\n";
160: } else {
161: $over .= $line . "\n";
162: }
163: }
164: if ($running) {
165: $blob .= " <green>Running:<end>\n" . $running;
166: }
167: if ($running && $over) {
168: $blob .= "\n";
169: }
170: if ($over) {
171: $blob .= " <red>Finshed:<end>\n" . $over;
172: }
173:
174: $msg = $this->text->makeBlob("Vote Listing", $blob);
175: } else {
176: $msg = "There are currently no votes to view.";
177: }
178: $sendto->reply($msg);
179: }
180:
181: 182: 183: 184: 185: 186:
187: public function voteKillCommand($message, $channel, $sender, $sendto, $args) {
188: $question = $args[1];
189: if ($this->accessManager->checkAccess($sender, "moderator")) {
190: $row = $this->db->queryRow("SELECT * FROM $this->table WHERE `question` = ?", $question);
191: } else {
192: $row = $this->db->queryRow("SELECT * FROM $this->table WHERE `question` = ? AND `author` = ? AND `duration` IS NOT NULL", $question, $sender);
193: }
194:
195: if ($row !== null) {
196: $this->db->exec("DELETE FROM $this->table WHERE `question` = ?", $row->question);
197: unset($this->votes[$row->question]);
198: $msg = "'$row->question' has been removed.";
199: } else {
200: $msg = "Either this vote does not exist, or you did not create it.";
201: }
202: $sendto->reply($msg);
203: }
204:
205: 206: 207: 208: 209: 210:
211: public function voteRemoveCommand($message, $channel, $sender, $sendto, $args) {
212: $question = $args[1];
213: if (!isset($this->votes[$question])) {
214: $msg = "Vote <highlight>$question<end> could not be found.";
215: } else {
216: $data = $this->db->query("SELECT * FROM $this->table WHERE `question` = ? AND `author` = ? AND `duration` IS NULL", $question, $sender);
217: if (count($data) > 0) {
218:
219: $this->db->exec("DELETE FROM $this->table WHERE `question` = ? AND `author` = ? AND `duration` IS NULL", $question, $sender);
220: $msg = "Your vote has been removed.";
221: } else {
222: $msg = "You have not voted on this topic.";
223: }
224: }
225: $sendto->reply($msg);
226: }
227:
228: 229: 230: 231: 232: 233:
234: public function voteEndCommand($message, $channel, $sender, $sendto, $args) {
235: $question = $args[1];
236: $row = $this->db->queryRow("SELECT * FROM $this->table WHERE `question` = ? AND `author` = ? AND `duration` IS NOT NULL", $question, $sender);
237:
238: if ($row === null) {
239: $msg = "Either this vote does not exist, or you did not create it.";
240: } else {
241: $started = $row->started;
242: $duration = $row->duration;
243: $timeleft = $started + $duration - time();
244:
245: if ($timeleft > 60) {
246: $duration = (time() - $started) + 61;
247: $this->db->exec("UPDATE $this->table SET `duration` = ? WHERE `question` = ?", $duration, $question);
248: $this->votes[$question]->duration = $duration;
249: $msg = "Vote duration reduced to 60 seconds.";
250: } else if ($timeleft <= 0) {
251: $msg = "This vote has already finished.";
252: } else {
253: $msg = "There is only <highlight>$timeleft<end> seconds left.";
254: }
255: }
256: $sendto->reply($msg);
257: }
258:
259: 260: 261: 262:
263: public function voteShowCommand($message, $channel, $sender, $sendto, $args) {
264: $question = $args[1];
265:
266: $blob = $this->getVoteBlob($question);
267:
268: $row = $this->db->queryRow("SELECT * FROM $this->table WHERE `author` = ? AND `question` = ? AND `duration` IS NULL", $sender, $question);
269: if ($row->answer && $timeleft > 0) {
270: $privmsg = "You voted: <highlight>(".$row->answer.")<end>.";
271: } else if ($timeleft > 0) {
272: $privmsg = "You have not voted on this.";
273: }
274:
275: $msg = $this->text->makeBlob("Vote: $question", $blob);
276: if ($privmsg) {
277: $sendto->reply($privmsg);
278: }
279:
280: $sendto->reply($msg);
281: }
282:
283: 284: 285: 286:
287: public function voteChooseCommand($message, $channel, $sender, $sendto, $args) {
288: list($question, $choice) = explode($this->delimiter, $args[1], 2);
289:
290: $row = $this->db->queryRow("SELECT * FROM $this->table WHERE `question` = ? AND `duration` IS NOT NULL", $question);
291: $question = $row->question;
292: $author = $row->author;
293: $started = $row->started;
294: $duration = $row->duration;
295: $status = $row->status;
296: $answer = $row->answer;
297: $timeleft = $started + $duration - time();
298:
299: if (!$duration) {
300: $msg = "Could not find any votes with this topic.";
301: } else if ($timeleft <= 0) {
302: $msg = "No longer accepting votes for this topic.";
303: } else {
304: $data = $this->db->query("SELECT * FROM $this->table WHERE `question` = ? AND `duration` IS NULL AND `author` = ?", $question, $sender);
305: if (count($data) > 0) {
306: $this->db->exec("UPDATE $this->table SET `answer` = ? WHERE `author` = ? AND `duration` IS NULL AND `question` = ?", $choice, $sender, $question);
307: $msg = "You have altered your choice to <highlight>$choice<end> for: $question.";
308: } else {
309: $this->db->exec("INSERT INTO $this->table (`author`, `answer`, `question`) VALUES (?, ?, ?)", $sender, $choice, $question);
310: $msg = "You have selected choice <highlight>$choice<end> for: $question.";
311: }
312: }
313: $sendto->reply($msg);
314: }
315:
316: 317: 318: 319:
320: public function voteAddCommand($message, $channel, $sender, $sendto, $args) {
321: list($settime, $question, $answers) = explode($this->delimiter, $args[1], 3);
322:
323:
324:
325: $newtime = $this->util->parseTime($settime);
326:
327: if ($newtime == 0) {
328: $msg = "Invalid time entered. Time format should be: 1d2h3m4s";
329: } else {
330: $answer = explode($this->delimiter, $answers);
331: if (count($answer) < 2) {
332: $msg = "You must have at least two options for this vote topic.";
333: } else if (!$question) {
334: $msg = "You must specify a question for your new vote topic.";
335: } else {
336: $status = self::STATUS_CREATED;
337: $data = $this->db->query("SELECT * FROM $this->table WHERE `question` = ?", $question);
338: if (count($data) == 0) {
339: $this->db->exec("INSERT INTO $this->table (`question`, `author`, `started`, `duration`, `answer`, `status`) VALUES (?, ?, ?, ?, ?, ?)", $question, $sender, time(), $newtime, $answers, $status);
340: $obj = new stdClass;
341: $obj->question = $question;
342: $obj->author = $sender;
343: $obj->started = time();
344: $obj->duration = $newtime;
345: $obj->answer = $answers;
346: $obj->status = $status;
347: $this->votes[$question] = $obj;
348: $msg = "Vote has been added.";
349: } else {
350: $msg = "There is already a vote topic with this question.";
351: }
352: }
353: }
354:
355: $sendto->reply($msg);
356: }
357:
358: public function getVoteBlob($question) {
359: $data = $this->db->query("SELECT * FROM $this->table WHERE `question` = ?", $question);
360: if (count($data) == 0) {
361: return "Could not find any votes with this topic.";
362: }
363:
364: $results = array();
365: forEach ($data as $row) {
366: if ($row->duration) {
367: $question = $row->question;
368: $author = $row->author;
369: $started = $row->started;
370: $duration = $row->duration;
371: $status = $row->status;
372: $timeleft = $started + $duration - time();
373: }
374: if ($sender == $author) {
375: $didvote = 1;
376: }
377: $answer = $row->answer;
378:
379: if (strpos($answer, $this->delimiter) === false) {
380: $results[$answer]++;
381: $totalresults++;
382: } else {
383:
384: $ans = explode($this->delimiter, $answer);
385: forEach ($ans as $value) {
386: if (!isset($results[$value])) {
387: $results[$value] = 0;
388: }
389: }
390: }
391: }
392:
393: $blob = "$author's Vote: <highlight>".$question."<end>\n";
394: if ($timeleft > 0) {
395: $blob .= $this->util->unixtimeToReadable($timeleft)." till this vote closes!\n\n";
396: } else {
397: $blob .= "<red>This vote has ended " . $this->util->unixtimeToReadable(time() - ($started + $duration), 1) . " ago.<end>\n\n";
398: }
399:
400: forEach ($results as $key => $value) {
401: $val = number_format(100 * ($value / $totalresults), 0);
402: if ($val < 10) {
403: $blob .= "<black>__<end>$val% ";
404: } else if ($val < 100) {
405: $blob .= "<black>_<end>$val% ";
406: } else {
407: $blob .= "$val% ";
408: }
409:
410: if ($timeleft > 0) {
411: $blob .= $this->text->makeChatcmd($key, "/tell <myname> vote choose $question{$this->delimiter}$key") . " (Votes: $value)\n";
412: } else {
413: $blob .= "<highlight>$key<end> (Votes: $value)\n";
414: }
415: }
416:
417:
418: if ($timeleft > 0) {
419: $blob .= "\n" . $this->text->makeChatcmd('Remove yourself from this vote', "/tell <myname> vote remove $question") . "\n";
420: }
421:
422: $blob .="\nDon't like these choices? Add your own:\n<tab>/tell <myname> vote $question{$this->delimiter}<highlight>your choice<end>\n";
423:
424: $blob .="\nIf you started this vote, you can:\n";
425: $blob .="<tab>" . $this->text->makeChatcmd('Kill the vote completely', "/tell <myname> vote kill $question") . "\n";
426: if ($timeleft > 0) {
427: $blob .="<tab>" . $this->text->makeChatcmd('End the vote early', "/tell <myname> vote end $question");
428: }
429:
430: return $blob;
431: }
432: }
433: