Jobs setup

This commit is contained in:
2023-06-12 21:14:07 -04:00
parent 03c1dac2f2
commit 88f91c4bd5
60 changed files with 965 additions and 495 deletions

View File

@ -0,0 +1,114 @@
<?php
namespace ProVM\Service;
use ProVM\Exception\Response\EmptyResponse;
use ProVM\Exception\Response\MissingResponse;
use Psr\Log\LoggerInterface;
use function Safe\json_decode;
class Attachments
{
public function __construct(protected Communicator $communicator, protected LoggerInterface $logger, protected array $passwords, protected string $base_command = 'qpdf') {}
protected array $attachments;
public function findAll(): \Generator
{
$this->logger->info('Finding all downloaded attachment files');
$folder = '/attachments';
$files = new \FilesystemIterator($folder);
foreach ($files as $file) {
if ($file->isDir()) {
continue;
}
yield $file->getRealPath();
}
}
public function getAll(): array
{
if (!isset($this->attachments)) {
$this->logger->info('Grabbing all attachments');
$response = $this->communicator->get('/attachments');
$body = $response->getBody()->getContents();
if (trim($body) === '') {
$this->attachments = [];
return $this->attachments;
}
$this->attachments = json_decode($body)->attachments;
}
return $this->attachments;
}
public function get(int $attachment_id): object
{
$this->logger->info("Getting attachment {$attachment_id}");
$uri = "/attachment/{$attachment_id}";
$response = $this->communicator->get($uri);
$body = $response->getBody()->getContents();
if (trim($body) === '') {
throw new EmptyResponse($uri);
}
$json = json_decode($body);
if (!isset($json->attachment)) {
throw new MissingResponse('attachment');
}
return $json->attachment;
}
public function find(string $filename): int
{
$this->logger->info("Finding attachment {$filename}");
foreach ($this->getAll() as $attachment) {
if ($attachment->fullfilename === $filename) {
return $attachment->id;
}
}
throw new \Exception("{$filename} is not in the database");
}
public function isEncrypted(string $filename): bool
{
if (!file_exists($filename)) {
throw new \InvalidArgumentException("File not found {$filename}");
}
$escaped_filename = escapeshellarg($filename);
$cmd = "{$this->base_command} --is-encrypted {$escaped_filename}";
exec($cmd, $output, $retcode);
return $retcode == 0;
}
public function scheduleDecrypt(int $attachment_id): bool
{
$this->logger->info("Scheduling decryption of attachment {$attachment_id}");
$uri = "/attachment/{$attachment_id}/decrypt";
$response = $this->communicator->get($uri);
$body = $response->getBody()->getContents();
if (trim($body) === '') {
throw new EmptyResponse($uri);
}
$json = json_decode($body);
if (!isset($json->status)) {
throw new MissingResponse('status');
}
return $json->status;
}
public function decrypt(string $basename): bool
{
$this->logger->info("Decrypting {$basename}");
$in_filename = implode('/', ['attachments', $basename]);
$out_filename = implode('/', ['attachments', 'decrypted', $basename]);
if (file_exists($out_filename)) {
throw new \Exception("{$basename} already decrypted");
}
foreach ($this->passwords as $password) {
$cmd = $this->base_command . ' -password=' . escapeshellarg($password) . ' -decrypt ' . escapeshellarg($in_filename) . ' ' . escapeshellarg($out_filename);
exec($cmd, $output, $retcode);
$success = $retcode == 0;
if ($success) {
return true;
}
if (file_exists($out_filename)) {
unlink($out_filename);
}
unset($output);
}
return false;
}
}

View File

