add Parser and refactor CheckCommand

This commit is contained in:
Simon Vieille 2019-04-25 10:28:03 +02:00
parent 75c369c77c
commit bdb92142d9
Signed by: deblan
GPG key ID: 03383D15A1D31745
2 changed files with 169 additions and 48 deletions

View file

@ -8,6 +8,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Command\Command as BaseCommand; use Symfony\Component\Console\Command\Command as BaseCommand;
use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
use Deblan\Whois\Parser;
/** /**
* class CheckCommand. * class CheckCommand.
@ -26,6 +27,16 @@ class CheckCommand extends BaseCommand
*/ */
protected $fails = []; protected $fails = [];
/**
* @var InputInterface
*/
protected $input;
/**
* @var OutputInterface
*/
protected $output;
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -33,7 +44,7 @@ class CheckCommand extends BaseCommand
{ {
$this $this
->setName('check') ->setName('check')
->addArgument('domains', InputArgument::REQUIRED, ''); ->addArgument('domains', InputArgument::REQUIRED, 'List of domains separated by commas');
} }
/** /**
@ -41,22 +52,97 @@ class CheckCommand extends BaseCommand
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$domains = explode(',', $input->getArgument('domains')); $this->input = $input;
$domains = array_map('trim', $domains); $this->output = $output;
sort($domains); $this->checkDomains();
foreach ($domains as $domain) { $table = new Table($output);
$this->check($domain); $table->setHeaders(['Domain', 'Date']);
foreach ($this->sort($this->successes) as $result) {
$table->addRow([
$result['domain'],
$this->createDateRender($result['expiryDate']),
]);
} }
usort($this->successes, function($a, $b) { foreach ($this->sort($this->fails) as $result) {
if ($a[2] > $b[2]) { $table->addRow([
$result['domain'],
$result['expiryDate'],
]);
}
$table->render();
}
/**
* Extracts domains.
*
* @return array
*/
protected function getDomains():array
{
$domains = explode(',', $this->input->getArgument('domains'));
$domains = array_map('trim', $domains);
return $domains;
}
/**
* Checks domains.
*/
protected function checkDomains():void
{
foreach ($this->getDomains() as $domain) {
$data = $this->checkDomain($domain);
if ($data['expiryDate'] === null) {
$this->fails[] = $data;
} else {
$this->successes[] = $data;
}
}
}
/**
* Checks domain.
*
* @return array
*/
protected function checkDomain($domain):array
{
$process = new Process(['whois', $domain]);
$process->run();
$whois = $process->getOutput();
$parser = new Parser($whois);
$expiryDate = $parser->getExpiryDate();
return [
'domain' => $domain,
'expiryDate' => $expiryDate,
'comparaison' => $expiryDate ? $expiryDate->getTimestamp() : 'FAIL',
];
}
/**
* Sorts by expiry date and domain.
*
* @param array $data
*
* @return array
*/
protected function sort(array $data):array
{
usort($data, function ($a, $b) {
if ($a['comparaison'] > $b['comparaison']) {
return 1; return 1;
} }
if ($a[2] === $b[2]) { if ($a['comparaison'] === $b['comparaison']) {
if ($a[0] > $b[0]) { if ($a['domain'] > $b['domain']) {
return 1; return 1;
} }
@ -66,53 +152,28 @@ class CheckCommand extends BaseCommand
return 0; return 0;
}); });
foreach ($this->successes as $k => $v) { return $data;
unset($this->successes[$k][2]);
}
$results = array_merge($this->successes, $this->fails);
$table = new Table($output);
$table
->setHeaders(['Domain', 'Date'])
->setRows($results);
$table->render();
} }
protected function check($domain) /**
* Creates date render for the table.
*
* @param \DateTime $date
*
* @return string
*/
protected function createDateRender(\DateTime $date):string
{ {
$process = new Process(['whois', $domain]); $timestamp = $date->getTimestamp();
$process->run();
if (!$process->isSuccessful()) { if ($timestamp - time() < 3600 * 24 * 14) {
$this->fails[] = [$domain, 'FAIL'];
return;
}
$whois = $process->getOutput();
preg_match('/Expiry Date: ([^\s]+)/i', $whois, $match);
if (!isset($match[0])) {
$this->fails[] = [$domain, 'FAIL'];
return;
}
$date = new \DateTime($match[1]);
if ($date->getTimestamp() - time() < 3600*24*14) {
$color = 'red'; $color = 'red';
} elseif ($date->getTimestamp() - time() < 3600*24*30) { } elseif ($timestamp - time() < 3600 * 24 * 30) {
$color = 'yellow'; $color = 'yellow';
} else { } else {
$color = 'green'; $color = 'green';
} }
$content = sprintf('<fg=%s>%s</>', $color, $date->format('Y-m-d H:i:s')); return sprintf('<fg=%s>%s</>', $color, $date->format('Y-m-d H:i:s'));
$this->successes[] = [$domain, $content, $date->format('Y-m-d H:i:s')];
} }
} }

View file

@ -0,0 +1,60 @@
<?php
namespace Deblan\Whois;
/**
* class Parser.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class Parser
{
/**
* @var string
*/
protected $whois;
/**
* Constructor.
*
* @param mixed $whois
*/
public function __construct(string $whois)
{
$this->whois = $whois;
}
/**
* Extracts expiry date.
*
* @return DateTime|null
*/
public function getExpiryDate(): ? \DateTime
{
$formats = [
'expiration date',
'expiry date',
'expires on',
'paid-till',
'renewal',
'expires',
'domain_datebilleduntil',
'expiration',
'registry expiry',
'registrar registration expiration',
];
foreach ($formats as $format) {
preg_match('/'.preg_quote($format).'\s*:?\s*([^\s]+)/i', $this->whois, $match);
if (isset($match[1])) {
try {
return new \DateTime($match[1]);
} catch (\Exception $e) {
}
}
}
return null;
}
}