Fork of nextcloud/integration_mastodon v5.2.0 (6a56211), AGPL-3.0, with
upstream copyright notices and CHANGELOG preserved unchanged.
Rebranded: app ID, namespace, dashboard widgets, reference provider, icon
component, search provider IDs and every user-facing string. GoToSocial
calls them posts, not toots, and its mascot is a sloth.
Deliberately NOT rebranded: MastodonAPIService, MastodonAPIController,
route names and config keys. They speak the Mastodon client API, which is
what GoToSocial implements -- renaming them would make the code claim a
protocol that does not exist, and would make this fork expensive to rebase
on future upstream releases.
Translations are inherited. Strings reworded by the rebrand fall back to
English; the rest still work in all 124 locales.
Assisted-by: Claude Code:claude-opus-5
137 lines
4.0 KiB
PHP
137 lines
4.0 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Nextcloud - mastodon
|
|
*
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
* later. See the COPYING file.
|
|
*
|
|
* @author Julien Veyssier <julien-nc@posteo.net>
|
|
* @copyright Julien Veyssier 2020
|
|
*/
|
|
|
|
namespace OCA\GoToSocial\Controller;
|
|
|
|
use OCA\GoToSocial\AppInfo\Application;
|
|
use OCA\GoToSocial\Service\MastodonAPIService;
|
|
use OCP\AppFramework\Controller;
|
|
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
|
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
|
use OCP\AppFramework\Http\DataDisplayResponse;
|
|
use OCP\AppFramework\Http\DataResponse;
|
|
use OCP\IConfig;
|
|
use OCP\IRequest;
|
|
use OCP\PreConditionNotMetException;
|
|
use OCP\Security\ICrypto;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
class MastodonAPIController extends Controller {
|
|
|
|
public function __construct(
|
|
string $appName,
|
|
IRequest $request,
|
|
private IConfig $config,
|
|
private LoggerInterface $logger,
|
|
private ICrypto $crypto,
|
|
private MastodonAPIService $mastodonAPIService,
|
|
private ?string $userId,
|
|
) {
|
|
parent::__construct($appName, $request);
|
|
}
|
|
|
|
/**
|
|
* @return DataResponse
|
|
*/
|
|
#[NoAdminRequired]
|
|
public function getGoToSocialUrl(): DataResponse {
|
|
return new DataResponse($this->mastodonAPIService->getGoToSocialUrl($this->userId));
|
|
}
|
|
|
|
/**
|
|
* get notification list
|
|
*
|
|
* @param string $redirect_uri
|
|
* @param string|null $oauth_origin
|
|
* @return DataResponse
|
|
* @throws PreConditionNotMetException
|
|
*/
|
|
#[NoAdminRequired]
|
|
public function declareApp(string $redirect_uri, ?string $oauth_origin = null): DataResponse {
|
|
$result = $this->mastodonAPIService->declareApp($this->userId, $redirect_uri);
|
|
if (isset($result['client_id'], $result['client_secret'])) {
|
|
// we save the client ID and secret and give the client ID back to the UI
|
|
$this->config->setUserValue($this->userId, Application::APP_ID, 'redirect_uri', $redirect_uri);
|
|
$encryptedClientId = $result['client_id'] === '' ? '' : $this->crypto->encrypt($result['client_id']);
|
|
$this->config->setUserValue($this->userId, Application::APP_ID, 'client_id', $encryptedClientId);
|
|
$encryptedClientSecret = $result['client_secret'] === '' ? '' : $this->crypto->encrypt($result['client_secret']);
|
|
$this->config->setUserValue($this->userId, Application::APP_ID, 'client_secret', $encryptedClientSecret);
|
|
if ($oauth_origin !== null) {
|
|
$this->config->setUserValue($this->userId, Application::APP_ID, 'oauth_origin', $oauth_origin);
|
|
}
|
|
$data = [
|
|
'client_id' => $result['client_id'],
|
|
];
|
|
$response = new DataResponse($data);
|
|
} else {
|
|
$warning = 'GoToSocial app declaration error : ' . ($result['error'] ?? '');
|
|
$this->logger->warning($warning, ['app' => Application::APP_ID]);
|
|
$response = new DataResponse($result, 401);
|
|
}
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* get mastodon user avatar
|
|
*
|
|
* @param string $imageUrl
|
|
* @return DataDisplayResponse
|
|
*/
|
|
#[NoAdminRequired]
|
|
#[NoCSRFRequired]
|
|
public function getGoToSocialAvatar(string $imageUrl): DataDisplayResponse {
|
|
$avatar = $this->mastodonAPIService->getGoToSocialAvatar($this->userId, $imageUrl);
|
|
if (is_null($avatar)) {
|
|
return new DataDisplayResponse('', 401);
|
|
} else {
|
|
$response = new DataDisplayResponse($avatar);
|
|
$response->cacheFor(60 * 60 * 24);
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get home timeline
|
|
*
|
|
* @param ?int $since
|
|
* @return DataResponse
|
|
*/
|
|
#[NoAdminRequired]
|
|
public function getHomeTimeline(?int $since = null): DataResponse {
|
|
$result = $this->mastodonAPIService->getHomeTimeline($this->userId, $since);
|
|
if (!isset($result['error'])) {
|
|
$response = new DataResponse($result);
|
|
} else {
|
|
$response = new DataResponse($result, 401);
|
|
}
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* get notification list
|
|
*
|
|
* @param ?int $since
|
|
* @return DataResponse
|
|
*/
|
|
#[NoAdminRequired]
|
|
public function getNotifications(?int $since = null): DataResponse {
|
|
$result = $this->mastodonAPIService->getNotifications($this->userId, $since);
|
|
if (!isset($result['error'])) {
|
|
$response = new DataResponse($result);
|
|
} else {
|
|
$response = new DataResponse($result, 401);
|
|
}
|
|
return $response;
|
|
}
|
|
|
|
}
|