send push notification to guest
Main daploy / deploy (push) Failing after 6s

This commit is contained in:
2024-12-02 10:01:23 +02:00
parent 096c1547d4
commit b5a25a6ece
6 changed files with 124 additions and 78 deletions
@@ -59,6 +59,7 @@ import { getUserChatSettingsDocument } from '@/api/userChatSettings'
import type { UserChatSettingsDocument } from '@hereconnect/types' import type { UserChatSettingsDocument } from '@hereconnect/types'
import { isNotFoundError } from '@/api/PouchDB' import { isNotFoundError } from '@/api/PouchDB'
import { saveUserChatSettings } from '@/api/userChatSettings' import { saveUserChatSettings } from '@/api/userChatSettings'
import { getQrCodeDocument } from '@/api/qrCode'
// Проверки iOS и запуска из главного экрана // Проверки iOS и запуска из главного экрана
const isIOS = computed( const isIOS = computed(
@@ -95,18 +96,16 @@ async function requestNotificationPermission() {
} }
const registration = await navigator.serviceWorker.ready const registration = await navigator.serviceWorker.ready
let subscription: PushSubscription | null = null const subscription = await registration.pushManager
.subscribe(await subscribeOptionsPromise)
try { .catch(async (error) => {
subscription = await registration.pushManager.subscribe(await subscribeOptionsPromise) const oldSubscription = await registration.pushManager.getSubscription()
} catch (error) { if (!oldSubscription) {
subscription = await registration.pushManager.getSubscription() throw error
if (!subscription) { }
throw error await oldSubscription.unsubscribe()
} return registration.pushManager.subscribe(await subscribeOptionsPromise)
await subscription.unsubscribe() })
subscription = await registration.pushManager.subscribe(await subscribeOptionsPromise)
}
return saveWebPushSubscription(subscription) return saveWebPushSubscription(subscription)
} }
@@ -161,7 +160,12 @@ const { isPending, isError, error, mutate } = useMutation({
}).catch((error) => { }).catch((error) => {
if (!isNotFoundError(error)) throw error if (!isNotFoundError(error)) throw error
}) })
if (chatSettingsDocument && chatSettingsDocument.is_push_notification_enabled) { if (
(chatSettingsDocument && chatSettingsDocument.is_push_notification_enabled) ||
(!chatSettingsDocument &&
user_chat_role === 'owner' &&
(await getQrCodeDocument(qr_code_uri)).messageDeliveryMethod === 'webPush')
) {
const [subscription, subscriptionDocument] = await Promise.all([ const [subscription, subscriptionDocument] = await Promise.all([
getPushSubscription(), getPushSubscription(),
getWebPushSubscriptionDocument().catch((error) => { getWebPushSubscriptionDocument().catch((error) => {
@@ -78,7 +78,10 @@ async function requestNotificationPermission() {
} }
try { try {
const applicationServerKeyPromise = getVapidPublicKey() const subscribeOptionsPromise = getVapidPublicKey().then((applicationServerKey) => ({
userVisibleOnly: true,
applicationServerKey,
}))
const permission = await Notification.requestPermission() const permission = await Notification.requestPermission()
if (permission !== 'granted') { if (permission !== 'granted') {
@@ -87,10 +90,16 @@ async function requestNotificationPermission() {
const registration = await navigator.serviceWorker.ready const registration = await navigator.serviceWorker.ready
const subscription = await registration.pushManager.subscribe({ const subscription = await registration.pushManager
userVisibleOnly: true, .subscribe(await subscribeOptionsPromise)
applicationServerKey: await applicationServerKeyPromise, .catch(async (error) => {
}) const oldSubscription = await registration.pushManager.getSubscription()
if (!oldSubscription) {
throw error
}
await oldSubscription.unsubscribe()
return registration.pushManager.subscribe(await subscribeOptionsPromise)
})
const webPushSubscriptionDoc = await saveWebPushSubscription(subscription) const webPushSubscriptionDoc = await saveWebPushSubscription(subscription)
emit('change') emit('change')
+7 -1
View File
@@ -2,7 +2,13 @@
"name": "@hereconnect/types", "name": "@hereconnect/types",
"version": "1.0.0", "version": "1.0.0",
"main": "index.ts", "main": "index.ts",
"types": "index.ts", "types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.d.ts",
"default": "./dist/index.d.ts"
}
},
"private": true, "private": true,
"scripts": { "scripts": {
"build": "tsc" "build": "tsc"
@@ -1,5 +1,6 @@
import webpush from "web-push"; import webpush from "web-push";
import PouchDB from "./PouchDB"; import PouchDB from "./PouchDB";
import { ServerSettingsDocument } from "@hereconnect/types";
if (!process.env.VAPID_SUBJECT) { if (!process.env.VAPID_SUBJECT) {
throw new Error("VAPID_SUBJECT env is empty!"); throw new Error("VAPID_SUBJECT env is empty!");
@@ -7,7 +8,10 @@ if (!process.env.VAPID_SUBJECT) {
const vapidKeys = webpush.generateVAPIDKeys(); const vapidKeys = webpush.generateVAPIDKeys();
await new PouchDB(`${process.env.API_URL}/server_settings`, { await new PouchDB<ServerSettingsDocument>(
`${process.env.API_URL}/server_settings`,
{ skip_setup: true },
).put({
_id: "server_settings:message_delivery_method_web_push_vapid", _id: "server_settings:message_delivery_method_web_push_vapid",
type: "server_settings", type: "server_settings",
name: "message_delivery_method_web_push_vapid", name: "message_delivery_method_web_push_vapid",
@@ -15,6 +19,7 @@ await new PouchDB(`${process.env.API_URL}/server_settings`, {
subject: process.env.VAPID_SUBJECT, subject: process.env.VAPID_SUBJECT,
keys: vapidKeys, keys: vapidKeys,
}, },
created_at: new Date().toISOString(),
}); });
await new PouchDB(`${process.env.API_URL}/public_settings`, { await new PouchDB(`${process.env.API_URL}/public_settings`, {
@@ -24,6 +29,7 @@ await new PouchDB(`${process.env.API_URL}/public_settings`, {
type: "public_settings", type: "public_settings",
name: "message_delivery_method_web_push_vapid_public_key", name: "message_delivery_method_web_push_vapid_public_key",
value: vapidKeys.publicKey, value: vapidKeys.publicKey,
created_at: new Date().toISOString(),
}); });
if (process.env.GCM_API_KEY) { if (process.env.GCM_API_KEY) {
@@ -34,5 +40,6 @@ if (process.env.GCM_API_KEY) {
type: "server_settings", type: "server_settings",
name: "message_delivery_method_web_push_gcm_api_key", name: "message_delivery_method_web_push_gcm_api_key",
value: process.env.GCM_API_KEY, value: process.env.GCM_API_KEY,
created_at: new Date().toISOString(),
}); });
} }
@@ -62,6 +62,7 @@ const start = async () => {
try { try {
if (msgDoc.from === "guest") { if (msgDoc.from === "guest") {
console.log("FROM GUEST");
// send message to owner // send message to owner
const qrDoc = await qrDb.get(`qr_code:${msgDoc.qr_code_uri}`); const qrDoc = await qrDb.get(`qr_code:${msgDoc.qr_code_uri}`);
if (qrDoc.messageDeliveryMethod !== "webPush") { if (qrDoc.messageDeliveryMethod !== "webPush") {
@@ -69,19 +70,37 @@ const start = async () => {
continue; continue;
} }
const { rows } = await webPushSubscriptionsDb.allDocs({ const [{ rows: pushSubscriptionRows }, { rows: userChatSettingsRows }] =
startkey: `web_push_subscription:${qrDoc.user_uuid}:`, await Promise.all([
endkey: `web_push_subscription:${qrDoc.user_uuid}:\uffff`, webPushSubscriptionsDb.allDocs({
include_docs: true, startkey: `web_push_subscription:${qrDoc.user_uuid}:`,
}); endkey: `web_push_subscription:${qrDoc.user_uuid}:\uffff`,
include_docs: true,
}),
if (rows.length === 0) { userChatSettingsDb.allDocs({
console.log("NO SUBSCRIPTIONS"); startkey: `user_chat_settings:${msgDoc.qr_code_uri}:${msgDoc.chat}:owner:`,
} else { endkey: `user_chat_settings:${msgDoc.qr_code_uri}:${msgDoc.chat}:owner:\uffff`,
console.log(`sending to ${rows.length} devices`); include_docs: true,
}),
]);
if (
userChatSettingsRows.some(
(row) => row.doc!.is_push_notification_enabled === false,
)
) {
console.log("push notifications is disabled");
continue;
} }
for (const row of rows) { if (pushSubscriptionRows.length === 0) {
console.log("NO SUBSCRIPTIONS");
} else {
console.log(`sending to ${pushSubscriptionRows.length} devices`);
}
for (const row of pushSubscriptionRows) {
try { try {
const subscription = row.doc!.subscription; const subscription = row.doc!.subscription;
const topic = `chat-${msgDoc.qr_code_uri}-${msgDoc.chat}`; const topic = `chat-${msgDoc.qr_code_uri}-${msgDoc.chat}`;
@@ -138,10 +157,11 @@ const start = async () => {
); );
for (const { doc: userChatSettingDoc } of userChatSettingsRows) { for (const { doc: userChatSettingDoc } of userChatSettingsRows) {
if (!userChatSettingDoc) { if (!userChatSettingDoc) {
console.log("push notification has not been configured");
continue; continue;
} }
if (!userChatSettingDoc.is_push_notification_enabled) { if (!userChatSettingDoc.is_push_notification_enabled) {
console.log("PUSH NOTIFICATION DISABLED"); console.log("push notification is disabled");
continue; continue;
} }
@@ -153,56 +173,56 @@ const start = async () => {
}); });
if (subscriptionRows.length === 0) { if (subscriptionRows.length === 0) {
console.log("NO SUBSCRIPTIONS"); console.log("no subscriptions");
} else { } else {
console.log(`sending to ${subscriptionRows.length} devices`); console.log(`sending to ${subscriptionRows.length} devices`);
} }
// for (const row of subscriptionRows) { for (const row of subscriptionRows) {
// try { try {
// const subscription = row.doc!.subscription; const subscription = row.doc!.subscription;
// const topic = `chat-${msgDoc.qr_code_uri}-${msgDoc.chat}`; const topic = `chat-${msgDoc.qr_code_uri}-${msgDoc.chat}`;
// const timestamp = new Date(msgDoc.created_at).getTime(); const timestamp = new Date(msgDoc.created_at).getTime();
// const tag = `${topic}-${(timestamp - new Date(qrDoc.created_at).getTime()).toString(36)}`; const tag = `${topic}-${(timestamp - new Date(qrDoc.created_at).getTime()).toString(36)}`;
//
// const title = limitStringLengthWithEllipsis( const title = limitStringLengthWithEllipsis(
// `${qrDoc.name}: новое сообщение`, `Новое сообщение`,
// 53, 53,
// ); );
// const body = limitStringLengthWithEllipsis(msgDoc.body, 470); const body = limitStringLengthWithEllipsis(msgDoc.body, 470);
//
// const options: NotificationOptions & { timestamp: number } = { const options: NotificationOptions & { timestamp: number } = {
// icon: "/images/qr-code-logo-200x200.jpg", icon: "/images/qr-code-logo-200x200.jpg",
// body, body,
// tag, tag,
// requireInteraction: true, requireInteraction: true,
// timestamp, timestamp,
// data: { data: {
// url: `/manage/${msgDoc.qr_code_uri}/chat/${msgDoc.chat}`, url: `/manage/${msgDoc.qr_code_uri}/chat/${msgDoc.chat}`,
// payload: { tag }, payload: { tag },
// }, },
// } as const; } as const;
//
// await webpush.sendNotification( await webpush.sendNotification(
// subscription, subscription,
// JSON.stringify({ JSON.stringify({
// type: "notification", type: "notification",
// notification: { notification: {
// title, title,
// options, options,
// }, },
// }), }),
// { {
// urgency: "high", urgency: "high",
// topic, topic,
// }, },
// ); );
// } catch (error) { } catch (error) {
// console.error( console.error(
// `Error sending notification to ${row.id} - ${JSON.stringify(error)}`, `Error sending notification to ${row.id} - ${JSON.stringify(error)}`,
// ); );
// } }
// } }
} }
} else { } else {
continue; continue;
@@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2020", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
"outDir": "./dist", "outDir": "./dist",
"rootDir": "./src", "rootDir": "./src",