implemented pinned posts
This commit is contained in:
parent
f67907176f
commit
1bf6eb7d94
@ -148,4 +148,23 @@ class ActionsPost
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public static function pin_post (Actor $actor, Note $note)
|
||||
{
|
||||
$client = new Client ();
|
||||
|
||||
try
|
||||
{
|
||||
$response = $client->post ($actor->outbox, [
|
||||
"json" => [
|
||||
"type" => "Pin",
|
||||
"object" => $note->note_id,
|
||||
]
|
||||
]);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
return ["error" => "Could not connect to server: " . $e->getMessage ()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,15 @@ use App\Models\User;
|
||||
use App\Models\Actor;
|
||||
use App\Models\Activity;
|
||||
use App\Models\Follow;
|
||||
use App\Models\Note;
|
||||
use App\Models\ProfilePin;
|
||||
|
||||
use App\Types\TypeOrderedCollection;
|
||||
use App\Types\TypeNote;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
use App\Types\TypeOrderedCollection;
|
||||
|
||||
class APActorController extends Controller
|
||||
{
|
||||
public function user (User $user)
|
||||
@ -31,7 +34,7 @@ class APActorController extends Controller
|
||||
$followers = Actor::whereIn ("id", $follower_ids->pluck ("actor")->toArray ());
|
||||
|
||||
$ordered_collection = new TypeOrderedCollection ();
|
||||
$ordered_collection->collection = $followers->get ()->pluck ("actor")->toArray ();
|
||||
$ordered_collection->collection = $followers->get ()->pluck ("actor_id")->toArray ();
|
||||
$ordered_collection->url = route ("ap.followers", $user->name);
|
||||
$ordered_collection->page_size = 10;
|
||||
|
||||
@ -49,7 +52,7 @@ class APActorController extends Controller
|
||||
$following = Actor::whereIn ("id", $following_ids->pluck ("object")->toArray ());
|
||||
|
||||
$ordered_collection = new TypeOrderedCollection ();
|
||||
$ordered_collection->collection = $following->get ()->pluck ("object")->toArray ();
|
||||
$ordered_collection->collection = $following->get ()->pluck ("actor_id")->toArray ();
|
||||
$ordered_collection->url = route ("ap.following", $user->name);
|
||||
$ordered_collection->page_size = 10;
|
||||
|
||||
@ -60,4 +63,28 @@ class APActorController extends Controller
|
||||
|
||||
return response ()->json ($ordered_collection->build_response_main ())->header ("Content-Type", "application/activity+json");
|
||||
}
|
||||
|
||||
public function featured (User $user)
|
||||
{
|
||||
$featured_ids = ProfilePin::where ("actor_id", $user->actor->id)->pluck ("note_id")->toArray ();
|
||||
$notes = Note::whereIn ("id", $featured_ids)->get ();
|
||||
|
||||
$collection = [];
|
||||
foreach ($notes as $note)
|
||||
{
|
||||
$collection[] = TypeNote::build_response ($note);
|
||||
}
|
||||
|
||||
$ordered_collection = new TypeOrderedCollection ();
|
||||
$ordered_collection->collection = $collection;
|
||||
$ordered_collection->url = route ("ap.featured", $user->name);
|
||||
$ordered_collection->page_size = 10;
|
||||
|
||||
if (request ()->has ("page")) {
|
||||
$page = request ()->input ("page");
|
||||
return response ()->json ($ordered_collection->build_response_for_page ($page))->header ("Content-Type", "application/activity+json");
|
||||
}
|
||||
|
||||
return response ()->json ($ordered_collection->build_response_main ())->header ("Content-Type", "application/activity+json");
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use App\Types\TypeActivity;
|
||||
use App\Types\TypeNote;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ProfilePin;
|
||||
|
||||
class APInstanceInboxController extends Controller
|
||||
{
|
||||
@ -32,6 +33,14 @@ class APInstanceInboxController extends Controller
|
||||
return $this->handle_announce ($activity);
|
||||
break;
|
||||
|
||||
case "Add":
|
||||
return $this->handle_add ($activity);
|
||||
break;
|
||||
|
||||
case "Remove":
|
||||
return $this->handle_remove ($activity);
|
||||
break;
|
||||
|
||||
case "Undo":
|
||||
return $this->handle_undo ($activity);
|
||||
break;
|
||||
@ -87,6 +96,50 @@ class APInstanceInboxController extends Controller
|
||||
return response ()->json (["status" => "ok"]);
|
||||
}
|
||||
|
||||
public function handle_add ($activity)
|
||||
{
|
||||
$actor = TypeActor::actor_exists_or_obtain ($activity ["actor"]);
|
||||
if (!$actor)
|
||||
return response ()->json (["status" => "error"]);
|
||||
|
||||
if ($activity["target"] != $actor->featured)
|
||||
// For now we only support adding notes to the featured actor
|
||||
return response ()->json (["error" => "not implemented"], 501);
|
||||
|
||||
$note = TypeNote::note_exists ($activity ["object"]);
|
||||
if (!$note)
|
||||
$note = TypeNote::obtain_external ($activity ["object"]);
|
||||
|
||||
$pin_exists = ProfilePin::where ("actor_id", $actor->id)->where ("note_id", $note->id)->first ();
|
||||
if ($pin_exists)
|
||||
return response ()->json (["status" => "ok"]);
|
||||
|
||||
ProfilePin::create ([
|
||||
"actor_id" => $actor->id,
|
||||
"note_id" => $note->id
|
||||
]);
|
||||
|
||||
return response ()->json (["status" => "ok"]);
|
||||
}
|
||||
|
||||
public function handle_remove ($activity)
|
||||
{
|
||||
$actor = TypeActor::actor_exists_or_obtain ($activity ["actor"]);
|
||||
if (!$actor)
|
||||
return response ()->json (["status" => "error"]);
|
||||
|
||||
if ($activity ["target"] != $actor->featured)
|
||||
// For now we only support removing notes from the featured actor
|
||||
return response ()->json (["error" => "not implemented"], 501);
|
||||
|
||||
$note = TypeNote::note_exists ($activity ["object"]);
|
||||
$pin_exists = ProfilePin::where ("actor_id", $actor->id)->where ("note_id", $note->id)->first ();
|
||||
if (!$pin_exists)
|
||||
return response ()->json (["status" => "ok"]);
|
||||
|
||||
$pin_exists->delete ();
|
||||
}
|
||||
|
||||
public function handle_undo ($activity)
|
||||
{
|
||||
return response ()->json (ActionsActivity::activity_undo($activity));
|
||||
@ -130,11 +183,11 @@ class APInstanceInboxController extends Controller
|
||||
|
||||
public function handle_update ($activity)
|
||||
{
|
||||
if (TypeActivity::activity_exists ($activity ["id"]))
|
||||
return response ()->json (["status" => "ok"]);
|
||||
|
||||
$activity ["activity_id"] = $activity ["id"];
|
||||
$new_activity = Activity::create ($activity);
|
||||
if (!TypeActivity::activity_exists ($activity ["id"]))
|
||||
{
|
||||
$activity ["activity_id"] = $activity ["id"];
|
||||
$new_activity = Activity::create ($activity);
|
||||
}
|
||||
|
||||
$object = $activity ["object"];
|
||||
|
||||
|
@ -23,6 +23,7 @@ use Illuminate\Http\Request;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ProfilePin;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class APOutboxController extends Controller
|
||||
@ -60,6 +61,10 @@ class APOutboxController extends Controller
|
||||
return $this->handle_boost ($user, $request->get ("object"));
|
||||
break;
|
||||
|
||||
case "Pin":
|
||||
return $this->handle_pin ($user, $request->get ("object"));
|
||||
break;
|
||||
|
||||
case "Post":
|
||||
return $this->handle_post ($user, $request);
|
||||
break;
|
||||
@ -295,6 +300,46 @@ class APOutboxController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
public function handle_pin (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_pinned = $object->is_pinned ($actor);
|
||||
if ($already_pinned)
|
||||
{
|
||||
$pin_activity = $already_pinned->activity;
|
||||
$remove_activity = TypeActivity::craft_remove ($actor, $object->note_id, $actor->featured);
|
||||
|
||||
$response = TypeActivity::post_to_instances ($remove_activity, $actor);
|
||||
|
||||
$pin_exists = ProfilePin::where ("note_id", $object->id)
|
||||
->where ("actor_id", $actor->id)
|
||||
->first ();
|
||||
if ($pin_exists)
|
||||
$pin_exists->delete ();
|
||||
|
||||
return [
|
||||
"success" => "unpinned"
|
||||
];
|
||||
}
|
||||
|
||||
$pin_activity = TypeActivity::craft_add ($actor, $object->note_id, $actor->featured);
|
||||
$pin = ProfilePin::create ([
|
||||
"activity_id" => $pin_activity->id,
|
||||
"actor_id" => $actor->id,
|
||||
"note_id" => $object->id,
|
||||
]);
|
||||
|
||||
$response = TypeActivity::post_to_instances ($pin_activity, $actor);
|
||||
|
||||
return [
|
||||
"success" => "pinned"
|
||||
];
|
||||
}
|
||||
|
||||
public function handle_post (User $user, $request)
|
||||
{
|
||||
$actor = $user->actor ()->first ();
|
||||
|
@ -96,6 +96,19 @@ class PostController extends Controller
|
||||
return back ()->with ("success", "Post boosted successfully.");
|
||||
}
|
||||
|
||||
public function pin (Note $note)
|
||||
{
|
||||
if (!auth ()->check ())
|
||||
return back ()->with ("error", "You need to be logged in to pin a post.");
|
||||
|
||||
$user = auth ()->user ();
|
||||
$actor = $user->actor ()->first ();
|
||||
|
||||
$response = ActionsPost::pin_post ($actor, $note);
|
||||
|
||||
return back ()->with ("success", "Post pinned successfully.");
|
||||
}
|
||||
|
||||
public function delete (Note $note)
|
||||
{
|
||||
$actor = auth ()->user ()->actor ()->first ();
|
||||
|
@ -25,6 +25,8 @@ class Actor extends Model
|
||||
"followers",
|
||||
|
||||
"liked",
|
||||
"featured",
|
||||
"featured_tags",
|
||||
|
||||
"inbox",
|
||||
"outbox",
|
||||
@ -55,6 +57,12 @@ class Actor extends Model
|
||||
return $this->belongsTo (User::class);
|
||||
}
|
||||
|
||||
public function get_pinned_posts ()
|
||||
{
|
||||
$pinned = $this->hasMany (ProfilePin::class, "actor_id")->orderBy ("created_at", "desc")->get ();
|
||||
return Note::whereIn ("id", $pinned->pluck ("note_id"))->get ();
|
||||
}
|
||||
|
||||
public function get_posts ()
|
||||
{
|
||||
$posts = $this->hasMany (Note::class, "actor_id")->orderBy ("created_at", "desc")->get ();
|
||||
|
@ -61,4 +61,9 @@ class Note extends Model
|
||||
{
|
||||
return $this->hasMany (NoteAttachment::class);
|
||||
}
|
||||
|
||||
public function is_pinned (Actor $actor)
|
||||
{
|
||||
return ProfilePin::where ("actor_id", $actor->id)->where ("note_id", $this->id)->first ();
|
||||
}
|
||||
}
|
||||
|
14
app/Models/ProfilePin.php
Normal file
14
app/Models/ProfilePin.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProfilePin extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
"activity_id",
|
||||
"note_id",
|
||||
"actor_id"
|
||||
];
|
||||
}
|
@ -145,6 +145,32 @@ class TypeActivity {
|
||||
return $announce_activity;
|
||||
}
|
||||
|
||||
public static function craft_add (Actor $actor, $object, $target)
|
||||
{
|
||||
$add_activity = new Activity ();
|
||||
$add_activity->activity_id = env ("APP_URL") . "/activity/" . uniqid ();
|
||||
$add_activity->type = "Add";
|
||||
$add_activity->actor = $actor->actor_id;
|
||||
$add_activity->object = $object;
|
||||
$add_activity->target = $target;
|
||||
$add_activity->save ();
|
||||
|
||||
return $add_activity;
|
||||
}
|
||||
|
||||
public static function craft_remove (Actor $actor, $object, $target)
|
||||
{
|
||||
$remove_activity = new Activity ();
|
||||
$remove_activity->activity_id = env ("APP_URL") . "/activity/" . uniqid ();
|
||||
$remove_activity->type = "Remove";
|
||||
$remove_activity->actor = $actor->actor_id;
|
||||
$remove_activity->object = $object;
|
||||
$remove_activity->target = $target;
|
||||
$remove_activity->save ();
|
||||
|
||||
return $remove_activity;
|
||||
}
|
||||
|
||||
public static function get_private_key (Actor $actor)
|
||||
{
|
||||
return openssl_get_privatekey ($actor->private_key);
|
||||
@ -217,6 +243,9 @@ class TypeActivity {
|
||||
|
||||
public static function post_to_instances (Activity $activity, Actor $source)
|
||||
{
|
||||
Log::info ("posting activity to instances");
|
||||
Log::info (json_encode (TypeActivity::craft_response ($activity)));
|
||||
|
||||
$instances = Instance::all ();
|
||||
foreach ($instances as $instance)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ namespace App\Types;
|
||||
use App\Models\User;
|
||||
use App\Models\Actor;
|
||||
use App\Models\Instance;
|
||||
use App\Models\ProfilePin;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@ -43,6 +44,8 @@ class TypeActor {
|
||||
"followers" => $app_url . "/ap/v1/user/" . $user->name . "/followers",
|
||||
|
||||
"liked" => $app_url . "/ap/v1/user/" . $user->name . "/liked",
|
||||
"featured" => $app_url . "/ap/v1/user/" . $user->name . "/collections/featured",
|
||||
"featured_tags" => $app_url . "/ap/v1/user/" . $user->name . "/collections/featured/tags",
|
||||
|
||||
"inbox" => $app_url . "/ap/v1/user/" . $user->name . "/inbox",
|
||||
"outbox" => $app_url . "/ap/v1/user/" . $user->name . "/outbox",
|
||||
@ -63,7 +66,17 @@ class TypeActor {
|
||||
$response = [
|
||||
"@context" => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1"
|
||||
"https://w3id.org/security/v1",
|
||||
[
|
||||
"featured" => [
|
||||
"@id" => "http://joinmastodon.org/ns#featured",
|
||||
"@type" => "@id"
|
||||
],
|
||||
"featuredTags" => [
|
||||
"@id" => "http://joinmastodon.org/ns#featuredTags",
|
||||
"@type" => "@id"
|
||||
]
|
||||
]
|
||||
],
|
||||
"id" => $actor->actor_id,
|
||||
"type" => $actor->type,
|
||||
@ -72,6 +85,8 @@ class TypeActor {
|
||||
"followers" => $actor->followers,
|
||||
|
||||
"liked" => $actor->liked,
|
||||
"featured" => $actor->featured,
|
||||
"featuredTags" => $actor->featured_tags,
|
||||
|
||||
"inbox" => $actor->inbox,
|
||||
"outbox" => $actor->outbox,
|
||||
@ -163,6 +178,8 @@ class TypeActor {
|
||||
$actor->followers = $request['followers'] ?? '';
|
||||
|
||||
$actor->liked = $request['liked'] ?? '';
|
||||
$actor->featured = $request['featured'] ?? '';
|
||||
$actor->featured_tags = $request['featuredTags'] ?? '';
|
||||
|
||||
$actor->inbox = $request['inbox'] ?? '';
|
||||
$actor->outbox = $request['outbox'] ?? '';
|
||||
@ -188,6 +205,27 @@ class TypeActor {
|
||||
$instance->save ();
|
||||
}
|
||||
|
||||
$featured_items = TypeActor::actor_process_featured ($actor);
|
||||
ProfilePin::where ("actor_id", $actor->id)->delete ();
|
||||
|
||||
foreach ($featured_items as $item)
|
||||
{
|
||||
if ($item ["type"] == "Note")
|
||||
{
|
||||
$note = TypeNote::note_exists ($item ["id"]);
|
||||
if (!$note)
|
||||
$note = TypeNote::obtain_external ($item ["id"]);
|
||||
|
||||
if (!$note)
|
||||
continue;
|
||||
|
||||
ProfilePin::create ([
|
||||
"actor_id" => $actor->id,
|
||||
"note_id" => $note->id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $actor;
|
||||
}
|
||||
|
||||
@ -317,4 +355,83 @@ class TypeActor {
|
||||
return null;
|
||||
return $actor;
|
||||
}
|
||||
|
||||
public static function actor_process_featured (Actor $actor)
|
||||
{
|
||||
$pinned = [];
|
||||
|
||||
if (!$actor->featured)
|
||||
return $pinned;
|
||||
|
||||
return TypeActor::actor_process_ordered_collection ($actor->featured);
|
||||
}
|
||||
|
||||
public static function actor_process_ordered_collection ($collection_link)
|
||||
{
|
||||
$items = [];
|
||||
|
||||
try
|
||||
{
|
||||
$client = new Client ();
|
||||
$response = $client->get ($collection_link, [
|
||||
"headers" => [
|
||||
"Accept" => "application/json"
|
||||
]
|
||||
]);
|
||||
|
||||
$collection = json_decode ($response->getBody ()->getContents (), true);
|
||||
|
||||
if (isset ($collection ["first"]) && isset ($collection ["last"]))
|
||||
{
|
||||
$first = $collection["first"];
|
||||
$last = $collection["last"];
|
||||
|
||||
$current_url = $first;
|
||||
$current_page = 1;
|
||||
do {
|
||||
$items = array_merge ($items, TypeActor::actor_processed_order_collection_page ($current_url));
|
||||
|
||||
$current_page++;
|
||||
$current_url = $collection_link . "?page=" . $current_page;
|
||||
} while ($current_url != $last);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $collection["orderedItems"];
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
Log::error ("TypeActor::actor_process_ordered_collection: " . $e->getMessage ());
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public static function actor_processed_order_collection_page ($page_link)
|
||||
{
|
||||
$items = [];
|
||||
|
||||
try
|
||||
{
|
||||
$client = new Client ();
|
||||
$response = $client->get ($page_link, [
|
||||
"headers" => [
|
||||
"Accept" => "application/json"
|
||||
]
|
||||
]);
|
||||
|
||||
$collection = json_decode ($response->getBody ()->getContents (), true);
|
||||
foreach ($collection["orderedItems"] as $item)
|
||||
{
|
||||
$items[] = $item;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
Log::error ("TypeActor::actor_processed_order_collection_page: " . $e->getMessage ());
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
|
@ -168,6 +168,11 @@ class TypeNote
|
||||
$note->in_reply_to = $parent->note_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset ($request ["replies"]))
|
||||
{
|
||||
// TODO: Handle replies
|
||||
}
|
||||
}
|
||||
|
||||
public static function create_from_request ($request, Activity $activity, Actor $actor)
|
||||
|
@ -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::table('actors', function (Blueprint $table) {
|
||||
$table->string ("featured")->nullable ();
|
||||
$table->string ("featured_tags")->nullable ();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('actors', function (Blueprint $table) {
|
||||
$table->dropColumn ("featured");
|
||||
$table->dropColumn ("featured_tags");
|
||||
});
|
||||
}
|
||||
};
|
@ -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('profile_pins', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId ("activity_id")->nullable ()->constrained ()->onDelete ("cascade");
|
||||
$table->foreignId ("note_id")->constrained ()->onDelete ("cascade");
|
||||
$table->foreignId ("actor_id")->constrained ()->onDelete ("cascade");
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('profile_pins');
|
||||
}
|
||||
};
|
@ -40,6 +40,7 @@
|
||||
<div class="col right">
|
||||
<h1 class="title">{{ $actor->name }}'s Post</h1>
|
||||
@if (auth ()->check () && auth ()->user ()->is ($actor->user))
|
||||
<div class="buttons" style="display: flex; gap: 5px;">
|
||||
<form action="#" method="POST">
|
||||
@csrf
|
||||
@method("DELETE")
|
||||
@ -48,6 +49,12 @@
|
||||
</a>
|
||||
<button type="submit">Delete</button>
|
||||
</form>
|
||||
|
||||
<form action="{{ route ('posts.pin', [ 'note' => $note ]) }}" method="POST">
|
||||
@csrf
|
||||
<button type="submit">{{ $note->is_pinned ($actor) ? "Unpin" : "Pin" }}</button>
|
||||
</form>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($note->in_reply_to)
|
||||
|
@ -320,6 +320,19 @@
|
||||
|
||||
<br>
|
||||
|
||||
@if ($actor->get_pinned_posts ()->count () > 0)
|
||||
<table class="comments-table" cellspacing="0" cellpadding="3" bordercollor="#ffffff" border="1">
|
||||
<tbody>
|
||||
<p><b>Pinned</b></p>
|
||||
@foreach ($actor->get_pinned_posts () as $post)
|
||||
<x-comment_block :post="$post" />
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
@endif
|
||||
|
||||
<table class="comments-table" cellspacing="0" cellpadding="3" bordercollor="#ffffff" border="1">
|
||||
<tbody>
|
||||
@foreach ($actor->get_posts () as $post)
|
||||
|
@ -23,6 +23,7 @@ Route::prefix ("/ap/v1")->group (function () {
|
||||
Route::post ("/user/{user:name}/outbox", [ APOutboxController::class, "outbox" ])->name ("ap.outbox");
|
||||
Route::get ("/user/{user:name}/followers", [ APActorController::class, "followers" ])->name ("ap.followers");
|
||||
Route::get ("/user/{user:name}/following", [ APActorController::class, "following" ])->name ("ap.following");
|
||||
Route::get ("/user/{user:name}/collections/featured", [ APActorController::class, "featured" ])->name ("ap.featured");
|
||||
Route::get ("/user/{user:name}", [ APActorController::class, "user" ])->name ("ap.user");
|
||||
|
||||
// notes
|
||||
|
@ -34,6 +34,7 @@ Route::middleware ("update_online")->group (function () {
|
||||
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::post ("/post/{note}/pin", [ PostController::class, "pin" ])->name ("posts.pin")->middleware ("auth");
|
||||
Route::get ("/post/{note}", [ PostController::class, "show" ])->name ("posts.show");
|
||||
Route::delete ("/post/{note}", [ PostController::class, "delete" ])->name ("posts.delete")->middleware ("auth");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user