summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl Schwan <carl@carlschwan.eu>2022-09-14 12:37:18 +0200
committerCarl Schwan <carl@carlschwan.eu>2022-09-14 12:37:18 +0200
commite037394a50297cbcffc5dc3a2d3adad7f26fcd4d (patch)
tree3d266d5a1c451a2767b367ad7e16c6a5cfb55411
parentb423ac536c10ff93c56d58f4e3dad0f5f40a1ee9 (diff)
Make uploading files work
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
-rw-r--r--lib/Controller/LocalController.php26
-rw-r--r--lib/Service/CacheDocumentService.php18
-rw-r--r--lib/Service/PostService.php85
-rw-r--r--src/components/Composer/Composer.vue27
-rw-r--r--src/store/timeline.js22
5 files changed, 112 insertions, 66 deletions
diff --git a/lib/Controller/LocalController.php b/lib/Controller/LocalController.php
index 291d6faa..eec19f0c 100644
--- a/lib/Controller/LocalController.php
+++ b/lib/Controller/LocalController.php
@@ -124,18 +124,27 @@ class LocalController extends Controller {
*
* @NoAdminRequired
*/
- public function postCreate(array $data): DataResponse {
+ public function postCreate(string $content = '', $to = null, string $type = null, ?string $replyTo = null, $attachments = null, ?string $hashtags = null): DataResponse {
+
+ $content = $content ?? '';
+ $to = is_string($to) ? [$to] : $to;
+ $to = $to ?? [];
+ $replyTo = $replyTo ?? '';
+ $type = $type ?? Stream::TYPE_PUBLIC;
+ $hashtags = $hashtags === '' ? [] : $hashtags;
+ $hashtags = $hashtags ?? [];
+ $attachments = $attachments ?? [];
+
try {
$actor = $this->accountService->getActorFromUserId($this->userId);
$post = new Post($actor);
- $post->setContent($this->get('content', $data, ''));
- $post->setReplyTo($this->get('replyTo', $data, ''));
- $post->setTo($this->getArray('to', $data, []));
- $post->addTo($this->get('to', $data, ''));
- $post->setType($this->get('type', $data, Stream::TYPE_PUBLIC));
- $post->setHashtags($this->getArray('hashtags', $data, []));
- $post->setAttachments($this->getArray('attachments', $data, []));
+ $post->setContent($content);
+ $post->setReplyTo($replyTo);
+ $post->setTo($to);
+ $post->setType($type);
+ $post->setHashtags($hashtags);
+ $post->setAttachments($attachments);
$token = '';
$activity = $this->postService->createPost($post, $token);
@@ -151,7 +160,6 @@ class LocalController extends Controller {
}
}
-
/**
* Get info about a post (limited to viewer rights).
*
diff --git a/lib/Service/CacheDocumentService.php b/lib/Service/CacheDocumentService.php
index c3b5e130..80412c81 100644
--- a/lib/Service/CacheDocumentService.php
+++ b/lib/Service/CacheDocumentService.php
@@ -137,6 +137,24 @@ class CacheDocumentService {
$document->setResizedCopy($resized);
}
+ public function saveFromTempToCache(Document $document, string $tmpPath) {
+ $mime = mime_content_type($tmpPath);
+
+ $this->filterMimeTypes($mime);
+
+ $document->setMediaType($mime);
+ $document->setMimeType($mime);
+
+ $file = fopen($tmpPath, 'r');
+ $content = fread($file, filesize($tmpPath));
+
+ $filename = $this->generateFileFromContent($content);
+ $document->setLocalCopy($filename);
+ $this->resizeImage($content);
+ $resized = $this->generateFileFromContent($content);
+ $document->setResizedCopy($resized);
+ }
+
/**
* @param string $content
diff --git a/lib/Service/PostService.php b/lib/Service/PostService.php
index c10145d6..beaa7386 100644
--- a/lib/Service/PostService.php
+++ b/lib/Service/PostService.php
@@ -53,34 +53,20 @@ use OCA\Social\Model\ActivityPub\Object\Note;
use OCA\Social\Model\Post;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
+use Psr\Log\LoggerInterface;
class PostService {
private StreamService $streamService;
-
private AccountService $accountService;
-
private ActivityService $activityService;
-
private CacheDocumentService $cacheDocumentService;
-
private ConfigService $configService;
-
private MiscService $miscService;
+ private LoggerInterface $logger;
-
- /**
- * PostService constructor.
- *
- * @param StreamService $streamService
- * @param AccountService $accountService
- * @param ActivityService $activityService
- * @param CacheDocumentService $cacheDocumentService
- * @param ConfigService $configService
- * @param MiscService $miscService
- */
public function __construct(
StreamService $streamService, AccountService $accountService, ActivityService $activityService,
- CacheDocumentService $cacheDocumentService, ConfigService $configService, MiscService $miscService
+ CacheDocumentService $cacheDocumentService, ConfigService $configService, MiscService $miscService, LoggerInterface $logger
) {
$this->streamService = $streamService;
$this->accountService = $accountService;
@@ -88,6 +74,7 @@ class PostService {
$this->cacheDocumentService = $cacheDocumentService;
$this->configService = $configService;
$this->miscService = $miscService;
+ $this->logger = $logger;
}
@@ -142,15 +129,45 @@ class PostService {
*/
private function generateDocumentsFromAttachments(Note $note, Post $post) {
$documents = [];
- foreach ($post->getAttachments() as $attachment) {
+ \OC::$server->getLogger()->error(var_export($_FILES["attachments"], true));
+ if (is_array($_FILES["attachments"]["error"])) {
+ foreach ($_FILES["attachments"]["error"] as $key => $error) {
+ if ($error == UPLOAD_ERR_OK) {
+ try {
+ $document = $this->generateDocumentFromAttachment($note, $key);
+
+ $service = AP::$activityPub->getInterfaceForItem($document);
+ $service->save($document);
+
+ $documents[] = $document;
+ } catch (Exception $e) {
+ }
+ }
+ }
+ } else {
try {
- $document = $this->generateDocumentFromAttachment($note, $attachment);
+ $tmp_name = $_FILES["attachments"]["tmp_name"];
+ $name = basename($_FILES["attachments"]["name"]);
+ $tmpFile = tmpfile();
+ $tmpPath = stream_get_meta_data($tmpFile)['uri'];
+ if (move_uploaded_file($tmp_name, $tmpPath)) {
+ $document = new Document();
+ $document->setUrlCloud($this->configService->getCloudUrl());
+ $document->generateUniqueId('/documents/local');
+ $document->setParentId($note->getId());
+ $document->setPublic(true);
+
+ $this->cacheDocumentService->saveFromTempToCache($document, $tmpPath);
+ }
$service = AP::$activityPub->getInterfaceForItem($document);
$service->save($document);
$documents[] = $document;
} catch (Exception $e) {
+ $this->logger->error($e->getMessage(), [
+ 'exception' => $e,
+ ]);
}
}
$post->setDocuments($documents);
@@ -168,21 +185,21 @@ class PostService {
* @throws SocialAppConfigException
* @throws UrlCloudException
*/
- private function generateDocumentFromAttachment(Note $note, string $attachment): Document {
- list(, $data) = explode(';', $attachment);
- list(, $data) = explode(',', $data);
- $content = base64_decode($data);
-
- $document = new Document();
- $document->setUrlCloud($this->configService->getCloudUrl());
- $document->generateUniqueId('/documents/local');
- $document->setParentId($note->getId());
- $document->setPublic(true);
-
- $mime = '';
- $this->cacheDocumentService->saveLocalUploadToCache($document, $content, $mime);
- $document->setMediaType($mime);
- $document->setMimeType($mime);
+ private function generateDocumentFromAttachment(Note $note, int $key): Document {
+ $tmp_name = $_FILES["attachments"]["tmp_name"][$key];
+ $name = basename($_FILES["attachments"]["name"][$key]);
+ $tmpFile = tmpfile();
+ $tmpPath = stream_get_meta_data($tmpFile)['uri'];
+ if (move_uploaded_file($tmp_name, $tmpPath)) {
+ $document = new Document();
+ $document->setUrlCloud($this->configService->getCloudUrl());
+ $document->generateUniqueId('/documents/local');
+ $document->setParentId($note->getId());
+ $document->setPublic(true);
+
+ $this->cacheDocumentService->saveFromTempToCache($document, $tmpPath);
+ }
+
return $document;
}
diff --git a/src/components/Composer/Composer.vue b/src/components/Composer/Composer.vue
index 6134591a..5def1bc7 100644
--- a/src/components/Composer/Composer.vue
+++ b/src/components/Composer/Composer.vue
@@ -458,19 +458,20 @@ export default {
let content = contentHtml.replace(/<(?!\/div)[^>]+>/gi, '').replace(/<\/div>/gi, '\n').trim()
content = he.decode(content)
- let data = {
- content: content,
- to: to,
- hashtags: hashtags,
- type: this.type,
- attachments: this.previewUrls.map(preview => preview.result), // TODO send the summary and other props too
+ let formData = new FormData()
+ formData.append('content', content)
+ formData.append('to', to)
+ formData.append('hashtags', hashtags)
+ formData.append('type', this.type)
+ for (const preview of this.previewUrls) {
+ // TODO send the summary and other props too
+ formData.append('attachments', preview.result)
}
-
if (this.replyTo) {
- data.replyTo = this.replyTo.id
+ formData.append('replyTo', this.replyTo.id)
}
- return data
+ return formData
},
keyup(event) {
if (event.shiftKey || event.ctrlKey) {
@@ -487,7 +488,7 @@ export default {
// Trick to validate last mention when the user directly clicks on the "post" button without validating it.
let regex = /@([-\w]+)$/
- let lastMention = postData.content.match(regex)
+ let lastMention = postData.get('content').match(regex)
if (lastMention) {
// Ask the server for matching accounts, and wait for the results
@@ -495,13 +496,13 @@ export default {
// Validate the last mention only when it matches a single account
if (result.data.result.accounts.length === 1) {
- postData.content = postData.content.replace(regex, '@' + result.data.result.accounts[0].account)
- postData.to.push(result.data.result.accounts[0].account)
+ postData.set('content', postData.get('content').replace(regex, '@' + result.data.result.accounts[0].account))
+ postData.set('to', postData.get('to').push(result.data.result.accounts[0].account))
}
}
// Abort if the post is a direct message and no valid mentions were found
- // if (this.type === 'direct' && postData.to.length === 0) {
+ // if (this.type === 'direct' && postData.get('to').length === 0) {
// OC.Notification.showTemporary(t('social', 'Error while trying to post your message: Could not find any valid recipients.'), { type: 'error' })
// return
// }
diff --git a/src/store/timeline.js b/src/store/timeline.js
index 031f3306..f80b72b0 100644
--- a/src/store/timeline.js
+++ b/src/store/timeline.js
@@ -144,17 +144,19 @@ const actions = {
context.commit('setTimelineType', 'account')
context.commit('setAccount', account)
},
- post(context, post) {
- return new Promise((resolve, reject) => {
- axios.post(generateUrl('apps/social/api/v1/post'), { data: post }).then((response) => {
- Logger.info('Post created with token ' + response.data.result.token)
- resolve(response)
- }).catch((error) => {
- OC.Notification.showTemporary('Failed to create a post')
- Logger.error('Failed to create a post', { 'error': error.response })
- reject(error)
+ async post(context, post) {
+ try {
+ const { data } = axios.post(generateUrl('apps/social/api/v1/post'), post, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
})
- })
+ Logger.info('Post created with token ' + data.result.token)
+ } catch (error) {
+ OC.Notification.showTemporary('Failed to create a post')
+ console.error(error)
+ Logger.error('Failed to create a post', { 'error': error.response })
+ }
},
postDelete(context, post) {
return axios.delete(generateUrl(`apps/social/api/v1/post?id=${post.id}`)).then((response) => {