add a button for testing push notification settings

This commit is contained in:
Athou
2026-02-19 22:13:11 +01:00
parent 6861fe303b
commit de7e4e9c69
35 changed files with 367 additions and 60 deletions

View File

@@ -20,6 +20,7 @@ import type {
PasswordResetConfirmationRequest,
PasswordResetRequest,
ProfileModificationRequest,
PushNotificationSettings,
RegistrationRequest,
ServerInfo,
Settings,
@@ -101,6 +102,8 @@ export const client = {
passwordResetCallback: async (req: PasswordResetConfirmationRequest) => await axiosInstance.post("user/passwordResetCallback", req),
getSettings: async () => await axiosInstance.get<Settings>("user/settings"),
saveSettings: async (settings: Settings) => await axiosInstance.post("user/settings", settings),
sendTestPushNotification: async (settings: PushNotificationSettings) =>
await axiosInstance.post("user/pushNotificationTest", settings),
getProfile: async () => await axiosInstance.get<UserModel>("user/profile"),
saveProfile: async (req: ProfileModificationRequest) => await axiosInstance.post("user/profile", req),
deleteProfile: async () => await axiosInstance.post("user/profile/deleteAccount"),

View File

@@ -1,13 +1,17 @@
import { msg } from "@lingui/core/macro"
import { useLingui } from "@lingui/react"
import { Trans } from "@lingui/react/macro"
import { Button, Group, Select, Stack, TextInput } from "@mantine/core"
import { Button, Divider, Group, Select, Stack, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { useEffect } from "react"
import { TbDeviceFloppy } from "react-icons/tb"
import { useAsyncCallback } from "react-async-hook"
import { TbDeviceFloppy, TbSend } from "react-icons/tb"
import { client, errorToStrings } from "@/app/client"
import { redirectToSelectedSource } from "@/app/redirect/thunks"
import { useAppDispatch, useAppSelector } from "@/app/store"
import type { PushNotificationSettings as PushNotificationSettingsModel } from "@/app/types"
import { changeNotificationSettings } from "@/app/user/thunks"
import { Alert } from "@/components/Alert"
export function PushNotificationSettings() {
const notificationSettings = useAppSelector(state => state.user.settings?.pushNotificationSettings)
@@ -24,6 +28,8 @@ export function PushNotificationSettings() {
dispatch(changeNotificationSettings(values))
}
const sendTestPushNotification = useAsyncCallback(client.user.sendTestPushNotification)
const typeInputProps = form.getInputProps("type")
if (!pushNotificationsEnabled) {
@@ -32,6 +38,14 @@ export function PushNotificationSettings() {
return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<Stack>
{sendTestPushNotification.status === "success" && (
<Alert level="success" messages={[_(msg`Test notification sent successfully.`)]} />
)}
{sendTestPushNotification.status === "error" && (
<Alert level="error" messages={errorToStrings(sendTestPushNotification.error)} />
)}
<Select
label={<Trans>Push notification service</Trans>}
description={
@@ -92,6 +106,17 @@ export function PushNotificationSettings() {
<Button type="submit" leftSection={<TbDeviceFloppy size={16} />}>
<Trans>Save</Trans>
</Button>
<Divider orientation="vertical" />
<Button
variant="outline"
leftSection={<TbSend size={16} />}
onClick={() => sendTestPushNotification.execute(form.values)}
loading={sendTestPushNotification.loading}
>
<Trans>Test</Trans>
</Button>
</Group>
</Stack>
</form>

View File

@@ -1061,6 +1061,14 @@ msgstr "الكلمات"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "عنوان URL للتغذية التي تريد الاشتراك فيها. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Etiquetes"
msgid "Teal"
msgstr "Blau verdós"
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "l'URL del canal al qual us voleu subscriure. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Značky"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Adresa URL kanálu, k jehož odběru se chcete přihlásit. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Tagiau"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Y URL ar gyfer y porthwr rydych chi am danysgrifio iddo. "

View File

@@ -1061,6 +1061,14 @@ msgstr ""
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL'en til det feed, du vil abonnere på. "

View File

@@ -1061,6 +1061,14 @@ msgstr ""
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Die URL für den Feed, den Sie abonnieren möchten. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Tags"
msgid "Teal"
msgstr "Teal"
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr "Test"
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr "Test notification sent successfully."
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."

View File

@@ -1062,6 +1062,14 @@ msgstr "Etiquetas"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "La URL del feed al que desea suscribirse. También puede utilizar la URL del sitio web directamente y CommaFeed intentará encontrar el feed en la página."

View File

@@ -1061,6 +1061,14 @@ msgstr "برچسب ها"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL فیدی که می خواهید در آن مشترک شوید. "

View File

@@ -1061,6 +1061,14 @@ msgstr ""
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Sen syötteen URL-osoite, jonka haluat tilata. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Marqueurs"
msgid "Teal"
msgstr "Bleu-vert"
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "L'URL du flux auquel vous souhaitez vous abonner. Vous pouvez aussi utiliser l'URL du site directement et CommaFeed va essayer de trouver le flux dans la page."

View File

@@ -1062,6 +1062,14 @@ msgstr "Etiquetas"
msgid "Teal"
msgstr "Verdoso"
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL da canle á que queres subscribirte. Podes usar a url do sitio web directamente e CommaFeed intentará atopar a canle na páxina."

View File

@@ -1061,6 +1061,14 @@ msgstr "Címkék"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Az előfizetni kívánt hírcsatorna URL-je. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Tag"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL untuk umpan yang ingin Anda langgani. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Tag"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "L'URL del feed a cui vuoi iscriverti. "

View File

@@ -1061,6 +1061,14 @@ msgstr "タグ"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "購読したいフィードのURL。ウェブサイトのURLを直接使用して、CommaFeedはページ内のフィードを検索します。"

View File

@@ -1061,6 +1061,14 @@ msgstr "태그"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "구독하려는 피드의 URL입니다. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Tag"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL untuk suapan yang anda ingin langgan. "

View File

@@ -1061,6 +1061,14 @@ msgstr ""
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL-en til feeden du vil abonnere på. "

View File

@@ -1061,6 +1061,14 @@ msgstr ""
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "De URL voor de feed waarop u zich wilt abonneren. "

View File

@@ -1061,6 +1061,14 @@ msgstr ""
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL-en til feeden du vil abonnere på. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Tagi"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL kanału, który chcesz subskrybować. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Etiquetas"
msgid "Teal"
msgstr "Azul petróleo"
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "A URL do feed que você deseja assinar. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Теги"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL канала, на который вы хотите подписаться. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Značky"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL zdroja, na odber ktorého sa chcete prihlásiť. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Taggar"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL:en för flödet du vill prenumerera på. "

View File

@@ -1061,6 +1061,14 @@ msgstr "Etiketler"
msgid "Teal"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Abone olmak istediğiniz beslemenin URL'si. "

View File

@@ -1061,6 +1061,14 @@ msgstr "标签"
msgid "Teal"
msgstr "青绿"
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test"
msgstr ""
#: src/components/settings/PushNotificationSettings.tsx
msgid "Test notification sent successfully."
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "您要订阅的信息流的网址。您也可以直接使用网站的网址CommaFeed 会尝试在页面中找到信息流。"

View File

@@ -40,9 +40,9 @@ public class FeedUpdateNotifier {
}
UserSettings settings = unitOfWork.call(() -> userSettingsDAO.findByUser(sub.getUser()));
if (settings != null && settings.getPushNotificationType() != null) {
if (settings != null && settings.getPushNotifications() != null && settings.getPushNotifications().getType() != null) {
for (FeedEntry entry : entries) {
pushNotificationService.notify(settings, sub, entry);
pushNotificationService.notify(settings.getPushNotifications(), sub, entry);
}
}
}

View File

@@ -3,6 +3,8 @@ package com.commafeed.backend.model;
import java.sql.Types;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
@@ -144,22 +146,6 @@ public class UserSettings extends AbstractModel {
private boolean unreadCountFavicon;
private boolean disablePullToRefresh;
@Enumerated(EnumType.STRING)
@Column(name = "push_notification_type", length = 16)
private PushNotificationType pushNotificationType;
@Column(name = "push_notification_server_url", length = 1024)
private String pushNotificationServerUrl;
@Column(name = "push_notification_user_id", length = 512)
private String pushNotificationUserId;
@Column(name = "push_notification_user_secret", length = 512)
private String pushNotificationUserSecret;
@Column(name = "push_notification_topic", length = 256)
private String pushNotificationTopic;
private boolean email;
private boolean gmail;
private boolean facebook;
@@ -169,4 +155,28 @@ public class UserSettings extends AbstractModel {
private boolean instapaper;
private boolean buffer;
@Embedded
private PushNotificationUserSettings pushNotifications = new PushNotificationUserSettings();
@Embeddable
@Getter
@Setter
public static class PushNotificationUserSettings {
@Enumerated(EnumType.STRING)
@Column(name = "push_notification_type", length = 16)
private PushNotificationType type;
@Column(name = "push_notification_server_url", length = 1024)
private String serverUrl;
@Column(name = "push_notification_user_id", length = 512)
private String userId;
@Column(name = "push_notification_user_secret", length = 512)
private String userSecret;
@Column(name = "push_notification_topic", length = 256)
private String topic;
}
}

View File

@@ -25,7 +25,7 @@ import com.commafeed.backend.HttpClientFactory;
import com.commafeed.backend.Urls;
import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.UserSettings;
import com.commafeed.backend.model.UserSettings.PushNotificationUserSettings;
import io.vertx.core.json.JsonObject;
import lombok.extern.slf4j.Slf4j;
@@ -44,12 +44,12 @@ public class PushNotificationService {
this.config = config;
}
public void notify(UserSettings settings, FeedSubscription subscription, FeedEntry entry) {
if (!config.pushNotifications().enabled() || settings.getPushNotificationType() == null) {
public void notify(PushNotificationUserSettings settings, FeedSubscription subscription, FeedEntry entry) {
if (!config.pushNotifications().enabled() || settings.getType() == null) {
return;
}
log.debug("sending {} push notification for entry {} in feed {}", settings.getPushNotificationType(), entry.getId(),
log.debug("sending {} push notification for entry {} in feed {}", settings.getType(), entry.getId(),
subscription.getFeed().getId());
String entryTitle = entry.getContent() != null ? entry.getContent().getTitle() : null;
String entryUrl = entry.getUrl();
@@ -60,11 +60,11 @@ public class PushNotificationService {
}
try {
switch (settings.getPushNotificationType()) {
switch (settings.getType()) {
case NTFY -> sendNtfy(settings, feedTitle, entryTitle, entryUrl);
case GOTIFY -> sendGotify(settings, feedTitle, entryTitle, entryUrl);
case PUSHOVER -> sendPushover(settings, feedTitle, entryTitle, entryUrl);
default -> throw new IllegalStateException("unsupported notification type: " + settings.getPushNotificationType());
default -> throw new IllegalStateException("unsupported notification type: " + settings.getType());
}
} catch (IOException e) {
throw new PushNotificationException("Failed to send external notification", e);
@@ -73,9 +73,9 @@ public class PushNotificationService {
meter.mark();
}
private void sendNtfy(UserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
String serverUrl = Urls.removeTrailingSlash(settings.getPushNotificationServerUrl());
String topic = settings.getPushNotificationTopic();
private void sendNtfy(PushNotificationUserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
String serverUrl = Urls.removeTrailingSlash(settings.getServerUrl());
String topic = settings.getTopic();
if (StringUtils.isBlank(serverUrl) || StringUtils.isBlank(topic)) {
log.warn("ntfy notification skipped: missing server URL or topic");
@@ -91,8 +91,8 @@ public class PushNotificationService {
request.addHeader("Click", entryUrl);
}
if (StringUtils.isNotBlank(settings.getPushNotificationUserSecret())) {
request.addHeader("Authorization", "Bearer " + settings.getPushNotificationUserSecret());
if (StringUtils.isNotBlank(settings.getUserSecret())) {
request.addHeader("Authorization", "Bearer " + settings.getUserSecret());
}
httpClient.execute(request, response -> {
@@ -103,9 +103,10 @@ public class PushNotificationService {
});
}
private void sendGotify(UserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
String serverUrl = Urls.removeTrailingSlash(settings.getPushNotificationServerUrl());
String token = settings.getPushNotificationUserSecret();
private void sendGotify(PushNotificationUserSettings settings, String feedTitle, String entryTitle, String entryUrl)
throws IOException {
String serverUrl = Urls.removeTrailingSlash(settings.getServerUrl());
String token = settings.getUserSecret();
if (StringUtils.isBlank(serverUrl) || StringUtils.isBlank(token)) {
log.warn("gotify notification skipped: missing server URL or token");
@@ -134,9 +135,10 @@ public class PushNotificationService {
});
}
private void sendPushover(UserSettings settings, String feedTitle, String entryTitle, String entryUrl) throws IOException {
String token = settings.getPushNotificationUserSecret();
String userKey = settings.getPushNotificationUserId();
private void sendPushover(PushNotificationUserSettings settings, String feedTitle, String entryTitle, String entryUrl)
throws IOException {
String token = settings.getUserSecret();
String userKey = settings.getUserId();
if (StringUtils.isBlank(token) || StringUtils.isBlank(userKey)) {
log.warn("pushover notification skipped: missing token or user key");

View File

@@ -38,19 +38,26 @@ import com.commafeed.backend.Urls;
import com.commafeed.backend.dao.UserDAO;
import com.commafeed.backend.dao.UserRoleDAO;
import com.commafeed.backend.dao.UserSettingsDAO;
import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryContent;
import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserRole;
import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.backend.model.UserSettings;
import com.commafeed.backend.model.UserSettings.IconDisplayMode;
import com.commafeed.backend.model.UserSettings.PushNotificationUserSettings;
import com.commafeed.backend.model.UserSettings.ReadingMode;
import com.commafeed.backend.model.UserSettings.ReadingOrder;
import com.commafeed.backend.model.UserSettings.ScrollMode;
import com.commafeed.backend.service.MailService;
import com.commafeed.backend.service.PasswordEncryptionService;
import com.commafeed.backend.service.PushNotificationService;
import com.commafeed.backend.service.UserService;
import com.commafeed.backend.service.db.DatabaseStartupService;
import com.commafeed.frontend.model.Settings;
import com.commafeed.frontend.model.Settings.PushNotificationSettings;
import com.commafeed.frontend.model.UserModel;
import com.commafeed.frontend.model.request.InitialSetupRequest;
import com.commafeed.frontend.model.request.PasswordResetConfirmationRequest;
@@ -84,6 +91,7 @@ public class UserREST {
private final MailService mailService;
private final CommaFeedConfiguration config;
private final UriInfo uri;
private final PushNotificationService pushNotificationService;
@Path("/settings")
@GET
@@ -126,11 +134,13 @@ public class UserREST {
s.setDisablePullToRefresh(settings.isDisablePullToRefresh());
s.setPrimaryColor(settings.getPrimaryColor());
s.getPushNotificationSettings().setType(settings.getPushNotificationType());
s.getPushNotificationSettings().setServerUrl(settings.getPushNotificationServerUrl());
s.getPushNotificationSettings().setUserId(settings.getPushNotificationUserId());
s.getPushNotificationSettings().setUserSecret(settings.getPushNotificationUserSecret());
s.getPushNotificationSettings().setTopic(settings.getPushNotificationTopic());
if (settings.getPushNotifications() != null) {
s.getPushNotificationSettings().setType(settings.getPushNotifications().getType());
s.getPushNotificationSettings().setServerUrl(settings.getPushNotifications().getServerUrl());
s.getPushNotificationSettings().setUserId(settings.getPushNotifications().getUserId());
s.getPushNotificationSettings().setUserSecret(settings.getPushNotifications().getUserSecret());
s.getPushNotificationSettings().setTopic(settings.getPushNotifications().getTopic());
}
} else {
s.setReadingMode(ReadingMode.UNREAD);
s.setReadingOrder(ReadingOrder.DESC);
@@ -196,11 +206,13 @@ public class UserREST {
s.setDisablePullToRefresh(settings.isDisablePullToRefresh());
s.setPrimaryColor(settings.getPrimaryColor());
s.setPushNotificationType(settings.getPushNotificationSettings().getType());
s.setPushNotificationServerUrl(settings.getPushNotificationSettings().getServerUrl());
s.setPushNotificationUserId(settings.getPushNotificationSettings().getUserId());
s.setPushNotificationUserSecret(settings.getPushNotificationSettings().getUserSecret());
s.setPushNotificationTopic(settings.getPushNotificationSettings().getTopic());
PushNotificationUserSettings ps = new PushNotificationUserSettings();
ps.setType(settings.getPushNotificationSettings().getType());
ps.setServerUrl(settings.getPushNotificationSettings().getServerUrl());
ps.setUserId(settings.getPushNotificationSettings().getUserId());
ps.setUserSecret(settings.getPushNotificationSettings().getUserSecret());
ps.setTopic(settings.getPushNotificationSettings().getTopic());
s.setPushNotifications(ps);
s.setEmail(settings.getSharingSettings().isEmail());
s.setGmail(settings.getSharingSettings().isGmail());
@@ -216,6 +228,37 @@ public class UserREST {
}
@Path("/pushNotificationTest")
@POST
@Transactional
@Operation(summary = "Send a test push notification")
public Response sendTestPushNotification(@Parameter(required = true) PushNotificationSettings settings) {
FeedSubscription sub = new FeedSubscription();
sub.setTitle("CommaFeed Test Feed");
sub.setFeed(new Feed());
FeedEntryContent content = new FeedEntryContent();
content.setTitle("Test Entry");
FeedEntry entry = new FeedEntry();
entry.setContent(content);
PushNotificationUserSettings pushSettings = new PushNotificationUserSettings();
pushSettings.setType(settings.getType());
pushSettings.setServerUrl(settings.getServerUrl());
pushSettings.setUserId(settings.getUserId());
pushSettings.setUserSecret(settings.getUserSecret());
pushSettings.setTopic(settings.getTopic());
try {
pushNotificationService.notify(pushSettings, sub, entry);
} catch (Exception e) {
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getCause().getMessage()).type(MediaType.TEXT_PLAIN).build();
}
return Response.ok().build();
}
@Path("/profile")
@GET
@Transactional

View File

@@ -22,8 +22,8 @@ import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryContent;
import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.UserSettings;
import com.commafeed.backend.model.UserSettings.PushNotificationType;
import com.commafeed.backend.model.UserSettings.PushNotificationUserSettings;
@ExtendWith(MockServerExtension.class)
class PushNotificationServiceTest {
@@ -31,7 +31,7 @@ class PushNotificationServiceTest {
private MockServerClient mockServerClient;
private PushNotificationService pushNotificationService;
private CommaFeedConfiguration config;
private UserSettings userSettings;
private PushNotificationUserSettings userSettings;
private FeedSubscription subscription;
private FeedEntry entry;
@@ -51,7 +51,7 @@ class PushNotificationServiceTest {
this.pushNotificationService = new PushNotificationService(httpClientFactory, metricRegistry, config);
this.userSettings = new UserSettings();
this.userSettings = new PushNotificationUserSettings();
this.subscription = createSubscription("Test Feed");
this.entry = createEntry("Test Entry", "http://example.com/entry");
@@ -59,10 +59,10 @@ class PushNotificationServiceTest {
@Test
void testNtfyNotification() {
userSettings.setPushNotificationType(PushNotificationType.NTFY);
userSettings.setPushNotificationServerUrl("http://localhost:" + mockServerClient.getPort());
userSettings.setPushNotificationTopic("test-topic");
userSettings.setPushNotificationUserSecret("test-secret");
userSettings.setType(PushNotificationType.NTFY);
userSettings.setServerUrl("http://localhost:" + mockServerClient.getPort());
userSettings.setTopic("test-topic");
userSettings.setUserSecret("test-secret");
mockServerClient.when(HttpRequest.request()
.withMethod("POST")
@@ -77,9 +77,9 @@ class PushNotificationServiceTest {
@Test
void testGotifyNotification() {
userSettings.setPushNotificationType(PushNotificationType.GOTIFY);
userSettings.setPushNotificationServerUrl("http://localhost:" + mockServerClient.getPort());
userSettings.setPushNotificationUserSecret("gotify-token");
userSettings.setType(PushNotificationType.GOTIFY);
userSettings.setServerUrl("http://localhost:" + mockServerClient.getPort());
userSettings.setUserSecret("gotify-token");
mockServerClient.when(HttpRequest.request()
.withMethod("POST")
@@ -107,9 +107,9 @@ class PushNotificationServiceTest {
@Test
void testPushNotificationDisabled() {
Mockito.when(config.pushNotifications().enabled()).thenReturn(false);
userSettings.setPushNotificationType(PushNotificationType.NTFY);
userSettings.setPushNotificationServerUrl("http://localhost:" + mockServerClient.getPort());
userSettings.setPushNotificationTopic("test-topic");
userSettings.setType(PushNotificationType.NTFY);
userSettings.setServerUrl("http://localhost:" + mockServerClient.getPort());
userSettings.setTopic("test-topic");
Assertions.assertDoesNotThrow(() -> pushNotificationService.notify(userSettings, subscription, entry));
mockServerClient.verifyZeroInteractions();