Adding and removing of pictures via API is now possible

This commit is contained in:
Michael 2023-02-28 06:19:19 +00:00
parent a56d2f2eb8
commit 98aed4dde3
3 changed files with 101 additions and 37 deletions

View file

@ -41,7 +41,7 @@ class StatusSource extends BaseFactory
$post = Post::selectFirst(['uri-id', 'raw-body', 'body', 'title'], ['uri-id' => $uriId, 'uid' => [0, $uid]]);
$spoiler_text = $post['title'] ?: BBCode::toPlaintext(BBCode::getAbstract($post['body'], Protocol::ACTIVITYPUB));
$body = BBCode::toMarkdown($post['body']);
$body = BBCode::toMarkdown(Post\Media::removeFromEndOfBody($post['body']));
return new \Friendica\Object\Api\Mastodon\StatusSource($post['uri-id'], $body, $spoiler_text);
}

View file

@ -721,7 +721,7 @@ class Media
*
* @param int $uri_id URI id
* @param array $types Media types
* @return bool Whether media attachment exists
* @return bool result of deletion
* @throws \Exception
*/
public static function deleteByURIId(int $uri_id, array $types = []): bool
@ -735,6 +735,18 @@ class Media
return DBA::delete('post-media', $condition);
}
/**
* Delete media by id
*
* @param int $id media id
* @return bool result of deletion
* @throws \Exception
*/
public static function deleteById(int $id): bool
{
return DBA::delete('post-media', ['id' => $id]);
}
/**
* Split the attachment media in the three segments "visual", "link" and "additional"
*

View file

@ -50,6 +50,7 @@ class Statuses extends BaseApi
$request = $this->getRequest([
'status' => '', // Text content of the status. If media_ids is provided, this becomes optional. Attaching a poll is optional while status is provided.
'media_ids' => [], // Array of Attachment ids to be attached as media. If provided, status becomes optional, and poll cannot be used.
'in_reply_to_id' => 0, // ID of the status being replied to, if status is a reply
'spoiler_text' => '', // Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field.
'language' => '', // ISO 639 language code for this status.
@ -65,7 +66,7 @@ class Statuses extends BaseApi
'origin' => true,
];
$post = Post::selectFirst(['uri-id', 'id'], $condition);
$post = Post::selectFirst(['uri-id', 'id', 'uid', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'], $condition);
if (empty($post['id'])) {
throw new HTTPException\NotFoundException('Item with URI ID ' . $this->parameters['id'] . ' not found for user ' . $uid . '.');
}
@ -85,6 +86,44 @@ class Statuses extends BaseApi
}
}
if (!empty($request['media_ids'])) {
/*
The provided ids in the request value consists of these two sources:
- The id in the "photo" table for newly uploaded media
- The id in the "post-media" table for already attached media
Because of this we have to add all media that isn't already attached.
Also we have to delete all media that isn't provided anymore.
There is a possible situation where the newly uploaded media
could have the same id as an existing, but deleted media.
We can't do anything about this, but the probability for this is extremely low.
*/
$media_ids = [];
$existing_media = array_column(Post\Media::getByURIId($post['uri-id'], [Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::IMAGE]), 'id');
foreach ($request['media_ids'] as $media) {
if (!in_array($media, $existing_media)) {
$media_ids[] = $media;
}
}
foreach ($existing_media as $media) {
if (!in_array($media, $request['media_ids'])) {
Post\Media::deleteById($media);
}
}
$item = $this->storeMediaIds($media_ids, array_merge($post, $item));
foreach ($item['attachments'] as $attachment) {
$attachment['uri-id'] = $post['uri-id'];
Post\Media::insert($attachment);
}
unset($item['attachments']);
}
Item::update($item, ['id' => $post['id']]);
Item::updateDisplayCache($post['uri-id']);
@ -222,40 +261,7 @@ class Statuses extends BaseApi
$item = DI::contentItem()->expandTags($item, $request['visibility'] == 'direct');
if (!empty($request['media_ids'])) {
$item['object-type'] = Activity\ObjectType::IMAGE;
$item['post-type'] = Item::PT_IMAGE;
$item['attachments'] = [];
foreach ($request['media_ids'] as $id) {
$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, $uid));
if (empty($media)) {
continue;
}
Photo::setPermissionForRessource($media[0]['resource-id'], $uid, $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
$ressources[] = $media[0]['resource-id'];
$phototypes = Images::supportedTypes();
$ext = $phototypes[$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'],
'description' => $media[0]['desc'] ?? '',
'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;
$attachment['preview-width'] = $media[1]['width'];
$attachment['preview-height'] = $media[1]['height'];
}
$item['attachments'][] = $attachment;
}
$item = $this->storeMediaIds($request['media_ids'], $item);
}
if (!empty($request['scheduled_at'])) {
@ -322,4 +328,50 @@ class Statuses extends BaseApi
return 'API';
}
}
/**
* Store provided media ids in the item array and adjust permissions
*
* @param array $media_ids
* @param array $item
* @return array
*/
private function storeMediaIds(array $media_ids, array $item): array
{
$item['object-type'] = Activity\ObjectType::IMAGE;
$item['post-type'] = Item::PT_IMAGE;
$item['attachments'] = [];
foreach ($media_ids as $id) {
$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']));
if (empty($media)) {
continue;
}
Photo::setPermissionForRessource($media[0]['resource-id'], $item['uid'], $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
$ressources[] = $media[0]['resource-id'];
$phototypes = Images::supportedTypes();
$ext = $phototypes[$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'],
'description' => $media[0]['desc'] ?? '',
'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;
$attachment['preview-width'] = $media[1]['width'];
$attachment['preview-height'] = $media[1]['height'];
}
$item['attachments'][] = $attachment;
}
return $item;
}
}