add media_attachments to api

Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/1586/head
Maxence Lange 2023-02-23 11:06:39 -01:00
rodzic 4753bca888
commit 0298fb6294
27 zmienionych plików z 1521 dodań i 247 usunięć

Wyświetl plik

@ -83,8 +83,13 @@ return [
['name' => 'Api#favourites', 'url' => '/api/v1/favourites/', 'verb' => 'GET'],
['name' => 'Api#notifications', 'url' => '/api/v1/notifications', 'verb' => 'GET'],
['name' => 'Api#tag', 'url' => '/api/v1/timelines/tag/{hashtag}', 'verb' => 'GET'],
['name' => 'Api#mediaNew', 'url' => '/api/v1/media', 'verb' => 'POST'],
['name' => 'Api#mediaGet', 'url' => '/api/v1/media/{nid}', 'verb' => 'GET'],
['name' => 'Api#mediaOpen', 'url' => '/media/{uuid}', 'verb' => 'GET'],
['name' => 'Api#statusNew', 'url' => '/api/v1/statuses', 'verb' => 'POST'],
['name' => 'Api#statusGet', 'url' => '/api/v1/statuses/{nid}', 'verb' => 'GET'],
['name' => 'Api#statusContext', 'url' => '/api/v1/statuses/{nid}/context', 'verb' => 'GET'],
['name' => 'Api#accountStatuses', 'url' => '/api/v1/accounts/{account}/statuses', 'verb' => 'GET'],
// Api for local front-end

Wyświetl plik

@ -24,7 +24,8 @@
},
"require": {
"gumlet/php-image-resize": "2.0.*",
"friendica/json-ld": "^1.0"
"friendica/json-ld": "^1.0",
"kornrunner/blurhash": "^1.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5",

232
composer.lock wygenerowano
Wyświetl plik

@ -4,15 +4,15 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bed6d4ecfb5f6fb104979f9c8eeff3f1",
"content-hash": "4babe68311d0661c2c9135eb8882265b",
"packages": [
{
"name": "friendica/json-ld",
"version": "1.1.1",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://git.friendi.ca/friendica/php-json-ld",
"reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1"
"reference": "5f6ea87b261d346e57f03457ae906e6835f0205f"
},
"require": {
"ext-json": "*",
@ -48,7 +48,7 @@
"Semantic Web",
"jsonld"
],
"time": "2018-10-08T20:41:00+00:00"
"time": "2023-02-20T21:56:16+00:00"
},
{
"name": "gumlet/php-image-resize",
@ -108,6 +108,54 @@
"source": "https://github.com/gumlet/php-image-resize/tree/2.0.3"
},
"time": "2022-06-21T16:20:34+00:00"
},
{
"name": "kornrunner/blurhash",
"version": "v1.2.2",
"source": {
"type": "git",
"url": "https://github.com/kornrunner/php-blurhash.git",
"reference": "bc8a4596cb0a49874f0158696a382ab3933fefe4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kornrunner/php-blurhash/zipball/bc8a4596cb0a49874f0158696a382ab3933fefe4",
"reference": "bc8a4596cb0a49874f0158696a382ab3933fefe4",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0"
},
"require-dev": {
"ext-gd": "*",
"ocramius/package-versions": "^1.4|^2.0",
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^9",
"vimeo/psalm": "^4.3"
},
"type": "library",
"autoload": {
"psr-4": {
"kornrunner\\Blurhash\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Boris Momčilović",
"email": "boris.momcilovic@gmail.com"
}
],
"description": "Pure PHP implementation of Blurhash",
"homepage": "https://github.com/kornrunner/php-blurhash",
"support": {
"issues": "https://github.com/kornrunner/php-blurhash/issues",
"source": "https://github.com/kornrunner/php-blurhash.git"
},
"time": "2022-07-13T19:38:39+00:00"
}
],
"packages-dev": [
@ -607,30 +655,30 @@
},
{
"name": "doctrine/annotations",
"version": "1.14.2",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b"
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/ad785217c1e9555a7d6c6c8c9f406395a5e2882b",
"reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"shasum": ""
},
"require": {
"doctrine/lexer": "^1 || ^2",
"doctrine/lexer": "^2 || ^3",
"ext-tokenizer": "*",
"php": "^7.1 || ^8.0",
"php": "^7.2 || ^8.0",
"psr/cache": "^1 || ^2 || ^3"
},
"require-dev": {
"doctrine/cache": "^1.11 || ^2.0",
"doctrine/coding-standard": "^9 || ^10",
"phpstan/phpstan": "~1.4.10 || ^1.8.0",
"doctrine/cache": "^2.0",
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.8.0",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"symfony/cache": "^4.4 || ^5.4 || ^6",
"symfony/cache": "^5.4 || ^6",
"vimeo/psalm": "^4.10"
},
"suggest": {
@ -677,9 +725,9 @@
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
"source": "https://github.com/doctrine/annotations/tree/1.14.2"
"source": "https://github.com/doctrine/annotations/tree/2.0.1"
},
"time": "2022-12-15T06:48:22+00:00"
"time": "2023-02-02T22:02:53+00:00"
},
{
"name": "doctrine/deprecations",
@ -975,16 +1023,16 @@
},
{
"name": "fidry/cpu-core-counter",
"version": "0.4.1",
"version": "0.5.1",
"source": {
"type": "git",
"url": "https://github.com/theofidry/cpu-core-counter.git",
"reference": "79261cc280aded96d098e1b0e0ba0c4881b432c2"
"reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/79261cc280aded96d098e1b0e0ba0c4881b432c2",
"reference": "79261cc280aded96d098e1b0e0ba0c4881b432c2",
"url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/b58e5a3933e541dc286cc91fc4f3898bbc6f1623",
"reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623",
"shasum": ""
},
"require": {
@ -1024,7 +1072,7 @@
],
"support": {
"issues": "https://github.com/theofidry/cpu-core-counter/issues",
"source": "https://github.com/theofidry/cpu-core-counter/tree/0.4.1"
"source": "https://github.com/theofidry/cpu-core-counter/tree/0.5.1"
},
"funding": [
{
@ -1032,55 +1080,56 @@
"type": "github"
}
],
"time": "2022-12-16T22:01:02+00:00"
"time": "2022-12-24T12:35:10+00:00"
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.13.2",
"version": "v3.14.4",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "3952f08a81bd3b1b15e11c3de0b6bf037faa8496"
"reference": "1b3d9dba63d93b8a202c31e824748218781eae6b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/3952f08a81bd3b1b15e11c3de0b6bf037faa8496",
"reference": "3952f08a81bd3b1b15e11c3de0b6bf037faa8496",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/1b3d9dba63d93b8a202c31e824748218781eae6b",
"reference": "1b3d9dba63d93b8a202c31e824748218781eae6b",
"shasum": ""
},
"require": {
"composer/semver": "^3.2",
"composer/semver": "^3.3",
"composer/xdebug-handler": "^3.0.3",
"doctrine/annotations": "^1.13",
"doctrine/annotations": "^2",
"doctrine/lexer": "^2 || ^3",
"ext-json": "*",
"ext-tokenizer": "*",
"php": "^7.4 || ^8.0",
"sebastian/diff": "^4.0",
"sebastian/diff": "^4.0 || ^5.0",
"symfony/console": "^5.4 || ^6.0",
"symfony/event-dispatcher": "^5.4 || ^6.0",
"symfony/filesystem": "^5.4 || ^6.0",
"symfony/finder": "^5.4 || ^6.0",
"symfony/options-resolver": "^5.4 || ^6.0",
"symfony/polyfill-mbstring": "^1.23",
"symfony/polyfill-php80": "^1.25",
"symfony/polyfill-php81": "^1.25",
"symfony/polyfill-mbstring": "^1.27",
"symfony/polyfill-php80": "^1.27",
"symfony/polyfill-php81": "^1.27",
"symfony/process": "^5.4 || ^6.0",
"symfony/stopwatch": "^5.4 || ^6.0"
},
"require-dev": {
"justinrainbow/json-schema": "^5.2",
"keradus/cli-executor": "^2.0",
"mikey179/vfsstream": "^1.6.10",
"php-coveralls/php-coveralls": "^2.5.2",
"mikey179/vfsstream": "^1.6.11",
"php-coveralls/php-coveralls": "^2.5.3",
"php-cs-fixer/accessible-object": "^1.1",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1",
"phpspec/prophecy": "^1.15",
"phpspec/prophecy": "^1.16",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"phpunitgoodpractices/polyfill": "^1.6",
"phpunitgoodpractices/traits": "^1.9.2",
"symfony/phpunit-bridge": "^6.0",
"symfony/phpunit-bridge": "^6.2.3",
"symfony/yaml": "^5.4 || ^6.0"
},
"suggest": {
@ -1113,7 +1162,7 @@
"description": "A tool to automatically fix PHP code style",
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.13.2"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.14.4"
},
"funding": [
{
@ -1121,7 +1170,7 @@
"type": "github"
}
],
"time": "2023-01-02T23:53:50+00:00"
"time": "2023-02-09T21:49:13+00:00"
},
{
"name": "myclabs/deep-copy",
@ -1280,12 +1329,12 @@
"source": {
"type": "git",
"url": "https://github.com/nextcloud-deps/ocp.git",
"reference": "b04607fb154ae49b6d9e1d4e971e5585a98de1bb"
"reference": "c4a05e2e3b749899fb3dd5577ecb5763d3993da3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/b04607fb154ae49b6d9e1d4e971e5585a98de1bb",
"reference": "b04607fb154ae49b6d9e1d4e971e5585a98de1bb",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/c4a05e2e3b749899fb3dd5577ecb5763d3993da3",
"reference": "c4a05e2e3b749899fb3dd5577ecb5763d3993da3",
"shasum": ""
},
"require": {
@ -1317,7 +1366,7 @@
"issues": "https://github.com/nextcloud-deps/ocp/issues",
"source": "https://github.com/nextcloud-deps/ocp/tree/master"
},
"time": "2023-01-21T00:37:31+00:00"
"time": "2023-02-22T00:36:09+00:00"
},
{
"name": "nikic/php-parser",
@ -1653,16 +1702,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.23",
"version": "9.2.24",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c"
"reference": "2cf940ebc6355a9d430462811b5aaa308b174bed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed",
"reference": "2cf940ebc6355a9d430462811b5aaa308b174bed",
"shasum": ""
},
"require": {
@ -1718,7 +1767,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24"
},
"funding": [
{
@ -1726,7 +1775,7 @@
"type": "github"
}
],
"time": "2022-12-28T12:41:10+00:00"
"time": "2023-01-26T08:26:55+00:00"
},
{
"name": "phpunit/php-file-iterator",
@ -1971,16 +2020,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.5.28",
"version": "9.6.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "954ca3113a03bf780d22f07bf055d883ee04b65e"
"reference": "e7b1615e3e887d6c719121c6d4a44b0ab9645555"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/954ca3113a03bf780d22f07bf055d883ee04b65e",
"reference": "954ca3113a03bf780d22f07bf055d883ee04b65e",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7b1615e3e887d6c719121c6d4a44b0ab9645555",
"reference": "e7b1615e3e887d6c719121c6d4a44b0ab9645555",
"shasum": ""
},
"require": {
@ -2022,7 +2071,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
"dev-master": "9.6-dev"
}
},
"autoload": {
@ -2053,7 +2102,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.28"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.3"
},
"funding": [
{
@ -2069,7 +2118,7 @@
"type": "tidelift"
}
],
"time": "2023-01-14T12:32:24+00:00"
"time": "2023-02-04T13:37:15+00:00"
},
{
"name": "psr/cache",
@ -2682,16 +2731,16 @@
},
{
"name": "sebastian/environment",
"version": "5.1.4",
"version": "5.1.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
"reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
"reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
"shasum": ""
},
"require": {
@ -2733,7 +2782,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.5"
},
"funding": [
{
@ -2741,7 +2790,7 @@
"type": "github"
}
],
"time": "2022-04-03T09:37:03+00:00"
"time": "2023-02-03T06:03:51+00:00"
},
{
"name": "sebastian/exporter",
@ -3055,16 +3104,16 @@
},
{
"name": "sebastian/recursion-context",
"version": "4.0.4",
"version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
"reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
"reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
"reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
"shasum": ""
},
"require": {
@ -3103,10 +3152,10 @@
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"homepage": "https://github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5"
},
"funding": [
{
@ -3114,7 +3163,7 @@
"type": "github"
}
],
"time": "2020-10-26T13:17:30+00:00"
"time": "2023-02-03T06:07:39+00:00"
},
{
"name": "sebastian/resource-operations",
@ -3173,16 +3222,16 @@
},
{
"name": "sebastian/type",
"version": "3.2.0",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
"reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
"reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
"shasum": ""
},
"require": {
@ -3217,7 +3266,7 @@
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
"source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
"source": "https://github.com/sebastianbergmann/type/tree/3.2.1"
},
"funding": [
{
@ -3225,7 +3274,7 @@
"type": "github"
}
],
"time": "2022-09-12T14:47:03+00:00"
"time": "2023-02-03T06:13:03+00:00"
},
{
"name": "sebastian/version",
@ -3512,16 +3561,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v5.4.17",
"version": "v5.4.19",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "8e18a9d559eb8ebc2220588f1faa726a2fcd31c9"
"reference": "abf49cc084c087d94b4cb939c3f3672971784e0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8e18a9d559eb8ebc2220588f1faa726a2fcd31c9",
"reference": "8e18a9d559eb8ebc2220588f1faa726a2fcd31c9",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/abf49cc084c087d94b4cb939c3f3672971784e0c",
"reference": "abf49cc084c087d94b4cb939c3f3672971784e0c",
"shasum": ""
},
"require": {
@ -3577,7 +3626,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v5.4.17"
"source": "https://github.com/symfony/event-dispatcher/tree/v5.4.19"
},
"funding": [
{
@ -3593,7 +3642,7 @@
"type": "tidelift"
}
],
"time": "2022-12-12T15:54:21+00:00"
"time": "2023-01-01T08:32:19+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@ -4786,16 +4835,16 @@
},
{
"name": "vimeo/psalm",
"version": "5.6.0",
"version": "5.7.5",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
"reference": "e784128902dfe01d489c4123d69918a9f3c1eac5"
"reference": "5390c212bab06ee230c8720c2e9c54b823db00c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/e784128902dfe01d489c4123d69918a9f3c1eac5",
"reference": "e784128902dfe01d489c4123d69918a9f3c1eac5",
"url": "https://api.github.com/repos/vimeo/psalm/zipball/5390c212bab06ee230c8720c2e9c54b823db00c8",
"reference": "5390c212bab06ee230c8720c2e9c54b823db00c8",
"shasum": ""
},
"require": {
@ -4814,12 +4863,12 @@
"ext-tokenizer": "*",
"felixfbecker/advanced-json-rpc": "^3.1",
"felixfbecker/language-server-protocol": "^1.5.2",
"fidry/cpu-core-counter": "^0.4.0",
"fidry/cpu-core-counter": "^0.4.1 || ^0.5.1",
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"nikic/php-parser": "^4.13",
"php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0",
"sebastian/diff": "^4.0 || ^5.0",
"spatie/array-to-xml": "^2.17.0",
"spatie/array-to-xml": "^2.17.0 || ^3.0",
"symfony/console": "^4.1.6 || ^5.0 || ^6.0",
"symfony/filesystem": "^5.4 || ^6.0"
},
@ -4828,13 +4877,13 @@
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.4",
"brianium/paratest": "^6.0",
"brianium/paratest": "^6.9",
"ext-curl": "*",
"mockery/mockery": "^1.5",
"nunomaduro/mock-final-classes": "^1.1",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpdoc-parser": "^1.6",
"phpunit/phpunit": "^9.5",
"phpunit/phpunit": "^9.6",
"psalm/plugin-mockery": "^1.1",
"psalm/plugin-phpunit": "^0.18",
"slevomat/coding-standard": "^8.4",
@ -4880,13 +4929,14 @@
"keywords": [
"code",
"inspection",
"php"
"php",
"static analysis"
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
"source": "https://github.com/vimeo/psalm/tree/5.6.0"
"source": "https://github.com/vimeo/psalm/tree/5.7.5"
},
"time": "2023-01-23T20:32:47+00:00"
"time": "2023-02-21T16:02:51+00:00"
},
{
"name": "webmozart/assert",

Wyświetl plik

@ -31,21 +31,26 @@ declare(strict_types=1);
namespace OCA\Social\Controller;
use Exception;
use OCA\Social\AP;
use OCA\Social\AppInfo\Application;
use OCA\Social\Exceptions\AccountDoesNotExistException;
use OCA\Social\Exceptions\ClientNotFoundException;
use OCA\Social\Exceptions\InstanceDoesNotExistException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\ActivityPub\Stream;
use OCA\Social\Model\Client\MediaAttachment;
use OCA\Social\Model\Client\Options\TimelineOptions;
use OCA\Social\Model\Client\SocialClient;
use OCA\Social\Model\Client\Status;
use OCA\Social\Model\Post;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\CacheDocumentService;
use OCA\Social\Service\ClientService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\DocumentService;
use OCA\Social\Service\FollowService;
use OCA\Social\Service\InstanceService;
use OCA\Social\Service\PostService;
@ -54,7 +59,10 @@ use OCA\Social\Tools\Traits\TNCDataResponse;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
use OCP\AppFramework\Http\Response;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserSession;
use Psr\Log\LoggerInterface;
@ -66,12 +74,15 @@ use Psr\Log\LoggerInterface;
class ApiController extends Controller {
use TNCDataResponse;
private IURLGenerator $urlGenerator;
private IUserSession $userSession;
private LoggerInterface $logger;
private InstanceService $instanceService;
private ClientService $clientService;
private AccountService $accountService;
private CacheActorService $cacheActorService;
private CacheDocumentService $cacheDocumentService;
private DocumentService $documentService;
private FollowService $followService;
private StreamService $streamService;
private PostService $postService;
@ -83,12 +94,15 @@ class ApiController extends Controller {
public function __construct(
IRequest $request,
IURLGenerator $urlGenerator,
IUserSession $userSession,
LoggerInterface $logger,
InstanceService $instanceService,
ClientService $clientService,
AccountService $accountService,
CacheActorService $cacheActorService,
CacheDocumentService $cacheDocumentService,
DocumentService $documentService,
FollowService $followService,
StreamService $streamService,
PostService $postService,
@ -96,12 +110,15 @@ class ApiController extends Controller {
) {
parent::__construct(Application::APP_NAME, $request);
$this->urlGenerator = $urlGenerator;
$this->userSession = $userSession;
$this->logger = $logger;
$this->instanceService = $instanceService;
$this->clientService = $clientService;
$this->accountService = $accountService;
$this->cacheActorService = $cacheActorService;
$this->cacheDocumentService = $cacheDocumentService;
$this->documentService = $documentService;
$this->followService = $followService;
$this->streamService = $streamService;
$this->postService = $postService;
@ -218,7 +235,7 @@ class ApiController extends Controller {
$this->initViewer(true);
$input = file_get_contents('php://input');
$this->logger->debug('[ApiController] newStatus: ' . $input);
$this->logger->debug('[ApiController] statusNew: ' . $input);
$status = new Status();
$status->import($this->convertInput($input));
@ -227,6 +244,17 @@ class ApiController extends Controller {
$post->setContent($status->getStatus());
$post->setType($status->getVisibility());
if (!empty($status->getMediaIds())) {
$post->setMedias(
array_map(function (Document $document): MediaAttachment {
return $document->convertToMediaAttachment($this->urlGenerator);
}, $this->documentService->getMediaFromArray(
$status->getMediaIds(),
$this->viewer->getPreferredUsername()
))
);
}
$activity = $this->postService->createPost($post);
$activity->setExportFormat(ACore::FORMAT_LOCAL);
@ -239,6 +267,118 @@ class ApiController extends Controller {
}
/**
* @PublicPage
* @NoCSRFRequired
*
* @return DataResponse
*/
public function mediaNew(): DataResponse {
try {
$this->initViewer(true);
$file = $_FILES['file'] ?? [];
if (empty($file)) {
throw new Exception('no media found');
}
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new Exception('error during upload');
}
$name = $file['tmp_name'] ?? '';
$size = $file['size'] ?? -1;
$type = $file['type'] ?? '';
if ($name === '' || $size === -1 || $type === '') {
throw new Exception('missing details');
}
$this->logger->debug('[ApiController] mediaNew: ' . json_encode($file));
$document = new Document();
$document->setAccount($this->viewer->getPreferredUsername());
$document->setUrlCloud($this->configService->getCloudUrl());
$document->generateUniqueId('/documents/local');
$document->setPublic(true);
$this->cacheDocumentService->saveFromTempToCache($document, $name);
$service = AP::$activityPub->getInterfaceForItem($document);
$service->save($document);
$mediaAttachment = $document->convertToMediaAttachment($this->urlGenerator);
$this->logger->debug('generated attachment: ' . json_encode($mediaAttachment));
return new DataResponse($mediaAttachment, Http::STATUS_OK);
} catch (Exception $e) {
$this->logger->warning('issues while mediaNew', ['exception' => $e]);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
}
/**
* @PublicPage
* @NoCSRFRequired
*
* @param string $id
*
* @return Response
*/
public function mediaGet(string $nid, string $preview = ''): Response {
try {
return new DataResponse([], Http::STATUS_OK);
} catch (Exception $e) {
$this->logger->warning('issues while mediaNew', ['exception' => $e]);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
}
/**
* @PublicPage
* @NoCSRFRequired
*
* @param string $id
*
* @return Response
*/
public function mediaOpen(string $uuid): Response {
$ext = '';
if (strpos($uuid, '.') > 0) {
[$uuid, $ext] = explode('.', $uuid, 2);
}
try {
$mime = '';
$file = $this->documentService->getFromUuid($uuid);
return new FileDisplayResponse(
$file, Http::STATUS_OK, ['Content-Type' => $this->mimeFromExt($ext)]
);
} catch (Exception $e) {
$this->logger->warning('issues while mediaOpen', ['exception' => $e]);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
}
/**
* @param string $ext
* only support image actually
*
* @return string
*/
private function mimeFromExt(string $ext): string {
if ($ext === '') {
return '';
}
return 'image/' . $ext;
}
/**
* @NoCSRFRequired
* @PublicPage
@ -302,6 +442,24 @@ class ApiController extends Controller {
}
/**
* @NoCSRFRequired
* @PublicPage
*
* @param int $nid
*
* @return DataResponse
*/
public function statusContext(int $nid): DataResponse {
try {
$this->initViewer(true);
$context = $this->streamService->getContextByNid($nid);
return new DataResponse($context, Http::STATUS_OK);
} catch (Exception $e) {
return $this->error($e->getMessage());
}
}
/**
* @NoCSRFRequired

Wyświetl plik

@ -38,7 +38,6 @@ class MediaApiController extends Controller {
'url' => '',
'preview_url' => '',
'remote_url' => null,
'text_url' => '',
'description' => '',
]);
}

Wyświetl plik

@ -39,15 +39,11 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
public const CACHING_TIMEOUT = 5; // 5 min
/**
* Insert cache about an Actor in database.
*
* @param Document $document
*/
public function save(Document $document): void {
$qb = $this->getCacheDocumentsInsertSql();
$qb->setValue('id', $qb->createNamedParameter($document->getId()))
->setValue('id_prim', $qb->createNamedParameter($qb->prim($document->getId())))
->setValue('account', $qb->createNamedParameter($document->getAccount()))
->setValue('type', $qb->createNamedParameter($document->getType()))
->setValue('url', $qb->createNamedParameter($document->getUrl()))
->setValue('media_type', $qb->createNamedParameter($document->getMediaType()))
@ -55,6 +51,8 @@ class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
->setValue('error', $qb->createNamedParameter($document->getError()))
->setValue('local_copy', $qb->createNamedParameter($document->getLocalCopy()))
->setValue('resized_copy', $qb->createNamedParameter($document->getResizedCopy()))
->setValue('blurhash', $qb->createNamedParameter($document->getBlurHash()))
->setValue('description', $qb->createNamedParameter($document->getDescription()))
->setValue('parent_id', $qb->createNamedParameter($document->getParentId()))
->setValue('parent_id_prim', $qb->createNamedParameter($qb->prim($document->getParentId())))
->setValue('public', $qb->createNamedParameter(($document->isPublic()) ? '1' : '0'));
@ -68,6 +66,7 @@ class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
}
$qb->executeStatement();
$document->setNid($qb->getLastInsertId());
}
@ -83,6 +82,8 @@ class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
->set('error', $qb->createNamedParameter($document->getError()))
->set('local_copy', $qb->createNamedParameter($document->getLocalCopy()))
->set('resized_copy', $qb->createNamedParameter($document->getResizedCopy()))
->set('blurhash', $qb->createNamedParameter($document->getBlurHash()))
->set('description', $qb->createNamedParameter($document->getDescription()))
->set('parent_id', $qb->createNamedParameter($document->getParentId()))
->set('parent_id_prim', $qb->createNamedParameter($qb->prim($document->getParentId())))
->set('public', $qb->createNamedParameter(($document->isPublic()) ? '1' : '0'));
@ -95,7 +96,7 @@ class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
} catch (Exception $e) {
}
$this->limitToIdString($qb, $document->getId());
$qb->limitToIdPrim($qb->prim($document->getId()));
$qb->executeStatement();
}
@ -126,6 +127,8 @@ class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
$this->limitToIdString($qb, $document->getId());
$qb->set('local_copy', $qb->createNamedParameter($document->getLocalCopy()));
$qb->set('resized_copy', $qb->createNamedParameter($document->getResizedCopy()));
$qb->set('blurhash', $qb->createNamedParameter($document->getBlurHash()));
$qb->set('description', $qb->createNamedParameter($document->getDescription()));
$qb->set('error', $qb->createNamedParameter($document->getError()));
$qb->executeStatement();
@ -155,16 +158,37 @@ class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
/**
* @param string $id
* @param array $mediaIds
* @param string $account - limit to account
*
* @return Document[]
*/
public function getFromArray(array $mediaIds, string $account = ''): array {
$qb = $this->getCacheDocumentsSelectSql();
$qb->limitToDBFieldArray('nid', $mediaIds);
$qb->limitToAccount($account);
$documents = [];
$cursor = $qb->execute();
while ($data = $cursor->fetch()) {
$documents[] = $this->parseCacheDocumentsSelectSql($data);
}
$cursor->closeCursor();
return $documents;
}
/**
* @param string $id
* @param bool $public
* @param bool $useNid
*
* @return Document
* @throws CacheDocumentDoesNotExistException
*/
public function getById(string $id, bool $public = false) {
$qb = $this->getCacheDocumentsSelectSql();
$this->limitToIdString($qb, $id);
$qb->limitToIdPrim($qb->prim($id));
if ($public === true) {
$this->limitToPublic($qb);

Wyświetl plik

@ -60,8 +60,10 @@ class CacheDocumentsRequestBuilder extends CoreRequestBuilder {
$qb = $this->getQueryBuilder();
$qb->select(
'cd.id', 'cd.type', 'cd.parent_id', 'cd.media_type', 'cd.mime_type', 'cd.url',
'cd.local_copy', 'cd.public', 'cd.error', 'cd.creation', 'cd.caching', 'cd.resized_copy'
'cd.nid', 'cd.id', 'cd.type', 'cd.parent_id', 'cd.account',
'cd.media_type', 'cd.mime_type', 'cd.url', 'cd.local_copy', 'cd.public',
'cd.error', 'cd.creation', 'cd.caching', 'cd.resized_copy', 'cd.blurhash',
'cd.description'
)
->from(self::TABLE_CACHE_DOCUMENTS, 'cd');

Wyświetl plik

@ -119,15 +119,19 @@ class CoreRequestBuilder {
'creation'
],
self::TABLE_CACHE_DOCUMENTS => [
'nid',
'id_prim',
'id',
'type',
'account',
'parent_id',
'media_type',
'mime_type',
'url',
'local_copy',
'resized_copy',
'blurhash',
'description',
'public',
'error',
'creation',
@ -1188,8 +1192,8 @@ class CoreRequestBuilder {
->selectAlias($prefix . '_f.follow_id', $prefix . '_follow_id')
->selectAlias($prefix . '_f.creation', $prefix . '_creation')
->leftJoin(
$this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, $prefix . '_f',
$andX
$this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, $prefix . '_f',
$andX
);
}

Wyświetl plik

@ -74,7 +74,9 @@ class DocumentInterface extends AbstractActivityPubInterface implements IActivit
$this->cacheDocumentsRequest->getById($item->getId());
$this->cacheDocumentsRequest->update($item);
} catch (CacheDocumentDoesNotExistException $e) {
if (!$this->cacheDocumentsRequest->isDuplicate($item)) {
// parentId / url can only be empty on new document, meaning owner cannot be empty here
if (($item->getUrl() === '' && $item->getParentId() === '' && $item->getAccount() !== '')
|| !$this->cacheDocumentsRequest->isDuplicate($item)) {
$this->cacheDocumentsRequest->save($item);
}
}

Wyświetl plik

@ -139,7 +139,7 @@ class Version1000Date20221118000001 extends SimpleMigrationStep {
);
$table->setPrimaryKey(['id_prim']);
$table->addUniqueIndex(['actor_id_prim', 'object_id_prim', 'type'], 'aot');
$table->addUniqueIndex(['actor_id_prim', 'object_id_prim', 'type'], 'apopt');
}
@ -896,6 +896,15 @@ class Version1000Date20221118000001 extends SimpleMigrationStep {
}
$table = $schema->createTable('social_cache_doc');
$table->addColumn(
'nid', Types::BIGINT,
[
'autoincrement' => true,
'notnull' => true,
'length' => 14,
'unsigned' => true,
]
);
$table->addColumn(
'id', Types::TEXT,
[
@ -969,6 +978,21 @@ class Version1000Date20221118000001 extends SimpleMigrationStep {
'default' => ''
]
);
$table->addColumn(
'blurhash', Types::STRING,
[
'notnull' => true,
'length' => 63,
'default' => ''
]
);
$table->addColumn(
'description', Types::TEXT,
[
'notnull' => true,
'default' => ''
]
);
$table->addColumn(
'public', Types::BOOLEAN,
[

Wyświetl plik

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2023, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Migration;
use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
class Version1000Date20230217000001 extends SimpleMigrationStep {
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if ($schema->hasTable('social_cache_doc')) {
$table = $schema->getTable('social_cache_doc');
if (!$table->hasColumn('nid')) {
$table->dropPrimaryKey();
}
}
return $schema;
}
}

Wyświetl plik

@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2023, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Migration;
use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
class Version1000Date20230217000002 extends SimpleMigrationStep {
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if ($schema->hasTable('social_cache_doc')) {
$table = $schema->getTable('social_cache_doc');
if (!$table->hasColumn('nid')) {
$table->addColumn(
'nid', Types::BIGINT,
[
'autoincrement' => true,
'notnull' => true,
'length' => 14,
'unsigned' => true,
]
);
$table->setPrimaryKey(['nid']);
}
if (!$table->hasColumn('account')) {
$table->addColumn(
'account', Types::STRING,
[
'notnull' => true,
'length' => 127,
]
);
}
if (!$table->hasColumn('blurhash')) {
$table->addColumn(
'blurhash', Types::STRING,
[
'notnull' => true,
'length' => 63,
'default' => ''
]
);
}
if (!$table->hasColumn('description')) {
$table->addColumn(
'description', Types::TEXT,
[
'notnull' => true,
'default' => ''
]
);
}
}
return $schema;
}
}

Wyświetl plik

@ -37,6 +37,11 @@ use JsonSerializable;
use OCA\Social\Exceptions\InvalidOriginException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\Client\AttachmentMeta;
use OCA\Social\Model\Client\AttachmentMetaDim;
use OCA\Social\Model\Client\AttachmentMetaFocus;
use OCA\Social\Model\Client\MediaAttachment;
use OCP\IURLGenerator;
/**
* Class Document
@ -46,22 +51,20 @@ use OCA\Social\Model\ActivityPub\ACore;
class Document extends ACore implements JsonSerializable {
public const TYPE = 'Document';
private string $account = '';
private string $mediaType = '';
private string $mimeType = '';
private string $localCopy = '';
private string $resizedCopy = '';
private string $blurHash = '';
private string $description = '';
private int $caching = 0;
private bool $public = false;
private int $error = 0;
private string $parentId = '';
private array $localCopySize = [0, 0];
private array $resizedCopySize = [0, 0];
/**
* Document constructor.
@ -75,6 +78,17 @@ class Document extends ACore implements JsonSerializable {
}
public function setAccount(string $account): self {
$this->account = $account;
return $this;
}
public function getAccount(): string {
return $this->account;
}
/**
* @return string
*/
@ -125,7 +139,7 @@ class Document extends ACore implements JsonSerializable {
*
* @return Document
*/
public function setLocalCopy(string $localCopy): Document {
public function setLocalCopy(string $localCopy): self {
$this->localCopy = $localCopy;
return $this;
@ -144,12 +158,51 @@ class Document extends ACore implements JsonSerializable {
*
* @return Document
*/
public function setResizedCopy(string $resizedCopy): Document {
public function setResizedCopy(string $resizedCopy): self {
$this->resizedCopy = $resizedCopy;
return $this;
}
public function setLocalCopySize(int $width, int $height): self {
$this->localCopySize = [$width, $height];
return $this;
}
public function getLocalCopySize(): array {
return $this->localCopySize;
}
public function setResizedCopySize(int $width, int $height): void {
$this->resizedCopySize = [$width, $height];
}
public function getResizedCopySize(): array {
return $this->resizedCopySize;
}
public function setBlurHash(string $blurHash): self {
$this->blurHash = $blurHash;
return $this;
}
public function getBlurHash(): string {
return $this->blurHash;
}
public function setDescription(string $description): self {
$this->description = $description;
return $this;
}
public function getDescription(): string {
return $this->description;
}
/**
* @return bool
@ -163,7 +216,7 @@ class Document extends ACore implements JsonSerializable {
*
* @return Document
*/
public function setPublic(bool $public): Document {
public function setPublic(bool $public): self {
$this->public = $public;
return $this;
@ -182,7 +235,7 @@ class Document extends ACore implements JsonSerializable {
*
* @return Document
*/
public function setParentId(string $parentId): Document {
public function setParentId(string $parentId): self {
$this->parentId = $parentId;
return $this;
@ -201,7 +254,7 @@ class Document extends ACore implements JsonSerializable {
*
* @return Document
*/
public function setError(int $error): Document {
public function setError(int $error): self {
$this->error = $error;
return $this;
@ -220,7 +273,7 @@ class Document extends ACore implements JsonSerializable {
*
* @return Document
*/
public function setCaching(int $caching): Document {
public function setCaching(int $caching): self {
$this->caching = $caching;
return $this;
@ -253,10 +306,13 @@ class Document extends ACore implements JsonSerializable {
public function importFromDatabase(array $data) {
parent::importFromDatabase($data);
$this->setPublic(($this->getInt('public', $data, 0) === 1) ? true : false);
$this->setAccount($this->get('account', $data));
$this->setPublic(($this->getInt('public', $data, 0) === 1));
$this->setError($this->getInt('error', $data, 0));
$this->setLocalCopy($this->get('local_copy', $data, ''));
$this->setResizedCopy($this->get('resized_copy', $data, ''));
$this->setBlurHash($this->get('blurhash', $data, ''));
$this->setDescription($this->get('description', $data, ''));
$this->setMediaType($this->get('media_type', $data, ''));
$this->setMimeType($this->get('mime_type', $data, ''));
$this->setParentId($this->get('parent_id', $data, ''));
@ -292,4 +348,43 @@ class Document extends ACore implements JsonSerializable {
return $result;
}
/**
* @return MediaAttachment
*/
public function convertToMediaAttachment(?IURLGenerator $urlGenerator = null): MediaAttachment {
$media = new MediaAttachment();
[$type, $mime] = explode('/', $this->getMediaType(), 2);
$media->setId((string)$this->getNid())
->setType($type);
if (!is_null($urlGenerator)) {
$media->setUrl(
$urlGenerator->linkToRouteAbsolute(
'social.Api.mediaOpen',
['uuid' => $this->getLocalCopy() . '.' . $mime]
)
);
$media->setPreviewUrl(
$urlGenerator->linkToRouteAbsolute(
'social.Api.mediaOpen',
['uuid' => $this->getResizedCopy() . '.' . $mime]
)
);
$media->setRemoteUrl($this->getUrl());
}
$meta = new AttachmentMeta();
$meta->setOriginal(new AttachmentMetaDim($this->getLocalCopySize()))
->setSmall(new AttachmentMetaDim($this->getResizedCopySize()))
->setFocus(new AttachmentMetaFocus(0, 0));
$media->setMeta($meta)
->setDescription($this->getDescription())
->setBlurHash($this->getBlurHash());
return $media;
}
}

Wyświetl plik

@ -42,7 +42,6 @@ use OCA\Social\Model\ActivityPub\Stream;
class Note extends Stream implements JsonSerializable {
public const TYPE = 'Note';
private array $attachments = [];
private array $hashtags = [];
public function __construct(ACore $parent = null) {
@ -51,16 +50,6 @@ class Note extends Stream implements JsonSerializable {
$this->setType(self::TYPE);
}
public function getAttachments(): array {
return $this->attachments;
}
public function setAttachments(array $attachments): Note {
$this->attachments = $attachments;
return $this;
}
public function getHashtags(): array {
return $this->hashtags;
}
@ -92,57 +81,13 @@ class Note extends Stream implements JsonSerializable {
public function import(array $data): void {
parent::import($data);
$this->importAttachments($this->getArray('attachment', $data, []));
$this->fillHashtags();
}
/**
* @throws ItemAlreadyExistsException
*/
public function importAttachments(array $list): void {
$new = [];
foreach ($list as $item) {
try {
$attachment = AP::$activityPub->getItemFromData($item, $this);
} catch (Exception $e) {
continue;
}
if ($attachment->getType() !== Document::TYPE
&& $attachment->getType() !== Image::TYPE) {
continue;
}
try {
$attachment->setUrl(
$this->validateEntryString(ACore::AS_URL, $attachment->getUrl())
);
} catch (InvalidResourceEntryException $e) {
continue;
}
if ($attachment->getUrl() === '') {
continue;
}
try {
$interface = AP::$activityPub->getInterfaceFromType($attachment->getType());
} catch (ItemUnknownException $e) {
continue;
}
$interface->save($attachment);
$new[] = $attachment;
}
$this->setAttachments($new);
}
public function importFromDatabase(array $data): void {
parent::importFromDatabase($data);
$this->setAttachments($this->getArray('attachments', $data, []));
$this->setHashtags($this->getArray('hashtags', $data, []));
}
@ -151,7 +96,6 @@ class Note extends Stream implements JsonSerializable {
if ($this->isCompleteDetails()) {
$result['hashtags'] = $this->getHashtags();
$result['attachment'] = $this->getAttachments();
}
$this->cleanArray($result);

Wyświetl plik

@ -33,10 +33,18 @@ namespace OCA\Social\Model\ActivityPub;
use DateTime;
use Exception;
use JsonSerializable;
use OCA\Social\AP;
use OCA\Social\Exceptions\InvalidResourceEntryException;
use OCA\Social\Exceptions\ItemAlreadyExistsException;
use OCA\Social\Exceptions\ItemUnknownException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Announce;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\ActivityPub\Object\Follow;
use OCA\Social\Model\ActivityPub\Object\Image;
use OCA\Social\Model\ActivityPub\Object\Like;
use OCA\Social\Model\Client\MediaAttachment;
use OCA\Social\Model\Post;
use OCA\Social\Model\StreamAction;
use OCA\Social\Tools\IQueryRow;
use OCA\Social\Tools\Model\Cache;
@ -67,6 +75,7 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
private string $language = 'en';
private string $attributedTo = '';
private string $inReplyTo = '';
private array $attachments = [];
private bool $sensitive = false;
private string $conversation = '';
private ?Cache $cache = null;
@ -198,6 +207,25 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
}
/**
* @return MediaAttachment[]
*/
public function getAttachments(): array {
return $this->attachments;
}
/**
* @param MediaAttachment[] $attachments
*
* @return self
*/
public function setAttachments(array $attachments): self {
$this->attachments = $attachments;
return $this;
}
/**
* @return bool
*/
@ -372,10 +400,57 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
$this->setObjectId($this->get('object', $data, ''));
$this->setConversation($this->validate(self::AS_ID, 'conversation', $data, ''));
$this->setContent($this->get('content', $data, ''));
try {
$this->importAttachments($this->getArray('attachments', $data, []));
} catch (ItemAlreadyExistsException $e) {
}
$this->convertPublished();
}
/**
* @throws ItemAlreadyExistsException
*/
public function importAttachments(array $list): void {
$new = [];
foreach ($list as $item) {
// try {
// $attachment = AP::$activityPub->getItemFromData($item, $this);
// } catch (Exception $e) {
// continue;
// }
//
// if ($attachment->getType() !== Document::TYPE
// && $attachment->getType() !== Image::TYPE) {
// continue;
// }
//
// try {
// $attachment->setUrl(
// $this->validateEntryString(ACore::AS_URL, $attachment->getUrl())
// );
// } catch (InvalidResourceEntryException $e) {
// continue;
// }
//
// if ($attachment->getUrl() === '') {
// continue;
// }
//
// try {
// $interface = AP::$activityPub->getInterfaceFromType($attachment->getType());
// } catch (ItemUnknownException $e) {
// continue;
// }
//
// $interface->save($attachment);
// $new[] = $attachment;
}
$this->setAttachments($new);
}
/**
* @param array $data
*/
@ -395,6 +470,7 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
$this->setInReplyTo($this->validate(self::AS_ID, 'in_reply_to', $data));
$this->setDetailsAll($this->getArray('details', $data, []));
$this->setFilterDuplicate($this->getBool('filter_duplicate', $data, false));
$this->setAttachments($this->getArray('attachments', $data, []));
$cache = new Cache();
$cache->import($this->getArray('cache', $data, []));
@ -438,10 +514,6 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
'publishedTime' => $this->getPublishedTime()
]
);
// $result['cc'] = '';
// $result['bcc'] = '';
// $result['to'] = '';
}
$this->cleanArray($result);
@ -488,6 +560,7 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
'uri' => $this->getId(),
'url' => $this->getId(),
"reblog" => null,
'media_attachments' => $this->getAttachments(),
"created_at" => date('Y-m-d\TH:i:s', $this->getPublishedTime()) . '.000Z'
];
@ -530,4 +603,17 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
return array_merge(parent::exportAsNotification(), $result);
}
public function jsonSerialize(): array {
$result = parent::jsonSerialize();
$result['media_attachments'] = $this->getAttachments();
// if ($this->isCompleteDetails()) {
// $result['attachments'] = $this->getAttachments();
// }
return $result;
}
}

Wyświetl plik

@ -0,0 +1,228 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\Client;
use JsonSerializable;
use OCA\Social\Tools\Traits\TArrayTools;
class AttachmentMeta implements JsonSerializable {
use TArrayTools;
private ?AttachmentMetaDim $original = null;
private ?AttachmentMetaDim $small = null;
private ?AttachmentMetaFocus $focus = null;
private ?int $width = null;
private ?int $height = null;
private ?float $aspect = null;
private string $size = '';
private string $length = '';
private ?float $duration = null;
private ?float $fps = null;
private string $audioEncode = '';
private string $audioBitrate = '';
private string $audioChannels = '';
private string $description = '';
private string $blurHash = '';
public function setOriginal(AttachmentMetaDim $original): self {
$this->original = $original;
return $this;
}
public function getOriginal(): ?AttachmentMetaDim {
return $this->original;
}
public function setSmall(AttachmentMetaDim $small): self {
$this->small = $small;
return $this;
}
public function getSmall(): ?AttachmentMetaDim {
return $this->small;
}
public function setFocus(AttachmentMetaFocus $focus): self {
$this->focus = $focus;
return $this;
}
public function getFocus(): ?AttachmentMetaFocus {
return $this->focus;
}
public function setWidth(int $width): self {
$this->width = $width;
return $this;
}
public function getWidth(): ?int {
return $this->width;
}
public function setHeight(int $height): self {
$this->height = $height;
return $this;
}
public function getHeight(): ?int {
return $this->height;
}
public function setAspect(float $aspect): self {
$this->aspect = $aspect;
return $this;
}
public function getAspect(): ?float {
return $this->aspect;
}
public function setSize(string $size): self {
$this->size = $size;
return $this;
}
public function getSize(): string {
return $this->size;
}
public function setLength(string $length): self {
$this->length = $length;
return $this;
}
public function getLength(): string {
return $this->length;
}
public function setDuration(float $duration): self {
$this->duration = $duration;
return $this;
}
public function getDuration(): ?float {
return $this->duration;
}
public function setFps(float $fps): self {
$this->fps = $fps;
return $this;
}
public function getFps(): ?float {
return $this->fps;
}
public function setAudioEncode(string $audioEncode): self {
$this->audioEncode = $audioEncode;
return $this;
}
public function getAudioEncode(): string {
return $this->audioEncode;
}
public function setAudioBitrate(string $audioBitrate): self {
$this->audioBitrate = $audioBitrate;
return $this;
}
public function getAudioBitrate(): string {
return $this->audioBitrate;
}
public function setAudioChannels(string $audioChannels): self {
$this->audioChannels = $audioChannels;
return $this;
}
public function getAudioChannels(): string {
return $this->audioChannels;
}
public function setDescription(string $description): self {
$this->description = $description;
return $this;
}
public function getDescription(): string {
return $this->description;
}
public function setBlurHash(string $blurHash): self {
$this->blurHash = $blurHash;
return $this;
}
public function getBlurHash(): ?string {
return $this->blurHash;
}
public function jsonSerialize(): array {
return array_filter(
[
'width' => $this->getWidth(),
'height' => $this->getHeight(),
'aspect' => $this->getAspect(),
'size' => $this->getSize(),
'length' => $this->getLength(),
'duration' => $this->getDuration(),
'fps' => $this->getFps(),
'original' => $this->getOriginal(),
'small' => $this->getSmall(),
'focus' => $this->getFocus(),
'audio_encode' => $this->getAudioEncode(),
'audio_bitrate' => $this->getAudioBitrate(),
'audio_channels' => $this->getAudioChannels(),
'description' => $this->getDescription(),
'blurhash' => $this->getBlurHash()
]
);
}
}

Wyświetl plik

@ -0,0 +1,138 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\Client;
use JsonSerializable;
class AttachmentMetaDim implements JsonSerializable {
private ?int $width = null;
private ?int $height = null;
private string $size = '';
private ?float $aspect = null;
private ?float $duration = null;
private ?float $bitrate = null;
private ?float $frameRate = null;
public function __construct(array $dim) {
$width = (int)$dim[0];
$height = (int)$dim[1];
if ($width > 0 && $height > 0) {
$this->width = $width;
$this->height = $height;
$this->size = $width . 'x' . $height;
$this->aspect = $width / $height;
}
}
public function setWidth(int $width): self {
$this->width = $width;
return $this;
}
public function getWidth(): ?int {
return $this->width;
}
public function setHeight(int $height): self {
$this->height = $height;
return $this;
}
public function getHeight(): int {
return $this->height;
}
public function setSize(string $size): self {
$this->size = $size;
return $this;
}
public function getSize(): string {
return $this->size;
}
public function setAspect(float $aspect): self {
$this->aspect = $aspect;
return $this;
}
public function getAspect(): ?float {
return $this->aspect;
}
public function setDuration(float $duration): self {
$this->duration = $duration;
return $this;
}
public function getDuration(): ?float {
return $this->duration;
}
public function setBitrate(float $bitrate): self {
$this->bitrate = $bitrate;
return $this;
}
public function getBitrate(): ?float {
return $this->bitrate;
}
public function setFrameRate(float $frameRate): self {
$this->frameRate = $frameRate;
return $this;
}
public function getFrameRate(): ?float {
return $this->frameRate;
}
public function jsonSerialize(): array {
return array_filter(
[
'width' => $this->getWidth(),
'height' => $this->getHeight(),
'size' => $this->getSize(),
'aspect' => $this->getAspect(),
'duration' => $this->getDuration(),
'bitrate' => $this->getBitrate(),
'frame_rate' => $this->getFrameRate()
]
);
}
}

Wyświetl plik

@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\Client;
use JsonSerializable;
class AttachmentMetaFocus implements JsonSerializable {
private ?float $x;
private ?float $y;
public function __construct(?float $x = null, ?float $y = null) {
$this->x = $x;
$this->y = $y;
}
public function setX(float $x): self {
$this->x = $x;
return $this;
}
public function getX(): ?float {
return $this->x;
}
public function setY(float $y): self {
$this->y = $y;
return $this;
}
public function getY(): ?float {
return $this->y;
}
public function jsonSerialize(): array {
return array_filter(
[
'x' => $this->getX(),
'y' => $this->getY()
]
);
}
}

Wyświetl plik

@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2022, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Model\Client;
use JsonSerializable;
use OCA\Social\Tools\Traits\TArrayTools;
class MediaAttachment implements JsonSerializable {
use TArrayTools;
private string $id = '';
private string $type = '';
private ?string $url = null;
private string $previewUrl = '';
private ?string $remoteUrl = null;
private string $textUrl = '';
private ?AttachmentMeta $meta = null;
private string $description = '';
private string $blurHash = '';
public function setId(string $id): self {
$this->id = $id;
return $this;
}
public function getId(): string {
return $this->id;
}
public function setType(string $type): self {
$this->type = $type;
return $this;
}
public function getType(): string {
return $this->type;
}
public function setUrl(string $url): self {
$this->url = $url;
return $this;
}
public function getUrl(): ?string {
return $this->url;
}
public function setPreviewUrl(string $previewUrl): self {
$this->previewUrl = $previewUrl;
return $this;
}
public function getPreviewUrl(): string {
return $this->previewUrl;
}
public function setRemoteUrl(string $remoteUrl): self {
$this->remoteUrl = $remoteUrl;
return $this;
}
public function getRemoteUrl(): ?string {
return $this->remoteUrl;
}
public function setTextUrl(string $textUrl): self {
$this->textUrl = $textUrl;
return $this;
}
public function getTextUrl(): string {
return $this->textUrl;
}
public function setMeta(AttachmentMeta $meta): self {
$this->meta = $meta;
return $this;
}
public function getMeta(): ?AttachmentMeta {
return $this->meta;
}
public function setDescription(string $description): self {
$this->description = $description;
return $this;
}
public function getDescription(): string {
return $this->description;
}
public function setBlurHash(string $blurHash): self {
$this->blurHash = $blurHash;
return $this;
}
public function getBlurHash(): string {
return $this->blurHash;
}
public function jsonSerialize(): array {
return array_filter(
[
'id' => $this->getId(),
'type' => $this->getType(),
'url' => $this->getUrl(),
'preview_url' => $this->getPreviewUrl(),
'remote_url' => $this->getRemoteUrl(),
'meta' => $this->getMeta(),
'description' => $this->getDescription(),
"blurhash" => $this->getBlurHash()
]
);
}
}

Wyświetl plik

@ -45,33 +45,19 @@ use JsonSerializable;
class SocialClient implements IQueryRow, JsonSerializable {
use TArrayTools;
private int $id = 0;
private string $appName = '';
private string $appWebsite = '';
private array $appRedirectUris = [];
private string $appClientId = '';
private string $appClientSecret = '';
private array $appScopes = [];
private array $authScopes = [];
private string $authAccount = '';
private string $authUserId = '';
private string $authCode = '';
private int $lastUpdate = -1;
private string $token = '';
private int $creation = -1;
// /** @var array */

Wyświetl plik

@ -38,6 +38,7 @@ class Status implements \JsonSerializable {
private bool $sensitive = false;
private string $visibility = '';
private string $spoilerText = '';
private array $mediaIds = [];
private string $status = '';
//"media_ids": [],
@ -121,6 +122,18 @@ class Status implements \JsonSerializable {
return $this->spoilerText;
}
public function setMediaIds(array $mediaIds): self {
$this->mediaIds = array_map(function (string $id): int {
return (int)$id;
}, $mediaIds);
return $this;
}
public function getMediaIds(): array {
return $this->mediaIds;
}
/**
* @param string $status
@ -146,6 +159,7 @@ class Status implements \JsonSerializable {
$this->setSensitive($this->getBool('sensitive', $data));
$this->setVisibility($this->get('visibility', $data));
$this->setSpoilerText($this->get('spoiler_text', $data));
$this->setMediaIds($this->getArray('media_ids', $data));
$this->setStatus($this->get('status', $data));
return $this;
@ -155,6 +169,7 @@ class Status implements \JsonSerializable {
return [
'contentType' => $this->getContentType(),
'sensitive' => $this->isSensitive(),
'mediaIds' => $this->getMediaIds(),
'visibility' => $this->getVisibility(),
'spoilerText' => $this->getSpoilerText(),
'status' => $this->getStatus()

Wyświetl plik

@ -30,10 +30,11 @@ declare(strict_types=1);
namespace OCA\Social\Model;
use OCA\Social\Tools\Traits\TArrayTools;
use JsonSerializable;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\Client\MediaAttachment;
use OCA\Social\Tools\Traits\TArrayTools;
/**
* Class Post
@ -52,6 +53,8 @@ class Post implements JsonSerializable {
/** @var string[] */
private array $attachments = [];
/** @var MediaAttachment[] */
private array $medias = [];
/** @var Document[] */
private array $documents = [];
@ -180,14 +183,30 @@ class Post implements JsonSerializable {
/**
* @param string[] $attachments
*
* @return Post
* @return self
*/
public function setAttachments(array $attachments): Post {
public function setAttachments(array $attachments): self {
$this->attachments = $attachments;
return $this;
}
/**
* @param MediaAttachment[] $medias
*/
public function setMedias(array $medias): self {
$this->medias = $medias;
return $this;
}
/**
* @return MediaAttachment[]
*/
public function getMedias(): array {
return $this->medias;
}
/**
* @return Document[]

Wyświetl plik

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2023, Maxence Lange <maxence@artificial-owl.com>
* @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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service;
use GdImage;
use kornrunner\Blurhash\Blurhash;
class BlurService {
public function __construct() {
}
public function generateBlurHash(GdImage $image): string {
$width = imagesx($image);
$height = imagesy($image);
$pixels = [];
for ($y = 0; $y < $height; ++$y) {
$row = [];
for ($x = 0; $x < $width; ++$x) {
$index = imagecolorat($image, $x, $y);
$colors = imagecolorsforindex($image, $index);
$row[] = [$colors['red'], $colors['green'], $colors['blue']];
}
$pixels[] = $row;
}
return Blurhash::encode($pixels, 4, 3);
}
}

Wyświetl plik

@ -29,15 +29,6 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use OCA\Social\Tools\Exceptions\MalformedArrayException;
use OCA\Social\Tools\Exceptions\RequestContentException;
use OCA\Social\Tools\Exceptions\RequestNetworkException;
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
use OCA\Social\Tools\Exceptions\RequestServerException;
use OCA\Social\Tools\Model\NCRequest;
use OCA\Social\Tools\Model\Request;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Tools\Traits\TStringTools;
use Exception;
use Gumlet\ImageResize;
use Gumlet\ImageResizeException;
@ -47,6 +38,15 @@ use OCA\Social\Exceptions\CacheDocumentDoesNotExistException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnauthorizedFediverseException;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Tools\Exceptions\MalformedArrayException;
use OCA\Social\Tools\Exceptions\RequestContentException;
use OCA\Social\Tools\Exceptions\RequestNetworkException;
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
use OCA\Social\Tools\Exceptions\RequestServerException;
use OCA\Social\Tools\Model\NCRequest;
use OCA\Social\Tools\Model\Request;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Tools\Traits\TStringTools;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
@ -56,22 +56,24 @@ class CacheDocumentService {
use TArrayTools;
use TStringTools;
public const RESIZED_WIDTH = 280;
public const RESIZED_WIDTH = 420;
public const RESIZED_HEIGHT = 180;
private IAppData $appData;
private CurlService $curlService;
private ConfigService $configService;
private MiscService $miscService;
private BlurService $blurService;
public function __construct(
IAppData $appData, CurlService $curlService, ConfigService $configService,
MiscService $miscService
IAppData $appData,
CurlService $curlService,
BlurService $blurService,
ConfigService $configService
) {
$this->appData = $appData;
$this->curlService = $curlService;
$this->blurService = $blurService;
$this->configService = $configService;
$this->miscService = $miscService;
}
@ -132,7 +134,8 @@ class CacheDocumentService {
$filename = $this->generateFileFromContent($content);
$document->setLocalCopy($filename);
$this->resizeImage($content);
$this->resizeImage($document, $content);
$resized = $this->generateFileFromContent($content);
$document->setResizedCopy($resized);
}
@ -150,7 +153,8 @@ class CacheDocumentService {
$filename = $this->generateFileFromContent($content);
$document->setLocalCopy($filename);
$this->resizeImage($content);
$this->resizeImage($document, $content);
$resized = $this->generateFileFromContent($content);
$document->setResizedCopy($resized);
}
@ -165,8 +169,7 @@ class CacheDocumentService {
*/
private function generateFileFromContent(string $content): string {
$filename = $this->uuid();
// creating a path aa/bb/cc/dd/ from the filename aabbccdd-0123-[...]
$path = chunk_split(substr($filename, 0, 8), 2, '/');
$path = $this->generatePath($filename);
try {
$folder = $this->appData->getFolder($path);
@ -177,7 +180,19 @@ class CacheDocumentService {
$cache = $folder->newFile($filename);
$cache->putContent($content);
return $path . $filename;
return $filename;
}
/**
* creating a path aa/bb/cc/dd/ from the filename aabbccdd-0123-[...]
*
* @param string $filename
*
* @return string
*/
private function generatePath(string $filename): string {
return chunk_split(substr($filename, 0, 8), 2, '/');
}
@ -204,57 +219,68 @@ class CacheDocumentService {
/**
* @param string $content
*
* @return string
*/
private function resizeImage(string &$content) {
private function resizeImage(Document $document, string &$content): void {
try {
$image = ImageResize::createFromString($content);
$image->quality_jpg = 100;
$image->quality_png = 9;
$image->quality_jpg = 80;
$image->quality_png = 7;
$image->resizeToBestFit(self::RESIZED_WIDTH, self::RESIZED_HEIGHT);
$newContent = $image->getImageAsString();
if (!$newContent) {
if ($newContent) {
$content = $newContent;
}
} catch (ImageResizeException $e) {
}
$document->setLocalCopySize($image->getSourceWidth(), $image->getSourceHeight());
$document->setResizedCopySize($image->getDestWidth(), $image->getDestHeight());
$hash = $this->blurService->generateBlurHash(imagecreatefromstring($content));
$document->setBlurHash($hash);
}
/**
* @param string $path
* @param string $filename
*
* @return ISimpleFile
* @throws CacheContentException
* @throws CacheDocumentDoesNotExistException
*/
public function getContentFromCache(string $path): ISimpleFile {
if ($path === '') {
public function getContentFromCache(string $filename): ISimpleFile {
if ($filename === '') {
throw new CacheDocumentDoesNotExistException();
}
// right now, we do not handle cache for local avatar, we need to change this
// so the current avatar is cached, or a new avatar is uploaded
if ($path === 'avatar') {
if ($filename === 'avatar') {
throw new CacheContentException();
}
$pos = strrpos($path, '/');
$dir = substr($path, 0, $pos);
$filename = substr($path, $pos + 1);
try {
$file = $this->appData->getFolder($dir)
->getFile($filename);
return $file;
return $this->appData->getFolder($this->generatePath($filename))
->getFile($filename);
} catch (Exception $e) {
throw new CacheContentException();
}
}
public function getFromUuid(string $uuid): ISimpleFile {
try {
return $this->appData->getFolder($this->generatePath($uuid))
->getFile($uuid);
} catch (NotFoundException $e) {
throw new NotFoundException('document not found');
}
}
/**
* @param string $url
*

Wyświetl plik

@ -31,12 +31,6 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use OCA\Social\Tools\Exceptions\MalformedArrayException;
use OCA\Social\Tools\Exceptions\RequestContentException;
use OCA\Social\Tools\Exceptions\RequestNetworkException;
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
use OCA\Social\Tools\Exceptions\RequestServerException;
use Exception;
use OCA\Social\AP;
use OCA\Social\Db\ActorsRequest;
@ -53,6 +47,12 @@ use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\ActivityPub\Object\Image;
use OCA\Social\Tools\Exceptions\MalformedArrayException;
use OCA\Social\Tools\Exceptions\RequestContentException;
use OCA\Social\Tools\Exceptions\RequestNetworkException;
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
use OCA\Social\Tools\Exceptions\RequestServerException;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
@ -164,9 +164,9 @@ class DocumentService {
$document->setError(self::ERROR_SIZE);
$this->cacheDocumentsRequest->endCaching($document);
} catch (RequestContentException $e) {
$this->cacheDocumentsRequest->deleteById($id);
$this->cacheDocumentsRequest->deleteById($document->getId());
} catch (UnauthorizedFediverseException $e) {
$this->cacheDocumentsRequest->deleteById($id);
$this->cacheDocumentsRequest->deleteById($document->getId());
} catch (RequestNetworkException $e) {
$this->cacheDocumentsRequest->endCaching($document);
} catch (RequestServerException $e) {
@ -208,13 +208,45 @@ class DocumentService {
* @throws MalformedArrayException
* @throws SocialAppConfigException
*/
public function getFromCache(string $id, string &$mimeType = '', bool $public = false): ISimpleFile {
public function getFromCache(
string $id, string &$mimeType = '', bool $public = false
): ISimpleFile {
$document = $this->cacheRemoteDocument($id, $public);
$mimeType = $document->getMimeType();
return $this->cacheService->getContentFromCache($document->getLocalCopy());
}
/**
* @param string $uuid
*
* @return ISimpleFile
* @throws NotFoundException
*/
public function getFromUuid(string $uuid): ISimpleFile {
if (preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', $uuid)
!== 1) {
throw new NotFoundException('invalid document');
}
return $this->cacheService->getFromUuid($uuid);
}
/**
* @param array $getMediaIds
* @param string $account
*
* @return Document[]
*/
public function getMediaFromArray(array $getMediaIds, string $account = ''): array {
return $this->cacheDocumentsRequest->getFromArray($getMediaIds, $account);
}
public function getByLocalId(int $id, string &$mimeType = '', bool $public = false): ISimpleFile {
}
/**
* @return int

Wyświetl plik

@ -106,13 +106,14 @@ class PostService {
$note->setAttributedTo($actor->getId());
$note->setContent(htmlentities($post->getContent(), ENT_QUOTES));
$note->setAttachments($post->getMedias());
$this->generateDocumentsFromAttachments($note, $post);
// $this->generateDocumentsFromAttachments($note, $post);
$this->streamService->replyTo($note, $post->getReplyTo());
$this->streamService->addRecipients($note, $post->getType(), $post->getTo());
$this->streamService->addHashtags($note, $post->getHashtags());
$this->streamService->addAttachments($note, $post->getDocuments());
// $this->streamService->addAttachments($note, $post->getDocuments());
$token = $this->activityService->createActivity($actor, $note, $activity);
$this->accountService->cacheLocalActorDetailCount($actor);

Wyświetl plik

@ -357,6 +357,14 @@ class StreamService {
return $this->streamRequest->getStreamById($id, $asViewer, $format);
}
// TODO: returns context for status
public function getContextByNid(int $nid): array {
return [
'ancestors' => [],
'descendants' => []
];
}
/**
* @param string $id