[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 Peralta Cordeiro
parent 3392939004
commit fe2168c5ae
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
- $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)) {
Event::handle('StartNoticeSearch', [$this->q]);
$stream = new SearchNoticeStream($this->q, $this->scoped);
$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
{
const PLUGIN_VERSION = '0.3.0alpha0';
const PLUGIN_VERSION = '0.4.0alpha0';
/**
* Returns a Actor's URI from its local $profile
@ -119,7 +119,7 @@ class ActivityPubPlugin extends Plugin
$client = new HTTPClient();
$headers = [];
$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);
$object = json_decode($response->getBody(), true);
Activitypub_notice::validate_note($object);
@ -398,6 +398,68 @@ class ActivityPubPlugin extends Plugin
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.
*

View File

@ -65,13 +65,14 @@ class Activitypub_explorer
* so that there is no erroneous data
*
* @param string $url User's url
* @param bool $remote remote lookup?
* @return array of Profile objects
* @throws HTTP_Request2_Exception
* @throws NoProfileException
* @throws ServerException
* @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)) {
return [];
@ -80,7 +81,7 @@ class Activitypub_explorer
common_debug('ActivityPub Explorer: Started now looking for '.$url);
$this->discovered_actor_profiles = [];
return $this->_lookup($url);
return $this->_lookup($url, $remote);
}
/**
@ -89,6 +90,7 @@ class Activitypub_explorer
* $discovered_actor_profiles array
*
* @param string $url User's url
* @param bool $remote remote lookup?
* @return array of Profile objects
* @throws HTTP_Request2_Exception
* @throws NoProfileException
@ -96,11 +98,13 @@ class Activitypub_explorer
* @throws Exception
* @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
// If the local fetch fails: grab it remotely, store locally and return
if (! ($this->grab_local_user($url) || $this->grab_remote_user($url))) {
$grab_local = $this->grab_local_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.');
}
@ -403,7 +407,7 @@ class Activitypub_explorer
$client = new HTTPClient();
$headers = [];
$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);
if (!$response->isOk()) {
throw new Exception('Invalid Actor URL.');