Add f7push v0.1: FCM device registry and push API for F7cloud.
Portable occ-based config, OCS endpoints for APK registration, notification relay, and server-side push dispatch.
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\F7Push\Service;
|
||||
|
||||
use OCA\F7Push\Db\Device;
|
||||
use OCA\F7Push\Db\DeviceMapper;
|
||||
use OCA\F7Push\Model\PushMessage;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Notification\INotification;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class PushDispatcher {
|
||||
public function __construct(
|
||||
private DeviceMapper $deviceMapper,
|
||||
private FirebaseClient $firebaseClient,
|
||||
private ConfigService $config,
|
||||
private ITimeFactory $timeFactory,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
public function registerDevice(
|
||||
string $userId,
|
||||
string $deviceId,
|
||||
string $fcmToken,
|
||||
string $platform,
|
||||
string $clientApp,
|
||||
): Device {
|
||||
$now = $this->timeFactory->getTime();
|
||||
try {
|
||||
$device = $this->deviceMapper->findByUserAndDevice($userId, $deviceId);
|
||||
$device->setFcmToken($fcmToken);
|
||||
$device->setPlatform($platform);
|
||||
$device->setClientApp($clientApp);
|
||||
$device->setLastSeen($now);
|
||||
return $this->deviceMapper->update($device);
|
||||
} catch (DoesNotExistException) {
|
||||
$device = new Device();
|
||||
$device->setUserId($userId);
|
||||
$device->setDeviceId($deviceId);
|
||||
$device->setFcmToken($fcmToken);
|
||||
$device->setPlatform($platform);
|
||||
$device->setClientApp($clientApp);
|
||||
$device->setCreatedAt($now);
|
||||
$device->setLastSeen($now);
|
||||
return $this->deviceMapper->insert($device);
|
||||
}
|
||||
}
|
||||
|
||||
public function unregisterDevice(string $userId, string $deviceId): void {
|
||||
$this->deviceMapper->deleteByUserAndDevice($userId, $deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Device[]
|
||||
*/
|
||||
public function listDevices(string $userId): array {
|
||||
return $this->deviceMapper->findByUser($userId);
|
||||
}
|
||||
|
||||
public function dispatch(PushMessage $message): int {
|
||||
if (!$this->config->isEnabled()) {
|
||||
return 0;
|
||||
}
|
||||
if (!$this->config->isSourceEnabled($message->source)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$devices = $this->deviceMapper->findByUser($message->userId);
|
||||
if ($devices === []) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$url = $message->url ?? $this->config->getDefaultClickUrl();
|
||||
$sent = 0;
|
||||
foreach ($devices as $device) {
|
||||
$token = $device->getFcmToken();
|
||||
if ($token === '') {
|
||||
continue;
|
||||
}
|
||||
if ($this->firebaseClient->sendToToken($token, $message->title, $message->body, $url, $message->priority)) {
|
||||
$sent++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->debug('f7push: dispatched push', [
|
||||
'app' => 'f7push',
|
||||
'user' => $message->userId,
|
||||
'source' => $message->source,
|
||||
'sent' => $sent,
|
||||
'devices' => count($devices),
|
||||
]);
|
||||
|
||||
return $sent;
|
||||
}
|
||||
|
||||
public function dispatchFromNotification(INotification $notification): int {
|
||||
if (!$this->config->listenNotifications()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$user = $notification->getUser();
|
||||
if ($user === null || $user === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$source = $notification->getApp();
|
||||
if (!$this->config->isSourceEnabled($source)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$title = $notification->getParsedSubject();
|
||||
if ($title === '') {
|
||||
$title = $notification->getSubject();
|
||||
}
|
||||
$body = $notification->getParsedMessage();
|
||||
if ($body === '') {
|
||||
$body = $notification->getMessage();
|
||||
}
|
||||
if ($title === '' && $body === '') {
|
||||
return 0;
|
||||
}
|
||||
if ($title === '') {
|
||||
$title = $body;
|
||||
}
|
||||
|
||||
$link = $notification->getLink();
|
||||
if ($link !== '' && !str_starts_with($link, 'http://') && !str_starts_with($link, 'https://')) {
|
||||
$link = $this->config->getDefaultClickUrl() . $link;
|
||||
}
|
||||
|
||||
$priority = $source === 'spreed' ? 'high' : 'normal';
|
||||
|
||||
return $this->dispatch(new PushMessage(
|
||||
userId: $user,
|
||||
title: $title,
|
||||
body: $body,
|
||||
source: $source,
|
||||
priority: $priority,
|
||||
url: $link !== '' ? $link : null,
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user