pixelfed/app/Http/Controllers/StoryController.php

351 lines
8.8 KiB
PHP
Raw Normal View History

2018-08-26 19:21:58 +00:00
<?php
namespace App\Http\Controllers;
2019-01-31 20:28:30 +00:00
use Illuminate\Http\Request;
2020-01-07 06:31:51 +00:00
use Illuminate\Support\Str;
use App\Media;
use App\Profile;
use App\Story;
use App\StoryView;
use App\Services\StoryService;
use Cache, Storage;
use Image as Intervention;
2020-01-07 06:31:51 +00:00
use App\Services\FollowerService;
2019-01-31 20:28:30 +00:00
2018-08-26 19:21:58 +00:00
class StoryController extends Controller
{
2020-01-07 06:31:51 +00:00
public function apiV1Add(Request $request)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
$this->validate($request, [
2020-01-11 02:45:46 +00:00
'file' => function() {
2020-01-07 06:31:51 +00:00
return [
'required',
'mimes:image/jpeg,image/png',
'max:' . config('pixelfed.max_photo_size'),
];
},
]);
$user = $request->user();
2020-01-11 02:45:46 +00:00
if(Story::whereProfileId($user->profile_id)->where('expires_at', '>', now())->count() >= Story::MAX_PER_DAY) {
abort(400, 'You have reached your limit for new Stories today.');
}
2020-01-07 06:31:51 +00:00
2020-01-11 02:45:46 +00:00
$photo = $request->file('file');
$path = $this->storePhoto($photo);
2020-01-07 06:31:51 +00:00
2020-01-11 02:45:46 +00:00
$story = new Story();
$story->duration = 3;
$story->profile_id = $user->profile_id;
$story->type = 'photo';
$story->mime = $photo->getMimeType();
2020-01-07 06:31:51 +00:00
$story->path = $path;
$story->local = true;
2020-01-11 02:45:46 +00:00
$story->size = $photo->getClientSize();
2020-01-07 06:31:51 +00:00
$story->expires_at = now()->addHours(24);
$story->save();
return [
'code' => 200,
'msg' => 'Successfully added',
'media_url' => url(Storage::url($story->path))
];
}
protected function storePhoto($photo)
{
$monthHash = substr(hash('sha1', date('Y').date('m')), 0, 12);
2020-02-05 06:18:51 +00:00
$sid = (string) Str::uuid();
$rid = Str::random(9).'.'.Str::random(9);
$mimes = explode(',', config('pixelfed.media_types'));
if(in_array($photo->getMimeType(), [
'image/jpeg',
'image/png'
]) == false) {
abort(400, 'Invalid media type');
return;
}
2020-02-05 06:18:51 +00:00
$storagePath = "public/_esm.t2/{$monthHash}/{$sid}/{$rid}";
$path = $photo->store($storagePath);
$fpath = storage_path('app/' . $path);
$img = Intervention::make($fpath);
$img->orientate();
$img->save($fpath, config('pixelfed.image_quality'));
$img->destroy();
return $path;
}
2020-01-07 06:31:51 +00:00
public function apiV1Delete(Request $request, $id)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
$user = $request->user();
$story = Story::whereProfileId($user->profile_id)
2020-01-11 02:45:46 +00:00
->findOrFail($id);
2020-01-07 06:31:51 +00:00
if(Storage::exists($story->path) == true) {
Storage::delete($story->path);
}
$story->delete();
return [
'code' => 200,
'msg' => 'Successfully deleted'
];
}
public function apiV1Recent(Request $request)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
$profile = $request->user()->profile;
2020-01-11 04:53:24 +00:00
$following = $profile->following->pluck('id')->toArray();
$groupBy = config('database.default') == 'pgsql' ? 'id' : 'profile_id';
2020-01-07 06:31:51 +00:00
$stories = Story::with('profile')
->groupBy($groupBy)
2020-01-11 02:45:46 +00:00
->whereIn('profile_id', $following)
->where('expires_at', '>', now())
->orderByDesc('expires_at')
->take(9)
->get()
->map(function($s, $k) {
return [
'id' => (string) $s->id,
'photo' => $s->profile->avatarUrl(),
'name' => $s->profile->username,
'link' => $s->profile->url(),
'lastUpdated' => (int) $s->created_at->format('U'),
'seen' => $s->seen(),
'items' => [],
'pid' => (string) $s->profile->id
];
2020-01-07 06:31:51 +00:00
});
return response()->json($stories, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
public function apiV1Fetch(Request $request, $id)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
2020-01-11 05:03:51 +00:00
$authed = $request->user()->profile;
$profile = Profile::findOrFail($id);
if($id == $authed->id) {
2020-01-07 06:31:51 +00:00
$publicOnly = true;
} else {
2020-01-11 05:03:51 +00:00
$publicOnly = (bool) $profile->followedBy($authed);
2020-01-07 06:31:51 +00:00
}
2020-01-11 05:03:51 +00:00
$stories = Story::whereProfileId($profile->id)
2020-01-11 02:45:46 +00:00
->orderBy('expires_at', 'desc')
->where('expires_at', '>', now())
->when(!$publicOnly, function($query, $publicOnly) {
return $query->wherePublic(true);
})
->get()
->map(function($s, $k) {
return [
'id' => (string) $s->id,
'type' => 'photo',
'length' => 3,
'src' => url(Storage::url($s->path)),
'preview' => null,
'link' => null,
'linkText' => null,
'time' => $s->created_at->format('U'),
'expires_at' => (int) $s->expires_at->format('U'),
'seen' => $s->seen()
];
})->toArray();
2020-01-07 06:31:51 +00:00
return response()->json($stories, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
2020-02-05 06:18:51 +00:00
public function apiV1Item(Request $request, $id)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
$authed = $request->user()->profile;
$story = Story::with('profile')
->where('expires_at', '>', now())
->findOrFail($id);
$profile = $story->profile;
if($story->profile_id == $authed->id) {
$publicOnly = true;
} else {
$publicOnly = (bool) $profile->followedBy($authed);
}
abort_if(!$publicOnly, 403);
$res = [
'id' => (string) $story->id,
'type' => 'photo',
'length' => 3,
'src' => url(Storage::url($story->path)),
'preview' => null,
'link' => null,
'linkText' => null,
'time' => $story->created_at->format('U'),
'expires_at' => (int) $story->expires_at->format('U'),
'seen' => $story->seen()
];
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
2020-01-07 06:31:51 +00:00
public function apiV1Profile(Request $request, $id)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
$authed = $request->user()->profile;
$profile = Profile::findOrFail($id);
if($id == $authed->id) {
$publicOnly = true;
} else {
2020-01-11 05:03:51 +00:00
$publicOnly = (bool) $profile->followedBy($authed);
2020-01-07 06:31:51 +00:00
}
$stories = Story::whereProfileId($profile->id)
2020-01-11 02:45:46 +00:00
->orderBy('expires_at')
->where('expires_at', '>', now())
->when(!$publicOnly, function($query, $publicOnly) {
return $query->wherePublic(true);
})
->get()
->map(function($s, $k) {
return [
'id' => $s->id,
'type' => 'photo',
'length' => 3,
'src' => url(Storage::url($s->path)),
'preview' => null,
'link' => null,
'linkText' => null,
'time' => $s->created_at->format('U'),
'expires_at' => (int) $s->expires_at->format('U'),
'seen' => $s->seen()
];
})->toArray();
2020-01-07 06:31:51 +00:00
if(count($stories) == 0) {
return [];
}
$cursor = count($stories) - 1;
$stories = [[
'id' => (string) $stories[$cursor]['id'],
'photo' => $profile->avatarUrl(),
'name' => $profile->username,
'link' => $profile->url(),
'lastUpdated' => (int) now()->format('U'),
'seen' => null,
'items' => $stories,
'pid' => (string) $profile->id
]];
return response()->json($stories, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
public function apiV1Viewed(Request $request)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
$this->validate($request, [
'id' => 'required|integer|min:1|exists:stories',
]);
2020-02-05 06:18:51 +00:00
$id = $request->input('id');
$authed = $request->user()->profile;
$story = Story::with('profile')
->where('expires_at', '>', now())
->orderByDesc('expires_at')
->findOrFail($id);
$profile = $story->profile;
if($story->profile_id == $authed->id) {
$publicOnly = true;
} else {
$publicOnly = (bool) $profile->followedBy($authed);
}
abort_if(!$publicOnly, 403);
2020-01-07 06:31:51 +00:00
StoryView::firstOrCreate([
2020-02-05 06:18:51 +00:00
'story_id' => $id,
'profile_id' => $authed->id
2020-01-07 06:31:51 +00:00
]);
return ['code' => 200];
}
public function apiV1Exists(Request $request, $id)
{
2020-02-05 06:18:51 +00:00
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
2020-01-07 06:31:51 +00:00
$res = (bool) Story::whereProfileId($id)
2020-01-11 02:45:46 +00:00
->where('expires_at', '>', now())
->count();
2020-01-07 06:31:51 +00:00
return response()->json($res);
}
2020-02-05 06:18:51 +00:00
public function apiV1Me(Request $request)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
$profile = $request->user()->profile;
$stories = Story::whereProfileId($profile->id)
->orderBy('expires_at')
->where('expires_at', '>', now())
->get()
->map(function($s, $k) {
return [
'id' => $s->id,
'type' => 'photo',
'length' => 3,
'src' => url(Storage::url($s->path)),
'preview' => null,
'link' => null,
'linkText' => null,
'time' => $s->created_at->format('U'),
'expires_at' => (int) $s->expires_at->format('U'),
'seen' => true
];
})->toArray();
$ts = count($stories) ? last($stories)['time'] : null;
$res = [
'id' => (string) $profile->id,
'photo' => $profile->avatarUrl(),
'name' => $profile->username,
'link' => $profile->url(),
'lastUpdated' => $ts,
'seen' => true,
'items' => $stories
];
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
public function compose(Request $request)
{
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
return view('stories.compose');
}
2020-01-07 06:31:51 +00:00
public function iRedirect(Request $request)
2019-01-31 20:28:30 +00:00
{
2020-02-05 06:18:51 +00:00
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
2020-01-07 06:31:51 +00:00
$user = $request->user();
abort_if(!$user, 404);
$username = $user->username;
return redirect("/stories/{$username}");
2019-01-31 20:28:30 +00:00
}
2018-08-28 03:07:36 +00:00
}