From 25bf33e64a2d1659cc110e008c951c4ef6c0f1c2 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 20:34:52 -0600 Subject: [PATCH 1/6] Update CW --- app/Status.php | 2 +- public/css/app.css | Bin 202777 -> 203269 bytes public/mix-manifest.json | Bin 250 -> 250 bytes resources/views/status/show.blade.php | 11 +++++++++++ resources/views/status/template.blade.php | 2 +- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/Status.php b/app/Status.php index dd9bf98c4..07879f510 100644 --- a/app/Status.php +++ b/app/Status.php @@ -25,7 +25,7 @@ class Status extends Model public function thumb() { - if($this->media->count() == 0) { + if($this->media->count() == 0 || $this->is_nsfw) { return "data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="; } return url(Storage::url($this->firstMedia()->thumbnail_path)); diff --git a/public/css/app.css b/public/css/app.css index 4fc774d1919e744b4b6828b87f8a69419855ccb5..dee2a793158e645d59bf5df6ca61e432b492f17a 100644 GIT binary patch delta 346 zcmbQafv0r~PeTi13)2>6M&8K_SVhHBQa$rr^2_t84OFZ13lftvODe4ltfxCVF-dbr zYUmp38JVW$YFbZUsK6v93gy+7Fwm^6b;wSwOe;#vO)XYP zOQfz1^$;8MQc_D2Gjob{6Z0~26H8K4qVo$<^J1%Y%TtrGGfSYtnfZCTc|d1aAzWb% h(SS_`Q*TOXQDO;Dsg<5-F;t@fNGG!RHeO~)ZUCy8bCdu8 delta 26 icmZqO!ZULNPeTi13)2>6M&9WY%NfPCGxIYuaRUH*@dtVU diff --git a/public/mix-manifest.json b/public/mix-manifest.json index a0fc846dab985ea32b2c1850d4fa1e5a94d40ab9..2d3e3dd2b0ceaa1b49bfa5e797a106c465b750cf 100644 GIT binary patch delta 30 lcmeyx_=|BuyokAZN}7>Hl97ptrGc4=S*oc)vc<&Wb^w~w36TH* delta 30 lcmeyx_=|Buyhw_9T8dd(nqiV
+ @if($status->is_nsfw) +
+

+

NSFW / Hidden Image + + + +

+
+ @else + @endif
diff --git a/resources/views/status/template.blade.php b/resources/views/status/template.blade.php index e43215bf8..2e56e6ee5 100644 --- a/resources/views/status/template.blade.php +++ b/resources/views/status/template.blade.php @@ -29,7 +29,7 @@
@if($item->is_nsfw) -
+

NSFW / Hidden Image From 3f0ad3ffe2c3e192091a026644fe60a3ab46fa69 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 17:14:10 -0600 Subject: [PATCH 2/6] Update StatusController, support multiple uploads --- app/Http/Controllers/StatusController.php | 42 ++++++++++++------- app/Jobs/StatusPipeline/NewStatusPipeline.php | 11 ++--- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 4e5c2e8d4..1ce080245 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use Auth, Cache; use App\Jobs\StatusPipeline\{NewStatusPipeline, StatusDelete}; +use App\Jobs\ImageOptimizePipeline\ImageOptimize; use Illuminate\Http\Request; use App\{Media, Profile, Status, User}; use Vinkla\Hashids\Facades\Hashids; @@ -14,7 +15,7 @@ class StatusController extends Controller { $user = Profile::whereUsername($username)->firstOrFail(); $status = Status::whereProfileId($user->id) - ->withCount(['likes', 'comments']) + ->withCount(['likes', 'comments', 'media']) ->findOrFail($id); if(!$status->media_path && $status->in_reply_to_id) { return redirect($status->url()); @@ -32,16 +33,16 @@ class StatusController extends Controller $user = Auth::user(); $this->validate($request, [ - 'photo' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'), + 'photo.*' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'), 'caption' => 'string|max:' . config('pixelfed.max_caption_length'), - 'cw' => 'nullable|string' + 'cw' => 'nullable|string', + 'filter_class' => 'nullable|string', + 'filter_name' => 'nullable|string', ]); $cw = $request->filled('cw') && $request->cw == 'on' ? true : false; $monthHash = hash('sha1', date('Y') . date('m')); $userHash = hash('sha1', $user->id . (string) $user->created_at); - $storagePath = "public/m/{$monthHash}/{$userHash}"; - $path = $request->photo->store($storagePath); $profile = $user->profile; $status = new Status; @@ -51,17 +52,28 @@ class StatusController extends Controller $status->save(); - $media = new Media; - $media->status_id = $status->id; - $media->profile_id = $profile->id; - $media->user_id = $user->id; - $media->media_path = $path; - $media->size = $request->file('photo')->getClientSize(); - $media->mime = $request->file('photo')->getClientMimeType(); - $media->save(); - NewStatusPipeline::dispatch($status, $media); + $photos = $request->file('photo'); + $order = 1; + foreach ($photos as $k => $v) { + $storagePath = "public/m/{$monthHash}/{$userHash}"; + $path = $v->store($storagePath); + $media = new Media; + $media->status_id = $status->id; + $media->profile_id = $profile->id; + $media->user_id = $user->id; + $media->media_path = $path; + $media->size = $v->getClientSize(); + $media->mime = $v->getClientMimeType(); + $media->filter_class = $request->input('filter_class'); + $media->filter_name = $request->input('filter_name'); + $media->order = $order; + $media->save(); + ImageOptimize::dispatch($media); + $order++; + } + + NewStatusPipeline::dispatch($status); - // TODO: Parse Caption // TODO: Send to subscribers return redirect($status->url()); diff --git a/app/Jobs/StatusPipeline/NewStatusPipeline.php b/app/Jobs/StatusPipeline/NewStatusPipeline.php index 01392aa47..8939dd9ad 100644 --- a/app/Jobs/StatusPipeline/NewStatusPipeline.php +++ b/app/Jobs/StatusPipeline/NewStatusPipeline.php @@ -16,17 +16,15 @@ class NewStatusPipeline implements ShouldQueue use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $status; - protected $media; /** * Create a new job instance. * * @return void */ - public function __construct(Status $status, $media = false) + public function __construct(Status $status) { $this->status = $status; - $this->media = $media; } /** @@ -37,13 +35,10 @@ class NewStatusPipeline implements ShouldQueue public function handle() { $status = $this->status; - $media = $this->media; StatusEntityLexer::dispatch($status); - StatusActivityPubDeliver::dispatch($status); - if($media) { - ImageOptimize::dispatch($media); - } + //StatusActivityPubDeliver::dispatch($status); + Cache::forever('post.' . $status->id, $status); $redis = Redis::connection(); From 5cb3e5c17b488e2f261741175a3821964339bbfc Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 17:14:44 -0600 Subject: [PATCH 3/6] Add new media migration --- ...6_11_030049_add_filters_to_media_table.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 database/migrations/2018_06_11_030049_add_filters_to_media_table.php diff --git a/database/migrations/2018_06_11_030049_add_filters_to_media_table.php b/database/migrations/2018_06_11_030049_add_filters_to_media_table.php new file mode 100644 index 000000000..5a3dbf73d --- /dev/null +++ b/database/migrations/2018_06_11_030049_add_filters_to_media_table.php @@ -0,0 +1,34 @@ +string('filter_name')->nullable()->after('orientation'); + $table->string('filter_class')->nullable()->after('filter_name'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('media', function (Blueprint $table) { + $table->dropColumn('filter_name'); + $table->dropColumn('filter_class'); + }); + } +} From 4e51fbd5eba9f3e4150af46ae3bdfb190126b554 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 18:52:42 -0600 Subject: [PATCH 4/6] Add soft-deletes --- app/Avatar.php | 8 +++ app/Jobs/StatusPipeline/StatusDelete.php | 5 +- app/Like.php | 10 ++++ app/Media.php | 12 +++- app/Mention.php | 9 +++ app/Notification.php | 41 ++++++++----- app/Profile.php | 9 +++ app/Status.php | 18 +++++- app/User.php | 10 +++- ...6_14_001318_add_soft_deletes_to_models.php | 58 +++++++++++++++++++ 10 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php diff --git a/app/Avatar.php b/app/Avatar.php index a7f8e4e67..b72510765 100644 --- a/app/Avatar.php +++ b/app/Avatar.php @@ -3,8 +3,16 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Avatar extends Model { + use SoftDeletes; + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; } diff --git a/app/Jobs/StatusPipeline/StatusDelete.php b/app/Jobs/StatusPipeline/StatusDelete.php index 571b41a55..30aecd7e2 100644 --- a/app/Jobs/StatusPipeline/StatusDelete.php +++ b/app/Jobs/StatusPipeline/StatusDelete.php @@ -2,7 +2,7 @@ namespace App\Jobs\StatusPipeline; -use App\{Media, StatusHashtag, Status}; +use App\{Media, Notification, StatusHashtag, Status}; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; @@ -60,6 +60,9 @@ class StatusDelete implements ShouldQueue } $status->likes()->delete(); + Notification::whereItemType('App\Status') + ->whereItemId($status->id) + ->delete(); StatusHashtag::whereStatusId($status->id)->delete(); $status->delete(); diff --git a/app/Like.php b/app/Like.php index a4ce9f0a8..c70b647bc 100644 --- a/app/Like.php +++ b/app/Like.php @@ -3,9 +3,19 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Like extends Model { + use SoftDeletes; + + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; + public function actor() { return $this->belongsTo(Profile::class, 'profile_id', 'id'); diff --git a/app/Media.php b/app/Media.php index 8cc2ffd1e..7c9138965 100644 --- a/app/Media.php +++ b/app/Media.php @@ -2,11 +2,21 @@ namespace App; -use Illuminate\Database\Eloquent\Model; use Storage; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Media extends Model { + use SoftDeletes; + + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; + public function url() { $path = $this->media_path; diff --git a/app/Mention.php b/app/Mention.php index 3473c2924..bc76bdc97 100644 --- a/app/Mention.php +++ b/app/Mention.php @@ -3,9 +3,18 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Mention extends Model { + use SoftDeletes; + + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; public function profile() { diff --git a/app/Notification.php b/app/Notification.php index c40e0a553..9aef5b197 100644 --- a/app/Notification.php +++ b/app/Notification.php @@ -3,28 +3,37 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Notification extends Model { + use SoftDeletes; - public function actor() - { - return $this->belongsTo(Profile::class, 'actor_id', 'id'); - } + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; + + public function actor() + { + return $this->belongsTo(Profile::class, 'actor_id', 'id'); + } - public function profile() - { - return $this->belongsTo(Profile::class, 'profile_id', 'id'); - } + public function profile() + { + return $this->belongsTo(Profile::class, 'profile_id', 'id'); + } - public function item() - { - return $this->morphTo(); - } + public function item() + { + return $this->morphTo(); + } - public function status() - { - return $this->belongsTo(Status::class, 'item_id', 'id'); - } + public function status() + { + return $this->belongsTo(Status::class, 'item_id', 'id'); + } } diff --git a/app/Profile.php b/app/Profile.php index b0bcd3da3..009ed2cbf 100644 --- a/app/Profile.php +++ b/app/Profile.php @@ -5,9 +5,18 @@ namespace App; use Storage; use App\Util\Lexer\PrettyNumber; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Profile extends Model { + use SoftDeletes; + + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; protected $hidden = [ 'private_key', ]; diff --git a/app/Status.php b/app/Status.php index 07879f510..fe3fc26d2 100644 --- a/app/Status.php +++ b/app/Status.php @@ -2,12 +2,21 @@ namespace App; -use Illuminate\Database\Eloquent\Model; use Storage; -use Vinkla\Hashids\Facades\Hashids; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Status extends Model { + use SoftDeletes; + + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; + public function profile() { return $this->belongsTo(Profile::class); @@ -43,6 +52,11 @@ class Status extends Model return url($path); } + public function editUrl() + { + return $this->url() . '/edit'; + } + public function mediaUrl() { $media = $this->firstMedia(); diff --git a/app/User.php b/app/User.php index 33297e481..38edc3e9d 100644 --- a/app/User.php +++ b/app/User.php @@ -3,11 +3,19 @@ namespace App; use Illuminate\Notifications\Notifiable; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { - use Notifiable; + use Notifiable, SoftDeletes; + + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = ['deleted_at']; /** * The attributes that are mass assignable. diff --git a/database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php b/database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php new file mode 100644 index 000000000..a839ddf74 --- /dev/null +++ b/database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php @@ -0,0 +1,58 @@ +softDeletes(); + }); + + Schema::table('likes', function ($table) { + $table->softDeletes(); + }); + + Schema::table('media', function ($table) { + $table->softDeletes(); + }); + + Schema::table('mentions', function ($table) { + $table->softDeletes(); + }); + + Schema::table('notifications', function ($table) { + $table->softDeletes(); + }); + + Schema::table('profiles', function ($table) { + $table->softDeletes(); + }); + + Schema::table('statuses', function ($table) { + $table->softDeletes(); + }); + + Schema::table('users', function ($table) { + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} From 231884c770e0371ad2f02f9f0f91e0573cd2a309 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 18:54:27 -0600 Subject: [PATCH 5/6] Update view entity encoding --- app/Http/Controllers/CommentController.php | 4 +-- app/Http/Controllers/StatusController.php | 2 +- resources/views/status/show.blade.php | 39 +++++++++++++++++++--- resources/views/status/template.blade.php | 9 ++--- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 1ec7bbf4d..8b8eded8e 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -34,8 +34,8 @@ class CommentController extends Controller $reply = new Status(); $reply->profile_id = $profile->id; - $reply->caption = $comment; - $reply->rendered = e($comment); + $reply->caption = e(strip_tags($comment)); + $reply->rendered = $comment; $reply->in_reply_to_id = $status->id; $reply->in_reply_to_profile_id = $status->profile_id; $reply->save(); diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 1ce080245..704beea6c 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -47,7 +47,7 @@ class StatusController extends Controller $status = new Status; $status->profile_id = $profile->id; - $status->caption = $request->caption; + $status->caption = strip_tags($request->caption); $status->is_nsfw = $cw; $status->save(); diff --git a/resources/views/status/show.blade.php b/resources/views/status/show.blade.php index 80e7e41d3..8d2e27d67 100644 --- a/resources/views/status/show.blade.php +++ b/resources/views/status/show.blade.php @@ -16,17 +16,46 @@
- @if($status->is_nsfw) + @if($status->is_nsfw && $status->media_count == 1)

NSFW / Hidden Image -
+

- @else - + @elseif(!$status->is_nsfw && $status->media_count == 1) +
+ +
+ @elseif($status->is_nsfw && $status->media_count > 1) + + @elseif(!$status->is_nsfw && $status->media_count > 1) + @endif
@@ -51,7 +80,7 @@ @foreach($status->comments->reverse()->take(10) as $item)

{{$item->profile->username}} - {!!$item->rendered!!} {{$item->created_at->diffForHumans(null, true, true ,true)}} + {!! $item->rendered ?? e($item->caption) !!} {{$item->created_at->diffForHumans(null, true, true ,true)}}

@endforeach
diff --git a/resources/views/status/template.blade.php b/resources/views/status/template.blade.php index 2e56e6ee5..7a3910887 100644 --- a/resources/views/status/template.blade.php +++ b/resources/views/status/template.blade.php @@ -15,6 +15,7 @@ Embed @if(Auth::check()) @if(Auth::user()->profile->id === $item->profile->id || Auth::user()->is_admin == true) + Edit
@csrf @@ -32,13 +33,13 @@

NSFW / Hidden Image - +

@else - + @endif @@ -84,7 +85,7 @@ {{$status->profile->username}} - {!!$status->rendered!!} + {!! $item->rendered ?? e($item->caption) !!} {{$status->created_at->diffForHumans(null, true, true, true)}} @@ -95,7 +96,7 @@ @foreach($item->comments->reverse()->take(3) as $comment)

{{$comment->profile->username}} - {{ str_limit($comment->caption, 125) }} + {!! str_limit($item->rendered ?? e($item->caption), 150) !!}

@endforeach @endif From 596f335dc6ddfb909b3233568590016eed6e42d1 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 19:47:08 -0600 Subject: [PATCH 6/6] Update StatusEntityLexer --- app/Jobs/StatusPipeline/StatusEntityLexer.php | 78 +++++++++++++++---- 1 file changed, 62 insertions(+), 16 deletions(-) diff --git a/app/Jobs/StatusPipeline/StatusEntityLexer.php b/app/Jobs/StatusPipeline/StatusEntityLexer.php index c1d09ccb7..c9dff4d59 100644 --- a/app/Jobs/StatusPipeline/StatusEntityLexer.php +++ b/app/Jobs/StatusPipeline/StatusEntityLexer.php @@ -6,21 +6,28 @@ use Cache; use App\{ Hashtag, Media, + Mention, + Profile, Status, StatusHashtag }; use App\Util\Lexer\Hashtag as HashtagLexer; +use App\Util\Lexer\{Autolink, Extractor}; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use App\Jobs\MentionPipeline\MentionPipeline; class StatusEntityLexer implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $status; + protected $entities; + protected $autolink; + /** * Create a new job instance. * @@ -39,22 +46,40 @@ class StatusEntityLexer implements ShouldQueue public function handle() { $status = $this->status; - $this->parseHashtags(); + $this->parseEntities(); } - public function parseHashtags() + public function parseEntities() + { + $this->extractEntities(); + } + + public function extractEntities() + { + $this->entities = Extractor::create()->extract($this->status->caption); + $this->autolinkStatus(); + } + + public function autolinkStatus() + { + $this->autolink = Autolink::create()->autolink($this->status->caption); + $this->storeEntities(); + } + + public function storeEntities() { $status = $this->status; - $text = e($status->caption); - $tags = HashtagLexer::getHashtags($text); - $rendered = $text; - if(count($tags) > 0) { - $rendered = HashtagLexer::replaceHashtagsWithLinks($text); - } - $status->rendered = $rendered; + $this->storeHashtags(); + $this->storeMentions(); + $status->rendered = $this->autolink; + $status->entities = json_encode($this->entities); $status->save(); - - Cache::forever('post.' . $status->id, $status); + } + + public function storeHashtags() + { + $tags = array_unique($this->entities['hashtags']); + $status = $this->status; foreach($tags as $tag) { $slug = str_slug($tag); @@ -64,11 +89,32 @@ class StatusEntityLexer implements ShouldQueue ['slug' => $slug] ); - $stag = new StatusHashtag; - $stag->status_id = $status->id; - $stag->hashtag_id = $htag->id; - $stag->save(); + StatusHashtag::firstOrCreate( + ['status_id' => $status->id], + ['hashtag_id' => $htag->id] + ); } - } + + public function storeMentions() + { + $mentions = array_unique($this->entities['mentions']); + $status = $this->status; + + foreach($mentions as $mention) { + $mentioned = Profile::whereUsername($mention)->first(); + + if(empty($mentioned) || !isset($mentioned->id)) { + continue; + } + + $m = new Mention; + $m->status_id = $status->id; + $m->profile_id = $mentioned->id; + $m->save(); + + MentionPipeline::dispatch($status, $m); + } + } + }