From 44643bafea9ccb8cf54eacd9bc632bc8513f89d9 Mon Sep 17 00:00:00 2001 From: amal Date: Wed, 2 Jul 2025 11:49:35 +0800 Subject: [PATCH 1/2] upd: fungsi delete iddevice yg gagal fcm --- src/app/api/mobile/announcement/route.ts | 13 +++++++------ src/app/api/mobile/fcm/[[...slug]]/route.ts | 8 +++++--- src/lib/firebase/fcm.ts | 1 - src/module/_global/fun/delete_device_error.ts | 17 +++++++++++++++++ src/module/_global/index.ts | 4 +++- xsendMany.ts | 15 ++++++++++++--- 6 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 src/module/_global/fun/delete_device_error.ts diff --git a/src/app/api/mobile/announcement/route.ts b/src/app/api/mobile/announcement/route.ts index 2c826f5..e237ec1 100644 --- a/src/app/api/mobile/announcement/route.ts +++ b/src/app/api/mobile/announcement/route.ts @@ -100,16 +100,17 @@ export async function GET(request: Request) { createdAt: moment(v.createdAt).format("ll") })) - // await sendFCMNotification('c89yuexsS_uc1tOErVPu5a:APA91bEb6tEKXAfReZjFVJ2mMyOzoW_RXryLSnSJTpbIVV3G0L_DCNkLuRvJ02Ip-Erz88QCQBAt-C2SN8eCRxu3-v1sBzXzKPtDv-huXpkjXsyrkifqvUo') await sendFCMNotificationMany({ token: [ - 'c89yuexsS_uc1tOErVPu5a:APA91bEb6tEKXAfReZjFVJ2mMyOzoW_RXryLSnSJTpbIVV3G0L_DCNkLuRvJ02Ip-Erz88QCQBAt-C2SN8eCRxu3-v1sBzXzKPtDv-huXpkjXsyrkifqvUo', - 'cRz96GHKTRaQaRJ35e8Hxa:APA91bEUSxE0VPbqKSzseQ_zGhbYsDofMexKykRw7o_3z2aPM9YFmZbeA2enrmb3qjdZ2g4-QQtiNHAyaZqAT1ITOrwo9jVJlShTeABmEFYP5GLEUZ3dlLc' + 'c89yuexsS_uc1tOErVPu5a:APA91bEb6tEKXAfReZjFVJ2mMyOzoW_RXryLSnSJTpbIVV3G0L_DCNkLuRvJ02Ip-Erz88QCQBAt-C2SN8eCRxu3-v1sBzXzKPtDv-huXpkjXsyrkifqvUo', + 'cRz96GHKTRaQaRJ35e8Hxa:APA91bEUSxE0VPbqKSzseQ_zGhbYsDofMexKykRw7o_3z2aPM9YFmZbeA2enrmb3qjdZ2g4-QQtiNHAyaZqAT1ITOrwo9jVJlShTeABmEFYP5GLEUZ3dlLc', + 'gagal_device1', + 'gagal_device2' ], - title: "Judul Notifikasi Pengumuman", - body: "Pengumuman untuk perangkat", + title: "Judul Notifikasi Pengumuman api biasa", + body: "Pengumuman untuk perangkat api biasa", data: { id: "cm1eqwkwj00067j2bzejyh9u7", category: "division", content: "cm1eqwkvu00017j2b8qnisp9g" } - }) + }) return NextResponse.json({ success: true, message: "Berhasil mendapatkan pengumuman", data: allData, }, { status: 200 }); } catch (error) { diff --git a/src/app/api/mobile/fcm/[[...slug]]/route.ts b/src/app/api/mobile/fcm/[[...slug]]/route.ts index 8c06e71..08838e1 100644 --- a/src/app/api/mobile/fcm/[[...slug]]/route.ts +++ b/src/app/api/mobile/fcm/[[...slug]]/route.ts @@ -9,10 +9,12 @@ const ApiV2 = new elysia({ await sendFCMNotificationMany({ token: [ 'c89yuexsS_uc1tOErVPu5a:APA91bEb6tEKXAfReZjFVJ2mMyOzoW_RXryLSnSJTpbIVV3G0L_DCNkLuRvJ02Ip-Erz88QCQBAt-C2SN8eCRxu3-v1sBzXzKPtDv-huXpkjXsyrkifqvUo', - 'cRz96GHKTRaQaRJ35e8Hxa:APA91bEUSxE0VPbqKSzseQ_zGhbYsDofMexKykRw7o_3z2aPM9YFmZbeA2enrmb3qjdZ2g4-QQtiNHAyaZqAT1ITOrwo9jVJlShTeABmEFYP5GLEUZ3dlLc' + 'cRz96GHKTRaQaRJ35e8Hxa:APA91bEUSxE0VPbqKSzseQ_zGhbYsDofMexKykRw7o_3z2aPM9YFmZbeA2enrmb3qjdZ2g4-QQtiNHAyaZqAT1ITOrwo9jVJlShTeABmEFYP5GLEUZ3dlLc', + 'gagal_device1', + 'gagal_device2' ], - title: "Judul Notifikasi Pengumuman", - body: "Pengumuman untuk perangkat", + title: "Judul Notifikasi Pengumuman Elysia", + body: "Pengumuman untuk perangkat Elysia", data: { id: "cm1eqwkwj00067j2bzejyh9u7", category: "division", content: "cm1eqwkvu00017j2b8qnisp9g" } }) return { diff --git a/src/lib/firebase/fcm.ts b/src/lib/firebase/fcm.ts index 1e8baf1..033a511 100644 --- a/src/lib/firebase/fcm.ts +++ b/src/lib/firebase/fcm.ts @@ -44,7 +44,6 @@ export async function sendFCM(token: string[], title: string, body: string) { tokens: token, ...message, }) - console.log("✅ FCM berhasil dikirim:", result); if (result.failureCount > 0) { const failedTokens: any[] = []; result.responses.forEach((resp, idx) => { diff --git a/src/module/_global/fun/delete_device_error.ts b/src/module/_global/fun/delete_device_error.ts new file mode 100644 index 0000000..6463be8 --- /dev/null +++ b/src/module/_global/fun/delete_device_error.ts @@ -0,0 +1,17 @@ +import { prisma } from "@/module/_global"; + +export default async function deleteDeviceError({ device }: { device: string[] }) { + try { + const deleteToken = await prisma.tokenDeviceUser.deleteMany({ + where: { + token: { + in: device + } + } + }); + return { success: true, message: "Success" } + } catch (error) { + console.error(error) + return { success: false, message: "Internal Server Error" } + } +} \ No newline at end of file diff --git a/src/module/_global/index.ts b/src/module/_global/index.ts index 9af3b68..f393160 100644 --- a/src/module/_global/index.ts +++ b/src/module/_global/index.ts @@ -30,6 +30,7 @@ import { funSendWebPush } from "./fun/send_web_push"; import ViewFilterData from "./view/view_filter_kategori_data"; import LayoutModalNew from "./layout/layout_modal_new"; import { funReadPdf } from "./fun/read_pdf"; +import deleteDeviceError from "./fun/delete_device_error"; export { WARNA }; export { LayoutLogin }; @@ -68,4 +69,5 @@ export { funViewDir } export { funSendWebPush } export { ViewFilterData } export { LayoutModalNew } -export { funReadPdf } \ No newline at end of file +export { funReadPdf } +export { deleteDeviceError } \ No newline at end of file diff --git a/xsendMany.ts b/xsendMany.ts index 72b05c5..3b06325 100644 --- a/xsendMany.ts +++ b/xsendMany.ts @@ -1,4 +1,4 @@ -// Impor Firebase Admin SDK +import { deleteDeviceError } from '@/module/_global'; import CryptoJs from 'crypto-js'; import { cert, getApps, initializeApp } from "firebase-admin/app"; import { getMessaging } from "firebase-admin/messaging"; @@ -46,8 +46,17 @@ export async function sendFCMNotificationMany({ token, title, body, data }: { to tokens: token, ...message, } as any); - console.log("Notifikasi berhasil dikirim:", response); - return response; + if (response.failureCount > 0) { + const failedTokens: any[] = []; + response.responses.forEach((resp, idx) => { + if (!resp.success) { + failedTokens.push(token[idx]); + } + }); + const del = await deleteDeviceError({ device: failedTokens }); + } + + return { success: true, message: "Notifikasi berhasil dikirim", }; } catch (error) { console.error("Error mengirim notifikasi:", error); throw error; From bf468f36e678eca4cc4011cb54a3b9bf24da77ff Mon Sep 17 00:00:00 2001 From: amal Date: Wed, 2 Jul 2025 15:31:40 +0800 Subject: [PATCH 2/2] upd: test fcm tambah pengumuman --- src/app/api/mobile/announcement/route.ts | 45 +++++++++++++++++------- src/app/api/version-app/route.ts | 2 +- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/app/api/mobile/announcement/route.ts b/src/app/api/mobile/announcement/route.ts index e237ec1..7d2d758 100644 --- a/src/app/api/mobile/announcement/route.ts +++ b/src/app/api/mobile/announcement/route.ts @@ -100,17 +100,6 @@ export async function GET(request: Request) { createdAt: moment(v.createdAt).format("ll") })) - await sendFCMNotificationMany({ - token: [ - 'c89yuexsS_uc1tOErVPu5a:APA91bEb6tEKXAfReZjFVJ2mMyOzoW_RXryLSnSJTpbIVV3G0L_DCNkLuRvJ02Ip-Erz88QCQBAt-C2SN8eCRxu3-v1sBzXzKPtDv-huXpkjXsyrkifqvUo', - 'cRz96GHKTRaQaRJ35e8Hxa:APA91bEUSxE0VPbqKSzseQ_zGhbYsDofMexKykRw7o_3z2aPM9YFmZbeA2enrmb3qjdZ2g4-QQtiNHAyaZqAT1ITOrwo9jVJlShTeABmEFYP5GLEUZ3dlLc', - 'gagal_device1', - 'gagal_device2' - ], - title: "Judul Notifikasi Pengumuman api biasa", - body: "Pengumuman untuk perangkat api biasa", - data: { id: "cm1eqwkwj00067j2bzejyh9u7", category: "division", content: "cm1eqwkvu00017j2b8qnisp9g" } - }) return NextResponse.json({ success: true, message: "Berhasil mendapatkan pengumuman", data: allData, }, { status: 200 }); } catch (error) { @@ -185,6 +174,11 @@ export async function POST(request: Request) { select: { subscription: true } + }, + TokenDeviceUser:{ + select:{ + token: true + } } } } @@ -193,10 +187,17 @@ export async function POST(request: Request) { // mengirim notifikasi + // dataFCM untuk push notifikasi mobile // datanotif untuk realtime notifikasi // datapush untuk web push notifikasi ketika aplikasi tidak aktif + const dataFCM = memberNotif.map((v: any) => ({ + ..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]), + tokens: v.User.TokenDeviceUser.map((v: any) => v.token) + })) + const tokenDup = dataFCM.filter((v: any) => v.tokens.length > 0).map((v: any) => v.tokens).flat(); + const dataNotif = memberNotif.map((v: any) => ({ - ..._.omit(v, ["idUser", "User", "Subscribe"]), + ..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]), idUserTo: v.idUser, idUserFrom: userId, category: 'announcement', @@ -205,12 +206,14 @@ export async function POST(request: Request) { desc: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.' })) + const dataPush = memberNotif.map((v: any) => ({ - ..._.omit(v, ["idUser", "User", "Subscribe"]), + ..._.omit(v, ["idUser", "User", "Subscribe", "TokenDeviceUser"]), idUser: v.idUser, subscription: v.User.Subscribe?.subscription, })) + if (userRoleLogin != "supadmin") { const perbekel = await prisma.user.findFirst({ where: { @@ -224,10 +227,16 @@ export async function POST(request: Request) { select: { subscription: true } + }, + TokenDeviceUser:{ + select:{ + token: true + } } } }) + tokenDup.push(perbekel?.TokenDeviceUser.map((v: any) => v.token).flat()) dataNotif.push({ idUserTo: perbekel?.id, @@ -245,6 +254,8 @@ export async function POST(request: Request) { } + + const pushNotif = dataPush.filter((item) => item.subscription != undefined) const sendWebPush = await funSendWebPush({ sub: pushNotif, message: { title: 'Pengumuman Baru', body: 'Anda memiliki pengumuman baru. Silahkan periksa detailnya.' } }) @@ -252,6 +263,14 @@ export async function POST(request: Request) { data: dataNotif }) + const tokenUnique = [...new Set(tokenDup)]; + await sendFCMNotificationMany({ + token: tokenUnique, + title: "Pengumuman Baru", + body: "Anda memiliki pengumuman baru. Silahkan periksa detailnya.", + data: { id: data.id, category: "announcement", content: data.id } + }) + // create log user const log = await createLogUserMobile({ act: 'CREATE', desc: 'User membuat data pengumuman baru', table: 'announcement', data: data.id, user: userMobile.id }) diff --git a/src/app/api/version-app/route.ts b/src/app/api/version-app/route.ts index 172f35f..9569bf8 100644 --- a/src/app/api/version-app/route.ts +++ b/src/app/api/version-app/route.ts @@ -2,7 +2,7 @@ import { NextResponse } from "next/server"; export async function GET(request: Request) { try { - return NextResponse.json({ success: true, version: "1.5.3", tahap: "beta", update: "-percobaan firebase admin fcm many device" }, { status: 200 }); + return NextResponse.json({ success: true, version: "1.5.4", tahap: "beta", update: "-percobaan firebase admin fcm many device (tambah pengumuman)" }, { status: 200 }); } catch (error) { console.error(error); return NextResponse.json({ success: false, version: "Gagal mendapatkan version, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 });