Merge pull request #7930 from MrPetovan/task/7887-api-followers-request

Add POST follow request Mastodon API endpoint
This commit is contained in:
Philipp 2019-12-18 22:12:52 +01:00 committed by GitHub
commit 5197833c55
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 424 additions and 142 deletions

View file

@ -2,11 +2,13 @@
namespace Friendica\Module\Api\Mastodon;
use Friendica\Api\Mastodon\Account;
use Friendica\Api\Mastodon;
use Friendica\App\BaseURL;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\APContact;
use Friendica\Model\Contact;
use Friendica\Model\Introduction;
use Friendica\Module\Base\Api;
use Friendica\Network\HTTPException;
@ -19,7 +21,40 @@ class FollowRequests extends Api
{
parent::init($parameters);
self::login();
if (!self::login()) {
throw new HTTPException\UnauthorizedException();
}
}
public static function post(array $parameters = [])
{
parent::post($parameters);
/** @var Introduction $Intro */
$Intro = self::getClass(Introduction::class);
$Intro->fetch(['id' => $parameters['id'], 'uid' => self::$current_user_id]);
$contactId = $Intro->{'contact-id'};
$relationship = new Mastodon\Relationship();
$relationship->id = $contactId;
switch ($parameters['action']) {
case 'authorize':
$Intro->confirm();
$relationship = Mastodon\Relationship::createFromContact(Contact::getById($contactId));
break;
case 'ignore':
$Intro->ignore();
break;
case 'reject':
$Intro->discard();
break;
default:
throw new HTTPException\BadRequestException('Unexpected action parameter, expecting "authorize", "ignore" or "reject"');
}
System::jsonExit($relationship);
}
/**
@ -34,26 +69,32 @@ class FollowRequests extends Api
$limit = intval($_GET['limit'] ?? 40);
if (isset($since_id) && isset($max_id)) {
$condition = ['`uid` = ? AND NOT `self` AND `pending` AND `id` > ? AND `id` < ?', self::$current_user_id, $since_id, $max_id];
$condition = ['`uid` = ? AND NOT `ignore` AND `id` > ? AND `id` < ?', self::$current_user_id, $since_id, $max_id];
} elseif (isset($since_id)) {
$condition = ['`uid` = ? AND NOT `self` AND `pending` AND `id` > ?', self::$current_user_id, $since_id];
$condition = ['`uid` = ? AND NOT `ignore` AND `id` > ?', self::$current_user_id, $since_id];
} elseif (isset($max_id)) {
$condition = ['`uid` = ? AND NOT `self` AND `pending` AND `id` < ?', self::$current_user_id, $max_id];
$condition = ['`uid` = ? AND NOT `ignore` AND `id` < ?', self::$current_user_id, $max_id];
} else {
$condition = ['`uid` = ? AND NOT `self` AND `pending`', self::$current_user_id];
$condition = ['`uid` = ? AND NOT `ignore`', self::$current_user_id];
}
$count = DBA::count('contact', $condition);
$count = DBA::count('intro', $condition);
$contacts = Contact::selectToArray(
$intros = DBA::selectToArray(
'intro',
[],
$condition,
['order' => ['id' => 'DESC'], 'limit' => $limit]
);
$return = [];
foreach ($contacts as $contact) {
$account = Account::createFromContact($contact);
foreach ($intros as $intro) {
$contact = Contact::getById($intro['contact-id']);
$apcontact = APContact::getByURL($contact['url'], false);
$account = Mastodon\Account::createFromContact($contact, $apcontact);
// Not ideal, the same "account" can have multiple ids depending on the context
$account->id = $intro['id'];
$return[] = $account;
}
@ -68,9 +109,9 @@ class FollowRequests extends Api
$links = [];
if ($count > $limit) {
$links[] = '<' . $BaseURL->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['max_id' => $contacts[count($contacts) - 1]['id']]) . '>; rel="next"';
$links[] = '<' . $BaseURL->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['max_id' => $intros[count($intros) - 1]['id']]) . '>; rel="next"';
}
$links[] = '<' . $BaseURL->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['since_id' => $contacts[0]['id']]) . '>; rel="prev"';
$links[] = '<' . $BaseURL->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['since_id' => $intros[0]['id']]) . '>; rel="prev"';
header('Link: ' . implode(', ', $links));

View file

@ -54,6 +54,7 @@ class Api extends BaseModule
*
* @brief Login API user
*
* @return bool Was a user authenticated?
* @throws HTTPException\ForbiddenException
* @throws HTTPException\UnauthorizedException
* @throws HTTPException\InternalServerErrorException
@ -69,6 +70,8 @@ class Api extends BaseModule
api_login(self::getApp());
self::$current_user_id = api_user();
return (bool)self::$current_user_id;
}
/**

View file

@ -1,17 +1,9 @@
<?php
namespace Friendica\Module;
use Friendica\App;
use Friendica\BaseModule;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\User;
use Friendica\Protocol\Diaspora;
use Friendica\Protocol\ActivityPub;
use Friendica\Util\DateTimeFormat;
use Friendica\Model\Introduction;
/**
* Process follow request confirmations
@ -30,67 +22,15 @@ class FollowConfirm extends BaseModule
$intro_id = intval($_POST['intro_id'] ?? 0);
$duplex = intval($_POST['duplex'] ?? 0);
$cid = intval($_POST['contact_id'] ?? 0);
$hidden = intval($_POST['hidden'] ?? 0);
if (empty($cid)) {
notice(L10n::t('No given contact.') . EOL);
return;
}
/** @var Introduction $Intro */
$Intro = self::getClass(Introduction::class);
$Intro->fetch(['id' => $intro_id, 'uid' => local_user()]);
Logger::info('Confirming follower', ['cid' => $cid]);
$cid = $Intro->{'contact-id'};
$contact = DBA::selectFirst('contact', [], ['id' => $cid, 'uid' => $uid]);
if (!DBA::isResult($contact)) {
Logger::warning('Contact not found in DB.', ['cid' => $cid]);
notice(L10n::t('Contact not found.') . EOL);
return;
}
$relation = $contact['rel'];
$new_relation = $contact['rel'];
$writable = $contact['writable'];
if (!empty($contact['protocol'])) {
$protocol = $contact['protocol'];
} else {
$protocol = $contact['network'];
}
if ($protocol == Protocol::ACTIVITYPUB) {
ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $uid);
}
if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) {
if ($duplex) {
$new_relation = Contact::FRIEND;
} else {
$new_relation = Contact::FOLLOWER;
}
if ($new_relation != Contact::FOLLOWER) {
$writable = 1;
}
}
$fields = ['name-date' => DateTimeFormat::utcNow(),
'uri-date' => DateTimeFormat::utcNow(),
'blocked' => false, 'pending' => false, 'protocol' => $protocol,
'writable' => $writable, 'hidden' => $hidden, 'rel' => $new_relation];
DBA::update('contact', $fields, ['id' => $cid]);
if ($new_relation == Contact::FRIEND) {
if ($protocol == Protocol::DIASPORA) {
$user = User::getById($uid);
$contact = Contact::getById($cid);
$ret = Diaspora::sendShare($user, $contact);
Logger::info('share returns', ['return' => $ret]);
} elseif ($protocol == Protocol::ACTIVITYPUB) {
ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $uid);
}
}
DBA::delete('intro', ['id' => $intro_id]);
$Intro->confirm($duplex, $hidden);
$a->internalRedirect('contact/' . intval($cid));
}