@ -4,29 +4,12 @@ namespace ProVM\Service;
use HttpResponseException;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Safe\Exceptions\JsonException;
use function Safe\json_encode;
class Communicator
{
public function __construct(ClientInterface $client)
{
$this->setClient($client);
}
protected ClientInterface $client;
public function getClient(): ClientInterface
{
return $this->client;
}
public function setClient(ClientInterface $client): Communicator
{
$this->client = $client;
return $this;
}
public function __construct(protected ClientInterface $client) {}
/**
* @throws HttpResponseException
@ -52,7 +35,7 @@ class Communicator
];
$options['body'] = json_encode($body);
}
return $this->handleResponse($this->getClient()->request($method, $uri, $options));
return $this->handleResponse($this->client->request($method, $uri, $options));
}
/**

View File

@ -0,0 +1,71 @@
<?php
namespace ProVM\Service;
use Psr\Log\LoggerInterface;
use ProVM\Exception\Response\{EmptyResponse, MissingResponse};
use function Safe\json_decode;
class Jobs
{
public function __construct(protected Communicator $communicator, protected LoggerInterface $logger) {}
public function getPending(): array
{
$this->logger->info('Getting pending jobs');
$response = $this->communicator->get('/jobs/pending');
$body = $response->getBody()->getContents();
if (trim($body) === '') {
return [];
}
$json = json_decode($body);
if (!isset($json->jobs)) {
return [];
}
return $json->jobs;
}
public function get(int $job_id): object
{
$this->logger->info("Getting Job {$job_id}");
$uri = "/job/{$job_id}";
return $this->send($uri, 'job');
}
public function run(object $job): bool
{
$this->logger->debug("Running Job {$job->id}");
$base_command = '/app/bin/emails';
$cmd = [$base_command, $job->command];
if ($job->arguments !== '') {
$cmd []= $job->arguments;
}
$cmd = implode(' ', $cmd);
$response = shell_exec($cmd);
if ($response !== false) {
return $this->finished($job->id);
}
return $this->failure($job->id);
}
protected function finished(int $job_id): bool
{
$uri = "/job/{$job_id}/finish";
return $this->send($uri, 'status');
}
protected function failure(int $job_id): bool
{
$uri = "/job/{$job_id}/failed";
return $this->send($uri, 'status');
}
protected function send(string $uri, string $param): mixed
{
$response = $this->communicator->get($uri);
$body = $response->getBody()->getContents();
if (trim($body) === '') {
throw new EmptyResponse($uri);
}
$json = json_decode($body);
if (!isset($json->{$param})) {
throw new MissingResponse($param);
}
return $json->{$param};
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace ProVM\Service;
use DateTimeImmutable;
use ProVM\Exception\Response\EmptyResponse;
use ProVM\Exception\Response\MissingResponse;
use Psr\Log\LoggerInterface;
use function Safe\json_decode;
class Mailboxes
{
public function __construct(protected Communicator $communicator, protected LoggerInterface $logger, protected int $min_check_days) {}
public function getAll(): array
{
$this->logger->info('Getting all registered mailboxes');
$response = $this->communicator->get('/mailboxes/registered');
$body = $response->getBody()->getContents();
if (trim($body) === '') {
return [];
}
$json = json_decode($body);
if (!isset($json->mailboxes)) {
return [];
}
return $json->mailboxes;
}
public function check(object $mailbox): bool
{
$this->logger->info("Checking mailbox {$mailbox->id}");
if ((new DateTimeImmutable())->diff(new DateTimeImmutable($mailbox->last_checked->date->date))->days < $this->min_check_days) {
return true;
}
$uri = "/mailbox/{$mailbox->id}/check";
$response = $this->communicator->get($uri);
$body = $response->getBody()->getContents();
if (trim($body) === '') {
throw new EmptyResponse($uri);
}
$json = json_decode($body);
if (!isset($json->status)) {
throw new MissingResponse('status');
}
return $json->status;
}
public function grabMessages(int $mailbox_id): int
{
$this->logger->info("Grabbing messages for {$mailbox_id}");
$uri = "/mailbox/{$mailbox_id}/messages/grab";
$response = $this->communicator->get($uri);
$body = $response->getBody()->getContents();
if (trim($body) === '') {
return 0;
}
$json = json_decode($body);
if (!isset($json->count)) {
return 0;
}
return $json->count;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace ProVM\Service;
use ProVM\Exception\Response\EmptyResponse;
use ProVM\Exception\Response\MissingResponse;
use Psr\Log\LoggerInterface;
use function Safe\json_decode;
class Messages
{
public function __construct(protected Communicator $communicator, protected LoggerInterface $logger) {}
public function get(int $message_id): object
{
$this->logger->info("Getting message {$message_id}");
$uri = "/message/{$message_id}";
$response = $this->communicator->get($uri);
$body = $response->getBody()->getContents();
if (trim($body) === '') {
throw new EmptyResponse($uri);
}
$json = json_decode($body);
if (!isset($json->message)) {
throw new MissingResponse('message');
}
return $json->message;
}
public function grabAttachments(string $message_uid): int
{
$this->logger->info("Grabbing attachments for message UID {$message_uid}");
$uri = '/attachments/grab';
$response = $this->communicator->put($uri, ['messages' => [$message_uid]]);
$body = $response->getBody()->getContents();
if (trim($body) === '') {
return 0;
}
$json = json_decode($body);
if (!isset($json->total)) {
return 0;
}
return $json->total;
}
}