Files
ladill-meet/app/Services/Meet/MeetNotificationService.php
T
isaaccladandCursor 965fb992e9
Deploy Ladill Meet / deploy (push) Failing after 7s
Initial Ladill Meet release.
Phases 0–18: core meetings, webinar, breakouts, team chat, live streaming, town hall, billing, and Ladill Mail calendar wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 23:35:29 +00:00

143 lines
4.7 KiB
PHP

<?php
namespace App\Services\Meet;
use App\Models\Invitation;
use App\Models\Recording;
use App\Models\Room;
use App\Models\Session;
use App\Models\User;
use App\Notifications\AiSummaryReadyNotification;
use App\Notifications\MeetingInvitationNotification;
use App\Notifications\MeetingReminderNotification;
use App\Notifications\RecordingReadyNotification;
use App\Services\Comms\EmailService;
class MeetNotificationService
{
public function __construct(
protected EmailService $email,
) {}
public function sendInvitations(Room $room, array $invites, User $host): void
{
foreach ($invites as $invite) {
$email = trim((string) ($invite['email'] ?? ''));
if ($email === '') {
continue;
}
$existing = $room->invitations()->where('email', $email)->first();
$invitation = $existing ?? $room->invitations()->create([
'owner_ref' => $room->owner_ref,
'email' => $email,
'user_ref' => $invite['user_ref'] ?? User::where('email', $email)->value('public_id'),
'display_name' => $invite['name'] ?? null,
'role' => $invite['role'] ?? 'participant',
'status' => 'pending',
'sent_at' => now(),
]);
if ($existing) {
$invitation->update(['sent_at' => now()]);
}
$this->sendInvitationEmail($room, $invitation, $host);
if ($user = User::where('email', $email)->first()) {
$user->notify(new MeetingInvitationNotification($room, $host));
}
}
}
public function sendInvitationEmail(Room $room, Invitation $invitation, User $host): void
{
$this->email->send(
$invitation->email,
'Invitation: '.$room->title,
$this->invitationBody($room, $host, $invitation),
);
}
public function meetingStarted(Session $session, User $host): void
{
AuditLogger::record(
$session->owner_ref,
'notification.meeting_started',
$session->room->organization_id,
$host->ownerRef(),
Session::class,
$session->id,
);
}
public function recordingReady(Recording $recording): void
{
$host = User::where('public_id', $recording->session->room->host_user_ref)->first();
if ($host) {
$host->notify(new RecordingReadyNotification($recording));
}
if ($host?->email) {
$this->email->send(
$host->email,
'Recording ready: '.$recording->session->room->title,
'Your meeting recording is ready to view at '.route('meet.recordings.show', $recording),
);
}
}
public function aiSummaryReady(\App\Models\AiSummary $summary): void
{
$host = User::where('public_id', $summary->session->room->host_user_ref)->first();
if ($host) {
$host->notify(new AiSummaryReadyNotification($summary));
}
}
public function sendReminder(Room $room, User $host): void
{
$this->email->send(
$host->email,
'Reminder: '.$room->title.' starts soon',
'Your meeting starts at '.$room->scheduled_at?->timezone($room->timezone)->format('M j, Y g:i A T')."\n\nJoin: ".$room->joinUrl(),
);
$host->notify(new MeetingReminderNotification($room));
foreach ($room->invitations()->where('status', 'accepted')->get() as $invitation) {
if (! $invitation->email) {
continue;
}
$this->email->send(
$invitation->email,
'Reminder: '.$room->title.' starts soon',
'You are invited to a meeting starting at '.$room->scheduled_at?->timezone($room->timezone)->format('M j, Y g:i A T')."\n\nJoin: ".$room->joinUrl(),
);
}
}
protected function invitationBody(Room $room, User $host, ?Invitation $invitation = null): string
{
$when = $room->scheduled_at
? $room->scheduled_at->timezone($room->timezone)->format('M j, Y g:i A T')
: 'Instant meeting';
$lines = [
$host->name.' invited you to a Ladill Meet session.',
'',
'Meeting: '.$room->title,
'When: '.$when,
'Join: '.$room->joinUrl(),
$room->passcode ? 'Passcode: '.$room->passcode : '',
];
if ($invitation?->rsvp_token) {
$lines[] = '';
$lines[] = 'RSVP: '.$invitation->rsvpUrl();
}
return implode("\n", array_filter($lines, fn ($l) => $l !== ''));
}
}