mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-22 22:41:27 +00:00
commit
abe8298999
20 changed files with 795 additions and 848 deletions
|
@ -1,10 +1,14 @@
|
||||||
# Release Notes
|
# Release Notes
|
||||||
|
|
||||||
## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.12.3...dev)
|
## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.12.3...dev)
|
||||||
|
|
||||||
|
### Updates
|
||||||
- Update AP helpers, reject statuses with invalid dates ([960f3849](https://github.com/pixelfed/pixelfed/commit/960f3849))
|
- Update AP helpers, reject statuses with invalid dates ([960f3849](https://github.com/pixelfed/pixelfed/commit/960f3849))
|
||||||
- Update DirectMessage API, fix broken threading ([044d410c](https://github.com/pixelfed/pixelfed/commit/044d410c))
|
- Update DirectMessage API, fix broken threading ([044d410c](https://github.com/pixelfed/pixelfed/commit/044d410c))
|
||||||
- Update Status caption render logic ([fb8dbb95](https://github.com/pixelfed/pixelfed/commit/fb8dbb95))
|
- Update Status caption render logic ([fb8dbb95](https://github.com/pixelfed/pixelfed/commit/fb8dbb95))
|
||||||
- Update ApiV1Controller, fix bookmark bug. Closes #5216 ([9f7cc52c](https://github.com/pixelfed/pixelfed/commit/9f7cc52c))
|
- Update ApiV1Controller, fix bookmark bug. Closes #5216 ([9f7cc52c](https://github.com/pixelfed/pixelfed/commit/9f7cc52c))
|
||||||
|
- Update Status caption logic, stop storing duplicate html caption in db and defer to cached StatusService rendering ([9eeb7b67](https://github.com/pixelfed/pixelfed/commit/9eeb7b67))
|
||||||
|
- Update AutolinkService, optimize lookups ([eac2c196](https://github.com/pixelfed/pixelfed/commit/eac2c196))
|
||||||
- ([](https://github.com/pixelfed/pixelfed/commit/))
|
- ([](https://github.com/pixelfed/pixelfed/commit/))
|
||||||
|
|
||||||
## [v0.12.4 (2024-11-08)](https://github.com/pixelfed/pixelfed/compare/v0.12.4...dev)
|
## [v0.12.4 (2024-11-08)](https://github.com/pixelfed/pixelfed/compare/v0.12.4...dev)
|
||||||
|
|
|
@ -2,17 +2,16 @@
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use App\Models\ImportPost;
|
|
||||||
use App\Services\ImportService;
|
|
||||||
use App\Media;
|
use App\Media;
|
||||||
|
use App\Models\ImportPost;
|
||||||
use App\Profile;
|
use App\Profile;
|
||||||
use App\Status;
|
|
||||||
use Storage;
|
|
||||||
use App\Services\AccountService;
|
use App\Services\AccountService;
|
||||||
|
use App\Services\ImportService;
|
||||||
use App\Services\MediaPathService;
|
use App\Services\MediaPathService;
|
||||||
|
use App\Status;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use App\Util\Lexer\Autolink;
|
use Storage;
|
||||||
|
|
||||||
class TransformImports extends Command
|
class TransformImports extends Command
|
||||||
{
|
{
|
||||||
|
@ -35,23 +34,24 @@ class TransformImports extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
if(!config('import.instagram.enabled')) {
|
if (! config('import.instagram.enabled')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ips = ImportPost::whereNull('status_id')->where('skip_missing_media', '!=', true)->take(500)->get();
|
$ips = ImportPost::whereNull('status_id')->where('skip_missing_media', '!=', true)->take(500)->get();
|
||||||
|
|
||||||
if(!$ips->count()) {
|
if (! $ips->count()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($ips as $ip) {
|
foreach ($ips as $ip) {
|
||||||
$id = $ip->user_id;
|
$id = $ip->user_id;
|
||||||
$pid = $ip->profile_id;
|
$pid = $ip->profile_id;
|
||||||
$profile = Profile::find($pid);
|
$profile = Profile::find($pid);
|
||||||
if(!$profile) {
|
if (! $profile) {
|
||||||
$ip->skip_missing_media = true;
|
$ip->skip_missing_media = true;
|
||||||
$ip->save();
|
$ip->save();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,39 +63,43 @@ class TransformImports extends Command
|
||||||
->where('creation_day', $ip->creation_day)
|
->where('creation_day', $ip->creation_day)
|
||||||
->exists();
|
->exists();
|
||||||
|
|
||||||
if($exists == true) {
|
if ($exists == true) {
|
||||||
$ip->skip_missing_media = true;
|
$ip->skip_missing_media = true;
|
||||||
$ip->save();
|
$ip->save();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$idk = ImportService::getId($ip->user_id, $ip->creation_year, $ip->creation_month, $ip->creation_day);
|
$idk = ImportService::getId($ip->user_id, $ip->creation_year, $ip->creation_month, $ip->creation_day);
|
||||||
if(!$idk) {
|
if (! $idk) {
|
||||||
$ip->skip_missing_media = true;
|
$ip->skip_missing_media = true;
|
||||||
$ip->save();
|
$ip->save();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Storage::exists('imports/' . $id . '/' . $ip->filename) === false) {
|
if (Storage::exists('imports/'.$id.'/'.$ip->filename) === false) {
|
||||||
ImportService::clearAttempts($profile->id);
|
ImportService::clearAttempts($profile->id);
|
||||||
ImportService::getPostCount($profile->id, true);
|
ImportService::getPostCount($profile->id, true);
|
||||||
$ip->skip_missing_media = true;
|
$ip->skip_missing_media = true;
|
||||||
$ip->save();
|
$ip->save();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$missingMedia = false;
|
$missingMedia = false;
|
||||||
foreach($ip->media as $ipm) {
|
foreach ($ip->media as $ipm) {
|
||||||
$fileName = last(explode('/', $ipm['uri']));
|
$fileName = last(explode('/', $ipm['uri']));
|
||||||
$og = 'imports/' . $id . '/' . $fileName;
|
$og = 'imports/'.$id.'/'.$fileName;
|
||||||
if(!Storage::exists($og)) {
|
if (! Storage::exists($og)) {
|
||||||
$missingMedia = true;
|
$missingMedia = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($missingMedia === true) {
|
if ($missingMedia === true) {
|
||||||
$ip->skip_missing_media = true;
|
$ip->skip_missing_media = true;
|
||||||
$ip->save();
|
$ip->save();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +107,6 @@ class TransformImports extends Command
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->profile_id = $pid;
|
$status->profile_id = $pid;
|
||||||
$status->caption = $caption;
|
$status->caption = $caption;
|
||||||
$status->rendered = strlen(trim($caption)) ? Autolink::create()->autolink($ip->caption) : null;
|
|
||||||
$status->type = $ip->post_type;
|
$status->type = $ip->post_type;
|
||||||
|
|
||||||
$status->scope = 'unlisted';
|
$status->scope = 'unlisted';
|
||||||
|
@ -112,20 +115,21 @@ class TransformImports extends Command
|
||||||
$status->created_at = now()->parse($ip->creation_date);
|
$status->created_at = now()->parse($ip->creation_date);
|
||||||
$status->save();
|
$status->save();
|
||||||
|
|
||||||
foreach($ip->media as $ipm) {
|
foreach ($ip->media as $ipm) {
|
||||||
$fileName = last(explode('/', $ipm['uri']));
|
$fileName = last(explode('/', $ipm['uri']));
|
||||||
$ext = last(explode('.', $fileName));
|
$ext = last(explode('.', $fileName));
|
||||||
$basePath = MediaPathService::get($profile);
|
$basePath = MediaPathService::get($profile);
|
||||||
$og = 'imports/' . $id . '/' . $fileName;
|
$og = 'imports/'.$id.'/'.$fileName;
|
||||||
if(!Storage::exists($og)) {
|
if (! Storage::exists($og)) {
|
||||||
$ip->skip_missing_media = true;
|
$ip->skip_missing_media = true;
|
||||||
$ip->save();
|
$ip->save();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$size = Storage::size($og);
|
$size = Storage::size($og);
|
||||||
$mime = Storage::mimeType($og);
|
$mime = Storage::mimeType($og);
|
||||||
$newFile = Str::random(40) . '.' . $ext;
|
$newFile = Str::random(40).'.'.$ext;
|
||||||
$np = $basePath . '/' . $newFile;
|
$np = $basePath.'/'.$newFile;
|
||||||
Storage::move($og, $np);
|
Storage::move($og, $np);
|
||||||
$media = new Media;
|
$media = new Media;
|
||||||
$media->profile_id = $pid;
|
$media->profile_id = $pid;
|
||||||
|
|
|
@ -3490,8 +3490,7 @@ class ApiV1Controller extends Controller
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = strip_tags($request->input('status'));
|
$content = $request->filled('status') ? strip_tags(Purify::clean($request->input('status'))) : null;
|
||||||
$rendered = Autolink::create()->autolink($content);
|
|
||||||
$cw = $user->profile->cw == true ? true : $request->boolean('sensitive', false);
|
$cw = $user->profile->cw == true ? true : $request->boolean('sensitive', false);
|
||||||
$spoilerText = $cw && $request->filled('spoiler_text') ? $request->input('spoiler_text') : null;
|
$spoilerText = $cw && $request->filled('spoiler_text') ? $request->input('spoiler_text') : null;
|
||||||
|
|
||||||
|
@ -3505,7 +3504,6 @@ class ApiV1Controller extends Controller
|
||||||
|
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->caption = $content;
|
$status->caption = $content;
|
||||||
$status->rendered = $rendered;
|
|
||||||
$status->scope = $visibility;
|
$status->scope = $visibility;
|
||||||
$status->visibility = $visibility;
|
$status->visibility = $visibility;
|
||||||
$status->profile_id = $user->profile_id;
|
$status->profile_id = $user->profile_id;
|
||||||
|
@ -3530,7 +3528,6 @@ class ApiV1Controller extends Controller
|
||||||
if (! $in_reply_to_id) {
|
if (! $in_reply_to_id) {
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->caption = $content;
|
$status->caption = $content;
|
||||||
$status->rendered = $rendered;
|
|
||||||
$status->profile_id = $user->profile_id;
|
$status->profile_id = $user->profile_id;
|
||||||
$status->is_nsfw = $cw;
|
$status->is_nsfw = $cw;
|
||||||
$status->cw_summary = $spoilerText;
|
$status->cw_summary = $spoilerText;
|
||||||
|
|
|
@ -37,7 +37,6 @@ use App\Status;
|
||||||
use App\StatusArchived;
|
use App\StatusArchived;
|
||||||
use App\User;
|
use App\User;
|
||||||
use App\UserSetting;
|
use App\UserSetting;
|
||||||
use App\Util\Lexer\Autolink;
|
|
||||||
use App\Util\Lexer\RestrictedNames;
|
use App\Util\Lexer\RestrictedNames;
|
||||||
use Cache;
|
use Cache;
|
||||||
use DB;
|
use DB;
|
||||||
|
@ -49,6 +48,7 @@ use Jenssegers\Agent\Agent;
|
||||||
use League\Fractal;
|
use League\Fractal;
|
||||||
use League\Fractal\Serializer\ArraySerializer;
|
use League\Fractal\Serializer\ArraySerializer;
|
||||||
use Mail;
|
use Mail;
|
||||||
|
use Purify;
|
||||||
|
|
||||||
class ApiV1Dot1Controller extends Controller
|
class ApiV1Dot1Controller extends Controller
|
||||||
{
|
{
|
||||||
|
@ -1293,14 +1293,12 @@ class ApiV1Dot1Controller extends Controller
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = strip_tags($request->input('status'));
|
$content = $request->filled('status') ? strip_tags(Purify::clean($request->input('status'))) : null;
|
||||||
$rendered = Autolink::create()->autolink($content);
|
|
||||||
$cw = $user->profile->cw == true ? true : $request->boolean('sensitive', false);
|
$cw = $user->profile->cw == true ? true : $request->boolean('sensitive', false);
|
||||||
$spoilerText = $cw && $request->filled('spoiler_text') ? $request->input('spoiler_text') : null;
|
$spoilerText = $cw && $request->filled('spoiler_text') ? $request->input('spoiler_text') : null;
|
||||||
|
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->caption = $content;
|
$status->caption = $content;
|
||||||
$status->rendered = $rendered;
|
|
||||||
$status->profile_id = $user->profile_id;
|
$status->profile_id = $user->profile_id;
|
||||||
$status->is_nsfw = $cw;
|
$status->is_nsfw = $cw;
|
||||||
$status->cw_summary = $spoilerText;
|
$status->cw_summary = $spoilerText;
|
||||||
|
|
|
@ -8,12 +8,12 @@ use App\Services\StatusService;
|
||||||
use App\Status;
|
use App\Status;
|
||||||
use App\Transformer\Api\StatusTransformer;
|
use App\Transformer\Api\StatusTransformer;
|
||||||
use App\UserFilter;
|
use App\UserFilter;
|
||||||
use App\Util\Lexer\Autolink;
|
|
||||||
use Auth;
|
use Auth;
|
||||||
use DB;
|
use DB;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use League\Fractal;
|
use League\Fractal;
|
||||||
use League\Fractal\Serializer\ArraySerializer;
|
use League\Fractal\Serializer\ArraySerializer;
|
||||||
|
use Purify;
|
||||||
|
|
||||||
class CommentController extends Controller
|
class CommentController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -56,12 +56,10 @@ class CommentController extends Controller
|
||||||
|
|
||||||
$reply = DB::transaction(function () use ($comment, $status, $profile, $nsfw) {
|
$reply = DB::transaction(function () use ($comment, $status, $profile, $nsfw) {
|
||||||
$scope = $profile->is_private == true ? 'private' : 'public';
|
$scope = $profile->is_private == true ? 'private' : 'public';
|
||||||
$autolink = Autolink::create()->autolink($comment);
|
$reply = new Status;
|
||||||
$reply = new Status();
|
|
||||||
$reply->profile_id = $profile->id;
|
$reply->profile_id = $profile->id;
|
||||||
$reply->is_nsfw = $nsfw;
|
$reply->is_nsfw = $nsfw;
|
||||||
$reply->caption = e($comment);
|
$reply->caption = Purify::clean($comment);
|
||||||
$reply->rendered = $autolink;
|
|
||||||
$reply->in_reply_to_id = $status->id;
|
$reply->in_reply_to_id = $status->id;
|
||||||
$reply->in_reply_to_profile_id = $status->profile_id;
|
$reply->in_reply_to_profile_id = $status->profile_id;
|
||||||
$reply->scope = $scope;
|
$reply->scope = $scope;
|
||||||
|
@ -76,9 +74,9 @@ class CommentController extends Controller
|
||||||
CommentPipeline::dispatch($status, $reply);
|
CommentPipeline::dispatch($status, $reply);
|
||||||
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
$fractal = new Fractal\Manager();
|
$fractal = new Fractal\Manager;
|
||||||
$fractal->setSerializer(new ArraySerializer());
|
$fractal->setSerializer(new ArraySerializer);
|
||||||
$entity = new Fractal\Resource\Item($reply, new StatusTransformer());
|
$entity = new Fractal\Resource\Item($reply, new StatusTransformer);
|
||||||
$entity = $fractal->createData($entity)->toArray();
|
$entity = $fractal->createData($entity)->toArray();
|
||||||
$response = [
|
$response = [
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
|
|
|
@ -25,7 +25,6 @@ use App\Services\UserStorageService;
|
||||||
use App\Status;
|
use App\Status;
|
||||||
use App\Transformer\Api\MediaTransformer;
|
use App\Transformer\Api\MediaTransformer;
|
||||||
use App\UserFilter;
|
use App\UserFilter;
|
||||||
use App\Util\Lexer\Autolink;
|
|
||||||
use App\Util\Media\Filter;
|
use App\Util\Media\Filter;
|
||||||
use App\Util\Media\License;
|
use App\Util\Media\License;
|
||||||
use Auth;
|
use Auth;
|
||||||
|
@ -43,8 +42,8 @@ class ComposeController extends Controller
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
$this->fractal = new Fractal\Manager();
|
$this->fractal = new Fractal\Manager;
|
||||||
$this->fractal->setSerializer(new ArraySerializer());
|
$this->fractal->setSerializer(new ArraySerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show(Request $request)
|
public function show(Request $request)
|
||||||
|
@ -112,14 +111,14 @@ class ComposeController extends Controller
|
||||||
|
|
||||||
abort_if(MediaBlocklistService::exists($hash) == true, 451);
|
abort_if(MediaBlocklistService::exists($hash) == true, 451);
|
||||||
|
|
||||||
$media = new Media();
|
$media = new Media;
|
||||||
$media->status_id = null;
|
$media->status_id = null;
|
||||||
$media->profile_id = $profile->id;
|
$media->profile_id = $profile->id;
|
||||||
$media->user_id = $user->id;
|
$media->user_id = $user->id;
|
||||||
$media->media_path = $path;
|
$media->media_path = $path;
|
||||||
$media->original_sha256 = $hash;
|
$media->original_sha256 = $hash;
|
||||||
$media->size = $photo->getSize();
|
$media->size = $photo->getSize();
|
||||||
$media->caption = "";
|
$media->caption = '';
|
||||||
$media->mime = $mime;
|
$media->mime = $mime;
|
||||||
$media->filter_class = $filterClass;
|
$media->filter_class = $filterClass;
|
||||||
$media->filter_name = $filterName;
|
$media->filter_name = $filterName;
|
||||||
|
@ -151,7 +150,7 @@ class ComposeController extends Controller
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
Cache::forget($limitKey);
|
Cache::forget($limitKey);
|
||||||
$resource = new Fractal\Resource\Item($media, new MediaTransformer());
|
$resource = new Fractal\Resource\Item($media, new MediaTransformer);
|
||||||
$res = $this->fractal->createData($resource)->toArray();
|
$res = $this->fractal->createData($resource)->toArray();
|
||||||
$res['preview_url'] = $preview_url;
|
$res['preview_url'] = $preview_url;
|
||||||
$res['url'] = $url;
|
$res['url'] = $url;
|
||||||
|
@ -571,7 +570,6 @@ class ComposeController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
$status->caption = strip_tags($request->caption);
|
$status->caption = strip_tags($request->caption);
|
||||||
$status->rendered = Autolink::create()->autolink($status->caption);
|
|
||||||
$status->scope = 'draft';
|
$status->scope = 'draft';
|
||||||
$status->visibility = 'draft';
|
$status->visibility = 'draft';
|
||||||
$status->profile_id = $profile->id;
|
$status->profile_id = $profile->id;
|
||||||
|
@ -693,7 +691,6 @@ class ComposeController extends Controller
|
||||||
$status->visibility = $visibility;
|
$status->visibility = $visibility;
|
||||||
$status->scope = $visibility;
|
$status->scope = $visibility;
|
||||||
$status->type = 'text';
|
$status->type = 'text';
|
||||||
$status->rendered = Autolink::create()->autolink($status->caption);
|
|
||||||
$status->entities = json_encode(array_merge([
|
$status->entities = json_encode(array_merge([
|
||||||
'timg' => [
|
'timg' => [
|
||||||
'version' => 0,
|
'version' => 0,
|
||||||
|
@ -806,7 +803,6 @@ class ComposeController extends Controller
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->profile_id = $request->user()->profile_id;
|
$status->profile_id = $request->user()->profile_id;
|
||||||
$status->caption = $request->input('caption');
|
$status->caption = $request->input('caption');
|
||||||
$status->rendered = Autolink::create()->autolink($status->caption);
|
|
||||||
$status->visibility = 'draft';
|
$status->visibility = 'draft';
|
||||||
$status->scope = 'draft';
|
$status->scope = 'draft';
|
||||||
$status->type = 'poll';
|
$status->type = 'poll';
|
||||||
|
|
|
@ -22,6 +22,7 @@ use App\Services\WebfingerService;
|
||||||
use App\Status;
|
use App\Status;
|
||||||
use App\UserFilter;
|
use App\UserFilter;
|
||||||
use App\Util\ActivityPub\Helpers;
|
use App\Util\ActivityPub\Helpers;
|
||||||
|
use App\Util\Lexer\Autolink;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
@ -326,7 +327,6 @@ class DirectMessageController extends Controller
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->profile_id = $profile->id;
|
$status->profile_id = $profile->id;
|
||||||
$status->caption = $msg;
|
$status->caption = $msg;
|
||||||
$status->rendered = $msg;
|
|
||||||
$status->visibility = 'direct';
|
$status->visibility = 'direct';
|
||||||
$status->scope = 'direct';
|
$status->scope = 'direct';
|
||||||
$status->in_reply_to_profile_id = $recipient->id;
|
$status->in_reply_to_profile_id = $recipient->id;
|
||||||
|
@ -636,7 +636,6 @@ class DirectMessageController extends Controller
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->profile_id = $profile->id;
|
$status->profile_id = $profile->id;
|
||||||
$status->caption = null;
|
$status->caption = null;
|
||||||
$status->rendered = null;
|
|
||||||
$status->visibility = 'direct';
|
$status->visibility = 'direct';
|
||||||
$status->scope = 'direct';
|
$status->scope = 'direct';
|
||||||
$status->in_reply_to_profile_id = $recipient->id;
|
$status->in_reply_to_profile_id = $recipient->id;
|
||||||
|
@ -830,6 +829,11 @@ class DirectMessageController extends Controller
|
||||||
{
|
{
|
||||||
$profile = $dm->author;
|
$profile = $dm->author;
|
||||||
$url = $dm->recipient->sharedInbox ?? $dm->recipient->inbox_url;
|
$url = $dm->recipient->sharedInbox ?? $dm->recipient->inbox_url;
|
||||||
|
$status = $dm->status;
|
||||||
|
|
||||||
|
if (! $status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$tags = [
|
$tags = [
|
||||||
[
|
[
|
||||||
|
@ -839,6 +843,8 @@ class DirectMessageController extends Controller
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
|
||||||
|
|
||||||
$body = [
|
$body = [
|
||||||
'@context' => [
|
'@context' => [
|
||||||
'https://w3id.org/security/v1',
|
'https://w3id.org/security/v1',
|
||||||
|
@ -854,7 +860,7 @@ class DirectMessageController extends Controller
|
||||||
'id' => $dm->status->url(),
|
'id' => $dm->status->url(),
|
||||||
'type' => 'Note',
|
'type' => 'Note',
|
||||||
'summary' => null,
|
'summary' => null,
|
||||||
'content' => $dm->status->rendered ?? $dm->status->caption,
|
'content' => $content,
|
||||||
'inReplyTo' => null,
|
'inReplyTo' => null,
|
||||||
'published' => $dm->status->created_at->toAtomString(),
|
'published' => $dm->status->created_at->toAtomString(),
|
||||||
'url' => $dm->status->url(),
|
'url' => $dm->status->url(),
|
||||||
|
|
|
@ -2,102 +2,106 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use App\Models\GroupPost;
|
use App\Models\GroupPost;
|
||||||
use App\Status;
|
|
||||||
use App\Models\InstanceActor;
|
use App\Models\InstanceActor;
|
||||||
use App\Services\MediaService;
|
use App\Services\MediaService;
|
||||||
|
use App\Status;
|
||||||
|
use App\Util\Lexer\Autolink;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class GroupFederationController extends Controller
|
class GroupFederationController extends Controller
|
||||||
{
|
{
|
||||||
public function getGroupObject(Request $request, $id)
|
public function getGroupObject(Request $request, $id)
|
||||||
{
|
{
|
||||||
$group = Group::whereLocal(true)->whereActivitypub(true)->findOrFail($id);
|
$group = Group::whereLocal(true)->whereActivitypub(true)->findOrFail($id);
|
||||||
$res = $this->showGroupObject($group);
|
$res = $this->showGroupObject($group);
|
||||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function showGroupObject($group)
|
return response()->json($res, 200, [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
{
|
}
|
||||||
return Cache::remember('ap:groups:object:' . $group->id, 3600, function() use($group) {
|
|
||||||
return [
|
|
||||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
|
||||||
'id' => $group->url(),
|
|
||||||
'inbox' => $group->permalink('/inbox'),
|
|
||||||
'name' => $group->name,
|
|
||||||
'outbox' => $group->permalink('/outbox'),
|
|
||||||
'summary' => $group->description,
|
|
||||||
'type' => 'Group',
|
|
||||||
'attributedTo' => [
|
|
||||||
'type' => 'Person',
|
|
||||||
'id' => $group->admin->permalink()
|
|
||||||
],
|
|
||||||
// 'endpoints' => [
|
|
||||||
// 'sharedInbox' => config('app.url') . '/f/inbox'
|
|
||||||
// ],
|
|
||||||
'preferredUsername' => 'gid_' . $group->id,
|
|
||||||
'publicKey' => [
|
|
||||||
'id' => $group->permalink('#main-key'),
|
|
||||||
'owner' => $group->permalink(),
|
|
||||||
'publicKeyPem' => InstanceActor::first()->public_key,
|
|
||||||
],
|
|
||||||
'url' => $group->permalink()
|
|
||||||
];
|
|
||||||
|
|
||||||
if($group->metadata && isset($group->metadata['avatar'])) {
|
public function showGroupObject($group)
|
||||||
$res['icon'] = [
|
{
|
||||||
'type' => 'Image',
|
return Cache::remember('ap:groups:object:'.$group->id, 3600, function () use ($group) {
|
||||||
'url' => $group->metadata['avatar']['url']
|
return [
|
||||||
];
|
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||||
}
|
'id' => $group->url(),
|
||||||
|
'inbox' => $group->permalink('/inbox'),
|
||||||
|
'name' => $group->name,
|
||||||
|
'outbox' => $group->permalink('/outbox'),
|
||||||
|
'summary' => $group->description,
|
||||||
|
'type' => 'Group',
|
||||||
|
'attributedTo' => [
|
||||||
|
'type' => 'Person',
|
||||||
|
'id' => $group->admin->permalink(),
|
||||||
|
],
|
||||||
|
// 'endpoints' => [
|
||||||
|
// 'sharedInbox' => config('app.url') . '/f/inbox'
|
||||||
|
// ],
|
||||||
|
'preferredUsername' => 'gid_'.$group->id,
|
||||||
|
'publicKey' => [
|
||||||
|
'id' => $group->permalink('#main-key'),
|
||||||
|
'owner' => $group->permalink(),
|
||||||
|
'publicKeyPem' => InstanceActor::first()->public_key,
|
||||||
|
],
|
||||||
|
'url' => $group->permalink(),
|
||||||
|
];
|
||||||
|
|
||||||
if($group->metadata && isset($group->metadata['header'])) {
|
if ($group->metadata && isset($group->metadata['avatar'])) {
|
||||||
$res['image'] = [
|
$res['icon'] = [
|
||||||
'type' => 'Image',
|
'type' => 'Image',
|
||||||
'url' => $group->metadata['header']['url']
|
'url' => $group->metadata['avatar']['url'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
ksort($res);
|
|
||||||
return $res;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStatusObject(Request $request, $gid, $sid)
|
if ($group->metadata && isset($group->metadata['header'])) {
|
||||||
{
|
$res['image'] = [
|
||||||
$group = Group::whereLocal(true)->whereActivitypub(true)->findOrFail($gid);
|
'type' => 'Image',
|
||||||
$gp = GroupPost::whereGroupId($gid)->findOrFail($sid);
|
'url' => $group->metadata['header']['url'],
|
||||||
$status = Status::findOrFail($gp->status_id);
|
];
|
||||||
// permission check
|
}
|
||||||
|
ksort($res);
|
||||||
|
|
||||||
$res = [
|
return $res;
|
||||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
});
|
||||||
'id' => $gp->url(),
|
}
|
||||||
|
|
||||||
'type' => 'Note',
|
public function getStatusObject(Request $request, $gid, $sid)
|
||||||
|
{
|
||||||
|
$group = Group::whereLocal(true)->whereActivitypub(true)->findOrFail($gid);
|
||||||
|
$gp = GroupPost::whereGroupId($gid)->findOrFail($sid);
|
||||||
|
$status = Status::findOrFail($gp->status_id);
|
||||||
|
// permission check
|
||||||
|
$content = $status->caption ? Autolink::create()->autolink($status->caption) : null;
|
||||||
|
$res = [
|
||||||
|
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||||
|
'id' => $gp->url(),
|
||||||
|
|
||||||
'summary' => null,
|
'type' => 'Note',
|
||||||
'content' => $status->rendered ?? $status->caption,
|
|
||||||
'inReplyTo' => null,
|
|
||||||
|
|
||||||
'published' => $status->created_at->toAtomString(),
|
'summary' => null,
|
||||||
'url' => $gp->url(),
|
'content' => $content,
|
||||||
'attributedTo' => $status->profile->permalink(),
|
'inReplyTo' => null,
|
||||||
'to' => [
|
|
||||||
'https://www.w3.org/ns/activitystreams#Public',
|
'published' => $status->created_at->toAtomString(),
|
||||||
$group->permalink('/followers'),
|
'url' => $gp->url(),
|
||||||
],
|
'attributedTo' => $status->profile->permalink(),
|
||||||
'cc' => [],
|
'to' => [
|
||||||
'sensitive' => (bool) $status->is_nsfw,
|
'https://www.w3.org/ns/activitystreams#Public',
|
||||||
'attachment' => MediaService::activitypub($status->id),
|
$group->permalink('/followers'),
|
||||||
'target' => [
|
],
|
||||||
'type' => 'Collection',
|
'cc' => [],
|
||||||
'id' => $group->permalink('/wall'),
|
'sensitive' => (bool) $status->is_nsfw,
|
||||||
'attributedTo' => $group->permalink()
|
'attachment' => MediaService::activitypub($status->id),
|
||||||
]
|
'target' => [
|
||||||
];
|
'type' => 'Collection',
|
||||||
// ksort($res);
|
'id' => $group->permalink('/wall'),
|
||||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
'attributedTo' => $group->permalink(),
|
||||||
}
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// ksort($res);
|
||||||
|
return response()->json($res, 200, [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,442 +2,424 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use App\AccountInterstitial;
|
||||||
use App\{
|
use App\Bookmark;
|
||||||
AccountInterstitial,
|
use App\DirectMessage;
|
||||||
Bookmark,
|
use App\DiscoverCategory;
|
||||||
DirectMessage,
|
use App\Follower;
|
||||||
DiscoverCategory,
|
|
||||||
Hashtag,
|
|
||||||
Follower,
|
|
||||||
Like,
|
|
||||||
Media,
|
|
||||||
MediaTag,
|
|
||||||
Notification,
|
|
||||||
Profile,
|
|
||||||
StatusHashtag,
|
|
||||||
Status,
|
|
||||||
User,
|
|
||||||
UserFilter,
|
|
||||||
};
|
|
||||||
use Auth,Cache;
|
|
||||||
use Illuminate\Support\Facades\Redis;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use League\Fractal;
|
|
||||||
use App\Transformer\Api\{
|
|
||||||
AccountTransformer,
|
|
||||||
StatusTransformer,
|
|
||||||
// StatusMediaContainerTransformer,
|
|
||||||
};
|
|
||||||
use App\Util\Media\Filter;
|
|
||||||
use App\Jobs\StatusPipeline\NewStatusPipeline;
|
|
||||||
use App\Jobs\ModPipeline\HandleSpammerPipeline;
|
use App\Jobs\ModPipeline\HandleSpammerPipeline;
|
||||||
use League\Fractal\Serializer\ArraySerializer;
|
use App\Profile;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use App\Services\BookmarkService;
|
||||||
use Illuminate\Validation\Rule;
|
use App\Services\DiscoverService;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use App\Services\MediaTagService;
|
|
||||||
use App\Services\ModLogService;
|
use App\Services\ModLogService;
|
||||||
use App\Services\PublicTimelineService;
|
use App\Services\PublicTimelineService;
|
||||||
use App\Services\SnowflakeService;
|
|
||||||
use App\Services\StatusService;
|
use App\Services\StatusService;
|
||||||
use App\Services\UserFilterService;
|
use App\Services\UserFilterService;
|
||||||
use App\Services\DiscoverService;
|
use App\Status; // StatusMediaContainerTransformer,
|
||||||
use App\Services\BookmarkService;
|
use App\Transformer\Api\StatusTransformer;
|
||||||
|
use App\User;
|
||||||
|
use Auth;
|
||||||
|
use Cache;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use League\Fractal;
|
||||||
|
use League\Fractal\Serializer\ArraySerializer;
|
||||||
|
|
||||||
class InternalApiController extends Controller
|
class InternalApiController extends Controller
|
||||||
{
|
{
|
||||||
protected $fractal;
|
protected $fractal;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
$this->fractal = new Fractal\Manager();
|
$this->fractal = new Fractal\Manager;
|
||||||
$this->fractal->setSerializer(new ArraySerializer());
|
$this->fractal->setSerializer(new ArraySerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated v2 compose api
|
// deprecated v2 compose api
|
||||||
public function compose(Request $request)
|
public function compose(Request $request)
|
||||||
{
|
{
|
||||||
return redirect('/');
|
return redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
public function discover(Request $request)
|
public function discover(Request $request) {}
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function discoverPosts(Request $request)
|
public function discoverPosts(Request $request)
|
||||||
{
|
{
|
||||||
$pid = $request->user()->profile_id;
|
$pid = $request->user()->profile_id;
|
||||||
$filters = UserFilterService::filters($pid);
|
$filters = UserFilterService::filters($pid);
|
||||||
$forYou = DiscoverService::getForYou();
|
$forYou = DiscoverService::getForYou();
|
||||||
$posts = $forYou->take(50)->map(function($post) {
|
$posts = $forYou->take(50)->map(function ($post) {
|
||||||
return StatusService::get($post);
|
return StatusService::get($post);
|
||||||
})
|
})
|
||||||
->filter(function($post) use($filters) {
|
->filter(function ($post) use ($filters) {
|
||||||
return $post &&
|
return $post &&
|
||||||
isset($post['account']) &&
|
isset($post['account']) &&
|
||||||
isset($post['account']['id']) &&
|
isset($post['account']['id']) &&
|
||||||
!in_array($post['account']['id'], $filters);
|
! in_array($post['account']['id'], $filters);
|
||||||
})
|
})
|
||||||
->take(12)
|
->take(12)
|
||||||
->values();
|
->values();
|
||||||
return response()->json(compact('posts'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function directMessage(Request $request, $profileId, $threadId)
|
return response()->json(compact('posts'));
|
||||||
{
|
}
|
||||||
$profile = Auth::user()->profile;
|
|
||||||
|
|
||||||
if($profileId != $profile->id) {
|
public function directMessage(Request $request, $profileId, $threadId)
|
||||||
abort(403);
|
{
|
||||||
}
|
$profile = Auth::user()->profile;
|
||||||
|
|
||||||
$msg = DirectMessage::whereToId($profile->id)
|
if ($profileId != $profile->id) {
|
||||||
->orWhere('from_id',$profile->id)
|
abort(403);
|
||||||
->findOrFail($threadId);
|
}
|
||||||
|
|
||||||
$thread = DirectMessage::with('status')->whereIn('to_id', [$profile->id, $msg->from_id])
|
$msg = DirectMessage::whereToId($profile->id)
|
||||||
->whereIn('from_id', [$profile->id,$msg->from_id])
|
->orWhere('from_id', $profile->id)
|
||||||
->orderBy('created_at', 'asc')
|
->findOrFail($threadId);
|
||||||
->paginate(30);
|
|
||||||
|
|
||||||
return response()->json(compact('msg', 'profile', 'thread'), 200, [], JSON_PRETTY_PRINT);
|
$thread = DirectMessage::with('status')->whereIn('to_id', [$profile->id, $msg->from_id])
|
||||||
}
|
->whereIn('from_id', [$profile->id, $msg->from_id])
|
||||||
|
->orderBy('created_at', 'asc')
|
||||||
|
->paginate(30);
|
||||||
|
|
||||||
public function statusReplies(Request $request, int $id)
|
return response()->json(compact('msg', 'profile', 'thread'), 200, [], JSON_PRETTY_PRINT);
|
||||||
{
|
}
|
||||||
$this->validate($request, [
|
|
||||||
'limit' => 'nullable|int|min:1|max:6'
|
|
||||||
]);
|
|
||||||
$parent = Status::whereScope('public')->findOrFail($id);
|
|
||||||
$limit = $request->input('limit') ?? 3;
|
|
||||||
$children = Status::whereInReplyToId($parent->id)
|
|
||||||
->orderBy('created_at', 'desc')
|
|
||||||
->take($limit)
|
|
||||||
->get();
|
|
||||||
$resource = new Fractal\Resource\Collection($children, new StatusTransformer());
|
|
||||||
$res = $this->fractal->createData($resource)->toArray();
|
|
||||||
|
|
||||||
return response()->json($res);
|
public function statusReplies(Request $request, int $id)
|
||||||
}
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'limit' => 'nullable|int|min:1|max:6',
|
||||||
|
]);
|
||||||
|
$parent = Status::whereScope('public')->findOrFail($id);
|
||||||
|
$limit = $request->input('limit') ?? 3;
|
||||||
|
$children = Status::whereInReplyToId($parent->id)
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->take($limit)
|
||||||
|
->get();
|
||||||
|
$resource = new Fractal\Resource\Collection($children, new StatusTransformer);
|
||||||
|
$res = $this->fractal->createData($resource)->toArray();
|
||||||
|
|
||||||
public function stories(Request $request)
|
return response()->json($res);
|
||||||
{
|
}
|
||||||
|
|
||||||
}
|
public function stories(Request $request) {}
|
||||||
|
|
||||||
public function discoverCategories(Request $request)
|
public function discoverCategories(Request $request)
|
||||||
{
|
{
|
||||||
$categories = DiscoverCategory::whereActive(true)->orderBy('order')->take(10)->get();
|
$categories = DiscoverCategory::whereActive(true)->orderBy('order')->take(10)->get();
|
||||||
$res = $categories->map(function($item) {
|
$res = $categories->map(function ($item) {
|
||||||
return [
|
return [
|
||||||
'name' => $item->name,
|
'name' => $item->name,
|
||||||
'url' => $item->url(),
|
'url' => $item->url(),
|
||||||
'thumb' => $item->thumb()
|
'thumb' => $item->thumb(),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
return response()->json($res);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function modAction(Request $request)
|
return response()->json($res);
|
||||||
{
|
}
|
||||||
abort_unless(Auth::user()->is_admin, 400);
|
|
||||||
$this->validate($request, [
|
|
||||||
'action' => [
|
|
||||||
'required',
|
|
||||||
'string',
|
|
||||||
Rule::in([
|
|
||||||
'addcw',
|
|
||||||
'remcw',
|
|
||||||
'unlist',
|
|
||||||
'spammer'
|
|
||||||
])
|
|
||||||
],
|
|
||||||
'item_id' => 'required|integer|min:1',
|
|
||||||
'item_type' => [
|
|
||||||
'required',
|
|
||||||
'string',
|
|
||||||
Rule::in(['profile', 'status'])
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$action = $request->input('action');
|
public function modAction(Request $request)
|
||||||
$item_id = $request->input('item_id');
|
{
|
||||||
$item_type = $request->input('item_type');
|
abort_unless(Auth::user()->is_admin, 400);
|
||||||
|
$this->validate($request, [
|
||||||
|
'action' => [
|
||||||
|
'required',
|
||||||
|
'string',
|
||||||
|
Rule::in([
|
||||||
|
'addcw',
|
||||||
|
'remcw',
|
||||||
|
'unlist',
|
||||||
|
'spammer',
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
'item_id' => 'required|integer|min:1',
|
||||||
|
'item_type' => [
|
||||||
|
'required',
|
||||||
|
'string',
|
||||||
|
Rule::in(['profile', 'status']),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
$status = Status::findOrFail($item_id);
|
$action = $request->input('action');
|
||||||
$author = User::whereProfileId($status->profile_id)->first();
|
$item_id = $request->input('item_id');
|
||||||
abort_if($author && $author->is_admin, 422, 'Cannot moderate administrator accounts');
|
$item_type = $request->input('item_type');
|
||||||
|
|
||||||
switch($action) {
|
$status = Status::findOrFail($item_id);
|
||||||
case 'addcw':
|
$author = User::whereProfileId($status->profile_id)->first();
|
||||||
$status->is_nsfw = true;
|
abort_if($author && $author->is_admin, 422, 'Cannot moderate administrator accounts');
|
||||||
$status->save();
|
|
||||||
ModLogService::boot()
|
|
||||||
->user(Auth::user())
|
|
||||||
->objectUid($status->profile->user_id)
|
|
||||||
->objectId($status->id)
|
|
||||||
->objectType('App\Status::class')
|
|
||||||
->action('admin.status.moderate')
|
|
||||||
->metadata([
|
|
||||||
'action' => 'cw',
|
|
||||||
'message' => 'Success!'
|
|
||||||
])
|
|
||||||
->accessLevel('admin')
|
|
||||||
->save();
|
|
||||||
|
|
||||||
if($status->uri == null) {
|
switch ($action) {
|
||||||
$media = $status->media;
|
case 'addcw':
|
||||||
$ai = new AccountInterstitial;
|
$status->is_nsfw = true;
|
||||||
$ai->user_id = $status->profile->user_id;
|
$status->save();
|
||||||
$ai->type = 'post.cw';
|
ModLogService::boot()
|
||||||
$ai->view = 'account.moderation.post.cw';
|
->user(Auth::user())
|
||||||
$ai->item_type = 'App\Status';
|
->objectUid($status->profile->user_id)
|
||||||
$ai->item_id = $status->id;
|
->objectId($status->id)
|
||||||
$ai->has_media = (bool) $media->count();
|
->objectType('App\Status::class')
|
||||||
$ai->blurhash = $media->count() ? $media->first()->blurhash : null;
|
->action('admin.status.moderate')
|
||||||
$ai->meta = json_encode([
|
->metadata([
|
||||||
'caption' => $status->caption,
|
'action' => 'cw',
|
||||||
'created_at' => $status->created_at,
|
'message' => 'Success!',
|
||||||
'type' => $status->type,
|
])
|
||||||
'url' => $status->url(),
|
->accessLevel('admin')
|
||||||
'is_nsfw' => $status->is_nsfw,
|
->save();
|
||||||
'scope' => $status->scope,
|
|
||||||
'reblog' => $status->reblog_of_id,
|
|
||||||
'likes_count' => $status->likes_count,
|
|
||||||
'reblogs_count' => $status->reblogs_count,
|
|
||||||
]);
|
|
||||||
$ai->save();
|
|
||||||
|
|
||||||
$u = $status->profile->user;
|
if ($status->uri == null) {
|
||||||
$u->has_interstitial = true;
|
$media = $status->media;
|
||||||
$u->save();
|
$ai = new AccountInterstitial;
|
||||||
}
|
$ai->user_id = $status->profile->user_id;
|
||||||
break;
|
$ai->type = 'post.cw';
|
||||||
|
$ai->view = 'account.moderation.post.cw';
|
||||||
|
$ai->item_type = 'App\Status';
|
||||||
|
$ai->item_id = $status->id;
|
||||||
|
$ai->has_media = (bool) $media->count();
|
||||||
|
$ai->blurhash = $media->count() ? $media->first()->blurhash : null;
|
||||||
|
$ai->meta = json_encode([
|
||||||
|
'caption' => $status->caption,
|
||||||
|
'created_at' => $status->created_at,
|
||||||
|
'type' => $status->type,
|
||||||
|
'url' => $status->url(),
|
||||||
|
'is_nsfw' => $status->is_nsfw,
|
||||||
|
'scope' => $status->scope,
|
||||||
|
'reblog' => $status->reblog_of_id,
|
||||||
|
'likes_count' => $status->likes_count,
|
||||||
|
'reblogs_count' => $status->reblogs_count,
|
||||||
|
]);
|
||||||
|
$ai->save();
|
||||||
|
|
||||||
case 'remcw':
|
$u = $status->profile->user;
|
||||||
$status->is_nsfw = false;
|
$u->has_interstitial = true;
|
||||||
$status->save();
|
$u->save();
|
||||||
ModLogService::boot()
|
}
|
||||||
->user(Auth::user())
|
break;
|
||||||
->objectUid($status->profile->user_id)
|
|
||||||
->objectId($status->id)
|
|
||||||
->objectType('App\Status::class')
|
|
||||||
->action('admin.status.moderate')
|
|
||||||
->metadata([
|
|
||||||
'action' => 'remove_cw',
|
|
||||||
'message' => 'Success!'
|
|
||||||
])
|
|
||||||
->accessLevel('admin')
|
|
||||||
->save();
|
|
||||||
if($status->uri == null) {
|
|
||||||
$ai = AccountInterstitial::whereUserId($status->profile->user_id)
|
|
||||||
->whereType('post.cw')
|
|
||||||
->whereItemId($status->id)
|
|
||||||
->whereItemType('App\Status')
|
|
||||||
->first();
|
|
||||||
$ai->delete();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'unlist':
|
case 'remcw':
|
||||||
$status->scope = $status->visibility = 'unlisted';
|
$status->is_nsfw = false;
|
||||||
$status->save();
|
$status->save();
|
||||||
PublicTimelineService::del($status->id);
|
ModLogService::boot()
|
||||||
ModLogService::boot()
|
->user(Auth::user())
|
||||||
->user(Auth::user())
|
->objectUid($status->profile->user_id)
|
||||||
->objectUid($status->profile->user_id)
|
->objectId($status->id)
|
||||||
->objectId($status->id)
|
->objectType('App\Status::class')
|
||||||
->objectType('App\Status::class')
|
->action('admin.status.moderate')
|
||||||
->action('admin.status.moderate')
|
->metadata([
|
||||||
->metadata([
|
'action' => 'remove_cw',
|
||||||
'action' => 'unlist',
|
'message' => 'Success!',
|
||||||
'message' => 'Success!'
|
])
|
||||||
])
|
->accessLevel('admin')
|
||||||
->accessLevel('admin')
|
->save();
|
||||||
->save();
|
if ($status->uri == null) {
|
||||||
|
$ai = AccountInterstitial::whereUserId($status->profile->user_id)
|
||||||
|
->whereType('post.cw')
|
||||||
|
->whereItemId($status->id)
|
||||||
|
->whereItemType('App\Status')
|
||||||
|
->first();
|
||||||
|
$ai->delete();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if($status->uri == null) {
|
case 'unlist':
|
||||||
$media = $status->media;
|
$status->scope = $status->visibility = 'unlisted';
|
||||||
$ai = new AccountInterstitial;
|
$status->save();
|
||||||
$ai->user_id = $status->profile->user_id;
|
PublicTimelineService::del($status->id);
|
||||||
$ai->type = 'post.unlist';
|
ModLogService::boot()
|
||||||
$ai->view = 'account.moderation.post.unlist';
|
->user(Auth::user())
|
||||||
$ai->item_type = 'App\Status';
|
->objectUid($status->profile->user_id)
|
||||||
$ai->item_id = $status->id;
|
->objectId($status->id)
|
||||||
$ai->has_media = (bool) $media->count();
|
->objectType('App\Status::class')
|
||||||
$ai->blurhash = $media->count() ? $media->first()->blurhash : null;
|
->action('admin.status.moderate')
|
||||||
$ai->meta = json_encode([
|
->metadata([
|
||||||
'caption' => $status->caption,
|
'action' => 'unlist',
|
||||||
'created_at' => $status->created_at,
|
'message' => 'Success!',
|
||||||
'type' => $status->type,
|
])
|
||||||
'url' => $status->url(),
|
->accessLevel('admin')
|
||||||
'is_nsfw' => $status->is_nsfw,
|
->save();
|
||||||
'scope' => $status->scope,
|
|
||||||
'reblog' => $status->reblog_of_id,
|
|
||||||
'likes_count' => $status->likes_count,
|
|
||||||
'reblogs_count' => $status->reblogs_count,
|
|
||||||
]);
|
|
||||||
$ai->save();
|
|
||||||
|
|
||||||
$u = $status->profile->user;
|
if ($status->uri == null) {
|
||||||
$u->has_interstitial = true;
|
$media = $status->media;
|
||||||
$u->save();
|
$ai = new AccountInterstitial;
|
||||||
}
|
$ai->user_id = $status->profile->user_id;
|
||||||
break;
|
$ai->type = 'post.unlist';
|
||||||
|
$ai->view = 'account.moderation.post.unlist';
|
||||||
|
$ai->item_type = 'App\Status';
|
||||||
|
$ai->item_id = $status->id;
|
||||||
|
$ai->has_media = (bool) $media->count();
|
||||||
|
$ai->blurhash = $media->count() ? $media->first()->blurhash : null;
|
||||||
|
$ai->meta = json_encode([
|
||||||
|
'caption' => $status->caption,
|
||||||
|
'created_at' => $status->created_at,
|
||||||
|
'type' => $status->type,
|
||||||
|
'url' => $status->url(),
|
||||||
|
'is_nsfw' => $status->is_nsfw,
|
||||||
|
'scope' => $status->scope,
|
||||||
|
'reblog' => $status->reblog_of_id,
|
||||||
|
'likes_count' => $status->likes_count,
|
||||||
|
'reblogs_count' => $status->reblogs_count,
|
||||||
|
]);
|
||||||
|
$ai->save();
|
||||||
|
|
||||||
case 'spammer':
|
$u = $status->profile->user;
|
||||||
HandleSpammerPipeline::dispatch($status->profile);
|
$u->has_interstitial = true;
|
||||||
ModLogService::boot()
|
$u->save();
|
||||||
->user(Auth::user())
|
}
|
||||||
->objectUid($status->profile->user_id)
|
break;
|
||||||
->objectId($status->id)
|
|
||||||
->objectType('App\User::class')
|
|
||||||
->action('admin.status.moderate')
|
|
||||||
->metadata([
|
|
||||||
'action' => 'spammer',
|
|
||||||
'message' => 'Success!'
|
|
||||||
])
|
|
||||||
->accessLevel('admin')
|
|
||||||
->save();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusService::del($status->id, true);
|
case 'spammer':
|
||||||
return ['msg' => 200];
|
HandleSpammerPipeline::dispatch($status->profile);
|
||||||
}
|
ModLogService::boot()
|
||||||
|
->user(Auth::user())
|
||||||
|
->objectUid($status->profile->user_id)
|
||||||
|
->objectId($status->id)
|
||||||
|
->objectType('App\User::class')
|
||||||
|
->action('admin.status.moderate')
|
||||||
|
->metadata([
|
||||||
|
'action' => 'spammer',
|
||||||
|
'message' => 'Success!',
|
||||||
|
])
|
||||||
|
->accessLevel('admin')
|
||||||
|
->save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
public function composePost(Request $request)
|
StatusService::del($status->id, true);
|
||||||
{
|
|
||||||
abort(400, 'Endpoint deprecated');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function bookmarks(Request $request)
|
return ['msg' => 200];
|
||||||
{
|
}
|
||||||
$pid = $request->user()->profile_id;
|
|
||||||
$res = Bookmark::whereProfileId($pid)
|
|
||||||
->orderByDesc('created_at')
|
|
||||||
->simplePaginate(10)
|
|
||||||
->map(function($bookmark) use($pid) {
|
|
||||||
$status = StatusService::get($bookmark->status_id, false);
|
|
||||||
if(!$status) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$status['bookmarked_at'] = str_replace('+00:00', 'Z', $bookmark->created_at->format(DATE_RFC3339_EXTENDED));
|
|
||||||
|
|
||||||
if($status) {
|
public function composePost(Request $request)
|
||||||
BookmarkService::add($pid, $status['id']);
|
{
|
||||||
}
|
abort(400, 'Endpoint deprecated');
|
||||||
return $status;
|
}
|
||||||
})
|
|
||||||
->filter(function($bookmark) {
|
|
||||||
return $bookmark && isset($bookmark['id']);
|
|
||||||
})
|
|
||||||
->values();
|
|
||||||
|
|
||||||
return response()->json($res);
|
public function bookmarks(Request $request)
|
||||||
}
|
{
|
||||||
|
$pid = $request->user()->profile_id;
|
||||||
|
$res = Bookmark::whereProfileId($pid)
|
||||||
|
->orderByDesc('created_at')
|
||||||
|
->simplePaginate(10)
|
||||||
|
->map(function ($bookmark) use ($pid) {
|
||||||
|
$status = StatusService::get($bookmark->status_id, false);
|
||||||
|
if (! $status) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$status['bookmarked_at'] = str_replace('+00:00', 'Z', $bookmark->created_at->format(DATE_RFC3339_EXTENDED));
|
||||||
|
|
||||||
public function accountStatuses(Request $request, $id)
|
if ($status) {
|
||||||
{
|
BookmarkService::add($pid, $status['id']);
|
||||||
$this->validate($request, [
|
}
|
||||||
'only_media' => 'nullable',
|
|
||||||
'pinned' => 'nullable',
|
|
||||||
'exclude_replies' => 'nullable',
|
|
||||||
'max_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
|
||||||
'since_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
|
||||||
'min_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
|
||||||
'limit' => 'nullable|integer|min:1|max:24'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$profile = Profile::whereNull('status')->findOrFail($id);
|
return $status;
|
||||||
|
})
|
||||||
|
->filter(function ($bookmark) {
|
||||||
|
return $bookmark && isset($bookmark['id']);
|
||||||
|
})
|
||||||
|
->values();
|
||||||
|
|
||||||
$limit = $request->limit ?? 9;
|
return response()->json($res);
|
||||||
$max_id = $request->max_id;
|
}
|
||||||
$min_id = $request->min_id;
|
|
||||||
$scope = $request->only_media == true ?
|
|
||||||
['photo', 'photo:album', 'video', 'video:album'] :
|
|
||||||
['photo', 'photo:album', 'video', 'video:album', 'share', 'reply'];
|
|
||||||
|
|
||||||
if($profile->is_private) {
|
public function accountStatuses(Request $request, $id)
|
||||||
if(!Auth::check()) {
|
{
|
||||||
return response()->json([]);
|
$this->validate($request, [
|
||||||
}
|
'only_media' => 'nullable',
|
||||||
$pid = Auth::user()->profile->id;
|
'pinned' => 'nullable',
|
||||||
$following = Cache::remember('profile:following:'.$pid, now()->addMinutes(1440), function() use($pid) {
|
'exclude_replies' => 'nullable',
|
||||||
$following = Follower::whereProfileId($pid)->pluck('following_id');
|
'max_id' => 'nullable|integer|min:0|max:'.PHP_INT_MAX,
|
||||||
return $following->push($pid)->toArray();
|
'since_id' => 'nullable|integer|min:0|max:'.PHP_INT_MAX,
|
||||||
});
|
'min_id' => 'nullable|integer|min:0|max:'.PHP_INT_MAX,
|
||||||
$visibility = true == in_array($profile->id, $following) ? ['public', 'unlisted', 'private'] : [];
|
'limit' => 'nullable|integer|min:1|max:24',
|
||||||
} else {
|
]);
|
||||||
if(Auth::check()) {
|
|
||||||
$pid = Auth::user()->profile->id;
|
|
||||||
$following = Cache::remember('profile:following:'.$pid, now()->addMinutes(1440), function() use($pid) {
|
|
||||||
$following = Follower::whereProfileId($pid)->pluck('following_id');
|
|
||||||
return $following->push($pid)->toArray();
|
|
||||||
});
|
|
||||||
$visibility = true == in_array($profile->id, $following) ? ['public', 'unlisted', 'private'] : ['public', 'unlisted'];
|
|
||||||
} else {
|
|
||||||
$visibility = ['public', 'unlisted'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$dir = $min_id ? '>' : '<';
|
$profile = Profile::whereNull('status')->findOrFail($id);
|
||||||
$id = $min_id ?? $max_id;
|
|
||||||
$timeline = Status::select(
|
|
||||||
'id',
|
|
||||||
'uri',
|
|
||||||
'caption',
|
|
||||||
'rendered',
|
|
||||||
'profile_id',
|
|
||||||
'type',
|
|
||||||
'in_reply_to_id',
|
|
||||||
'reblog_of_id',
|
|
||||||
'is_nsfw',
|
|
||||||
'likes_count',
|
|
||||||
'reblogs_count',
|
|
||||||
'scope',
|
|
||||||
'local',
|
|
||||||
'created_at',
|
|
||||||
'updated_at'
|
|
||||||
)->whereProfileId($profile->id)
|
|
||||||
->whereIn('type', $scope)
|
|
||||||
->where('id', $dir, $id)
|
|
||||||
->whereIn('visibility', $visibility)
|
|
||||||
->latest()
|
|
||||||
->limit($limit)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
$resource = new Fractal\Resource\Collection($timeline, new StatusTransformer());
|
$limit = $request->limit ?? 9;
|
||||||
$res = $this->fractal->createData($resource)->toArray();
|
$max_id = $request->max_id;
|
||||||
|
$min_id = $request->min_id;
|
||||||
|
$scope = $request->only_media == true ?
|
||||||
|
['photo', 'photo:album', 'video', 'video:album'] :
|
||||||
|
['photo', 'photo:album', 'video', 'video:album', 'share', 'reply'];
|
||||||
|
|
||||||
return response()->json($res);
|
if ($profile->is_private) {
|
||||||
}
|
if (! Auth::check()) {
|
||||||
|
return response()->json([]);
|
||||||
|
}
|
||||||
|
$pid = Auth::user()->profile->id;
|
||||||
|
$following = Cache::remember('profile:following:'.$pid, now()->addMinutes(1440), function () use ($pid) {
|
||||||
|
$following = Follower::whereProfileId($pid)->pluck('following_id');
|
||||||
|
|
||||||
public function remoteProfile(Request $request, $id)
|
return $following->push($pid)->toArray();
|
||||||
{
|
});
|
||||||
return redirect('/i/web/profile/' . $id);
|
$visibility = in_array($profile->id, $following) == true ? ['public', 'unlisted', 'private'] : [];
|
||||||
}
|
} else {
|
||||||
|
if (Auth::check()) {
|
||||||
|
$pid = Auth::user()->profile->id;
|
||||||
|
$following = Cache::remember('profile:following:'.$pid, now()->addMinutes(1440), function () use ($pid) {
|
||||||
|
$following = Follower::whereProfileId($pid)->pluck('following_id');
|
||||||
|
|
||||||
public function remoteStatus(Request $request, $profileId, $statusId)
|
return $following->push($pid)->toArray();
|
||||||
{
|
});
|
||||||
return redirect('/i/web/post/' . $statusId);
|
$visibility = in_array($profile->id, $following) == true ? ['public', 'unlisted', 'private'] : ['public', 'unlisted'];
|
||||||
}
|
} else {
|
||||||
|
$visibility = ['public', 'unlisted'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function requestEmailVerification(Request $request)
|
$dir = $min_id ? '>' : '<';
|
||||||
{
|
$id = $min_id ?? $max_id;
|
||||||
$pid = $request->user()->profile_id;
|
$timeline = Status::select(
|
||||||
$exists = Redis::sismember('email:manual', $pid);
|
'id',
|
||||||
return view('account.email.request_verification', compact('exists'));
|
'uri',
|
||||||
}
|
'caption',
|
||||||
|
'profile_id',
|
||||||
|
'type',
|
||||||
|
'in_reply_to_id',
|
||||||
|
'reblog_of_id',
|
||||||
|
'is_nsfw',
|
||||||
|
'likes_count',
|
||||||
|
'reblogs_count',
|
||||||
|
'scope',
|
||||||
|
'local',
|
||||||
|
'created_at',
|
||||||
|
'updated_at'
|
||||||
|
)->whereProfileId($profile->id)
|
||||||
|
->whereIn('type', $scope)
|
||||||
|
->where('id', $dir, $id)
|
||||||
|
->whereIn('visibility', $visibility)
|
||||||
|
->latest()
|
||||||
|
->limit($limit)
|
||||||
|
->get();
|
||||||
|
|
||||||
public function requestEmailVerificationStore(Request $request)
|
$resource = new Fractal\Resource\Collection($timeline, new StatusTransformer);
|
||||||
{
|
$res = $this->fractal->createData($resource)->toArray();
|
||||||
$pid = $request->user()->profile_id;
|
|
||||||
Redis::sadd('email:manual', $pid);
|
return response()->json($res);
|
||||||
return redirect('/i/verify-email')->with(['status' => 'Successfully sent manual verification request!']);
|
}
|
||||||
}
|
|
||||||
|
public function remoteProfile(Request $request, $id)
|
||||||
|
{
|
||||||
|
return redirect('/i/web/profile/'.$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function remoteStatus(Request $request, $profileId, $statusId)
|
||||||
|
{
|
||||||
|
return redirect('/i/web/post/'.$statusId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function requestEmailVerification(Request $request)
|
||||||
|
{
|
||||||
|
$pid = $request->user()->profile_id;
|
||||||
|
$exists = Redis::sismember('email:manual', $pid);
|
||||||
|
|
||||||
|
return view('account.email.request_verification', compact('exists'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function requestEmailVerificationStore(Request $request)
|
||||||
|
{
|
||||||
|
$pid = $request->user()->profile_id;
|
||||||
|
Redis::sadd('email:manual', $pid);
|
||||||
|
|
||||||
|
return redirect('/i/verify-email')->with(['status' => 'Successfully sent manual verification request!']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,66 +2,65 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Status;
|
||||||
|
use Auth;
|
||||||
|
use DB;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\{
|
|
||||||
Profile,
|
|
||||||
Status,
|
|
||||||
};
|
|
||||||
use Auth, DB, Purify;
|
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
class MicroController extends Controller
|
class MicroController extends Controller
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function composeText(Request $request)
|
public function composeText(Request $request)
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'type' => [
|
'type' => [
|
||||||
'required',
|
'required',
|
||||||
'string',
|
'string',
|
||||||
Rule::in(['text'])
|
Rule::in(['text']),
|
||||||
],
|
],
|
||||||
'title' => 'nullable|string|max:140',
|
'title' => 'nullable|string|max:140',
|
||||||
'content' => 'required|string|max:500',
|
'content' => 'required|string|max:500',
|
||||||
'visibility' => [
|
'visibility' => [
|
||||||
'required',
|
'required',
|
||||||
'string',
|
'string',
|
||||||
Rule::in([
|
Rule::in([
|
||||||
'public',
|
'public',
|
||||||
'unlisted',
|
'unlisted',
|
||||||
'private',
|
'private',
|
||||||
'draft'
|
'draft',
|
||||||
])
|
]),
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
$profile = Auth::user()->profile;
|
$profile = Auth::user()->profile;
|
||||||
$title = $request->input('title');
|
$title = $request->input('title');
|
||||||
$content = $request->input('content');
|
$content = $request->input('content');
|
||||||
$visibility = $request->input('visibility');
|
$visibility = $request->input('visibility');
|
||||||
|
|
||||||
$status = DB::transaction(function() use($profile, $content, $visibility, $title) {
|
$status = DB::transaction(function () use ($profile, $content, $visibility, $title) {
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->type = 'text';
|
$status->type = 'text';
|
||||||
$status->profile_id = $profile->id;
|
$status->profile_id = $profile->id;
|
||||||
$status->caption = strip_tags($content);
|
$status->caption = strip_tags($content);
|
||||||
$status->rendered = Purify::clean($content);
|
$status->is_nsfw = false;
|
||||||
$status->is_nsfw = false;
|
|
||||||
|
|
||||||
// TODO: remove deprecated visibility in favor of scope
|
// TODO: remove deprecated visibility in favor of scope
|
||||||
$status->visibility = $visibility;
|
$status->visibility = $visibility;
|
||||||
$status->scope = $visibility;
|
$status->scope = $visibility;
|
||||||
$status->entities = json_encode(['title'=>$title]);
|
$status->entities = json_encode(['title' => $title]);
|
||||||
$status->save();
|
$status->save();
|
||||||
return $status;
|
|
||||||
});
|
|
||||||
|
|
||||||
$fractal = new \League\Fractal\Manager();
|
return $status;
|
||||||
$fractal->setSerializer(new \League\Fractal\Serializer\ArraySerializer());
|
});
|
||||||
$s = new \League\Fractal\Resource\Item($status, new \App\Transformer\Api\StatusTransformer());
|
|
||||||
return $fractal->createData($s)->toArray();
|
$fractal = new \League\Fractal\Manager;
|
||||||
}
|
$fractal->setSerializer(new \League\Fractal\Serializer\ArraySerializer);
|
||||||
|
$s = new \League\Fractal\Resource\Item($status, new \App\Transformer\Api\StatusTransformer);
|
||||||
|
|
||||||
|
return $fractal->createData($s)->toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ use App\Profile;
|
||||||
use App\Services\WebfingerService;
|
use App\Services\WebfingerService;
|
||||||
use App\Status;
|
use App\Status;
|
||||||
use App\Util\ActivityPub\Helpers;
|
use App\Util\ActivityPub\Helpers;
|
||||||
|
use App\Util\Lexer\Autolink;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
@ -320,17 +321,21 @@ class SearchController extends Controller
|
||||||
|
|
||||||
if (Status::whereUri($tag)->whereLocal(false)->exists()) {
|
if (Status::whereUri($tag)->whereLocal(false)->exists()) {
|
||||||
$item = Status::whereUri($tag)->first();
|
$item = Status::whereUri($tag)->first();
|
||||||
|
if (! $item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$media = $item->firstMedia();
|
$media = $item->firstMedia();
|
||||||
$url = null;
|
$url = null;
|
||||||
if ($media) {
|
if ($media) {
|
||||||
$url = $media->remote_url;
|
$url = $media->remote_url;
|
||||||
}
|
}
|
||||||
|
$content = $item->caption ? Autolink::create()->autolink($item->caption) : null;
|
||||||
$this->tokens['posts'] = [[
|
$this->tokens['posts'] = [[
|
||||||
'count' => 0,
|
'count' => 0,
|
||||||
'url' => "/i/web/post/_/$item->profile_id/$item->id",
|
'url' => "/i/web/post/_/$item->profile_id/$item->id",
|
||||||
'type' => 'status',
|
'type' => 'status',
|
||||||
'username' => $item->profile->username,
|
'username' => $item->profile->username,
|
||||||
'caption' => $item->rendered ?? $item->caption,
|
'caption' => $content,
|
||||||
'thumb' => $url,
|
'thumb' => $url,
|
||||||
'timestamp' => $item->created_at->diffForHumans(),
|
'timestamp' => $item->created_at->diffForHumans(),
|
||||||
]];
|
]];
|
||||||
|
@ -340,17 +345,21 @@ class SearchController extends Controller
|
||||||
|
|
||||||
if (isset($remote['type']) && $remote['type'] == 'Note') {
|
if (isset($remote['type']) && $remote['type'] == 'Note') {
|
||||||
$item = Helpers::statusFetch($tag);
|
$item = Helpers::statusFetch($tag);
|
||||||
|
if (! $item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$media = $item->firstMedia();
|
$media = $item->firstMedia();
|
||||||
$url = null;
|
$url = null;
|
||||||
if ($media) {
|
if ($media) {
|
||||||
$url = $media->remote_url;
|
$url = $media->remote_url;
|
||||||
}
|
}
|
||||||
|
$content = $item->caption ? Autolink::create()->autolink($item->caption) : null;
|
||||||
$this->tokens['posts'] = [[
|
$this->tokens['posts'] = [[
|
||||||
'count' => 0,
|
'count' => 0,
|
||||||
'url' => "/i/web/post/_/$item->profile_id/$item->id",
|
'url' => "/i/web/post/_/$item->profile_id/$item->id",
|
||||||
'type' => 'status',
|
'type' => 'status',
|
||||||
'username' => $item->profile->username,
|
'username' => $item->profile->username,
|
||||||
'caption' => $item->rendered ?? $item->caption,
|
'caption' => $content,
|
||||||
'thumb' => $url,
|
'thumb' => $url,
|
||||||
'timestamp' => $item->created_at->diffForHumans(),
|
'timestamp' => $item->created_at->diffForHumans(),
|
||||||
]];
|
]];
|
||||||
|
|
|
@ -281,7 +281,7 @@ class StoryApiV1Controller extends Controller
|
||||||
$photo = $request->file('file');
|
$photo = $request->file('file');
|
||||||
$path = $this->storeMedia($photo, $user);
|
$path = $this->storeMedia($photo, $user);
|
||||||
|
|
||||||
$story = new Story();
|
$story = new Story;
|
||||||
$story->duration = $request->input('duration', 3);
|
$story->duration = $request->input('duration', 3);
|
||||||
$story->profile_id = $user->profile_id;
|
$story->profile_id = $user->profile_id;
|
||||||
$story->type = Str::endsWith($photo->getMimeType(), 'mp4') ? 'video' : 'photo';
|
$story->type = Str::endsWith($photo->getMimeType(), 'mp4') ? 'video' : 'photo';
|
||||||
|
@ -418,7 +418,6 @@ class StoryApiV1Controller extends Controller
|
||||||
$status->type = 'story:reply';
|
$status->type = 'story:reply';
|
||||||
$status->profile_id = $pid;
|
$status->profile_id = $pid;
|
||||||
$status->caption = $text;
|
$status->caption = $text;
|
||||||
$status->rendered = $text;
|
|
||||||
$status->scope = 'direct';
|
$status->scope = 'direct';
|
||||||
$status->visibility = 'direct';
|
$status->visibility = 'direct';
|
||||||
$status->in_reply_to_profile_id = $story->profile_id;
|
$status->in_reply_to_profile_id = $story->profile_id;
|
||||||
|
|
|
@ -54,7 +54,7 @@ class StoryComposeController extends Controller
|
||||||
$photo = $request->file('file');
|
$photo = $request->file('file');
|
||||||
$path = $this->storePhoto($photo, $user);
|
$path = $this->storePhoto($photo, $user);
|
||||||
|
|
||||||
$story = new Story();
|
$story = new Story;
|
||||||
$story->duration = 3;
|
$story->duration = 3;
|
||||||
$story->profile_id = $user->profile_id;
|
$story->profile_id = $user->profile_id;
|
||||||
$story->type = Str::endsWith($photo->getMimeType(), 'mp4') ? 'video' : 'photo';
|
$story->type = Str::endsWith($photo->getMimeType(), 'mp4') ? 'video' : 'photo';
|
||||||
|
@ -403,7 +403,6 @@ class StoryComposeController extends Controller
|
||||||
$status->profile_id = $pid;
|
$status->profile_id = $pid;
|
||||||
$status->type = 'story:reaction';
|
$status->type = 'story:reaction';
|
||||||
$status->caption = $text;
|
$status->caption = $text;
|
||||||
$status->rendered = $text;
|
|
||||||
$status->scope = 'direct';
|
$status->scope = 'direct';
|
||||||
$status->visibility = 'direct';
|
$status->visibility = 'direct';
|
||||||
$status->in_reply_to_profile_id = $story->profile_id;
|
$status->in_reply_to_profile_id = $story->profile_id;
|
||||||
|
@ -477,7 +476,6 @@ class StoryComposeController extends Controller
|
||||||
$status->type = 'story:reply';
|
$status->type = 'story:reply';
|
||||||
$status->profile_id = $pid;
|
$status->profile_id = $pid;
|
||||||
$status->caption = $text;
|
$status->caption = $text;
|
||||||
$status->rendered = $text;
|
|
||||||
$status->scope = 'direct';
|
$status->scope = 'direct';
|
||||||
$status->visibility = 'direct';
|
$status->visibility = 'direct';
|
||||||
$status->in_reply_to_profile_id = $story->profile_id;
|
$status->in_reply_to_profile_id = $story->profile_id;
|
||||||
|
|
|
@ -2,129 +2,122 @@
|
||||||
|
|
||||||
namespace App\Jobs\GroupPipeline;
|
namespace App\Jobs\GroupPipeline;
|
||||||
|
|
||||||
use App\Notification;
|
|
||||||
use App\Hashtag;
|
use App\Hashtag;
|
||||||
use App\Mention;
|
use App\Mention;
|
||||||
use App\Profile;
|
|
||||||
use App\Status;
|
|
||||||
use App\StatusHashtag;
|
|
||||||
use App\Models\GroupPostHashtag;
|
|
||||||
use App\Models\GroupPost;
|
use App\Models\GroupPost;
|
||||||
use Cache;
|
use App\Models\GroupPostHashtag;
|
||||||
|
use App\Profile;
|
||||||
|
use App\Services\StatusService;
|
||||||
|
use App\Status;
|
||||||
|
use App\Util\Lexer\Autolink;
|
||||||
|
use App\Util\Lexer\Extractor;
|
||||||
use DB;
|
use DB;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Redis;
|
|
||||||
use App\Services\MediaStorageService;
|
|
||||||
use App\Services\NotificationService;
|
|
||||||
use App\Services\StatusService;
|
|
||||||
use App\Util\Lexer\Autolink;
|
|
||||||
use App\Util\Lexer\Extractor;
|
|
||||||
|
|
||||||
class NewStatusPipeline implements ShouldQueue
|
class NewStatusPipeline implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
protected $status;
|
protected $status;
|
||||||
protected $gp;
|
|
||||||
protected $tags;
|
|
||||||
protected $mentions;
|
|
||||||
|
|
||||||
public function __construct(Status $status, GroupPost $gp)
|
protected $gp;
|
||||||
{
|
|
||||||
$this->status = $status;
|
|
||||||
$this->gp = $gp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle()
|
protected $tags;
|
||||||
{
|
|
||||||
$status = $this->status;
|
|
||||||
|
|
||||||
$autolink = Autolink::create()
|
protected $mentions;
|
||||||
->setAutolinkActiveUsersOnly(true)
|
|
||||||
->setBaseHashPath("/groups/{$status->group_id}/topics/")
|
public function __construct(Status $status, GroupPost $gp)
|
||||||
->setBaseUserPath("/groups/{$status->group_id}/username/")
|
{
|
||||||
->autolink($status->caption);
|
$this->status = $status;
|
||||||
|
$this->gp = $gp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$status = $this->status;
|
||||||
|
|
||||||
|
$autolink = Autolink::create()
|
||||||
|
->setAutolinkActiveUsersOnly(true)
|
||||||
|
->setBaseHashPath("/groups/{$status->group_id}/topics/")
|
||||||
|
->setBaseUserPath("/groups/{$status->group_id}/username/")
|
||||||
|
->autolink($status->caption);
|
||||||
|
|
||||||
$entities = Extractor::create()->extract($status->caption);
|
$entities = Extractor::create()->extract($status->caption);
|
||||||
|
$status->entities = null;
|
||||||
|
$status->save();
|
||||||
|
|
||||||
$autolink = str_replace('/discover/tags/', '/groups/' . $status->group_id . '/topics/', $autolink);
|
$this->tags = array_unique($entities['hashtags']);
|
||||||
|
$this->mentions = array_unique($entities['mentions']);
|
||||||
|
|
||||||
$status->rendered = nl2br($autolink);
|
if (count($this->tags)) {
|
||||||
$status->entities = null;
|
$this->storeHashtags();
|
||||||
$status->save();
|
}
|
||||||
|
|
||||||
$this->tags = array_unique($entities['hashtags']);
|
if (count($this->mentions)) {
|
||||||
$this->mentions = array_unique($entities['mentions']);
|
$this->storeMentions($this->mentions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(count($this->tags)) {
|
protected function storeHashtags()
|
||||||
$this->storeHashtags();
|
{
|
||||||
}
|
$tags = $this->tags;
|
||||||
|
$status = $this->status;
|
||||||
|
$gp = $this->gp;
|
||||||
|
|
||||||
if(count($this->mentions)) {
|
foreach ($tags as $tag) {
|
||||||
$this->storeMentions($this->mentions);
|
if (mb_strlen($tag) > 124) {
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function storeHashtags()
|
DB::transaction(function () use ($status, $tag, $gp) {
|
||||||
{
|
$slug = str_slug($tag, '-', false);
|
||||||
$tags = $this->tags;
|
$hashtag = Hashtag::firstOrCreate(
|
||||||
$status = $this->status;
|
['name' => $tag, 'slug' => $slug]
|
||||||
$gp = $this->gp;
|
);
|
||||||
|
GroupPostHashtag::firstOrCreate(
|
||||||
|
[
|
||||||
|
'group_id' => $status->group_id,
|
||||||
|
'group_post_id' => $gp->id,
|
||||||
|
'status_id' => $status->id,
|
||||||
|
'hashtag_id' => $hashtag->id,
|
||||||
|
'profile_id' => $status->profile_id,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
foreach ($tags as $tag) {
|
});
|
||||||
if(mb_strlen($tag) > 124) {
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DB::transaction(function () use ($status, $tag, $gp) {
|
if (count($this->mentions)) {
|
||||||
$slug = str_slug($tag, '-', false);
|
$this->storeMentions();
|
||||||
$hashtag = Hashtag::firstOrCreate(
|
}
|
||||||
['name' => $tag, 'slug' => $slug]
|
StatusService::del($status->id);
|
||||||
);
|
}
|
||||||
GroupPostHashtag::firstOrCreate(
|
|
||||||
[
|
|
||||||
'group_id' => $status->group_id,
|
|
||||||
'group_post_id' => $gp->id,
|
|
||||||
'status_id' => $status->id,
|
|
||||||
'hashtag_id' => $hashtag->id,
|
|
||||||
'profile_id' => $status->profile_id,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
protected function storeMentions()
|
||||||
}
|
{
|
||||||
|
$mentions = $this->mentions;
|
||||||
|
$status = $this->status;
|
||||||
|
|
||||||
if(count($this->mentions)) {
|
foreach ($mentions as $mention) {
|
||||||
$this->storeMentions();
|
$mentioned = Profile::whereUsername($mention)->first();
|
||||||
}
|
|
||||||
StatusService::del($status->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function storeMentions()
|
if (empty($mentioned) || ! isset($mentioned->id)) {
|
||||||
{
|
continue;
|
||||||
$mentions = $this->mentions;
|
}
|
||||||
$status = $this->status;
|
|
||||||
|
|
||||||
foreach ($mentions as $mention) {
|
DB::transaction(function () use ($status, $mentioned) {
|
||||||
$mentioned = Profile::whereUsername($mention)->first();
|
$m = new Mention;
|
||||||
|
$m->status_id = $status->id;
|
||||||
|
$m->profile_id = $mentioned->id;
|
||||||
|
$m->save();
|
||||||
|
|
||||||
if (empty($mentioned) || !isset($mentioned->id)) {
|
MentionPipeline::dispatch($status, $m);
|
||||||
continue;
|
});
|
||||||
}
|
}
|
||||||
|
StatusService::del($status->id);
|
||||||
DB::transaction(function () use ($status, $mentioned) {
|
}
|
||||||
$m = new Mention();
|
|
||||||
$m->status_id = $status->id;
|
|
||||||
$m->profile_id = $mentioned->id;
|
|
||||||
$m->save();
|
|
||||||
|
|
||||||
MentionPipeline::dispatch($status, $m);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
StatusService::del($status->id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,11 +91,6 @@ class StatusEntityLexer implements ShouldQueue
|
||||||
public function storeEntities()
|
public function storeEntities()
|
||||||
{
|
{
|
||||||
$this->storeHashtags();
|
$this->storeHashtags();
|
||||||
DB::transaction(function () {
|
|
||||||
$status = $this->status;
|
|
||||||
$status->rendered = nl2br($this->autolink);
|
|
||||||
$status->save();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function storeHashtags()
|
public function storeHashtags()
|
||||||
|
@ -146,7 +141,7 @@ class StatusEntityLexer implements ShouldQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::transaction(function () use ($status, $mentioned) {
|
DB::transaction(function () use ($status, $mentioned) {
|
||||||
$m = new Mention();
|
$m = new Mention;
|
||||||
$m->status_id = $status->id;
|
$m->status_id = $status->id;
|
||||||
$m->profile_id = $mentioned->id;
|
$m->profile_id = $mentioned->id;
|
||||||
$m->save();
|
$m->save();
|
||||||
|
|
|
@ -120,8 +120,7 @@ class StatusRemoteUpdatePipeline implements ShouldQueue
|
||||||
protected function updateImmediateAttributes($status, $activity)
|
protected function updateImmediateAttributes($status, $activity)
|
||||||
{
|
{
|
||||||
if (isset($activity['content'])) {
|
if (isset($activity['content'])) {
|
||||||
$status->caption = strip_tags($activity['content']);
|
$status->caption = strip_tags(Purify::clean($activity['content']));
|
||||||
$status->rendered = Purify::clean($activity['content']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($activity['sensitive'])) {
|
if (isset($activity['sensitive'])) {
|
||||||
|
|
|
@ -2,53 +2,25 @@
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use Cache;
|
|
||||||
use App\Profile;
|
use App\Profile;
|
||||||
use Illuminate\Support\Str;
|
use Cache;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Purify;
|
||||||
use App\Util\Webfinger\WebfingerUrl;
|
|
||||||
|
|
||||||
class AutolinkService
|
class AutolinkService
|
||||||
{
|
{
|
||||||
const CACHE_KEY = 'pf:services:autolink:';
|
const CACHE_KEY = 'pf:services:autolink:mue:';
|
||||||
|
|
||||||
public static function mentionedUsernameExists($username)
|
public static function mentionedUsernameExists($username)
|
||||||
{
|
{
|
||||||
$key = 'pf:services:autolink:userexists:' . hash('sha256', $username);
|
if (str_starts_with($username, '@')) {
|
||||||
|
if (substr_count($username, '@') === 1) {
|
||||||
|
$username = substr($username, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$name = Purify::clean(strtolower($username));
|
||||||
|
|
||||||
return Cache::remember($key, 3600, function() use($username) {
|
return Cache::remember(self::CACHE_KEY.base64_encode($name), 7200, function () use ($name) {
|
||||||
$remote = Str::of($username)->contains('@');
|
return Profile::where('username', $name)->exists();
|
||||||
$profile = Profile::whereUsername($username)->first();
|
});
|
||||||
if($profile) {
|
}
|
||||||
if($profile->domain != null) {
|
|
||||||
$instance = InstanceService::getByDomain($profile->domain);
|
|
||||||
if($instance && $instance->banned == true) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if($remote) {
|
|
||||||
$parts = explode('@', $username);
|
|
||||||
$domain = last($parts);
|
|
||||||
$instance = InstanceService::getByDomain($domain);
|
|
||||||
|
|
||||||
if($instance) {
|
|
||||||
if($instance->banned == true) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
$wf = WebfingerUrl::generateWebfingerUrl($username);
|
|
||||||
$res = Http::head($wf);
|
|
||||||
return $res->ok();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$wf = WebfingerUrl::generateWebfingerUrl($username);
|
|
||||||
$res = Http::head($wf);
|
|
||||||
return $res->ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,135 +3,133 @@
|
||||||
namespace App\Services\Status;
|
namespace App\Services\Status;
|
||||||
|
|
||||||
use App\Media;
|
use App\Media;
|
||||||
use App\ModLog;
|
|
||||||
use App\Status;
|
|
||||||
use App\Models\StatusEdit;
|
use App\Models\StatusEdit;
|
||||||
use Purify;
|
use App\ModLog;
|
||||||
use App\Util\Lexer\Autolink;
|
|
||||||
use App\Services\MediaService;
|
use App\Services\MediaService;
|
||||||
use App\Services\MediaStorageService;
|
use App\Services\MediaStorageService;
|
||||||
use App\Services\StatusService;
|
use App\Services\StatusService;
|
||||||
|
use App\Status;
|
||||||
|
use Purify;
|
||||||
|
|
||||||
class UpdateStatusService
|
class UpdateStatusService
|
||||||
{
|
{
|
||||||
public static function call(Status $status, $attributes)
|
public static function call(Status $status, $attributes)
|
||||||
{
|
{
|
||||||
self::createPreviousEdit($status);
|
self::createPreviousEdit($status);
|
||||||
self::updateMediaAttachements($status, $attributes);
|
self::updateMediaAttachements($status, $attributes);
|
||||||
self::handleImmediateAttributes($status, $attributes);
|
self::handleImmediateAttributes($status, $attributes);
|
||||||
self::createEdit($status, $attributes);
|
self::createEdit($status, $attributes);
|
||||||
|
|
||||||
return StatusService::get($status->id);
|
return StatusService::get($status->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function updateMediaAttachements(Status $status, $attributes)
|
public static function updateMediaAttachements(Status $status, $attributes)
|
||||||
{
|
{
|
||||||
$count = $status->media()->count();
|
$count = $status->media()->count();
|
||||||
if($count === 0 || $count === 1) {
|
if ($count === 0 || $count === 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$oids = $status->media()->orderBy('order')->pluck('id')->map(function($m) { return (string) $m; });
|
$oids = $status->media()->orderBy('order')->pluck('id')->map(function ($m) {
|
||||||
$nids = collect($attributes['media_ids']);
|
return (string) $m;
|
||||||
|
});
|
||||||
|
$nids = collect($attributes['media_ids']);
|
||||||
|
|
||||||
if($oids->toArray() === $nids->toArray()) {
|
if ($oids->toArray() === $nids->toArray()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($oids->diff($nids)->values()->toArray() as $mid) {
|
foreach ($oids->diff($nids)->values()->toArray() as $mid) {
|
||||||
$media = Media::find($mid);
|
$media = Media::find($mid);
|
||||||
if(!$media) {
|
if (! $media) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$media->status_id = null;
|
$media->status_id = null;
|
||||||
$media->save();
|
$media->save();
|
||||||
MediaStorageService::delete($media, true);
|
MediaStorageService::delete($media, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$nids->each(function($nid, $idx) {
|
$nids->each(function ($nid, $idx) {
|
||||||
$media = Media::find($nid);
|
$media = Media::find($nid);
|
||||||
if(!$media) {
|
if (! $media) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$media->order = $idx;
|
$media->order = $idx;
|
||||||
$media->save();
|
$media->save();
|
||||||
});
|
});
|
||||||
MediaService::del($status->id);
|
MediaService::del($status->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function handleImmediateAttributes(Status $status, $attributes)
|
public static function handleImmediateAttributes(Status $status, $attributes)
|
||||||
{
|
{
|
||||||
if(isset($attributes['status'])) {
|
if (isset($attributes['status'])) {
|
||||||
$cleaned = Purify::clean($attributes['status']);
|
$cleaned = Purify::clean($attributes['status']);
|
||||||
$status->caption = $cleaned;
|
$status->caption = $cleaned;
|
||||||
$status->rendered = nl2br(Autolink::create()->autolink($cleaned));
|
} else {
|
||||||
} else {
|
$status->caption = null;
|
||||||
$status->caption = null;
|
}
|
||||||
$status->rendered = null;
|
if (isset($attributes['sensitive'])) {
|
||||||
}
|
if ($status->is_nsfw != (bool) $attributes['sensitive'] &&
|
||||||
if(isset($attributes['sensitive'])) {
|
(bool) $attributes['sensitive'] == false) {
|
||||||
if($status->is_nsfw != (bool) $attributes['sensitive'] &&
|
$exists = ModLog::whereObjectType('App\Status::class')
|
||||||
(bool) $attributes['sensitive'] == false)
|
->whereObjectId($status->id)
|
||||||
{
|
->whereAction('admin.status.moderate')
|
||||||
$exists = ModLog::whereObjectType('App\Status::class')
|
->exists();
|
||||||
->whereObjectId($status->id)
|
if (! $exists) {
|
||||||
->whereAction('admin.status.moderate')
|
$status->is_nsfw = (bool) $attributes['sensitive'];
|
||||||
->exists();
|
}
|
||||||
if(!$exists) {
|
} else {
|
||||||
$status->is_nsfw = (bool) $attributes['sensitive'];
|
$status->is_nsfw = (bool) $attributes['sensitive'];
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
$status->is_nsfw = (bool) $attributes['sensitive'];
|
if (isset($attributes['spoiler_text'])) {
|
||||||
}
|
$status->cw_summary = Purify::clean($attributes['spoiler_text']);
|
||||||
}
|
} else {
|
||||||
if(isset($attributes['spoiler_text'])) {
|
$status->cw_summary = null;
|
||||||
$status->cw_summary = Purify::clean($attributes['spoiler_text']);
|
}
|
||||||
} else {
|
if (isset($attributes['location'])) {
|
||||||
$status->cw_summary = null;
|
if (isset($attributes['location']['id'])) {
|
||||||
}
|
$status->place_id = $attributes['location']['id'];
|
||||||
if(isset($attributes['location'])) {
|
} else {
|
||||||
if (isset($attributes['location']['id'])) {
|
$status->place_id = null;
|
||||||
$status->place_id = $attributes['location']['id'];
|
}
|
||||||
} else {
|
}
|
||||||
$status->place_id = null;
|
if ($status->cw_summary && ! $status->is_nsfw) {
|
||||||
}
|
$status->cw_summary = null;
|
||||||
}
|
}
|
||||||
if($status->cw_summary && !$status->is_nsfw) {
|
$status->edited_at = now();
|
||||||
$status->cw_summary = null;
|
$status->save();
|
||||||
}
|
StatusService::del($status->id);
|
||||||
$status->edited_at = now();
|
}
|
||||||
$status->save();
|
|
||||||
StatusService::del($status->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function createPreviousEdit(Status $status)
|
public static function createPreviousEdit(Status $status)
|
||||||
{
|
{
|
||||||
if(!$status->edits()->count()) {
|
if (! $status->edits()->count()) {
|
||||||
StatusEdit::create([
|
StatusEdit::create([
|
||||||
'status_id' => $status->id,
|
'status_id' => $status->id,
|
||||||
'profile_id' => $status->profile_id,
|
'profile_id' => $status->profile_id,
|
||||||
'caption' => $status->caption,
|
'caption' => $status->caption,
|
||||||
'spoiler_text' => $status->cw_summary,
|
'spoiler_text' => $status->cw_summary,
|
||||||
'is_nsfw' => $status->is_nsfw,
|
'is_nsfw' => $status->is_nsfw,
|
||||||
'ordered_media_attachment_ids' => $status->media()->orderBy('order')->pluck('id')->toArray(),
|
'ordered_media_attachment_ids' => $status->media()->orderBy('order')->pluck('id')->toArray(),
|
||||||
'created_at' => $status->created_at
|
'created_at' => $status->created_at,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createEdit(Status $status, $attributes)
|
public static function createEdit(Status $status, $attributes)
|
||||||
{
|
{
|
||||||
$cleaned = isset($attributes['status']) ? Purify::clean($attributes['status']) : null;
|
$cleaned = isset($attributes['status']) ? Purify::clean($attributes['status']) : null;
|
||||||
$spoiler_text = isset($attributes['spoiler_text']) ? Purify::clean($attributes['spoiler_text']) : null;
|
$spoiler_text = isset($attributes['spoiler_text']) ? Purify::clean($attributes['spoiler_text']) : null;
|
||||||
$sensitive = isset($attributes['sensitive']) ? $attributes['sensitive'] : null;
|
$sensitive = isset($attributes['sensitive']) ? $attributes['sensitive'] : null;
|
||||||
$mids = $status->media()->count() ? $status->media()->orderBy('order')->pluck('id')->toArray() : null;
|
$mids = $status->media()->count() ? $status->media()->orderBy('order')->pluck('id')->toArray() : null;
|
||||||
StatusEdit::create([
|
StatusEdit::create([
|
||||||
'status_id' => $status->id,
|
'status_id' => $status->id,
|
||||||
'profile_id' => $status->profile_id,
|
'profile_id' => $status->profile_id,
|
||||||
'caption' => $cleaned,
|
'caption' => $cleaned,
|
||||||
'spoiler_text' => $spoiler_text,
|
'spoiler_text' => $spoiler_text,
|
||||||
'is_nsfw' => $sensitive,
|
'is_nsfw' => $sensitive,
|
||||||
'ordered_media_attachment_ids' => $mids
|
'ordered_media_attachment_ids' => $mids,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -694,8 +694,7 @@ class Helpers
|
||||||
$status->url = isset($res['url']) ? $res['url'] : $url;
|
$status->url = isset($res['url']) ? $res['url'] : $url;
|
||||||
$status->uri = isset($res['url']) ? $res['url'] : $url;
|
$status->uri = isset($res['url']) ? $res['url'] : $url;
|
||||||
$status->object_url = $id;
|
$status->object_url = $id;
|
||||||
$status->caption = strip_tags($res['content']);
|
$status->caption = strip_tags(Purify::clean($res['content']));
|
||||||
$status->rendered = Purify::clean($res['content']);
|
|
||||||
$status->created_at = Carbon::parse($ts)->tz('UTC');
|
$status->created_at = Carbon::parse($ts)->tz('UTC');
|
||||||
$status->in_reply_to_id = null;
|
$status->in_reply_to_id = null;
|
||||||
$status->local = false;
|
$status->local = false;
|
||||||
|
|
|
@ -438,7 +438,6 @@ class Inbox
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->profile_id = $actor->id;
|
$status->profile_id = $actor->id;
|
||||||
$status->caption = $msgText;
|
$status->caption = $msgText;
|
||||||
$status->rendered = $msg;
|
|
||||||
$status->visibility = 'direct';
|
$status->visibility = 'direct';
|
||||||
$status->scope = 'direct';
|
$status->scope = 'direct';
|
||||||
$status->url = $activity['id'];
|
$status->url = $activity['id'];
|
||||||
|
@ -1081,7 +1080,6 @@ class Inbox
|
||||||
$status->uri = $url;
|
$status->uri = $url;
|
||||||
$status->object_url = $url;
|
$status->object_url = $url;
|
||||||
$status->caption = $text;
|
$status->caption = $text;
|
||||||
$status->rendered = $text;
|
|
||||||
$status->scope = 'direct';
|
$status->scope = 'direct';
|
||||||
$status->visibility = 'direct';
|
$status->visibility = 'direct';
|
||||||
$status->in_reply_to_profile_id = $story->profile_id;
|
$status->in_reply_to_profile_id = $story->profile_id;
|
||||||
|
@ -1199,7 +1197,6 @@ class Inbox
|
||||||
$status->profile_id = $actorProfile->id;
|
$status->profile_id = $actorProfile->id;
|
||||||
$status->type = 'story:reply';
|
$status->type = 'story:reply';
|
||||||
$status->caption = $text;
|
$status->caption = $text;
|
||||||
$status->rendered = $text;
|
|
||||||
$status->url = $url;
|
$status->url = $url;
|
||||||
$status->uri = $url;
|
$status->uri = $url;
|
||||||
$status->object_url = $url;
|
$status->object_url = $url;
|
||||||
|
|
Loading…
Reference in a new issue