From 6b9ec6531ccdc9dbaf9d7aeca664835506e7dfaa Mon Sep 17 00:00:00 2001 From: Ghostie Date: Sun, 5 Jan 2025 21:54:54 -0500 Subject: [PATCH] now boosts are supported --- TODO.md | 3 +- app/Actions/ActionsActivity.php | 33 +++++++++ app/Http/Controllers/AP/APInboxController.php | 20 +----- .../AP/APInstanceInboxController.php | 45 ++++++++++++ app/Models/Actor.php | 9 ++- app/Models/Announcement.php | 29 ++++++++ app/Models/User.php | 5 +- app/Types/TypeActor.php | 3 + app/Types/TypeNote.php | 71 +++++++++++++++++-- ...1_06_013945_create_announcements_table.php | 30 ++++++++ resources/views/browse.blade.php | 2 +- .../views/components/comment_block.blade.php | 32 +++++---- resources/views/home_loggedin.blade.php | 2 +- resources/views/posts/show.blade.php | 2 +- resources/views/users/profile.blade.php | 6 +- 15 files changed, 248 insertions(+), 44 deletions(-) create mode 100644 app/Actions/ActionsActivity.php create mode 100644 app/Models/Announcement.php create mode 100644 database/migrations/2025_01_06_013945_create_announcements_table.php diff --git a/TODO.md b/TODO.md index 59f571a..eb681d4 100644 --- a/TODO.md +++ b/TODO.md @@ -50,4 +50,5 @@ - [ ] Announcements - [ ] Fixes - - [ ] Fix that weird json encoding in the object field of an activity + - [x] Fix that weird json encoding in the object field of an activity + - [ ] The profile attachments are not working, they are not being federalised somehow (the interests thingy) diff --git a/app/Actions/ActionsActivity.php b/app/Actions/ActionsActivity.php new file mode 100644 index 0000000..6fda905 --- /dev/null +++ b/app/Actions/ActionsActivity.php @@ -0,0 +1,33 @@ + "Activity not found",]; + + $child_activity = Activity::where ("activity_id", $child_activity_id)->first (); + $child_activity->delete (); + + // TODO: Should Undo create a new activity in database? + return ["success" => "Activity undone",]; + } +} diff --git a/app/Http/Controllers/AP/APInboxController.php b/app/Http/Controllers/AP/APInboxController.php index 579c8df..6f4b1a4 100644 --- a/app/Http/Controllers/AP/APInboxController.php +++ b/app/Http/Controllers/AP/APInboxController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\AP; +use App\Actions\ActionsActivity; use App\Models\User; use App\Models\Actor; use App\Models\Activity; @@ -87,24 +88,7 @@ class APInboxController extends Controller public function handle_undo (User $user, $activity) { - $actor = TypeActor::actor_exists_or_obtain ($activity ["actor"]); - - $child_activity = $activity ["object"]; - $child_activity_id = ""; - - if (is_array ($child_activity)) - $child_activity_id = $child_activity ["id"]; - else - $child_activity_id = $child_activity; - - if (!TypeActivity::activity_exists ($child_activity_id)) - return response ()->json (["error" => "Child activity doesn't exist",], 404); - - $child_activity = Activity::where ("activity_id", $child_activity_id)->first (); - $child_activity->delete (); - - // TODO: Should Undo create a new activity in database? - return response ()->json (["success" => "Activity undone",], 200); + return response ()->json (ActionsActivity::activity_undo ($activity)); } public function handle_like (User $user, $activity) diff --git a/app/Http/Controllers/AP/APInstanceInboxController.php b/app/Http/Controllers/AP/APInstanceInboxController.php index ad0ce25..9c1aff0 100644 --- a/app/Http/Controllers/AP/APInstanceInboxController.php +++ b/app/Http/Controllers/AP/APInstanceInboxController.php @@ -2,11 +2,13 @@ namespace App\Http\Controllers\AP; +use App\Actions\ActionsActivity; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use App\Models\Actor; use App\Models\Activity; +use App\Models\Announcement; use App\Types\TypeActor; use App\Types\TypeActivity; @@ -26,6 +28,14 @@ class APInstanceInboxController extends Controller switch ($activity_type) { + case "Announce": + return $this->handle_announce ($activity); + break; + + case "Undo": + return $this->handle_undo ($activity); + break; + case "Create": return $this->handle_create ($activity); break; @@ -47,6 +57,41 @@ class APInstanceInboxController extends Controller return response ()->json (["status" => "ok"]); } + public function handle_announce ($activity) + { + // we suppose an announce is always a note + $note_exists = TypeNote::note_exists ($activity ["object"]); + if (!$note_exists) + { + $note_exists = TypeNote::obtain_external ($activity ["object"]); + if (!$note_exists) + return response ()->json (["status" => "error"]); + } + + $announcement_exists = TypeActivity::activity_exists ($activity ["id"]); + if ($announcement_exists) + return response ()->json (["status" => "ok"]); + + $announcement_actor = TypeActor::actor_exists_or_obtain ($activity ["actor"]); + if (!$announcement_actor) + return response ()->json (["status" => "error"]); + + $activity["activity_id"] = $activity["id"]; + $ann_act = Activity::create ($activity); + $announcement = Announcement::create ([ + "activity_id" => $ann_act->id, + "actor_id" => $announcement_actor->id, + "note_id" => $note_exists->id + ]); + + return response ()->json (["status" => "ok"]); + } + + public function handle_undo ($activity) + { + return response ()->json (ActionsActivity::activity_undo($activity)); + } + public function handle_create ($activity) { if (TypeActivity::activity_exists ($activity ["id"])) diff --git a/app/Models/Actor.php b/app/Models/Actor.php index 775c2b6..55fc673 100644 --- a/app/Models/Actor.php +++ b/app/Models/Actor.php @@ -53,9 +53,14 @@ class Actor extends Model return $this->belongsTo (User::class); } - public function posts () + public function get_posts () { - return $this->hasMany (Note::class, "actor_id")->orderBy ("created_at", "desc"); + $posts = $this->hasMany (Note::class, "actor_id")->orderBy ("created_at", "desc")->get (); + $announcements = $this->hasMany (Announcement::class, "actor_id")->orderBy ("created_at", "desc")->get (); + + $all = $posts->merge ($announcements)->sortByDesc ("created_at"); + + return $all; } public function create_from_user (User $user) diff --git a/app/Models/Announcement.php b/app/Models/Announcement.php new file mode 100644 index 0000000..38570b6 --- /dev/null +++ b/app/Models/Announcement.php @@ -0,0 +1,29 @@ +belongsTo(Activity::class); + } + + public function actor () + { + return $this->belongsTo(Actor::class); + } + + public function note () + { + return $this->belongsTo(Note::class); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 04cea8d..c4f1c3a 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -148,7 +148,10 @@ class User extends Authenticatable } $notes = Note::whereIn ("actor_id", $friends_id)->orderBy ("created_at", "desc")->get (); + $announcements = Announcement::whereIn ("actor_id", $friends_id)->orderBy ("created_at", "desc")->get (); - return $notes; + $feed = $notes->merge ($announcements)->sortByDesc ("created_at"); + + return $feed; } } diff --git a/app/Types/TypeActor.php b/app/Types/TypeActor.php index 50739ec..85ec99d 100644 --- a/app/Types/TypeActor.php +++ b/app/Types/TypeActor.php @@ -96,6 +96,9 @@ class TypeActor { "url" => $actor->image ], + "published" => $actor->created_at, + "updated" => $actor->updated_at, + "publicKey" => [ "id" => $actor->actor_id . "#main-key", "owner" => $actor->actor_id, diff --git a/app/Types/TypeNote.php b/app/Types/TypeNote.php index 536ddd8..3de56c3 100644 --- a/app/Types/TypeNote.php +++ b/app/Types/TypeNote.php @@ -8,6 +8,8 @@ use App\Models\Actor; use App\Models\Activity; use App\Models\NoteAttachment; +use GuzzleHttp\Client; + use Illuminate\Support\Facades\Log; class TypeNote @@ -78,13 +80,30 @@ class TypeNote return $note; } - public static function update_from_request (Note $note, $request, Activity $activity, Actor $actor) + public static function update_from_request (Note $note, $request, Activity $activity = null, Actor $actor = null) { - $note->activity_id = $activity->id; - $note->actor_id = $actor->id; + if ($activity) + $note->activity_id = $activity->id; + + if ($actor) + $note->actor_id = $actor->id; + else + { + $actor = TypeActor::actor_exists ($request ["attributedTo"]); + if (!$actor) + { + $actor = TypeActor::obtain_actor_info($request ["attributedTo"]); + if (!$actor) + { + Log::error ("TypeNote::update_from_request: Could not obtain actor info."); + } + } + + $note->actor_id = $actor->id; + } $note->note_id = $request["id"] ?? null; - $note->in_reply_to = $request["inReplyTo"] ?? null; + // $note->in_reply_to = $request["inReplyTo"] ?? null; $note->summary = $request["summary"] ?? null; $note->url = $request["url"] ?? null; $note->attributedTo = $request["attributedTo"] ?? null; @@ -116,6 +135,9 @@ class TypeNote { foreach ($request ["tag"] as $tag) { + if ($tag ["type"] != "Hashtag") + continue; + $tag_name = $tag ["name"]; $hashtag_exists = Hashtag::where ("name", $tag_name)->first (); @@ -131,6 +153,17 @@ class TypeNote $note->get_hashtags ()->attach ($hashtag->id); } } + + if ($request ["inReplyTo"]) + { + $parent_exists = Note::where ("note_id", $request ["inReplyTo"])->first (); + if (!$parent_exists) + { + $parent = TypeNote::obtain_external ($request ["inReplyTo"]); + if ($parent) + $note->in_reply_to = $parent->note_id; + } + } } public static function create_from_request ($request, Activity $activity, Actor $actor) @@ -144,6 +177,36 @@ class TypeNote return $note; } + public static function obtain_external ($note_id) + { + $note = Note::where ("note_id", $note_id)->first (); + if ($note) + return $note; + + try { + $client = new Client (); + $res = $client->request ("GET", $note_id, [ + "headers" => [ + "Accept" => "application/activity+json" + ] + ]); + $body = $res->getBody ()->getContents (); + + $note = Note::create ([ + "note_id" => $note_id + ]); + TypeNote::update_from_request ($note, json_decode ($body, true)); + $note->save (); + } + catch (\Exception $e) + { + Log::error ("TypeNote::obtain_external: " . $e->getMessage ()); + return null; + } + + return $note; + } + // some little functions public static function note_exists ($note_id) { diff --git a/database/migrations/2025_01_06_013945_create_announcements_table.php b/database/migrations/2025_01_06_013945_create_announcements_table.php new file mode 100644 index 0000000..a9f4fe7 --- /dev/null +++ b/database/migrations/2025_01_06_013945_create_announcements_table.php @@ -0,0 +1,30 @@ +id(); + $table->foreignId ("activity_id")->constrained ()->onDelete ('cascade'); + $table->foreignId ('actor_id')->constrained ()->onDelete ('cascade'); + $table->foreignId ("note_id")->constrained ()->onDelete ('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('announcements'); + } +}; diff --git a/resources/views/browse.blade.php b/resources/views/browse.blade.php index c39eea3..bc54212 100644 --- a/resources/views/browse.blade.php +++ b/resources/views/browse.blade.php @@ -46,7 +46,7 @@ @foreach ($popular_notes as $post) - + @endforeach
diff --git a/resources/views/components/comment_block.blade.php b/resources/views/components/comment_block.blade.php index 9c3ce9c..57b5d87 100644 --- a/resources/views/components/comment_block.blade.php +++ b/resources/views/components/comment_block.blade.php @@ -1,6 +1,14 @@ @php $actor_url = ""; +$display_post = null; +if ($post instanceof App\Models\Note) + $display_post = $post; +else if ($post instanceof App\Models\Announcement) + $display_post = $post->note ()->first (); + +$actor = $display_post->get_actor ()->first (); + if ($actor->user_id) $actor_url = route ('users.show', [ 'user_name' => $actor->user->name ]); else @@ -27,32 +35,32 @@ else

