-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
241 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,3 +13,4 @@ logging: | |
|
||
storage: | ||
admin: Room11\Jeeves\Storage\File\Admin | ||
ban: Room11\Jeeves\Storage\File\Ban |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Room11\Jeeves\Chat\Message; | ||
|
||
interface UserMessage { | ||
public function getUserId(): int; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Room11\Jeeves\Chat\Plugin; | ||
|
||
use Room11\Jeeves\Chat\Client\ChatClient; | ||
use Room11\Jeeves\Storage\Admin as AdminStorage; | ||
use Room11\Jeeves\Storage\Ban as Storage; | ||
use Room11\Jeeves\Chat\Command\Command; | ||
use Room11\Jeeves\Chat\Command\Message; | ||
|
||
class Ban implements Plugin | ||
{ | ||
const COMMANDS = ["ban", "unban"]; | ||
|
||
private $chatClient; | ||
|
||
private $admin; | ||
|
||
private $storage; | ||
|
||
public function __construct(ChatClient $chatClient, AdminStorage $admin, Storage $storage) { | ||
$this->chatClient = $chatClient; | ||
$this->admin = $admin; | ||
$this->storage = $storage; | ||
} | ||
|
||
public function handle(Message $message): \Generator { | ||
if (!$this->validMessage($message)) { | ||
return; | ||
} | ||
|
||
yield from $this->execute($message); | ||
} | ||
|
||
private function validMessage(Message $message): bool { | ||
return $message instanceof Command | ||
&& in_array($message->getCommand(), self::COMMANDS, true) | ||
&& $message->getParameters(); | ||
} | ||
|
||
private function execute(Message $message): \Generator { | ||
if (!yield from $this->admin->isAdmin($message->getMessage()->getUserId())) { | ||
yield from $this->chatClient->postMessage( | ||
sprintf(":%d I'm sorry Dave, I'm afraid I can't do that", $message->getOrigin()) | ||
); | ||
|
||
return; | ||
} | ||
|
||
if ($message->getCommand() === "ban" && $message->getParameters()[0] === 'list') { | ||
yield from $this->list(); | ||
} elseif ($message->getCommand() === "ban") { | ||
yield from $this->add((int)$message->getParameters()[0], $message->getParameters()[1]); | ||
} elseif ($message->getCommand() === "unban") { | ||
yield from $this->remove((int) $message->getParameters()[0]); | ||
} | ||
} | ||
|
||
private function list(): \Generator | ||
{ | ||
$bans = yield from $this->storage->getAll(); | ||
|
||
if (!$bans) { | ||
yield from $this->chatClient->postMessage("No users are currently on the naughty list."); | ||
return; | ||
} | ||
|
||
$list = implode(", ", array_map(function($expiration, $userId) { | ||
return sprintf("%s (%s)", $userId, $expiration); | ||
}, $bans, array_keys($bans))); | ||
|
||
yield from $this->chatClient->postMessage($list); | ||
} | ||
|
||
private function add(int $userId, string $duration): \Generator { | ||
yield from $this->storage->add($userId, $duration); | ||
|
||
yield from $this->chatClient->postMessage("User is banned."); | ||
} | ||
|
||
private function remove(int $userId): \Generator { | ||
yield from $this->storage->remove($userId); | ||
|
||
yield from $this->chatClient->postMessage("User is unbanned."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Room11\Jeeves\Storage; | ||
|
||
interface Ban | ||
{ | ||
public function getAll(): \Generator; | ||
|
||
public function isBanned(int $userId): \Generator; | ||
|
||
public function add(int $userId, string $duration): \Generator; | ||
|
||
public function remove(int $userId): \Generator; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Room11\Jeeves\Storage\File; | ||
|
||
use Room11\Jeeves\Storage\Ban as BanList; | ||
use function Amp\File\exists; | ||
use function Amp\File\get; | ||
use function Amp\File\put; | ||
|
||
class Ban implements BanList | ||
{ | ||
private $dataFile; | ||
|
||
public function __construct(string $dataFile) { | ||
$this->dataFile = $dataFile; | ||
} | ||
|
||
public function getAll(): \Generator { | ||
if (!yield exists($this->dataFile)) { | ||
return []; | ||
} | ||
|
||
$banned = yield get($this->dataFile); | ||
|
||
return json_decode($banned, true); | ||
} | ||
|
||
public function isBanned(int $userId): \Generator { | ||
// inb4 people "testing" banning me | ||
if ($userId === 508666) { | ||
//return false; | ||
} | ||
|
||
$banned = yield from $this->getAll(); | ||
|
||
return array_key_exists($userId, $banned) && $banned[$userId] > (new \DateTime())->format('Y-m-d H:i:s'); | ||
} | ||
|
||
public function add(int $userId, string $duration): \Generator { | ||
$banned = yield from $this->getAll(); | ||
|
||
$banned[$userId] = $this->getExpiration($duration)->format('Y-m-d H:i:s'); | ||
|
||
yield put($this->dataFile, json_encode($banned)); | ||
} | ||
|
||
// duration string should be in the format of [nd(ays)][nh(ours)][nm(inutes)][ns(econds)] | ||
private function getExpiration(string $duration): \DateTimeImmutable { | ||
$expiration = new \DateTimeImmutable(); | ||
|
||
if (!preg_match('/^((?P<days>\d+)d)?((?P<hours>\d+)h)?((?P<minutes>\d+)m)?((?P<seconds>\d+)s)?$/', $duration, $matches)) { | ||
return $expiration; | ||
} | ||
|
||
$dateInterval = 'P'; | ||
$timeDelimiter = 'T'; | ||
|
||
if (!empty($matches['days'])) { | ||
$dateInterval .= $matches['days'] . 'D'; | ||
} | ||
|
||
if (!empty($matches['hours'])) { | ||
$dateInterval .= $timeDelimiter . $matches['hours'] . 'D'; | ||
|
||
$timeDelimiter = ''; | ||
} | ||
|
||
if (!empty($matches['hours'])) { | ||
$dateInterval .= $timeDelimiter . $matches['hours'] . 'H'; | ||
|
||
$timeDelimiter = ''; | ||
} | ||
|
||
if (!empty($matches['minutes'])) { | ||
$dateInterval .= $timeDelimiter . $matches['minutes'] . 'M'; | ||
|
||
$timeDelimiter = ''; | ||
} | ||
|
||
if (!empty($matches['seconds'])) { | ||
$dateInterval .= $timeDelimiter . $matches['seconds'] . 'S'; | ||
} | ||
|
||
return $expiration->add(new \DateInterval($dateInterval)); | ||
} | ||
|
||
public function remove(int $userId): \Generator { | ||
if (!yield from $this->isBanned($userId)) { | ||
return; | ||
} | ||
|
||
$banned = yield from $this->getAll(); | ||
|
||
unset($banned[$userId]); | ||
|
||
yield put($this->dataFile, json_encode($banned)); | ||
} | ||
} |