now boosts are supported

This commit is contained in:
Ghostie 2025-01-05 21:54:54 -05:00
parent c556441b4c
commit 6b9ec6531c
15 changed files with 248 additions and 44 deletions

View File

@ -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)

View File

@ -0,0 +1,33 @@
<?php
namespace App\Actions;
use App\Models\Activity;
use App\Types\TypeActor;
use App\Types\TypeActivity;
class ActionsActivity
{
public static function activity_undo ($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 ["error" => "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",];
}
}

View File

@ -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)

View File

@ -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"]))

View File

@ -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)

View File

@ -0,0 +1,29 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Announcement extends Model
{
protected $fillable = [
"activity_id",
"actor_id",
"note_id"
];
public function activity ()
{
return $this->belongsTo(Activity::class);
}
public function actor ()
{
return $this->belongsTo(Actor::class);
}
public function note ()
{
return $this->belongsTo(Note::class);
}
}

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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)
{
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)
{

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('announcements', function (Blueprint $table) {
$table->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');
}
};

View File

@ -46,7 +46,7 @@
<table class="comments-table" cellspacing="0" cellpadding="3" bordercollor="#ffffff" border="1">
<tbody>
@foreach ($popular_notes as $post)
<x-comment_block :post="$post" :actor="$post->get_actor ()->first ()" />
<x-comment_block :post="$post" />
@endforeach
</tbody>
</table>

View File

@ -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
<td>
<p>
<b>
<time>{{ $post->created_at->diffForHumans () }}</time>
<time>{{ $display_post->created_at->diffForHumans () }}</time>
</b>
</p>
@if ($post->in_reply_to)
@if ($display_post->in_reply_to)
<small>
In response to
<a href="{{ route ('posts.show', [ 'note' => $post->get_parent ()->first ()->id ]) }}">this post</a>
<a href="{{ route ('posts.show', [ 'note' => $display_post->get_parent ()->first ()->id ]) }}">this post</a>
</small>
@endif
<h4>{{ $post->summary }}</h4>
<h4>{{ $display_post->summary }}</h4>
{!! $post->content !!}
{!! $display_post->content !!}
<p>
@foreach ($post->attachments as $attachment)
@foreach ($display_post->attachments as $attachment)
<img loading="lazy" src="{{ $attachment->url }}" alt="{{ $attachment->name }}" width="100">
@endforeach
</p>
<br>
@if ($post->get_replies ()->count () > 0)
@if ($display_post->get_replies ()->count () > 0)
<div class="comment-replies">
@foreach ($post->get_replies ()->get () as $reply)
@foreach ($display_post->get_replies ()->get () as $reply)
<div class="comment-reply">
<h4>{{ $reply->summary }}</h4>
@ -79,7 +87,7 @@ else
</div>
@endif
@if ($post->get_hashtags ()->count () > 0)
@if ($display_post->get_hashtags ()->count () > 0)
<p>
<b>Tags:</b>
@foreach ($post->get_hashtags ()->get () as $hashtag)
@ -93,13 +101,13 @@ else
<hr>
<p>
<b>Likes:</b> {{ $post->get_likes ()->count () }}
<b>Likes:</b> {{ $display_post->get_likes ()->count () }}
</p>
<p>
<b>Replies:</b> {{ $post->get_replies ()->count () }}
<b>Replies:</b> {{ $display_post->get_replies ()->count () }}
</p>
<a href="{{ route ('posts.show', [ 'note' => $post ]) }}">
<a href="{{ route ('posts.show', [ 'note' => $display_post ]) }}">
<button type="button">View</button>
</a>
{{-- @if ($actor->user && auth ()->check () && auth ()->user ()->is ($actor->user))

View File

@ -139,7 +139,7 @@
<table class="comments-table" cellspacing="0" cellpadding="3" bordercollor="#ffffff" border="1">
<tbody>
@foreach (auth ()->user ()->feed () as $post)
<x-comment_block :actor="$post->get_actor ()->first ()" :post="$post" />
<x-comment_block :post="$post" />
@endforeach
</tbody>
</table>

View File

@ -100,7 +100,7 @@
<table class="comments-table" cellspacing="0" cellpadding="3" bordercolor="ffffff" border="1">
<tbody>
@foreach ($note->get_replies ()->get () as $reply)
<x-comment_block :actor="$reply->get_actor ()->first ()" :post="$reply" />
<x-comment_block :post="$reply" />
@endforeach
</tbody>
</table>

View File

@ -303,7 +303,7 @@
</div>
<div class="inner">
<p>
<b>{{ $actor->name }} has <span class="count">{{ count ($actor->posts) }}</span> posts.</b>
<b>{{ $actor->name }} has <span class="count">{{ count ($actor->get_posts ()) }}</span> posts.</b>
</p>
@if (auth ()->user () && auth ()->user ()->is ($user))
@ -314,8 +314,8 @@
<table class="comments-table" cellspacing="0" cellpadding="3" bordercollor="#ffffff" border="1">
<tbody>
@foreach ($actor->posts as $post)
<x-comment_block :actor="$actor" :post="$post" />
@foreach ($actor->get_posts () as $post)
<x-comment_block :post="$post" />
@endforeach
</tbody>
</table>