[ActivityPub] Add support fox search-box profile/notice grabbing

NoticeSearchAction:
- Add new event before finding query matches

ActivityPubPlugin:
- Subscribe new searchNotice event
- Bump minor version number

Activitypub_explorer:
- Update lookup to make remote-grabbing optional
This commit is contained in:
tenma 2019-08-29 16:49:13 +01:00 committed by Diogo Cordeiro
parent c06182c38f
commit 19409cb999
4 changed files with 90 additions and 9 deletions

View File

@ -1496,3 +1496,16 @@ StartDocNav: Before outputting the docs Nav
EndDocNav: After outputting the docs Nav EndDocNav: After outputting the docs Nav
- $nav: The DoclNav widget - $nav: The DoclNav widget
StartNoticeSearch: Before finding notices that match the given query
- string $query: The text query
StartNoticeSearchShowResults: Before displaying notices matching the query
- $out: HTMLOutputter used to output
- $query: The text query
- $notices: Array of DB notice objects
EndNoticeSearchShowResults: After displaying notices matching the query
- $out: HTMLOutputter used to output
- $query: The text query
- $notices: Array of DB notice objects

View File

@ -65,6 +65,8 @@ class NoticesearchAction extends SearchAction
if (!empty($this->q)) { if (!empty($this->q)) {
Event::handle('StartNoticeSearch', [$this->q]);
$stream = new SearchNoticeStream($this->q, $this->scoped); $stream = new SearchNoticeStream($this->q, $this->scoped);
$page = $this->trimmed('page'); $page = $this->trimmed('page');

View File

@ -50,7 +50,7 @@ const ACTIVITYPUB_PUBLIC_TO = ['https://www.w3.org/ns/activitystreams#Public',
*/ */
class ActivityPubPlugin extends Plugin class ActivityPubPlugin extends Plugin
{ {
const PLUGIN_VERSION = '0.3.0alpha0'; const PLUGIN_VERSION = '0.4.0alpha0';
/** /**
* Returns a Actor's URI from its local $profile * Returns a Actor's URI from its local $profile
@ -119,7 +119,7 @@ class ActivityPubPlugin extends Plugin
$client = new HTTPClient(); $client = new HTTPClient();
$headers = []; $headers = [];
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"'; $headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social'; $headers[] = 'User-Agent: GNUSocialBot ' . GNUSOCIAL_VERSION . ' - https://gnu.io/social';
$response = $client->get($url, $headers); $response = $client->get($url, $headers);
$object = json_decode($response->getBody(), true); $object = json_decode($response->getBody(), true);
Activitypub_notice::validate_note($object); Activitypub_notice::validate_note($object);
@ -398,6 +398,68 @@ class ActivityPubPlugin extends Plugin
return true; return true;
} }
/**
* Hack the notice search-box and try to grab remote profiles or notices.
*
* Note that, on successful grabbing, this function will redirect to the
* new profile/notice, so URL searching is directly affected. A good solution
* for this is to store the URLs in the notice text without the https/http
* prefixes. This would change the queries for URL searching and therefore we
* could do both search and grab.
*
* @param string $query search query
* @return void
*/
public function onStartNoticeSearch(string $query): void
{
if (!common_logged_in()) {
// early return, search-only for non-logged sessions
return;
}
if (!filter_var($query, FILTER_VALIDATE_URL) &&
!preg_match('!^((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)$!', $query)) {
// early return, not an url or webfinger ID
return;
}
// someone we know about ?
try {
$explorer = new Activitypub_explorer();
$profile = $explorer->lookup($query, false)[0];
if ($profile instanceof Profile) {
return;
}
} catch (Exception $e) {
// nope
}
// some notice we know about ?
try {
$notice = self::grab_notice_from_url($query, false);
if ($notice instanceof Notice) {
return;
}
} catch (Exception $e) {
// nope
}
// try to grab profile
$aprofile = self::pull_remote_profile($query);
if ($aprofile instanceof Activitypub_profile) {
$url = common_local_url('userbyid', ['id' => $aprofile->getID()], null, null, false);
common_redirect($url, 303);
return;
}
// try to grab notice
$notice = self::grab_notice_from_url($query);
if ($notice instanceof Notice) {
$url = common_local_url('shownotice', ['notice' => $notice->getID()]);
common_redirect($url, 303);
}
}
/** /**
* Make sure necessary tables are filled out. * Make sure necessary tables are filled out.
* *

View File

@ -65,13 +65,14 @@ class Activitypub_explorer
* so that there is no erroneous data * so that there is no erroneous data
* *
* @param string $url User's url * @param string $url User's url
* @param bool $remote remote lookup?
* @return array of Profile objects * @return array of Profile objects
* @throws HTTP_Request2_Exception * @throws HTTP_Request2_Exception
* @throws NoProfileException * @throws NoProfileException
* @throws ServerException * @throws ServerException
* @author Diogo Cordeiro <diogo@fc.up.pt> * @author Diogo Cordeiro <diogo@fc.up.pt>
*/ */
public function lookup($url) public function lookup(string $url, bool $remote = true)
{ {
if (in_array($url, ACTIVITYPUB_PUBLIC_TO)) { if (in_array($url, ACTIVITYPUB_PUBLIC_TO)) {
return []; return [];
@ -80,7 +81,7 @@ class Activitypub_explorer
common_debug('ActivityPub Explorer: Started now looking for '.$url); common_debug('ActivityPub Explorer: Started now looking for '.$url);
$this->discovered_actor_profiles = []; $this->discovered_actor_profiles = [];
return $this->_lookup($url); return $this->_lookup($url, $remote);
} }
/** /**
@ -89,6 +90,7 @@ class Activitypub_explorer
* $discovered_actor_profiles array * $discovered_actor_profiles array
* *
* @param string $url User's url * @param string $url User's url
* @param bool $remote remote lookup?
* @return array of Profile objects * @return array of Profile objects
* @throws HTTP_Request2_Exception * @throws HTTP_Request2_Exception
* @throws NoProfileException * @throws NoProfileException
@ -96,11 +98,13 @@ class Activitypub_explorer
* @throws Exception * @throws Exception
* @author Diogo Cordeiro <diogo@fc.up.pt> * @author Diogo Cordeiro <diogo@fc.up.pt>
*/ */
private function _lookup($url) private function _lookup(string $url, bool $remote)
{ {
// First check if we already have it locally and, if so, return it $grab_local = $this->grab_local_user($url);
// If the local fetch fails: grab it remotely, store locally and return
if (! ($this->grab_local_user($url) || $this->grab_remote_user($url))) { // First check if we already have it locally and, if so, return it.
// If the local fetch fails and remote grab is required: store locally and return.
if (!$grab_local && (!$remote || !$this->grab_remote_user($url))) {
throw new Exception('User not found.'); throw new Exception('User not found.');
} }
@ -403,7 +407,7 @@ class Activitypub_explorer
$client = new HTTPClient(); $client = new HTTPClient();
$headers = []; $headers = [];
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"'; $headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social'; $headers[] = 'User-Agent: GNUSocialBot ' . GNUSOCIAL_VERSION . ' - https://gnu.io/social';
$response = $client->get($url, $headers); $response = $client->get($url, $headers);
if (!$response->isOk()) { if (!$response->isOk()) {
throw new Exception('Invalid Actor URL.'); throw new Exception('Invalid Actor URL.');