- +

- @if ($post->in_reply_to) + @if ($display_post->in_reply_to) In response to - this post + this post @endif -

{{ $post->summary }}

+

{{ $display_post->summary }}

- {!! $post->content !!} + {!! $display_post->content !!}

- @foreach ($post->attachments as $attachment) + @foreach ($display_post->attachments as $attachment) {{ $attachment->name }} @endforeach


- @if ($post->get_replies ()->count () > 0) + @if ($display_post->get_replies ()->count () > 0)
- @foreach ($post->get_replies ()->get () as $reply) + @foreach ($display_post->get_replies ()->get () as $reply)

{{ $reply->summary }}

@@ -79,7 +87,7 @@ else
@endif - @if ($post->get_hashtags ()->count () > 0) + @if ($display_post->get_hashtags ()->count () > 0)

Tags: @foreach ($post->get_hashtags ()->get () as $hashtag) @@ -93,13 +101,13 @@ else


- Likes: {{ $post->get_likes ()->count () }} + Likes: {{ $display_post->get_likes ()->count () }}

- Replies: {{ $post->get_replies ()->count () }} + Replies: {{ $display_post->get_replies ()->count () }}

- + {{-- @if ($actor->user && auth ()->check () && auth ()->user ()->is ($actor->user)) diff --git a/resources/views/home_loggedin.blade.php b/resources/views/home_loggedin.blade.php index 77ebd42..6ad1b2e 100644 --- a/resources/views/home_loggedin.blade.php +++ b/resources/views/home_loggedin.blade.php @@ -139,7 +139,7 @@ @foreach (auth ()->user ()->feed () as $post) - + @endforeach
diff --git a/resources/views/posts/show.blade.php b/resources/views/posts/show.blade.php index 5274ebc..439a6f0 100644 --- a/resources/views/posts/show.blade.php +++ b/resources/views/posts/show.blade.php @@ -100,7 +100,7 @@ @foreach ($note->get_replies ()->get () as $reply) - + @endforeach
diff --git a/resources/views/users/profile.blade.php b/resources/views/users/profile.blade.php index 7c7955a..1227148 100644 --- a/resources/views/users/profile.blade.php +++ b/resources/views/users/profile.blade.php @@ -303,7 +303,7 @@

- {{ $actor->name }} has {{ count ($actor->posts) }} posts. + {{ $actor->name }} has {{ count ($actor->get_posts ()) }} posts.

@if (auth ()->user () && auth ()->user ()->is ($user)) @@ -314,8 +314,8 @@ - @foreach ($actor->posts as $post) - + @foreach ($actor->get_posts () as $post) + @endforeach