From 61b272625bc1daef7a527f6f29bc69f02fe45d53 Mon Sep 17 00:00:00 2001 From: Ghostie Date: Mon, 6 Jan 2025 21:45:01 -0500 Subject: [PATCH] now posts can be boosted locally --- TODO.md | 8 +++- app/Actions/ActionsPost.php | 21 +++++++++ .../Controllers/AP/APOutboxController.php | 45 +++++++++++++++++++ app/Http/Controllers/HomeController.php | 6 +-- app/Http/Controllers/PostController.php | 13 ++++++ app/Models/Actor.php | 7 ++- app/Models/Note.php | 5 +++ app/Types/TypeActivity.php | 12 +++++ app/Types/TypeNote.php | 4 +- resources/views/posts/show.blade.php | 10 ++++- routes/web.php | 1 + 11 files changed, 122 insertions(+), 10 deletions(-) diff --git a/TODO.md b/TODO.md index 46e7dd2..e8a0f62 100644 --- a/TODO.md +++ b/TODO.md @@ -14,10 +14,14 @@ - [x] Likes - [x] Comments - [x] Boosts - - [ ] Local Boost + - [x] Local Boost - [x] Tags + - [ ] Mentions + - [ ] Local mentions + - [ ] Private post - [ ] Pinned Posts - [ ] Nodeinfo + - [ ] Notifications - [-] Social features - [x] Profile @@ -37,7 +41,7 @@ - [x] Delete posts - [x] Like posts - [x] Comment posts - - [ ] Boost posts + - [x] Boost posts - [x] Post tags - [ ] Blog - [ ] Bulletin diff --git a/app/Actions/ActionsPost.php b/app/Actions/ActionsPost.php index 534a76b..7016d27 100644 --- a/app/Actions/ActionsPost.php +++ b/app/Actions/ActionsPost.php @@ -127,4 +127,25 @@ class ActionsPost return $response; } + + public static function boost_post (Actor $actor, Note $note) + { + $client = new Client (); + + try + { + $response = $client->post ($actor->outbox, [ + "json" => [ + "type" => "Boost", + "object" => $note->note_id, + ] + ]); + } + catch (\Exception $e) + { + return ["error" => "Could not connect to server: " . $e->getMessage ()]; + } + + return $response; + } } diff --git a/app/Http/Controllers/AP/APOutboxController.php b/app/Http/Controllers/AP/APOutboxController.php index 1028a1d..4dbf746 100644 --- a/app/Http/Controllers/AP/APOutboxController.php +++ b/app/Http/Controllers/AP/APOutboxController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\AP; use App\Models\Note; use App\Models\NoteAttachment; +use App\Models\Announcement; use App\Models\User; use App\Models\Actor; use App\Models\Activity; @@ -55,6 +56,10 @@ class APOutboxController extends Controller return $this->handle_like ($user, $request->get ("object")); break; + case "Boost": + return $this->handle_boost ($user, $request->get ("object")); + break; + case "Post": return $this->handle_post ($user, $request); break; @@ -250,6 +255,46 @@ class APOutboxController extends Controller ]; } + public function handle_boost (User $user, $object) + { + $object = Note::where ("note_id", $object)->first (); + if (!$object) + return response ()->json ([ "error" => "object not found" ], 404); + + $actor = $user->actor ()->first (); + $already_boosted = $actor->boosted_note ($object); + if ($already_boosted) + { + $boost_activity = $already_boosted->activity; + $undo_activity = TypeActivity::craft_undo ($boost_activity, $actor); + + $response = TypeActivity::post_to_instances ($undo_activity, $actor); + + $boost_exists = Announcement::where ("note_id", $object->id) + ->where ("actor_id", $actor->id) + ->first (); + if ($boost_exists) + $boost_exists->delete (); + + return [ + "success" => "unboosted" + ]; + } + + $boost_activity = TypeActivity::craft_announce ($actor, $object->note_id); + $announcement = Announcement::create ([ + "activity_id" => $boost_activity->id, + "actor_id" => $actor->id, + "note_id" => $object->id, + ]); + + $response = TypeActivity::post_to_instances ($boost_activity, $actor); + + return [ + "success" => "boosted" + ]; + } + public function handle_post (User $user, $request) { $actor = $user->actor ()->first (); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index c6e29f0..1f8b4f6 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -93,12 +93,12 @@ class HomeController extends Controller } } - $local_users = User::where ("name", "like", "%$query%")->get (); - $actors = Actor::where ("name", "like", "%$query%")->orWhere ("preferredUsername", "like", "%$query%")->get (); + $local_users = User::where ("name", "like", "%$query%")->orderBy ("created_at", "desc")->get (); + $actors = Actor::where ("name", "like", "%$query%")->orWhere ("preferredUsername", "like", "%$query%")->orderBy ("created_at", "desc")->get (); $users = $local_users->merge ($actors)->take (10); $hashtags = Hashtag::withCount ("get_notes")->where ("name", "like", "%$query%")->orderBy ("get_notes_count", "desc")->take (16)->get ()->shuffle (); - $posts = Note::where ("content", "like", "%$query%")->paginate (10); + $posts = Note::where ("content", "like", "%$query%")->orderBy ("created_at", "desc")->paginate (10); return view ("search", compact ("users", "hashtags", "posts")); } diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/PostController.php index cef27d3..1fdd2a5 100644 --- a/app/Http/Controllers/PostController.php +++ b/app/Http/Controllers/PostController.php @@ -83,6 +83,19 @@ class PostController extends Controller return back ()->with ("success", "Post liked successfully."); } + public function boost (Note $note) + { + if (!auth ()->check ()) + return back ()->with ("error", "You need to be logged in to boost a post."); + + $user = auth ()->user (); + $actor = $user->actor ()->first (); + + $response = ActionsPost::boost_post ($actor, $note); + + return back ()->with ("success", "Post boosted successfully."); + } + public function delete (Note $note) { $actor = auth ()->user ()->actor ()->first (); diff --git a/app/Models/Actor.php b/app/Models/Actor.php index 55fc673..e7fb312 100644 --- a/app/Models/Actor.php +++ b/app/Models/Actor.php @@ -3,7 +3,7 @@ namespace App\Models; use App\Models\User; -use App\Models\Activity; +use App\Models\Announcement; use App\Models\Note; use App\Types\TypeActor; @@ -86,4 +86,9 @@ class Actor extends Model { return Like::where ("actor_id", $this->id)->where ("note_id", $note->id)->first (); } + + public function boosted_note (Note $note) + { + return Announcement::where ("actor_id", $this->id)->where ("note_id", $note->id)->first (); + } } diff --git a/app/Models/Note.php b/app/Models/Note.php index f09ea67..b008f60 100644 --- a/app/Models/Note.php +++ b/app/Models/Note.php @@ -36,6 +36,11 @@ class Note extends Model return $this->hasMany (Like::class); } + public function get_boosts () + { + return $this->hasMany (Announcement::class); + } + public function get_replies () { return $this->hasMany (Note::class, "in_reply_to", "note_id"); diff --git a/app/Types/TypeActivity.php b/app/Types/TypeActivity.php index fc9c8bc..1f63515 100644 --- a/app/Types/TypeActivity.php +++ b/app/Types/TypeActivity.php @@ -133,6 +133,18 @@ class TypeActivity { return $like_activity; } + public static function craft_announce (Actor $actor, $id) + { + $announce_activity = new Activity (); + $announce_activity->activity_id = env ("APP_URL") . "/activity/" . uniqid (); + $announce_activity->type = "Announce"; + $announce_activity->actor = $actor->actor_id; + $announce_activity->object = $id; + $announce_activity->save (); + + return $announce_activity; + } + public static function get_private_key (Actor $actor) { return openssl_get_privatekey ($actor->private_key); diff --git a/app/Types/TypeNote.php b/app/Types/TypeNote.php index d960984..f8dc8a2 100644 --- a/app/Types/TypeNote.php +++ b/app/Types/TypeNote.php @@ -118,7 +118,7 @@ class TypeNote foreach ($attachments as $attachment) $attachment->delete (); - if ($request ["attachment"]) + if (isset ($request ["attachment"]) && $request ["attachment"]) { foreach ($request ["attachment"] as $attachment) @@ -135,7 +135,7 @@ class TypeNote } } - if ($request ["tag"]) + if (isset ($request ["tag"]) && $request ["tag"]) { foreach ($request ["tag"] as $tag) { diff --git a/resources/views/posts/show.blade.php b/resources/views/posts/show.blade.php index 439a6f0..ff53c5e 100644 --- a/resources/views/posts/show.blade.php +++ b/resources/views/posts/show.blade.php @@ -70,16 +70,22 @@
@auth -
+
@csrf
+ +
+ @csrf + +
@endauth

- Likes: {{ $note->get_likes ()->count () }} + Likes: {{ $note->get_likes ()->count () }}
+ Boosts: {{ $note->get_boosts ()->count () }}

diff --git a/routes/web.php b/routes/web.php index 75b22cb..9b58aef 100644 --- a/routes/web.php +++ b/routes/web.php @@ -33,6 +33,7 @@ Route::middleware ("update_online")->group (function () { Route::get ("/post/{note}/edit", [ PostController::class, "edit" ])->name ("posts.edit")->middleware ("auth"); Route::post ("/post/{note}/edit", [ PostController::class, "update" ])->middleware ("auth"); Route::post ("/post/{note}/like", [ PostController::class, "like" ])->name ("posts.like")->middleware ("auth"); + Route::post ("/post/{note}/boost", [ PostController::class, "boost" ])->name ("posts.boost")->middleware ("auth"); Route::get ("/post/{note}", [ PostController::class, "show" ])->name ("posts.show"); Route::delete ("/post/{note}", [ PostController::class, "delete" ])->name ("posts.delete")->middleware ("auth");