mirror of
https://github.com/friendica/friendica
synced 2025-04-23 19:50:11 +00:00
Merge branch 'stable' into develop
This commit is contained in:
commit
95229140f8
194 changed files with 11224 additions and 9691 deletions
|
@ -22,9 +22,11 @@
|
|||
namespace Friendica\Module\ActivityPub;
|
||||
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Module\Special\HTTPException;
|
||||
|
@ -103,6 +105,7 @@ class Inbox extends BaseApi
|
|||
$uid = 0;
|
||||
}
|
||||
|
||||
Item::incrementInbound(Protocol::ACTIVITYPUB);
|
||||
ActivityPub\Receiver::processInbox($postdata, $_SERVER, $uid);
|
||||
|
||||
throw new \Friendica\Network\HTTPException\AcceptedException();
|
||||
|
|
|
@ -28,6 +28,12 @@ use Friendica\Module\BaseAdmin;
|
|||
|
||||
class Index extends BaseAdmin
|
||||
{
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
parent::content();
|
||||
|
|
|
@ -30,6 +30,12 @@ use Friendica\Util\Strings;
|
|||
|
||||
class Details extends BaseAdmin
|
||||
{
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
parent::content();
|
||||
|
|
|
@ -29,6 +29,12 @@ use Friendica\Util\Strings;
|
|||
|
||||
class Index extends BaseAdmin
|
||||
{
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
parent::content();
|
||||
|
|
|
@ -43,9 +43,9 @@ class Block extends BaseApi
|
|||
|
||||
Contact\User::setBlocked($this->parameters['id'], $uid, true);
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
|
||||
if (!empty($cdata['user'])) {
|
||||
$contact = Contact::getById($cdata['user']);
|
||||
$ucid = Contact::getUserContactId($this->parameters['id'], $uid);
|
||||
if ($ucid) {
|
||||
$contact = Contact::getById($ucid);
|
||||
if (!empty($contact)) {
|
||||
// Mastodon-expected behavior: relationship is severed on block
|
||||
Contact::terminateFriendship($contact);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon\Accounts;
|
||||
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
|
@ -75,6 +75,9 @@ class Followers extends BaseApi
|
|||
$params['order'] = ['pid'];
|
||||
}
|
||||
|
||||
$networks = Widget::unavailableNetworks();
|
||||
$condition = DBA::mergeConditions($condition, array_merge(["NOT `network` IN (" . substr(str_repeat("?, ", count($networks)), 0, -2) . ")"], $networks));
|
||||
|
||||
$accounts = [];
|
||||
|
||||
foreach (Contact::selectAccountToArray(['pid'], $condition, $params) as $follower) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon\Accounts;
|
||||
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
|
@ -75,6 +75,9 @@ class Following extends BaseApi
|
|||
$params['order'] = ['pid'];
|
||||
}
|
||||
|
||||
$networks = Widget::unavailableNetworks();
|
||||
$condition = DBA::mergeConditions($condition, array_merge(["NOT `network` IN (" . substr(str_repeat("?, ", count($networks)), 0, -2) . ")"], $networks));
|
||||
|
||||
$accounts = [];
|
||||
|
||||
foreach (Contact::selectAccountToArray(['pid'], $condition, $params) as $follower) {
|
||||
|
|
|
@ -51,9 +51,9 @@ class Lists extends BaseApi
|
|||
|
||||
$lists = [];
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($id, $uid);
|
||||
if (!empty($cdata['user'])) {
|
||||
$circles = DBA::select('group_member', ['gid'], ['contact-id' => $cdata['user']]);
|
||||
$ucid = Contact::getUserContactId($id, $uid);
|
||||
if ($ucid) {
|
||||
$circles = DBA::select('group_member', ['gid'], ['contact-id' => $ucid]);
|
||||
while ($circle = DBA::fetch($circles)) {
|
||||
$lists[] = DI::mstdnList()->createFromCircleId($circle['gid']);
|
||||
}
|
||||
|
|
|
@ -45,12 +45,12 @@ class Note extends BaseApi
|
|||
'comment' => '',
|
||||
], $request);
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
|
||||
if (empty($cdata['user'])) {
|
||||
$ucid = Contact::getUserContactId($this->parameters['id'], $uid);
|
||||
if (!$ucid) {
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
}
|
||||
|
||||
Contact::update(['info' => $request['comment']], ['id' => $cdata['user']]);
|
||||
Contact::update(['info' => $request['comment']], ['id' => $ucid]);
|
||||
|
||||
$this->jsonExit(DI::mstdnRelationship()->createFromContactId($this->parameters['id'], $uid)->toArray());
|
||||
}
|
||||
|
|
|
@ -40,12 +40,12 @@ class Unfollow extends BaseApi
|
|||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
}
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
|
||||
if (empty($cdata['user'])) {
|
||||
$ucid = Contact::getUserContactId($this->parameters['id'], $uid);
|
||||
if (!$ucid) {
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
}
|
||||
|
||||
$contact = Contact::getById($cdata['user']);
|
||||
$contact = Contact::getById($ucid);
|
||||
|
||||
Contact::unfollow($contact);
|
||||
|
||||
|
|
|
@ -100,12 +100,12 @@ class UpdateCredentials extends BaseApi
|
|||
User::update($user, $uid);
|
||||
Profile::update($profile, $uid);
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($owner['id'], $uid);
|
||||
if (empty($cdata)) {
|
||||
$ucid = Contact::getUserContactId($owner['id'], $uid);
|
||||
if (!$ucid) {
|
||||
DI::mstdnError()->InternalError();
|
||||
}
|
||||
|
||||
$account = DI::mstdnAccount()->createFromContactId($cdata['user'], $uid);
|
||||
$account = DI::mstdnAccount()->createFromContactId($ucid, $uid);
|
||||
$this->response->addJsonContent($account->toArray());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,13 +45,13 @@ class VerifyCredentials extends BaseApi
|
|||
DI::mstdnError()->InternalError();
|
||||
}
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($self['id'], $uid);
|
||||
if (empty($cdata)) {
|
||||
$ucid = Contact::getUserContactId($self['id'], $uid);
|
||||
if (!$ucid) {
|
||||
DI::mstdnError()->InternalError();
|
||||
}
|
||||
|
||||
// @todo Support the source property,
|
||||
$account = DI::mstdnAccount()->createFromContactId($cdata['user'], $uid);
|
||||
$account = DI::mstdnAccount()->createFromContactId($ucid, $uid);
|
||||
$this->response->addJsonContent($account->toArray());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon;
|
||||
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
@ -47,12 +46,12 @@ class FollowRequests extends BaseApi
|
|||
$this->checkAllowedScope(self::SCOPE_FOLLOW);
|
||||
$uid = self::getCurrentUserID();
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
|
||||
if (empty($cdata['user'])) {
|
||||
$ucid = Contact::getUserContactId($this->parameters['id'], $uid);
|
||||
if (!$ucid) {
|
||||
throw new HTTPException\NotFoundException('Contact not found');
|
||||
}
|
||||
|
||||
$introduction = DI::intro()->selectForContact($cdata['user']);
|
||||
$introduction = DI::intro()->selectForContact($ucid);
|
||||
|
||||
$contactId = $introduction->cid;
|
||||
|
||||
|
|
|
@ -131,12 +131,19 @@ class InstanceV2 extends BaseApi
|
|||
|
||||
return new InstanceEntity\Configuration(
|
||||
$statuses_config,
|
||||
new InstanceEntity\MediaAttachmentsConfig(Images::supportedMimeTypes(), $image_size_limit, $image_matrix_limit),
|
||||
new InstanceEntity\MediaAttachmentsConfig($this->supportedMimeTypes(), $image_size_limit, $image_matrix_limit),
|
||||
new InstanceEntity\Polls(),
|
||||
new InstanceEntity\Accounts(),
|
||||
);
|
||||
}
|
||||
|
||||
private function supportedMimeTypes(): array
|
||||
{
|
||||
$mimetypes = ['audio/aac', 'audio/flac', 'audio/mpeg', 'audio/mp4', 'audio/ogg', 'audio/wav',
|
||||
'audio/webm', 'video/mp4', 'video/ogg', 'video/webm'];
|
||||
return array_merge(Images::supportedMimeTypes(), $mimetypes);
|
||||
}
|
||||
|
||||
private function buildContactInfo(): InstanceEntity\Contact
|
||||
{
|
||||
$email = implode(',', User::getAdminEmailList());
|
||||
|
|
|
@ -22,8 +22,9 @@
|
|||
namespace Friendica\Module\Api\Mastodon;
|
||||
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Attach;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
@ -51,14 +52,38 @@ class Media extends BaseApi
|
|||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
}
|
||||
|
||||
$media = Photo::upload($uid, $_FILES['file'], '', null, null, '', '', $request['description']);
|
||||
if (empty($media)) {
|
||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
$type = Post\Media::getType($_FILES['file']['type']);
|
||||
|
||||
if (in_array($type, [Post\Media::IMAGE, Post\Media::UNKNOWN])) {
|
||||
$media = Photo::upload($uid, $_FILES['file'], '', null, null, '', '', $request['description']);
|
||||
if (empty($media)) {
|
||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
}
|
||||
|
||||
Logger::info('Uploaded photo', ['media' => $media]);
|
||||
|
||||
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($media['id']));
|
||||
} else {
|
||||
$tempFileName = $_FILES['file']['tmp_name'];
|
||||
$fileName = basename($_FILES['file']['name']);
|
||||
$fileSize = intval($_FILES['file']['size']);
|
||||
$maxFileSize = DI::config()->get('system', 'maxfilesize');
|
||||
|
||||
if ($fileSize <= 0) {
|
||||
@unlink($tempFileName);
|
||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
}
|
||||
|
||||
if ($maxFileSize && $fileSize > $maxFileSize) {
|
||||
@unlink($tempFileName);
|
||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
}
|
||||
|
||||
$id = Attach::storeFile($tempFileName, self::getCurrentUserID(), $fileName, $_FILES['file']['type'], '<' . Contact::getPublicIdByUserId(self::getCurrentUserID()) . '>');
|
||||
@unlink($tempFileName);
|
||||
Logger::info('Uploaded media', ['id' => $id]);
|
||||
$this->jsonExit(DI::mstdnAttachment()->createFromAttach($id));
|
||||
}
|
||||
|
||||
Logger::info('Uploaded photo', ['media' => $media]);
|
||||
|
||||
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($media['id']));
|
||||
}
|
||||
|
||||
public function put(array $request = [])
|
||||
|
@ -77,6 +102,10 @@ class Media extends BaseApi
|
|||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
}
|
||||
|
||||
if (DI::mstdnAttachment()->isAttach($this->parameters['id']) && Attach::exists(['id' => substr($this->parameters['id'], 7)])) {
|
||||
$this->jsonExit(DI::mstdnAttachment()->createFromAttach(substr($this->parameters['id'], 7)));
|
||||
}
|
||||
|
||||
$photo = Photo::selectFirst(['resource-id'], ['id' => $this->parameters['id'], 'uid' => $uid]);
|
||||
if (empty($photo['resource-id'])) {
|
||||
$media = Post\Media::getById($this->parameters['id']);
|
||||
|
@ -108,10 +137,15 @@ class Media extends BaseApi
|
|||
}
|
||||
|
||||
$id = $this->parameters['id'];
|
||||
if (!Photo::exists(['id' => $id, 'uid' => $uid])) {
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
|
||||
if (Photo::exists(['id' => $id, 'uid' => $uid])) {
|
||||
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($id));
|
||||
}
|
||||
|
||||
$this->jsonExit(DI::mstdnAttachment()->createFromPhoto($id));
|
||||
if (DI::mstdnAttachment()->isAttach($id) && Attach::exists(['id' => substr($id, 7)])) {
|
||||
$this->jsonExit(DI::mstdnAttachment()->createFromAttach(substr($id, 7)));
|
||||
}
|
||||
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,13 +98,13 @@ class PushSubscription extends BaseApi
|
|||
}
|
||||
|
||||
$fields = [
|
||||
Notification::TYPE_FOLLOW => $request['data']['alerts'][Notification::TYPE_FOLLOW] ?? false,
|
||||
Notification::TYPE_LIKE => $request['data']['alerts'][Notification::TYPE_LIKE] ?? false,
|
||||
Notification::TYPE_RESHARE => $request['data']['alerts'][Notification::TYPE_RESHARE] ?? false,
|
||||
Notification::TYPE_MENTION => $request['data']['alerts'][Notification::TYPE_MENTION] ?? false,
|
||||
Notification::TYPE_POLL => $request['data']['alerts'][Notification::TYPE_POLL] ?? false,
|
||||
Notification::TYPE_INTRODUCTION => $request['data']['alerts'][Notification::TYPE_INTRODUCTION] ?? false,
|
||||
Notification::TYPE_POST => $request['data']['alerts'][Notification::TYPE_POST] ?? false,
|
||||
Notification::TYPE_FOLLOW => $this->setBoolean($request['data']['alerts'][Notification::TYPE_FOLLOW] ?? false),
|
||||
Notification::TYPE_LIKE => $this->setBoolean($request['data']['alerts'][Notification::TYPE_LIKE] ?? false),
|
||||
Notification::TYPE_RESHARE => $this->setBoolean($request['data']['alerts'][Notification::TYPE_RESHARE] ?? false),
|
||||
Notification::TYPE_MENTION => $this->setBoolean($request['data']['alerts'][Notification::TYPE_MENTION] ?? false),
|
||||
Notification::TYPE_POLL => $this->setBoolean($request['data']['alerts'][Notification::TYPE_POLL] ?? false),
|
||||
Notification::TYPE_INTRODUCTION => $this->setBoolean($request['data']['alerts'][Notification::TYPE_INTRODUCTION] ?? false),
|
||||
Notification::TYPE_POST => $this->setBoolean($request['data']['alerts'][Notification::TYPE_POST] ?? false),
|
||||
];
|
||||
|
||||
$ret = Subscription::update($application['id'], $uid, $fields);
|
||||
|
@ -120,6 +120,14 @@ class PushSubscription extends BaseApi
|
|||
$this->response->addJsonContent($subscriptionObj->toArray());
|
||||
}
|
||||
|
||||
private function setBoolean($input): bool
|
||||
{
|
||||
if (is_bool($input)) {
|
||||
return $input;
|
||||
}
|
||||
return strtolower($input) == 'true';
|
||||
}
|
||||
|
||||
protected function delete(array $request = []): void
|
||||
{
|
||||
$this->checkAllowedScope(self::SCOPE_PUSH);
|
||||
|
|
|
@ -28,6 +28,7 @@ use Friendica\Core\Protocol;
|
|||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Attach;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Circle;
|
||||
use Friendica\Model\Item;
|
||||
|
@ -397,6 +398,20 @@ class Statuses extends BaseApi
|
|||
$item['attachments'] = [];
|
||||
|
||||
foreach ($media_ids as $id) {
|
||||
if (DI::mstdnAttachment()->isAttach($id) && Attach::exists(['id' => substr($id, 7)])) {
|
||||
$attach = Attach::selectFirst([], ['id' => substr($id, 7)]);
|
||||
$attachment = [
|
||||
'type' => Post\Media::getType($attach['filetype']),
|
||||
'mimetype' => $attach['filetype'],
|
||||
'url' => DI::baseUrl() . '/attach/' . substr($id, 7),
|
||||
'size' => $attach['filetype'],
|
||||
'name' => $attach['filename']
|
||||
];
|
||||
$item['attachments'][] = $attachment;
|
||||
Attach::setPermissionForId(substr($id, 7), $item['uid'], $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
|
||||
continue;
|
||||
}
|
||||
|
||||
$media = DBA::toArray(DBA::p("SELECT `resource-id`, `scale`, `type`, `desc`, `filename`, `datasize`, `width`, `height` FROM `photo`
|
||||
WHERE `resource-id` IN (SELECT `resource-id` FROM `photo` WHERE `id` = ?) AND `photo`.`uid` = ?
|
||||
ORDER BY `photo`.`width` DESC LIMIT 2", $id, $item['uid']));
|
||||
|
@ -409,13 +424,16 @@ class Statuses extends BaseApi
|
|||
|
||||
$ext = Images::getExtensionByMimeType($media[0]['type']);
|
||||
|
||||
$attachment = ['type' => Post\Media::IMAGE, 'mimetype' => $media[0]['type'],
|
||||
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . $ext,
|
||||
'size' => $media[0]['datasize'],
|
||||
'name' => $media[0]['filename'] ?: $media[0]['resource-id'],
|
||||
$attachment = [
|
||||
'type' => Post\Media::IMAGE,
|
||||
'mimetype' => $media[0]['type'],
|
||||
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . $ext,
|
||||
'size' => $media[0]['datasize'],
|
||||
'name' => $media[0]['filename'] ?: $media[0]['resource-id'],
|
||||
'description' => $media[0]['desc'] ?? '',
|
||||
'width' => $media[0]['width'],
|
||||
'height' => $media[0]['height']];
|
||||
'width' => $media[0]['width'],
|
||||
'height' => $media[0]['height']
|
||||
];
|
||||
|
||||
if (count($media) > 1) {
|
||||
$attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . $ext;
|
||||
|
|
|
@ -110,8 +110,7 @@ class ListTimeline extends BaseApi
|
|||
|
||||
private function getStatusesForGroup(int $uid, array $request): array
|
||||
{
|
||||
$cdata = Contact::getPublicAndUserContactID((int)substr($this->parameters['id'], 6), $uid);
|
||||
$cid = $cdata['public'];
|
||||
$cid = Contact::getPublicContactId((int)substr($this->parameters['id'], 6), $uid);
|
||||
|
||||
$condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`))", 0, $uid];
|
||||
|
||||
|
|
|
@ -21,26 +21,47 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon\Timelines;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Module\Api\ApiResponse;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Module\Conversation\Community;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Object\Api\Mastodon\TimelineOrderByTypes;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @see https://docs.joinmastodon.org/methods/timelines/
|
||||
*/
|
||||
class PublicTimeline extends BaseApi
|
||||
{
|
||||
/**
|
||||
* @var IManageConfigValues
|
||||
*/
|
||||
private $config;
|
||||
|
||||
public function __construct(IManageConfigValues $config, \Friendica\Factory\Api\Mastodon\Error $errorFactory, App $app, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, ApiResponse $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($errorFactory, $app, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
$this->config = $config;
|
||||
}
|
||||
/**
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
if ($this->config->get('system', 'block_public') || $this->config->get('system', 'community_page_style') == Community::DISABLED_VISITOR) {
|
||||
$this->checkAllowedScope(BaseApi::SCOPE_READ);
|
||||
}
|
||||
|
||||
$uid = self::getCurrentUserID();
|
||||
|
||||
$request = $this->getRequest([
|
||||
|
@ -56,6 +77,10 @@ class PublicTimeline extends BaseApi
|
|||
'friendica_order' => TimelineOrderByTypes::ID, // Sort order options (defaults to ID)
|
||||
], $request);
|
||||
|
||||
if (!$this->localAllowed() && !$this->globalAllowed()) {
|
||||
$this->jsonExit([]);
|
||||
}
|
||||
|
||||
$condition = [
|
||||
'gravity' => [Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT], 'private' => Item::PUBLIC,
|
||||
'network' => Protocol::FEDERATED, 'author-blocked' => false, 'author-hidden' => false
|
||||
|
@ -64,13 +89,13 @@ class PublicTimeline extends BaseApi
|
|||
$condition = $this->addPagingConditions($request, $condition);
|
||||
$params = $this->buildOrderAndLimitParams($request);
|
||||
|
||||
if ($request['local']) {
|
||||
if ($request['local'] && $this->localAllowed()) {
|
||||
$condition = DBA::mergeConditions($condition, ['origin' => true]);
|
||||
} else {
|
||||
$condition = DBA::mergeConditions($condition, ['uid' => 0]);
|
||||
}
|
||||
|
||||
if ($request['remote']) {
|
||||
if ($request['remote'] && $this->globalAllowed()) {
|
||||
$condition = DBA::mergeConditions($condition, ["NOT `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin` AND `post-user`.`uri-id` = `post-timeline-view`.`uri-id`)"]);
|
||||
}
|
||||
|
||||
|
@ -113,4 +138,14 @@ class PublicTimeline extends BaseApi
|
|||
self::setLinkHeader($request['friendica_order'] != TimelineOrderByTypes::ID);
|
||||
$this->jsonExit($statuses);
|
||||
}
|
||||
|
||||
private function localAllowed(): bool
|
||||
{
|
||||
return in_array($this->config->get('system', 'community_page_style'), [Community::LOCAL, Community::LOCAL_AND_GLOBAL, Community::DISABLED_VISITOR]);
|
||||
}
|
||||
|
||||
private function globalAllowed(): bool
|
||||
{
|
||||
return in_array($this->config->get('system', 'community_page_style'), [Community::GLOBAL, Community::LOCAL_AND_GLOBAL, Community::DISABLED_VISITOR]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,25 +21,46 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon\Trends;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Module\Api\ApiResponse;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Module\Conversation\Community;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @see https://docs.joinmastodon.org/methods/trends/#statuses
|
||||
*/
|
||||
class Statuses extends BaseApi
|
||||
{
|
||||
/**
|
||||
* @var IManageConfigValues
|
||||
*/
|
||||
private $config;
|
||||
|
||||
public function __construct(IManageConfigValues $config, \Friendica\Factory\Api\Mastodon\Error $errorFactory, App $app, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, ApiResponse $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($errorFactory, $app, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
if ($this->config->get('system', 'block_public') || $this->config->get('system', 'community_page_style') == Community::DISABLED_VISITOR) {
|
||||
$this->checkAllowedScope(BaseApi::SCOPE_READ);
|
||||
}
|
||||
|
||||
$uid = self::getCurrentUserID();
|
||||
|
||||
$request = $this->getRequest([
|
||||
|
|
|
@ -47,7 +47,8 @@ class Destroy extends BaseApi
|
|||
|
||||
$this->dba = $dba;
|
||||
}
|
||||
protected function rawContent(array $request = [])
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$this->checkAllowedScope(BaseApi::SCOPE_WRITE);
|
||||
$uid = BaseApi::getCurrentUserID();
|
||||
|
|
|
@ -54,7 +54,7 @@ class NewDM extends BaseApi
|
|||
$this->directMessage = $directMessage;
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$this->checkAllowedScope(BaseApi::SCOPE_WRITE);
|
||||
$uid = BaseApi::getCurrentUserID();
|
||||
|
@ -81,9 +81,9 @@ class NewDM extends BaseApi
|
|||
}
|
||||
}
|
||||
|
||||
$cdata = Contact::getPublicAndUserContactID($cid, $uid);
|
||||
$ucid = Contact::getUserContactId($cid, $uid);
|
||||
|
||||
$id = Mail::send($uid, $cdata['user'], $request['text'], $sub, $replyto);
|
||||
$id = Mail::send($uid, $ucid, $request['text'], $sub, $replyto);
|
||||
|
||||
if ($id > -1) {
|
||||
$ret = $this->directMessage->createFromMailId($id, $uid, $this->getRequestValue($request, 'getText', ''));
|
||||
|
|
|
@ -88,9 +88,9 @@ abstract class DirectMessagesEndpoint extends BaseApi
|
|||
|
||||
$cid = BaseApi::getContactIDForSearchterm($this->getRequestValue($request, 'screen_name', ''), $this->getRequestValue($request, 'profileurl', ''), $this->getRequestValue($request, 'user_id', 0), 0);
|
||||
if (!empty($cid)) {
|
||||
$cdata = Contact::getPublicAndUserContactID($cid, $uid);
|
||||
if (!empty($cdata['user'])) {
|
||||
$condition = DBA::mergeConditions($condition, ["`contact-id` = ?", $cdata['user']]);
|
||||
$ucid = Contact::getUserContactId($cid, $uid);
|
||||
if ($ucid) {
|
||||
$condition = DBA::mergeConditions($condition, ["`contact-id` = ?", $ucid]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,13 +71,13 @@ class Destroy extends ContactEndpoint
|
|||
}
|
||||
|
||||
// Get Contact by given id
|
||||
$cdata = Contact::getPublicAndUserContactID($contact_id, $uid);
|
||||
if (!empty($cdata['user'])) {
|
||||
$ucid = Contact::getUserContactId($contact_id, $uid);
|
||||
if (!$ucid) {
|
||||
Logger::notice(BaseApi::LOG_PREFIX . 'Not following contact', ['module' => 'api', 'action' => 'friendships_destroy']);
|
||||
throw new HTTPException\NotFoundException('Not following Contact');
|
||||
}
|
||||
|
||||
$contact = Contact::getById($cdata['user']);
|
||||
$contact = Contact::getById($ucid);
|
||||
$user = $this->twitterUser->createFromContactId($contact_id, $uid, true)->toArray();
|
||||
|
||||
try {
|
||||
|
|
|
@ -55,9 +55,9 @@ class Show extends ContactEndpoint
|
|||
$following = false;
|
||||
|
||||
if ($source_cid == Contact::getPublicIdByUserId($uid)) {
|
||||
$cdata = Contact::getPublicAndUserContactID($target_cid, $uid);
|
||||
if (!empty($cdata['user'])) {
|
||||
$usercontact = Contact::getById($cdata['user'], ['rel']);
|
||||
$ucid = Contact::getUserContactId($target_cid, $uid);
|
||||
if ($ucid) {
|
||||
$usercontact = Contact::getById($ucid, ['rel']);
|
||||
switch ($usercontact['rel'] ?? Contact::NOTHING) {
|
||||
case Contact::FOLLOWER:
|
||||
$follower = true;
|
||||
|
|
|
@ -54,7 +54,7 @@ class Create extends BaseApi
|
|||
$this->friendicaCircle = $friendicaCircle;
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$this->checkAllowedScope(BaseApi::SCOPE_WRITE);
|
||||
$uid = BaseApi::getCurrentUserID();
|
||||
|
|
|
@ -54,7 +54,7 @@ class Destroy extends BaseApi
|
|||
$this->friendicaCircle = $friendicaCircle;
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$this->checkAllowedScope(BaseApi::SCOPE_WRITE);
|
||||
$uid = BaseApi::getCurrentUserID();
|
||||
|
|
|
@ -54,7 +54,7 @@ class Update extends BaseApi
|
|||
$this->friendicaCircle = $friendicaCircle;
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$this->checkAllowedScope(BaseApi::SCOPE_WRITE);
|
||||
$uid = BaseApi::getCurrentUserID();
|
||||
|
|
|
@ -58,7 +58,13 @@ class Contact extends BaseModule
|
|||
return;
|
||||
}
|
||||
|
||||
$redirectUrl = $_POST['redirect_url'] ?? 'contact';
|
||||
$redirectUrl = $_POST['command'] ?? '';
|
||||
if (substr($redirectUrl, 0, 7) != 'contact') {
|
||||
$redirectUrl = 'contact';
|
||||
}
|
||||
if (!empty($_POST['parameter'])) {
|
||||
$redirectUrl .= '?' . $_POST['parameter'];
|
||||
}
|
||||
|
||||
self::checkFormSecurityTokenRedirectOnError($redirectUrl, 'contact_batch_actions');
|
||||
|
||||
|
@ -253,7 +259,7 @@ class Contact extends BaseModule
|
|||
$sql_extra = " AND `archive` AND NOT `blocked` AND NOT `pending`";
|
||||
break;
|
||||
case 'pending':
|
||||
$sql_extra = " AND `pending` AND NOT `archive` AND NOT `failed` AND ((`rel` = ?)
|
||||
$sql_extra = " AND `pending` AND NOT `archive` AND ((`rel` = ?)
|
||||
OR `id` IN (SELECT `contact-id` FROM `intro` WHERE `intro`.`uid` = ? AND NOT `ignore`))";
|
||||
$sql_values[] = Model\Contact::SHARING;
|
||||
$sql_values[] = DI::userSession()->getLocalUserId();
|
||||
|
@ -459,6 +465,7 @@ class Contact extends BaseModule
|
|||
'$finding' => $searching ? DI::l10n()->t('Results for: %s', $search) : '',
|
||||
'$submit' => DI::l10n()->t('Find'),
|
||||
'$cmd' => DI::args()->getCommand(),
|
||||
'$parameter' => http_build_query($request),
|
||||
'$contacts' => $contacts,
|
||||
'$form_security_token' => BaseModule::getFormSecurityToken('contact_batch_actions'),
|
||||
'multiselect' => 1,
|
||||
|
|
|
@ -81,18 +81,18 @@ class Conversations extends BaseModule
|
|||
|
||||
// Backward compatibility: Ensure to use the public contact when the user contact is provided
|
||||
// Remove by version 2022.03
|
||||
$data = Model\Contact::getPublicAndUserContactID(intval($this->parameters['id']), $this->userSession->getLocalUserId());
|
||||
if (empty($data)) {
|
||||
$pcid = Model\Contact::getPublicContactId(intval($this->parameters['id']), $this->userSession->getLocalUserId());
|
||||
if (!$pcid) {
|
||||
throw new NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
$contact = Model\Contact::getById($data['public']);
|
||||
$contact = Model\Contact::getById($pcid);
|
||||
if (empty($contact)) {
|
||||
throw new NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
// Don't display contacts that are about to be deleted
|
||||
if (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM) {
|
||||
if ($contact['deleted'] || $contact['network'] == Protocol::PHANTOM) {
|
||||
throw new NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ class Follow extends BaseModule
|
|||
|
||||
$this->baseUrl->redirect($returnPath);
|
||||
} elseif (!empty($result['cid'])) {
|
||||
$this->baseUrl->redirect('contact/' . $result['cid']);
|
||||
$this->baseUrl->redirect('contact/' . Contact::getPublicContactId($result['cid'], $this->session->getLocalUserId()));
|
||||
}
|
||||
|
||||
$this->sysMessages->addNotice($this->t('The contact could not be added.'));
|
||||
|
|
|
@ -65,7 +65,7 @@ class Media extends BaseModule
|
|||
|
||||
$o = Contact::getTabsHTML($contact, Contact::TAB_MEDIA);
|
||||
|
||||
$o .= ModelContact::getPostsFromUrl($contact['url'], $this->userSession->getLocalUserId(), true);
|
||||
$o .= ModelContact::getPostsFromUrl($contact['url'], $this->userSession->getLocalUserId(), true, $request['last_created'] ?? '');
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
|
|
@ -73,18 +73,18 @@ class Posts extends BaseModule
|
|||
|
||||
// Backward compatibility: Ensure to use the public contact when the user contact is provided
|
||||
// Remove by version 2022.03
|
||||
$data = Model\Contact::getPublicAndUserContactID(intval($this->parameters['id']), $this->userSession->getLocalUserId());
|
||||
if (empty($data)) {
|
||||
$pcid = Model\Contact::getPublicContactId(intval($this->parameters['id']), $this->userSession->getLocalUserId());
|
||||
if (!$pcid) {
|
||||
throw new NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
$contact = Model\Contact::getById($data['public']);
|
||||
$contact = Model\Contact::getById($pcid);
|
||||
if (!DBA::isResult($contact)) {
|
||||
throw new NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
// Don't display contacts that are about to be deleted
|
||||
if (DBA::isResult($contact) && (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM)) {
|
||||
if ($contact['deleted'] || $contact['network'] == Protocol::PHANTOM) {
|
||||
throw new NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ class Profile extends BaseModule
|
|||
|
||||
// Backward compatibility: The update still needs a user-specific contact ID
|
||||
// Change to user-contact table check by version 2022.03
|
||||
$cdata = Contact::getPublicAndUserContactID($contact_id, $this->session->getLocalUserId());
|
||||
if (empty($cdata['user']) || !$this->db->exists('contact', ['id' => $cdata['user'], 'deleted' => false])) {
|
||||
$ucid = Contact::getUserContactId($contact_id, $this->session->getLocalUserId());
|
||||
if (!$ucid || !$this->db->exists('contact', ['id' => $ucid, 'deleted' => false])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -134,14 +134,14 @@ class Profile extends BaseModule
|
|||
}
|
||||
|
||||
if (isset($request['channel_frequency'])) {
|
||||
Contact\User::setChannelFrequency($cdata['user'], $this->session->getLocalUserId(), $request['channel_frequency']);
|
||||
Contact\User::setChannelFrequency($ucid, $this->session->getLocalUserId(), $request['channel_frequency']);
|
||||
}
|
||||
|
||||
if (isset($request['channel_only'])) {
|
||||
Contact\User::setChannelOnly($cdata['user'], $this->session->getLocalUserId(), $request['channel_only']);
|
||||
Contact\User::setChannelOnly($ucid, $this->session->getLocalUserId(), $request['channel_only']);
|
||||
}
|
||||
|
||||
if (!Contact::update($fields, ['id' => $cdata['user'], 'uid' => $this->session->getLocalUserId()])) {
|
||||
if (!Contact::update($fields, ['id' => $ucid, 'uid' => $this->session->getLocalUserId()])) {
|
||||
$this->systemMessages->addNotice($this->t('Failed to update contact record.'));
|
||||
}
|
||||
}
|
||||
|
@ -164,8 +164,22 @@ class Profile extends BaseModule
|
|||
throw new HTTPException\NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
// Fetch the protocol from the user's contact.
|
||||
if ($data['user']) {
|
||||
$usercontact = Contact::getById($data['user'], ['network', 'protocol']);
|
||||
if ($this->db->isResult($usercontact)) {
|
||||
$contact['network'] = $usercontact['network'];
|
||||
$contact['protocol'] = $usercontact['protocol'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($contact['network']) && Contact::isLocal($contact['url']) ) {
|
||||
$contact['network'] = Protocol::DFRN;
|
||||
$contact['protocol'] = Protocol::ACTIVITYPUB;
|
||||
}
|
||||
|
||||
// Don't display contacts that are about to be deleted
|
||||
if ($this->db->isResult($contact) && (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM)) {
|
||||
if ($contact['deleted'] || $contact['network'] == Protocol::PHANTOM) {
|
||||
throw new HTTPException\NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ use Friendica\Core\Renderer;
|
|||
use Friendica\Database\Database;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model;
|
||||
use Friendica\Model\Contact as ModelContact;
|
||||
use Friendica\Module\Contact;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Module\Security\Login;
|
||||
|
@ -58,16 +59,12 @@ class Revoke extends BaseModule
|
|||
return;
|
||||
}
|
||||
|
||||
$data = Model\Contact::getPublicAndUserContactID($this->parameters['id'], DI::userSession()->getLocalUserId());
|
||||
if (!$this->dba->isResult($data)) {
|
||||
throw new HTTPException\NotFoundException($this->t('Unknown contact.'));
|
||||
}
|
||||
|
||||
if (empty($data['user'])) {
|
||||
$ucid = Model\Contact::getUserContactId($this->parameters['id'], DI::userSession()->getLocalUserId());
|
||||
if (!$ucid) {
|
||||
throw new HTTPException\ForbiddenException();
|
||||
}
|
||||
|
||||
$this->contact = Model\Contact::getById($data['user']);
|
||||
$this->contact = Model\Contact::getById($ucid);
|
||||
|
||||
if ($this->contact['deleted']) {
|
||||
throw new HTTPException\NotFoundException($this->t('Contact is deleted.'));
|
||||
|
@ -90,7 +87,7 @@ class Revoke extends BaseModule
|
|||
|
||||
DI::sysmsg()->addNotice($this->t('Follow was successfully revoked.'));
|
||||
|
||||
$this->baseUrl->redirect('contact/' . $this->parameters['id']);
|
||||
$this->baseUrl->redirect('contact/' . ModelContact::getPublicContactId($this->parameters['id'], DI::userSession()->getLocalUserId()));
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
|
|
|
@ -168,7 +168,7 @@ class Unfollow extends \Friendica\BaseModule
|
|||
$this->baseUrl->redirect($base_return_path);
|
||||
}
|
||||
|
||||
$return_path = $base_return_path . '/' . $contact['id'];
|
||||
$return_path = $base_return_path . '/' . Contact::getPublicContactId($contact['id'], $uid);
|
||||
|
||||
try {
|
||||
Contact::unfollow($contact);
|
||||
|
|
|
@ -47,10 +47,12 @@ use Friendica\Core\L10n;
|
|||
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Circle;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Model\Profile;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Module\Security\Login;
|
||||
|
@ -231,7 +233,7 @@ class Network extends Timeline
|
|||
} else {
|
||||
$items = $this->getItems();
|
||||
}
|
||||
|
||||
|
||||
$o .= $this->conversation->render($items, Conversation::MODE_NETWORK, false, false, $this->getOrder(), $this->session->getLocalUserId());
|
||||
} catch (\Exception $e) {
|
||||
$o .= $this->l10n->t('Error %d (%s) while fetching the timeline.', $e->getCode(), $e->getMessage());
|
||||
|
@ -470,23 +472,20 @@ class Network extends Timeline
|
|||
$items = array_reverse($items);
|
||||
}
|
||||
|
||||
if ($this->database->isResult($items)) {
|
||||
$parents = array_column($items, 'uri-id');
|
||||
} else {
|
||||
$parents = [];
|
||||
if ($this->ping || !$this->database->isResult($items)) {
|
||||
return $items;
|
||||
}
|
||||
|
||||
// We aren't going to try and figure out at the item, circle, and page
|
||||
// level which items you've seen and which you haven't. If you're looking
|
||||
// at the top level network page just mark everything seen.
|
||||
if (!$this->circleId && !$this->star && !$this->mention) {
|
||||
$condition = ['unseen' => true, 'uid' => $this->session->getLocalUserId()];
|
||||
$this->setItemsSeenByCondition($condition);
|
||||
} elseif (!empty($parents)) {
|
||||
$condition = ['unseen' => true, 'uid' => $this->session->getLocalUserId(), 'parent-uri-id' => $parents];
|
||||
$this->setItemsSeenByCondition($condition);
|
||||
$this->setItemsSeenByCondition(['unseen' => true, 'uid' => $this->session->getLocalUserId(), 'parent-uri-id' => array_column($items, 'uri-id')]);
|
||||
|
||||
$posts = Post::selectToArray(['uri-id'], ['unseen' => true, 'uid' => $this->session->getLocalUserId()], ['limit' => 100]);
|
||||
if (!empty($posts)) {
|
||||
$this->setItemsSeenByCondition(['unseen' => true, 'uid' => $this->session->getLocalUserId(), 'uri-id' => array_column($posts, 'uri-id')]);
|
||||
}
|
||||
|
||||
if (count($posts) == 100) {
|
||||
Worker::add(Worker::PRIORITY_MEDIUM, 'SetSeen', $this->session->getLocalUserId());
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,10 @@
|
|||
namespace Friendica\Module\DFRN;
|
||||
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Conversation;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
@ -45,6 +47,8 @@ class Notify extends BaseModule
|
|||
throw new HTTPException\BadRequestException();
|
||||
}
|
||||
|
||||
Item::incrementInbound(Protocol::DFRN);
|
||||
|
||||
$data = json_decode($postdata);
|
||||
if (is_object($data) && !empty($this->parameters['nickname'])) {
|
||||
$user = User::getByNickname($this->parameters['nickname']);
|
||||
|
|
|
@ -29,6 +29,12 @@ use Friendica\Util\JsonLD;
|
|||
|
||||
class ActivityPubConversion extends BaseModule
|
||||
{
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
function visible_whitespace($s)
|
||||
|
|
|
@ -35,6 +35,12 @@ use Friendica\Util\XML;
|
|||
*/
|
||||
class Babel extends BaseModule
|
||||
{
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
function visible_whitespace($s)
|
||||
|
|
|
@ -25,6 +25,8 @@ use Friendica\App;
|
|||
use Friendica\BaseModule;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
@ -57,6 +59,8 @@ class Receive extends BaseModule
|
|||
throw new HTTPException\ForbiddenException($this->t('Access denied.'));
|
||||
}
|
||||
|
||||
Item::incrementInbound(Protocol::DIASPORA);
|
||||
|
||||
if ($this->parameters['type'] === 'public') {
|
||||
$this->receivePublic();
|
||||
} else if ($this->parameters['type'] === 'users') {
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
namespace Friendica\Module;
|
||||
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Protocol\Feed as ProtocolFeed;
|
||||
|
@ -68,6 +70,8 @@ class Feed extends BaseModule
|
|||
throw new HTTPException\UnauthorizedException($this->t('Access to this profile has been restricted.'));
|
||||
}
|
||||
|
||||
Item::incrementOutbound(Protocol::FEED);
|
||||
|
||||
$feed = ProtocolFeed::atom($owner, $last_update, 10, $type);
|
||||
|
||||
$this->httpExit($feed, Response::TYPE_ATOM);
|
||||
|
|
|
@ -36,7 +36,7 @@ use Friendica\Protocol\Diaspora;
|
|||
*/
|
||||
class Activity extends BaseModule
|
||||
{
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
if (!DI::userSession()->isAuthenticated()) {
|
||||
throw new HTTPException\ForbiddenException();
|
||||
|
|
|
@ -33,7 +33,7 @@ use Friendica\Network\HTTPException;
|
|||
*/
|
||||
class Follow extends BaseModule
|
||||
{
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$l10n = DI::l10n();
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ use Friendica\Network\HTTPException;
|
|||
*/
|
||||
class Ignore extends BaseModule
|
||||
{
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$l10n = DI::l10n();
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ use Friendica\Network\HTTPException;
|
|||
*/
|
||||
class Pin extends BaseModule
|
||||
{
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$l10n = DI::l10n();
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ use Friendica\Network\HTTPException;
|
|||
*/
|
||||
class Star extends BaseModule
|
||||
{
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$l10n = DI::l10n();
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ class Upload extends \Friendica\BaseModule
|
|||
$this->return(401, $msg);
|
||||
}
|
||||
|
||||
$newid = Attach::storeFile($tempFileName, $owner['uid'], $fileName, '<' . $owner['id'] . '>');
|
||||
$newid = Attach::storeFile($tempFileName, $owner['uid'], $fileName, $_FILES['userfile']['type'] ?? '', '<' . $owner['id'] . '>');
|
||||
|
||||
@unlink($tempFileName);
|
||||
|
||||
|
|
|
@ -45,6 +45,12 @@ class Source extends BaseModeration
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
parent::content();
|
||||
|
|
|
@ -48,6 +48,12 @@ class Reports extends BaseModeration
|
|||
$this->database = $database;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
parent::content();
|
||||
|
|
|
@ -56,10 +56,11 @@ class NodeInfo120 extends BaseModule
|
|||
],
|
||||
'protocols' => ['dfrn', 'activitypub'],
|
||||
'services' => Nodeinfo::getServices(),
|
||||
'usage' => Nodeinfo::getUsage(),
|
||||
'openRegistrations' => Register::getPolicy() !== Register::CLOSED,
|
||||
'usage' => Nodeinfo::getUsage(),
|
||||
'metadata' => [
|
||||
'nodeName' => $this->config->get('config', 'sitename'),
|
||||
'nodeName' => $this->config->get('config', 'sitename'),
|
||||
'nodeDescription' => $this->config->get('config', 'info'),
|
||||
],
|
||||
];
|
||||
|
||||
|
|
90
src/Module/NodeInfo121.php
Normal file
90
src/Module/NodeInfo121.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Module;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Capabilities\ICanCreateResponses;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\Nodeinfo;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Version 2.1 of Nodeinfo, a standardized way of exposing metadata about a server running one of the distributed social networks.
|
||||
* @see https://github.com/jhass/nodeinfo/blob/master/PROTOCOL.md
|
||||
*/
|
||||
class NodeInfo121 extends BaseModule
|
||||
{
|
||||
/** @var IManageConfigValues */
|
||||
protected $config;
|
||||
|
||||
public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IManageConfigValues $config, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
$nodeinfo = [
|
||||
'version' => '2.1',
|
||||
'software' => [
|
||||
'name' => 'friendica',
|
||||
'version' => App::VERSION . '-' . DB_UPDATE_VERSION,
|
||||
'repository' => 'https://github.com/friendica/friendica',
|
||||
'homepage' => 'https://friendi.ca',
|
||||
],
|
||||
'protocols' => ['dfrn', 'activitypub'],
|
||||
'services' => Nodeinfo::getServices(),
|
||||
'openRegistrations' => Register::getPolicy() !== Register::CLOSED,
|
||||
'usage' => Nodeinfo::getUsage(),
|
||||
'metadata' => [
|
||||
'nodeName' => $this->config->get('config', 'sitename'),
|
||||
'nodeDescription' => $this->config->get('config', 'info'),
|
||||
],
|
||||
];
|
||||
|
||||
if (!empty($this->config->get('system', 'diaspora_enabled'))) {
|
||||
$nodeinfo['protocols'][] = 'diaspora';
|
||||
}
|
||||
|
||||
if (empty($this->config->get('system', 'ostatus_disabled'))) {
|
||||
$nodeinfo['protocols'][] = 'ostatus';
|
||||
}
|
||||
|
||||
$nodeinfo['services']['inbound'][] = 'atom1.0';
|
||||
$nodeinfo['services']['inbound'][] = 'rss2.0';
|
||||
$nodeinfo['services']['outbound'][] = 'atom1.0';
|
||||
|
||||
if (function_exists('imap_open') && !$this->config->get('system', 'imap_disabled')) {
|
||||
$nodeinfo['services']['inbound'][] = 'imap';
|
||||
}
|
||||
|
||||
$nodeinfo['metadata']['explicitContent'] = $this->config->get('system', 'explicit_content', false) == true;
|
||||
|
||||
$this->response->setType(ICanCreateResponses::TYPE_JSON, 'application/json; charset=utf-8');
|
||||
$this->response->addContent(json_encode($nodeinfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
}
|
91
src/Module/NodeInfo122.php
Normal file
91
src/Module/NodeInfo122.php
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Module;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Capabilities\ICanCreateResponses;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\Nodeinfo;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Version 2.2 of Nodeinfo, a standardized way of exposing metadata about a server running one of the distributed social networks.
|
||||
* @see https://github.com/jhass/nodeinfo/blob/master/PROTOCOL.md
|
||||
*/
|
||||
class NodeInfo122 extends BaseModule
|
||||
{
|
||||
/** @var IManageConfigValues */
|
||||
protected $config;
|
||||
|
||||
public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IManageConfigValues $config, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
$nodeinfo = [
|
||||
'version' => '2.2',
|
||||
'instance' => [
|
||||
'name' => $this->config->get('config', 'sitename'),
|
||||
'description' => $this->config->get('config', 'info'),
|
||||
],
|
||||
'software' => [
|
||||
'name' => 'friendica',
|
||||
'version' => App::VERSION . '-' . DB_UPDATE_VERSION,
|
||||
'repository' => 'https://github.com/friendica/friendica',
|
||||
'homepage' => 'https://friendi.ca',
|
||||
],
|
||||
'protocols' => ['dfrn', 'activitypub'],
|
||||
'services' => Nodeinfo::getServices(),
|
||||
'openRegistrations' => Register::getPolicy() !== Register::CLOSED,
|
||||
'usage' => Nodeinfo::getUsage(),
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
if (!empty($this->config->get('system', 'diaspora_enabled'))) {
|
||||
$nodeinfo['protocols'][] = 'diaspora';
|
||||
}
|
||||
|
||||
if (empty($this->config->get('system', 'ostatus_disabled'))) {
|
||||
$nodeinfo['protocols'][] = 'ostatus';
|
||||
}
|
||||
|
||||
$nodeinfo['services']['inbound'][] = 'atom1.0';
|
||||
$nodeinfo['services']['inbound'][] = 'rss2.0';
|
||||
$nodeinfo['services']['outbound'][] = 'atom1.0';
|
||||
|
||||
if (function_exists('imap_open') && !$this->config->get('system', 'imap_disabled')) {
|
||||
$nodeinfo['services']['inbound'][] = 'imap';
|
||||
}
|
||||
|
||||
$nodeinfo['metadata']['explicitContent'] = $this->config->get('system', 'explicit_content', false) == true;
|
||||
|
||||
$this->response->setType(ICanCreateResponses::TYPE_JSON, 'application/json; charset=utf-8');
|
||||
$this->response->addContent(json_encode($nodeinfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ use Psr\Log\LoggerInterface;
|
|||
|
||||
/**
|
||||
* Version 1.0 of Nodeinfo 2, a sStandardized way of exposing metadata about a server running one of the distributed social networks.
|
||||
* @see https://github.com/jhass/nodeinfo/blob/master/PROTOCOL.md
|
||||
* @see https://github.com/jaywink/nodeinfo2/blob/master/PROTOCOL.md
|
||||
*/
|
||||
class NodeInfo210 extends BaseModule
|
||||
{
|
||||
|
|
|
@ -77,6 +77,12 @@ class Introductions extends BaseNotifications
|
|||
];
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
Nav::setSelected('introductions');
|
||||
|
|
|
@ -96,6 +96,12 @@ class Notifications extends BaseNotifications
|
|||
];
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->content($request);
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
Nav::setSelected('notifications');
|
||||
|
|
|
@ -45,7 +45,7 @@ class Acknowledge extends BaseApi
|
|||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
DI::session()->set('return_path', $_REQUEST['return_path'] ?? '');
|
||||
DI::session()->set('return_path', 'oauth/authorize?' . $request['return_authorize']);
|
||||
|
||||
$o = Renderer::replaceMacros(Renderer::getMarkupTemplate('oauth_authorize.tpl'), [
|
||||
'$title' => DI::l10n()->t('Authorize application connection'),
|
||||
|
|
|
@ -68,19 +68,19 @@ class Authorize extends BaseApi
|
|||
|
||||
$redirect_request = $_REQUEST;
|
||||
unset($redirect_request['pagename']);
|
||||
$redirect = 'oauth/authorize?' . http_build_query($redirect_request);
|
||||
$redirect = http_build_query($redirect_request);
|
||||
|
||||
$uid = DI::userSession()->getLocalUserId();
|
||||
if (empty($uid)) {
|
||||
Logger::info('Redirect to login');
|
||||
DI::app()->redirect('login?return_path=' . urlencode($redirect));
|
||||
DI::app()->redirect('login?' . http_build_query(['return_authorize' => $redirect]));
|
||||
} else {
|
||||
Logger::info('Already logged in user', ['uid' => $uid]);
|
||||
}
|
||||
|
||||
if (!OAuth::existsTokenForUser($application, $uid) && !DI::session()->get('oauth_acknowledge')) {
|
||||
Logger::info('Redirect to acknowledge');
|
||||
DI::app()->redirect('oauth/acknowledge?' . http_build_query(['return_path' => $redirect, 'application' => $application['name']]));
|
||||
DI::app()->redirect('oauth/acknowledge?' . http_build_query(['return_authorize' => $redirect, 'application' => $application['name']]));
|
||||
}
|
||||
|
||||
DI::session()->remove('oauth_acknowledge');
|
||||
|
|
|
@ -28,6 +28,7 @@ use Friendica\Core\System;
|
|||
use Friendica\Database\Database;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\GServer;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
@ -101,6 +102,7 @@ class PubSub extends \Friendica\BaseModule
|
|||
|
||||
$this->logger->info('Import item from Contact.', ['nickname' => $nickname, 'contact-nickname' => $contact['nick'], 'contact-id' => $contact['id']]);
|
||||
$feedhub = '';
|
||||
Item::incrementOutbound(Protocol::OSTATUS);
|
||||
OStatus::import($xml, $importer, $contact, $feedhub);
|
||||
|
||||
throw new HTTPException\OKException();
|
||||
|
|
|
@ -26,6 +26,7 @@ use Friendica\Core\L10n;
|
|||
use Friendica\Core\Protocol;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\GServer;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Protocol\ActivityNamespace;
|
||||
|
@ -210,6 +211,7 @@ class Salmon extends \Friendica\BaseModule
|
|||
|
||||
$contact = $contact ?: [];
|
||||
|
||||
Item::incrementOutbound(Protocol::OSTATUS);
|
||||
OStatus::import($data, $importer, $contact, $hub);
|
||||
|
||||
throw new HTTPException\OKException();
|
||||
|
|
|
@ -68,7 +68,7 @@ class Remove extends \Friendica\BaseModule
|
|||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
$returnUrl = $request['return'] ?? '';
|
||||
$returnUrl = hex2bin($request['return'] ?? '');
|
||||
|
||||
if (!$this->session->getLocalUserId()) {
|
||||
$this->baseUrl->redirect($returnUrl);
|
||||
|
|
|
@ -64,7 +64,7 @@ class Media extends BaseProfile
|
|||
|
||||
$o = self::getTabsHTML('media', $is_owner, $profile['nickname'], $profile['hide-friends']);
|
||||
|
||||
$o .= Contact::getPostsFromUrl($profile['url'], $this->userSession->getLocalUserId(), true);
|
||||
$o .= Contact::getPostsFromUrl($profile['url'], $this->userSession->getLocalUserId(), true, $request['last_created'] ?? '');
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
|
|
@ -26,13 +26,13 @@ use Friendica\Content\Feature;
|
|||
use Friendica\Content\GroupManager;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\HTML;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\Model\Contact;
|
||||
|
@ -43,12 +43,14 @@ use Friendica\Module\BaseProfile;
|
|||
use Friendica\Module\Response;
|
||||
use Friendica\Module\Security\Login;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Profile\ProfileField\Repository\ProfileField;
|
||||
use Friendica\Protocol\ActivityPub;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\Profiler;
|
||||
use Friendica\Util\Strings;
|
||||
use Friendica\Util\Temporal;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Profile extends BaseProfile
|
||||
|
@ -164,7 +166,7 @@ class Profile extends BaseProfile
|
|||
|
||||
$basic_fields = [];
|
||||
|
||||
$basic_fields += self::buildField('fullname', $this->t('Full Name:'), $profile['name']);
|
||||
$basic_fields += self::buildField('fullname', $this->t('Full Name:'), $this->cleanInput($profile['uri-id'], $profile['name']));
|
||||
|
||||
if (Feature::isEnabled($profile['uid'], Feature::MEMBER_SINCE)) {
|
||||
$basic_fields += self::buildField(
|
||||
|
@ -196,18 +198,18 @@ class Profile extends BaseProfile
|
|||
}
|
||||
|
||||
if ($profile['xmpp']) {
|
||||
$basic_fields += self::buildField('xmpp', $this->t('XMPP:'), $profile['xmpp']);
|
||||
$basic_fields += self::buildField('xmpp', $this->t('XMPP:'), $this->cleanInput($profile['uri-id'], $profile['xmpp']));
|
||||
}
|
||||
|
||||
if ($profile['matrix']) {
|
||||
$basic_fields += self::buildField('matrix', $this->t('Matrix:'), $profile['matrix']);
|
||||
$basic_fields += self::buildField('matrix', $this->t('Matrix:'), $this->cleanInput($profile['uri-id'], $profile['matrix']));
|
||||
}
|
||||
|
||||
if ($profile['homepage']) {
|
||||
$basic_fields += self::buildField(
|
||||
'homepage',
|
||||
$this->t('Homepage:'),
|
||||
$this->tryRelMe($profile['homepage']) ?: $profile['homepage']
|
||||
$this->tryRelMe($profile['homepage']) ?: $this->cleanInput($profile['uri-id'], $profile['homepage'])
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -218,7 +220,7 @@ class Profile extends BaseProfile
|
|||
|| $profile['region']
|
||||
|| $profile['country-name']
|
||||
) {
|
||||
$basic_fields += self::buildField('location', $this->t('Location:'), ProfileModel::formatLocation($profile));
|
||||
$basic_fields += self::buildField('location', $this->t('Location:'), $this->cleanInput($profile['uri-id'], ProfileModel::formatLocation($profile)));
|
||||
}
|
||||
|
||||
if ($profile['pub_keywords']) {
|
||||
|
@ -372,10 +374,28 @@ class Profile extends BaseProfile
|
|||
*/
|
||||
private function tryRelMe(string $input): string
|
||||
{
|
||||
if (preg_match(Strings::onlyLinkRegEx(), trim($input))) {
|
||||
return '<a href="' . trim($input) . '" target="_blank" rel="noopener noreferrer me">' . trim($input) . '</a>';
|
||||
$input = trim($input);
|
||||
if (Network::isValidHttpUrl($input)) {
|
||||
try {
|
||||
$input = (string)Uri::fromParts(parse_url($input));
|
||||
return '<a href="' . $input . '" target="_blank" rel="noopener noreferrer me">' . $input . '</a>';
|
||||
} catch (\Throwable $th) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the provided input to prevent XSS problems
|
||||
* @param int $uri_id
|
||||
* @param string $input
|
||||
* @return string
|
||||
* @throws InternalServerErrorException
|
||||
*/
|
||||
private function cleanInput(int $uri_id, string $input): string
|
||||
{
|
||||
return BBCode::convertForUriId($uri_id, HTML::toBBCode($input));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,11 @@ class Acl extends BaseModule
|
|||
$this->database = $database;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$this->rawContent($request);
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
if (!$this->session->getLocalUserId()) {
|
||||
|
|
|
@ -48,7 +48,11 @@ class Saved extends BaseModule
|
|||
$action = $this->args->get(2, 'none');
|
||||
$search = trim(rawurldecode($_GET['term'] ?? ''));
|
||||
|
||||
$return_url = $_GET['return_url'] ?? Search::getSearchPath($search);
|
||||
if (!empty($_GET['return_url'])) {
|
||||
$return_url = hex2bin($_GET['return_url']);
|
||||
} else {
|
||||
$return_url = Search::getSearchPath($search);
|
||||
}
|
||||
|
||||
if (DI::userSession()->getLocalUserId() && $search) {
|
||||
switch ($action) {
|
||||
|
|
|
@ -49,7 +49,7 @@ class Tags extends BaseModule
|
|||
$this->database = $database;
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
$tags = $request['s'] ?? '';
|
||||
$perPage = intval($request['n'] ?? self::DEFAULT_ITEMS_PER_PAGE);
|
||||
|
|
|
@ -60,7 +60,11 @@ class Login extends BaseModule
|
|||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
$return_path = $request['return_path'] ?? $this->session->pop('return_path', '') ;
|
||||
if (!empty($request['return_authorize'])) {
|
||||
$return_path = 'oauth/authorize?' . $request['return_authorize'];
|
||||
} else {
|
||||
$return_path = $request['return_path'] ?? $this->session->pop('return_path', '') ;
|
||||
}
|
||||
|
||||
if ($this->session->getLocalUserId()) {
|
||||
$this->baseUrl->redirect($return_path);
|
||||
|
|
|
@ -56,6 +56,11 @@ class Logout extends BaseModule
|
|||
$this->session = $session;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
// @todo check if POST is really used here
|
||||
$this->rawContent($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process logout requests
|
||||
|
|
|
@ -330,6 +330,11 @@ class Account extends BaseSettings
|
|||
}
|
||||
|
||||
User::setCommunityUserSettings(DI::userSession()->getLocalUserId());
|
||||
|
||||
if ($account_type == User::ACCOUNT_TYPE_RELAY) {
|
||||
Profile::setResponsibleRelayContact(DI::userSession()->getLocalUserId());
|
||||
}
|
||||
|
||||
DI::baseUrl()->redirect($redirectUrl);
|
||||
}
|
||||
|
||||
|
@ -425,7 +430,7 @@ class Account extends BaseSettings
|
|||
$user['account-type'] = User::ACCOUNT_TYPE_COMMUNITY;
|
||||
}
|
||||
|
||||
if (DI::config()->get('system', 'allow_relay_channels')) {
|
||||
if (!empty($user['parent-uid']) && DI::config()->get('system', 'allow_relay_channels')) {
|
||||
$account_relay = [
|
||||
'account-type',
|
||||
DI::l10n()->t('Channel Relay'),
|
||||
|
|
|
@ -125,18 +125,21 @@ class Index extends BaseSettings
|
|||
$country_name = trim($request['country_name']);
|
||||
$pub_keywords = self::cleanKeywords(trim($request['pub_keywords']));
|
||||
$prv_keywords = self::cleanKeywords(trim($request['prv_keywords']));
|
||||
$xmpp = trim($request['xmpp']);
|
||||
$matrix = trim($request['matrix']);
|
||||
$homepage = trim($request['homepage']);
|
||||
$xmpp = $this->cleanInput(trim($request['xmpp']));
|
||||
$matrix = $this->cleanInput(trim($request['matrix']));
|
||||
$homepage = $this->cleanInput(trim($request['homepage']));
|
||||
if ((strpos($homepage, 'http') !== 0) && (strlen($homepage))) {
|
||||
// neither http nor https in URL, add them
|
||||
$homepage = 'http://' . $homepage;
|
||||
}
|
||||
|
||||
$user = User::getById($this->session->getLocalUserId());
|
||||
$about = Profile::addResponsibleRelayContact($about, $user['parent-uid'], $user['account-type'], $user['language']);
|
||||
|
||||
$profileFieldsNew = $this->getProfileFieldsFromInput(
|
||||
$this->session->getLocalUserId(),
|
||||
$request['profile_field'],
|
||||
$request['profile_field_order']
|
||||
(array)$request['profile_field'],
|
||||
(array)$request['profile_field_order']
|
||||
);
|
||||
|
||||
$this->profileFieldRepo->saveCollectionForUser($this->session->getLocalUserId(), $profileFieldsNew);
|
||||
|
@ -187,6 +190,8 @@ class Index extends BaseSettings
|
|||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
$owner['about'] = Profile::addResponsibleRelayContact($owner['about'], $owner['parent-uid'], $owner['account-type'], $owner['language']);
|
||||
|
||||
$this->page->registerFooterScript('view/asset/es-jquery-sortable/source/js/jquery-sortable-min.js');
|
||||
$this->page->registerFooterScript(Theme::getPathForFile('js/module/settings/profile/index.js'));
|
||||
|
||||
|
@ -353,6 +358,11 @@ class Index extends BaseSettings
|
|||
return $profileFields;
|
||||
}
|
||||
|
||||
private function cleanInput(string $input): string
|
||||
{
|
||||
return str_replace(['<', '>', '"', ' '], '', $input);
|
||||
}
|
||||
|
||||
private static function cleanKeywords($keywords): string
|
||||
{
|
||||
$keywords = str_replace(',', ' ', $keywords);
|
||||
|
|
205
src/Module/Stats.php
Normal file
205
src/Module/Stats.php
Normal file
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Module;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\Register;
|
||||
use Friendica\Moderation\Entity\Report;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
||||
class Stats extends BaseModule
|
||||
{
|
||||
/** @var IManageConfigValues */
|
||||
protected $config;
|
||||
/** @var Database */
|
||||
protected $dba;
|
||||
/** @var LoggerInterface */
|
||||
protected $logger;
|
||||
/** @var IManageKeyValuePairs */
|
||||
protected $keyValue;
|
||||
|
||||
public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, IManageConfigValues $config, IManageKeyValuePairs $keyValue, Database $dba, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->config = $config;
|
||||
$this->keyValue = $keyValue;
|
||||
$this->dba = $dba;
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
if (!$this->isAllowed($request)) {
|
||||
throw new HTTPException\NotFoundException($this->l10n->t('Page not found.'));
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
if (!$this->isAllowed($request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$report = $this->dba->selectFirst('report', ['created'], [], ['order' => ['created' => true]]);
|
||||
if (!empty($report)) {
|
||||
$report_datetime = DateTimeFormat::utc($report['created'], DateTimeFormat::JSON);
|
||||
$report_timestamp = strtotime($report['created']);
|
||||
} else {
|
||||
$report_datetime = '';
|
||||
$report_timestamp = 0;
|
||||
}
|
||||
|
||||
$statistics = [
|
||||
'cron' => [
|
||||
'lastExecution' => [
|
||||
'datetime' => date(DateTimeFormat::JSON, (int)$this->keyValue->get('last_cron')),
|
||||
'timestamp' => (int)$this->keyValue->get('last_cron'),
|
||||
],
|
||||
],
|
||||
'worker' => [
|
||||
'lastExecution' => [
|
||||
'datetime' => DateTimeFormat::utc($this->keyValue->get('last_worker_execution'), DateTimeFormat::JSON),
|
||||
'timestamp' => strtotime($this->keyValue->get('last_worker_execution')),
|
||||
],
|
||||
'jpm' => [
|
||||
1 => $this->dba->count('workerqueue', ["`done` AND `executed` > ?", DateTimeFormat::utc('now - 1 minute')]),
|
||||
3 => round($this->dba->count('workerqueue', ["`done` AND `executed` > ?", DateTimeFormat::utc('now - 3 minute')]) / 3),
|
||||
5 => round($this->dba->count('workerqueue', ["`done` AND `executed` > ?", DateTimeFormat::utc('now - 5 minute')]) / 5),
|
||||
],
|
||||
'active' => [],
|
||||
'deferred' => [],
|
||||
'total' => [],
|
||||
],
|
||||
'users' => [
|
||||
'total' => intval($this->keyValue->get('nodeinfo_total_users')),
|
||||
'activeWeek' => intval($this->keyValue->get('nodeinfo_active_users_weekly')),
|
||||
'activeMonth' => intval($this->keyValue->get('nodeinfo_active_users_monthly')),
|
||||
'activeHalfyear' => intval($this->keyValue->get('nodeinfo_active_users_halfyear')),
|
||||
'pending' => Register::getPendingCount(),
|
||||
],
|
||||
'posts' => [
|
||||
'inbound' => [
|
||||
'posts' => intval($this->keyValue->get('nodeinfo_total_posts')) - intval($this->keyValue->get('nodeinfo_local_posts')),
|
||||
'comments' => intval($this->keyValue->get('nodeinfo_total_comments')) - intval($this->keyValue->get('nodeinfo_local_comments')),
|
||||
],
|
||||
'outbound' => [
|
||||
'posts' => intval($this->keyValue->get('nodeinfo_local_posts')),
|
||||
'comments' => intval($this->keyValue->get('nodeinfo_local_comments')),
|
||||
],
|
||||
],
|
||||
'packets' => [
|
||||
'inbound' => [
|
||||
Protocol::ACTIVITYPUB => intval($this->keyValue->get('stats_packets_inbound_' . Protocol::ACTIVITYPUB) ?? 0),
|
||||
Protocol::DFRN => intval($this->keyValue->get('stats_packets_inbound_' . Protocol::DFRN) ?? 0),
|
||||
Protocol::DIASPORA => intval($this->keyValue->get('stats_packets_inbound_' . Protocol::DIASPORA) ?? 0),
|
||||
Protocol::OSTATUS => intval($this->keyValue->get('stats_packets_inbound_' . Protocol::OSTATUS) ?? 0),
|
||||
Protocol::FEED => intval($this->keyValue->get('stats_packets_inbound_' . Protocol::FEED) ?? 0),
|
||||
Protocol::MAIL => intval($this->keyValue->get('stats_packets_inbound_' . Protocol::MAIL) ?? 0),
|
||||
],
|
||||
'outbound' => [
|
||||
Protocol::ACTIVITYPUB => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::ACTIVITYPUB) ?? 0),
|
||||
Protocol::DFRN => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::DFRN) ?? 0),
|
||||
Protocol::DIASPORA => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::DIASPORA) ?? 0),
|
||||
Protocol::OSTATUS => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::OSTATUS) ?? 0),
|
||||
Protocol::FEED => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::FEED) ?? 0),
|
||||
Protocol::MAIL => intval($this->keyValue->get('stats_packets_outbound_' . Protocol::MAIL) ?? 0),
|
||||
]
|
||||
],
|
||||
'reports' => [
|
||||
'newest' => [
|
||||
'datetime' => $report_datetime,
|
||||
'timestamp' => $report_timestamp,
|
||||
],
|
||||
'open' => $this->dba->count('report', ['status' => Report::STATUS_OPEN]),
|
||||
'closed' => $this->dba->count('report', ['status' => Report::STATUS_CLOSED]),
|
||||
]
|
||||
];
|
||||
|
||||
if (Addon::isEnabled('bluesky')) {
|
||||
$statistics['packets']['inbound'][Protocol::BLUESKY] = intval($this->keyValue->get('stats_packets_inbound_' . Protocol::BLUESKY) ?? 0);
|
||||
$statistics['packets']['outbound'][Protocol::BLUESKY] = intval($this->keyValue->get('stats_packets_outbound_' . Protocol::BLUESKY) ?? 0);
|
||||
}
|
||||
if (Addon::isEnabled('tumblr')) {
|
||||
$statistics['packets']['inbound'][Protocol::TUMBLR] = intval($this->keyValue->get('stats_packets_inbound_' . Protocol::TUMBLR) ?? 0);
|
||||
$statistics['packets']['outbound'][Protocol::TUMBLR] = intval($this->keyValue->get('stats_packets_outbound_' . Protocol::TUMBLR) ?? 0);
|
||||
}
|
||||
|
||||
$statistics = $this->getJobsPerPriority($statistics);
|
||||
|
||||
$this->jsonExit($statistics);
|
||||
}
|
||||
|
||||
private function isAllowed(array $request): bool
|
||||
{
|
||||
return empty(!$request['key']) && $request['key'] == $this->config->get('system', 'stats_key');
|
||||
}
|
||||
|
||||
private function getJobsPerPriority(array $statistics): array
|
||||
{
|
||||
$statistics['worker']['active'] = $statistics['worker']['total'] = [
|
||||
Worker::PRIORITY_UNDEFINED => 0,
|
||||
Worker::PRIORITY_CRITICAL => 0,
|
||||
Worker::PRIORITY_HIGH => 0,
|
||||
Worker::PRIORITY_MEDIUM => 0,
|
||||
Worker::PRIORITY_LOW => 0,
|
||||
Worker::PRIORITY_NEGLIGIBLE => 0,
|
||||
'total' => 0,
|
||||
];
|
||||
|
||||
for ($i = 1; $i <= $this->config->get('system', 'worker_defer_limit'); $i++) {
|
||||
$statistics['worker']['deferred'][$i] = 0;
|
||||
}
|
||||
$statistics['worker']['deferred']['total'] = 0;
|
||||
|
||||
$jobs = $this->dba->p("SELECT COUNT(*) AS `entries`, `priority` FROM `workerqueue` WHERE NOT `done` AND `retrial` = ? GROUP BY `priority`", 0);
|
||||
while ($entry = $this->dba->fetch($jobs)) {
|
||||
$running = $this->dba->count('workerqueue-view', ['priority' => $entry['priority']]);
|
||||
$statistics['worker']['active']['total'] += $running;
|
||||
$statistics['worker']['active'][$entry['priority']] = $running;
|
||||
$statistics['worker']['total']['total'] += $entry['entries'];
|
||||
$statistics['worker']['total'][$entry['priority']] = $entry['entries'];
|
||||
}
|
||||
$this->dba->close($jobs);
|
||||
$statistics['worker']['active'][Worker::PRIORITY_UNDEFINED] = max(0, Worker::activeWorkers() - $statistics['worker']['active']['total']);
|
||||
|
||||
$jobs = $this->dba->p("SELECT COUNT(*) AS `entries`, `retrial` FROM `workerqueue` WHERE NOT `done` AND `retrial` > ? GROUP BY `retrial`", 0);
|
||||
while ($entry = $this->dba->fetch($jobs)) {
|
||||
$statistics['worker']['deferred']['total'] += $entry['entries'];
|
||||
$statistics['worker']['deferred'][$entry['retrial']] = $entry['entries'];
|
||||
}
|
||||
$this->dba->close($jobs);
|
||||
|
||||
return $statistics;
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@
|
|||
namespace Friendica\Module\WellKnown;
|
||||
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
|
||||
/**
|
||||
|
@ -35,10 +34,22 @@ class NodeInfo extends BaseModule
|
|||
{
|
||||
$nodeinfo = [
|
||||
'links' => [
|
||||
['rel' => 'http://nodeinfo.diaspora.software/ns/schema/1.0',
|
||||
'href' => DI::baseUrl() . '/nodeinfo/1.0'],
|
||||
['rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.0',
|
||||
'href' => DI::baseUrl() . '/nodeinfo/2.0'],
|
||||
[
|
||||
'rel' => 'http://nodeinfo.diaspora.software/ns/schema/1.0',
|
||||
'href' => DI::baseUrl() . '/nodeinfo/1.0'
|
||||
],
|
||||
[
|
||||
'rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.0',
|
||||
'href' => DI::baseUrl() . '/nodeinfo/2.0'
|
||||
],
|
||||
[
|
||||
'rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.1',
|
||||
'href' => DI::baseUrl() . '/nodeinfo/2.1'
|
||||
],
|
||||
[
|
||||
'rel' => 'http://nodeinfo.diaspora.software/ns/schema/2.2',
|
||||
'href' => DI::baseUrl() . '/nodeinfo/2.2'
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue