49 lines
1.6 KiB
PHP
49 lines
1.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
final class RepeatState
|
|
{
|
|
public function __construct(private string $baseDir = Settings::STATE_DIR, private ?int $now = null)
|
|
{
|
|
}
|
|
|
|
public function shouldSend(string $owner, string $ruleId, string $recipient, string $sender, int $repeatMinutes): bool
|
|
{
|
|
if ($repeatMinutes <= 0) {
|
|
return true;
|
|
}
|
|
$path = $this->path($owner, $ruleId, $recipient, $sender);
|
|
if (!is_file($path)) {
|
|
return true;
|
|
}
|
|
$data = json_decode((string)file_get_contents($path), true);
|
|
$last = is_array($data) ? (int)($data['last_sent_at'] ?? 0) : 0;
|
|
return ($this->time() - $last) >= ($repeatMinutes * 60);
|
|
}
|
|
|
|
public function record(string $owner, string $ruleId, string $recipient, string $sender): void
|
|
{
|
|
$path = $this->path($owner, $ruleId, $recipient, $sender);
|
|
$dir = dirname($path);
|
|
if (!is_dir($dir)) {
|
|
mkdir($dir, 0700, true);
|
|
}
|
|
file_put_contents($path, json_encode(['last_sent_at' => $this->time()], JSON_PRETTY_PRINT), LOCK_EX);
|
|
@chmod($path, 0600);
|
|
}
|
|
|
|
private function path(string $owner, string $ruleId, string $recipient, string $sender): string
|
|
{
|
|
if (!preg_match('/^[A-Za-z0-9._-]+$/', $owner)) {
|
|
throw new InvalidArgumentException('Invalid owner');
|
|
}
|
|
$hash = hash('sha256', implode('|', [$owner, $ruleId, strtolower($recipient), strtolower($sender)]));
|
|
return rtrim($this->baseDir, '/') . '/replies/' . $owner . '/' . $hash . '.json';
|
|
}
|
|
|
|
private function time(): int
|
|
{
|
|
return $this->now ?? time();
|
|
}
|
|
}
|