Files
BetiX/app/Http/Controllers/DirectMessageController.php
Dolo 0280278978
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
Initialer Laravel Commit für BetiX
2026-04-04 18:01:50 +02:00

199 lines
6.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\DirectMessage;
use App\Models\DirectMessageReport;
use App\Models\Friend;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class DirectMessageController extends Controller
{
private function formatUser(User $u): array
{
return [
'id' => $u->id,
'username' => $u->username,
'name' => $u->name,
'avatar' => $u->avatar,
'avatar_url' => $u->avatar_url,
];
}
private function formatMessage(DirectMessage $m): array
{
return [
'id' => $m->id,
'message' => $m->is_deleted ? null : $m->message,
'sender_id' => $m->sender_id,
'is_deleted' => $m->is_deleted,
'is_read' => $m->is_read,
'created_at' => $m->created_at,
'user' => $m->sender ? $this->formatUser($m->sender) : null,
'reply_to' => $m->replyTo ? [
'id' => $m->replyTo->id,
'message' => $m->replyTo->is_deleted ? null : $m->replyTo->message,
'sender_id' => $m->replyTo->sender_id,
] : null,
];
}
// GET /api/dm/conversations
public function conversations()
{
$me = Auth::id();
$sent = DirectMessage::where('sender_id', $me)->select('receiver_id as partner_id');
$received = DirectMessage::where('receiver_id', $me)->select('sender_id as partner_id');
$partnerIds = $sent->union($received)->pluck('partner_id')->unique()->values();
$conversations = $partnerIds->map(function ($pid) use ($me) {
$partner = User::select('id', 'username', 'name', 'avatar', 'avatar_url')->find($pid);
if (!$partner) return null;
$lastMsg = DirectMessage::where(function ($q) use ($me, $pid) {
$q->where('sender_id', $me)->where('receiver_id', $pid);
})->orWhere(function ($q) use ($me, $pid) {
$q->where('sender_id', $pid)->where('receiver_id', $me);
})->orderByDesc('created_at')->first();
$unread = DirectMessage::where('sender_id', $pid)
->where('receiver_id', $me)
->where('is_read', false)
->count();
return [
'partner' => $this->formatUser($partner),
'last_message' => $lastMsg ? [
'id' => $lastMsg->id,
'message' => $lastMsg->is_deleted ? null : $lastMsg->message,
'sender_id' => $lastMsg->sender_id,
'created_at' => $lastMsg->created_at,
] : null,
'unread_count' => $unread,
];
})->filter()->sortByDesc(fn ($c) => optional($c['last_message'])['created_at'])->values();
return response()->json(['data' => $conversations]);
}
// GET /api/dm/{userId}
public function messages($userId)
{
$me = Auth::id();
$msgs = DirectMessage::where(function ($q) use ($me, $userId) {
$q->where('sender_id', $me)->where('receiver_id', $userId);
})->orWhere(function ($q) use ($me, $userId) {
$q->where('sender_id', $userId)->where('receiver_id', $me);
})
->with(['sender:id,username,name,avatar,avatar_url', 'replyTo'])
->orderBy('created_at')
->limit(100)
->get()
->map(fn ($m) => $this->formatMessage($m));
// Mark as read
DirectMessage::where('sender_id', $userId)
->where('receiver_id', $me)
->where('is_read', false)
->update(['is_read' => true]);
return response()->json(['data' => $msgs]);
}
// POST /api/dm/{userId}
public function send(Request $request, $userId)
{
$me = Auth::id();
$request->validate([
'message' => 'required|string|max:1000',
'reply_to_id' => 'nullable|integer|exists:direct_messages,id',
]);
User::findOrFail($userId);
$areFriends = Friend::where(function ($q) use ($me, $userId) {
$q->where('user_id', $me)->where('friend_id', $userId);
})->orWhere(function ($q) use ($me, $userId) {
$q->where('user_id', $userId)->where('friend_id', $me);
})->where('status', 'accepted')->exists();
if (!$areFriends) {
return response()->json(['error' => 'You must be friends to send messages.'], 403);
}
$msg = DirectMessage::create([
'sender_id' => $me,
'receiver_id' => $userId,
'message' => $request->message,
'reply_to_id' => $request->reply_to_id,
]);
$msg->load(['sender:id,username,name,avatar,avatar_url', 'replyTo']);
return response()->json(['data' => $this->formatMessage($msg)], 201);
}
// POST /api/dm/messages/{id}/report
public function report(Request $request, $messageId)
{
$me = Auth::id();
$request->validate([
'reason' => 'required|string|max:64',
'details' => 'nullable|string|max:500',
]);
$msg = DirectMessage::where(function ($q) use ($me) {
$q->where('sender_id', $me)->orWhere('receiver_id', $me);
})->findOrFail($messageId);
DirectMessageReport::firstOrCreate(
['reporter_id' => $me, 'message_id' => $msg->id],
['reason' => $request->reason, 'details' => $request->details]
);
return response()->json(['ok' => true]);
}
// GET /api/friends
public function friends()
{
$me = Auth::id();
$friends = Friend::where(function ($q) use ($me) {
$q->where('user_id', $me)->orWhere('friend_id', $me);
})->where('status', 'accepted')
->with(['user:id,username,name,avatar,avatar_url', 'friend:id,username,name,avatar,avatar_url'])
->get()
->map(function ($f) use ($me) {
$partner = $f->user_id === $me ? $f->friend : $f->user;
return $partner ? $this->formatUser($partner) : null;
})->filter()->values();
return response()->json(['data' => $friends]);
}
// GET /api/friends/requests
public function friendRequests()
{
$me = Auth::id();
$requests = Friend::where('friend_id', $me)
->where('status', 'pending')
->with('user:id,username,name,avatar,avatar_url')
->orderByDesc('created_at')
->get()
->map(fn ($f) => [
'id' => $f->id,
'from' => $f->user ? $this->formatUser($f->user) : null,
'created_at' => $f->created_at,
])->filter(fn ($r) => $r['from'] !== null)->values();
return response()->json(['data' => $requests]);
}
}