activitypub-1.0.x-dev/src/Services/ResolveService.php
src/Services/ResolveService.php
<?php
namespace Drupal\activitypub\Services;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Component\Utility\EmailValidatorInterface;
use Drupal\Component\Utility\UrlHelper;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\RequestException;
use Psr\Log\LoggerInterface;
use Drupal\Core\Utility\Error;
/**
* Provides the resolve service.
*/
class ResolveService implements ResolveServiceInterface {
/**
* The actor storage.
*
* @var \Drupal\activitypub\Entity\Storage\ActivityPubActorStorageInterface
*/
protected $actorStorage;
/**
* The activitypub storage.
*
* @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface
*/
protected $activityStorage;
/**
* A logger instance.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* The ActivityPub Utility service.
*
* @var \Drupal\activitypub\Services\ActivityPubUtilityInterface
*/
protected $activitypubUtility;
/**
* The HTTP client.
*
* @var \GuzzleHttp\Client
*/
protected $httpClient;
/**
* The email validator.
*
* @var \Drupal\Component\Utility\EmailValidatorInterface
*/
protected $emailValidator;
/**
* ActivityPub Resolve service constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\activitypub\Services\ActivityPubUtilityInterface $activitypub_utility
* The utility to work with activitypub.
* @param \GuzzleHttp\ClientInterface $http_client
* The HTTP client.
* @param \Egulias\EmailValidator\EmailValidator $email_validator
* The email validator.
* @param \Psr\Log\LoggerInterface $logger
* The logger.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, ActivityPubUtilityInterface $activitypub_utility, ClientInterface $http_client, EmailValidatorInterface $email_validator, LoggerInterface $logger) {
$this->activitypubUtility = $activitypub_utility;
$this->httpClient = $http_client;
$this->emailValidator = $email_validator;
$this->actorStorage = $entity_type_manager->getStorage('activitypub_actor');
$this->activityStorage = $entity_type_manager->getStorage('activitypub_activity');
$this->logger = $logger;
}
/**
* Resolves a uri to valid status or actor.
*/
public function resolveQuery($uri) {
$default = [
'accounts' => [],
// @todo not implemented.
'hashtags' => [],
'statuses' => [],
];
if (substr($uri, 0, 1) === '@' or $this->emailValidator->isValid($uri)) {
try {
$server = $this->activitypubUtility->getServer(['instance' => ['debug' => TRUE]]);
// Get actor.
$actor = $server->actor($uri);
// Get a WebFinger instance.
$webfinger = $actor->webfinger();
if ($webfinger) {
$uri = $webfinger->getProfileId();
// @todo check if domain is banned.
}
}
catch (\Exception $e) {
// Catch all request exceptions and return default
// It would be more specific but is on activityphp side
// logging it's not needed as it may saturate logger.
return $default;
}
}
// Now let's look to allowed protocols to get objects from
// (with some dreaming of distributed networks too)
UrlHelper::setAllowedProtocols(['https', 'did']);
$uri = UrlHelper::filterBadProtocol($uri);
if (UrlHelper::isValid($uri, TRUE)) {
try {
$response = $this->httpClient->get($uri, [
'timeout' => 10,
'headers' => [
'Accept' => 'application/activity+json',
],
]);
$content = $response->getBody();
if ($content) {
$json = json_decode($content, TRUE);
if (
!$json ||
!isset($json['@context']) ||
!isset($json['type']) ||
!in_array($json['type'], ['Note', 'Person'])
) {
return $default;
}
switch ($json['type']) {
case 'Note':
$default['statuses'][] = $json;
break;
case 'Person':
$default['accounts'][] = $json;
break;
}
return $default;
}
}
catch (RequestException $e) {
$variables = Error::decodeException($e);
$this->logger->error('%type: @message in %function (line %line of %file).', $variables);
return $default;
}
}
}
}
