70 lines
2.2 KiB
PHP
70 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Messaging;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Cache\Repository;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class MessagingPresenceService
|
|
{
|
|
public function touch(User|int $user, ?int $conversationId = null): void
|
|
{
|
|
$userId = $user instanceof User ? (int) $user->id : (int) $user;
|
|
$store = $this->store();
|
|
$onlineKey = $this->onlineKey($userId);
|
|
$existing = $store->get($onlineKey, []);
|
|
$previousConversationId = (int) ($existing['conversation_id'] ?? 0) ?: null;
|
|
$onlineTtl = max(30, (int) config('messaging.presence.ttl_seconds', 90));
|
|
$conversationTtl = max(15, (int) config('messaging.presence.conversation_ttl_seconds', 45));
|
|
|
|
if ($previousConversationId && $previousConversationId !== $conversationId) {
|
|
$store->forget($this->conversationKey($previousConversationId, $userId));
|
|
}
|
|
|
|
$store->put($onlineKey, [
|
|
'conversation_id' => $conversationId,
|
|
'seen_at' => now()->toIso8601String(),
|
|
], now()->addSeconds($onlineTtl));
|
|
|
|
if ($conversationId) {
|
|
$store->put($this->conversationKey($conversationId, $userId), now()->toIso8601String(), now()->addSeconds($conversationTtl));
|
|
}
|
|
}
|
|
|
|
public function isUserOnline(int $userId): bool
|
|
{
|
|
return $this->store()->has($this->onlineKey($userId));
|
|
}
|
|
|
|
public function isViewingConversation(int $conversationId, int $userId): bool
|
|
{
|
|
return $this->store()->has($this->conversationKey($conversationId, $userId));
|
|
}
|
|
|
|
private function onlineKey(int $userId): string
|
|
{
|
|
return 'messages:presence:user:' . $userId;
|
|
}
|
|
|
|
private function conversationKey(int $conversationId, int $userId): string
|
|
{
|
|
return 'messages:presence:conversation:' . $conversationId . ':user:' . $userId;
|
|
}
|
|
|
|
private function store(): Repository
|
|
{
|
|
$store = (string) config('messaging.presence.cache_store', 'redis');
|
|
|
|
if ($store === 'redis' && ! class_exists('Redis')) {
|
|
return Cache::store();
|
|
}
|
|
|
|
try {
|
|
return Cache::store($store);
|
|
} catch (\Throwable) {
|
|
return Cache::store();
|
|
}
|
|
}
|
|
}
|