Add /api/v1/media endpoint

This commit is contained in:
Daniel Supernault 2019-09-25 22:54:05 -06:00
parent 9b5aac4f50
commit 39f3e3138d
No known key found for this signature in database
GPG key ID: 0DEF1C662C9033F7
2 changed files with 101 additions and 11 deletions

View file

@ -6,11 +6,8 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use App\Util\ActivityPub\Helpers; use App\Util\ActivityPub\Helpers;
use App\Jobs\LikePipeline\LikePipeline;
use App\Jobs\StatusPipeline\StatusDelete;
use App\Jobs\FollowPipeline\FollowPipeline;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use Auth, Cache, DB; use Auth, Cache, DB, URL;
use App\{ use App\{
Follower, Follower,
FollowRequest, FollowRequest,
@ -24,6 +21,7 @@ use App\{
use League\Fractal; use League\Fractal;
use App\Transformer\Api\{ use App\Transformer\Api\{
AccountTransformer, AccountTransformer,
MediaTransformer,
RelationshipTransformer, RelationshipTransformer,
StatusTransformer, StatusTransformer,
}; };
@ -31,6 +29,16 @@ use App\Http\Controllers\FollowerController;
use League\Fractal\Serializer\ArraySerializer; use League\Fractal\Serializer\ArraySerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use App\Jobs\LikePipeline\LikePipeline;
use App\Jobs\StatusPipeline\StatusDelete;
use App\Jobs\FollowPipeline\FollowPipeline;
use App\Jobs\ImageOptimizePipeline\ImageOptimize;
use App\Jobs\VideoPipeline\{
VideoOptimize,
VideoPostProcess,
VideoThumbnail
};
use App\Services\NotificationService; use App\Services\NotificationService;
class ApiV1Controller extends Controller class ApiV1Controller extends Controller
@ -873,6 +881,87 @@ class ApiV1Controller extends Controller
return response()->json([]); return response()->json([]);
} }
/**
* POST /api/v1/media
*
*
* @return App\Transformer\Api\MediaTransformer
*/
public function mediaUpload(Request $request)
{
abort_if(!$request->user(), 403);
$this->validate($request, [
'file.*' => function() {
return [
'required',
'mimes:' . config('pixelfed.media_types'),
'max:' . config('pixelfed.max_photo_size'),
];
},
'filter_name' => 'nullable|string|max:24',
'filter_class' => 'nullable|alpha_dash|max:24'
]);
$user = $request->user();
$profile = $user->profile;
if(config('pixelfed.enforce_account_limit') == true) {
$size = Cache::remember($user->storageUsedKey(), now()->addDays(3), function() use($user) {
return Media::whereUserId($user->id)->sum('size') / 1000;
});
$limit = (int) config('pixelfed.max_account_size');
if ($size >= $limit) {
abort(403, 'Account size limit reached.');
}
}
$monthHash = hash('sha1', date('Y').date('m'));
$userHash = hash('sha1', $user->id . (string) $user->created_at);
$photo = $request->file('file');
$mimes = explode(',', config('pixelfed.media_types'));
if(in_array($photo->getMimeType(), $mimes) == false) {
abort(403, 'Invalid or unsupported mime type.');
}
$storagePath = "public/m/{$monthHash}/{$userHash}";
$path = $photo->store($storagePath);
$hash = \hash_file('sha256', $photo);
$media = new Media();
$media->status_id = null;
$media->profile_id = $profile->id;
$media->user_id = $user->id;
$media->media_path = $path;
$media->original_sha256 = $hash;
$media->size = $photo->getSize();
$media->mime = $photo->getMimeType();
$media->filter_class = $request->input('filter_class');
$media->filter_name = $request->input('filter_name');
$media->save();
switch ($media->mime) {
case 'image/jpeg':
case 'image/png':
ImageOptimize::dispatch($media);
break;
case 'video/mp4':
VideoThumbnail::dispatch($media);
$preview_url = '/storage/no-preview.png';
$url = '/storage/no-preview.png';
break;
}
$resource = new Fractal\Resource\Item($media, new MediaTransformer());
$res = $this->fractal->createData($resource)->toArray();
$res['preview_url'] = url('/storage/no-preview.png');
$res['url'] = url('/storage/no-preview.png');
return response()->json($res);
}
public function statusById(Request $request, $id) public function statusById(Request $request, $id)
{ {
$status = Status::whereVisibility('public')->findOrFail($id); $status = Status::whereVisibility('public')->findOrFail($id);

View file

@ -110,14 +110,15 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('lists', 'Api\ApiV1Controller@accountLists')->middleware('auth:api'); Route::get('lists', 'Api\ApiV1Controller@accountLists')->middleware('auth:api');
Route::get('accounts/{id}/lists', 'Api\ApiV1Controller@accountListsById')->middleware('auth:api'); Route::get('accounts/{id}/lists', 'Api\ApiV1Controller@accountListsById')->middleware('auth:api');
Route::get('lists/{id}/accounts', 'Api\ApiV1Controller@accountListsById')->middleware('auth:api'); Route::get('lists/{id}/accounts', 'Api\ApiV1Controller@accountListsById')->middleware('auth:api');
Route::post('media', 'Api\ApiV1Controller@mediaUpload')->middleware('auth:api');
Route::get('likes', 'ApiController@hydrateLikes'); // Route::get('likes', 'ApiController@hydrateLikes');
Route::post('media', 'ApiController@uploadMedia')->middleware('auth:api'); // Route::post('media', 'ApiController@uploadMedia')->middleware('auth:api');
Route::delete('media', 'ApiController@deleteMedia')->middleware('auth:api'); // Route::delete('media', 'ApiController@deleteMedia')->middleware('auth:api');
Route::get('notifications', 'ApiController@notifications')->middleware('auth:api'); // Route::get('notifications', 'ApiController@notifications')->middleware('auth:api');
Route::get('timelines/public', 'PublicApiController@publicTimelineApi'); // Route::get('timelines/public', 'PublicApiController@publicTimelineApi');
Route::get('timelines/home', 'PublicApiController@homeTimelineApi')->middleware('auth:api'); // Route::get('timelines/home', 'PublicApiController@homeTimelineApi')->middleware('auth:api');
Route::post('status', 'Api\ApiV1Controller@createStatus')->middleware('auth:api'); // Route::post('status', 'Api\ApiV1Controller@createStatus')->middleware('auth:api');
}); });
Route::group(['prefix' => 'v2'], function() { Route::group(['prefix' => 'v2'], function() {
Route::get('config', 'ApiController@siteConfiguration'); Route::get('config', 'ApiController@siteConfiguration');