PageSourceSearch

https://cdn.haibunda.com/js/firebase.js?v=5.5.4

js haibunda.com collected 2026-10-02 03:03:35 UTC 10,886 bytes, 351 lines download raw bytes

1import { initializeApp } from "https://www.gstatic.com/firebasejs/10.13.0/firebase-app.js";
2import { deleteToken, getMessaging, getToken, onMessage } from 'https://www.gstatic.com/firebasejs/10.13.0/firebase-messaging.js';
3
4import { config, vapidKey } from "https://cdn.detik.net.id/libs/kayumanis/v1/haibunda.js";
5import { idbSet, idbGet } from "https://cdn.detik.net.id/libs/kayumanis/v1/utils.js";
6
7// Initialize Firebase
8initializeApp(config);
9const messaging = getMessaging();
10
11onMessage(messaging, async (payload) => {
12    console.log('Message received.', payload);
13
14    if(payload.data.url.indexOf('haibunda.com') < 0) return;
15    if (Notification.permission !== 'granted') return;
16
17    const { title, content, icon, id, url, app } = payload.data;
18
19    const notification = new Notification(title, {
20        body: content,
21        icon
22    });
23
24    const trackerUrl = payload.data?.tracker;
25    if (trackerUrl) {
26        fetch(trackerUrl, {
27            method: 'GET',
28            mode: 'no-cors',
29            keepalive: true,
30            credentials: 'omit'
31        }).catch(err => {
32            console.log('Tracker fetch failed, fallback to beacon:', err);
33            if (navigator.sendBeacon) {
34                navigator.sendBeacon(trackerUrl);
35            }
36        });
37    }
38
39
40    let device = '3'; 
41    let token;
42
43    try {
44        token = await getToken(messaging, { vapidKey });
45        const deviceData = await new Promise((resolve) => {
46            const req = indexedDB.open('device-token-database', 1);
47
48            req.onsuccess = (event) => {
49                const db = event.target.result;
50                const getReq = db
51                    .transaction('device-token-store', 'readonly')
52                    .objectStore('device-token-store')
53                    .get('device-token');
54
55                getReq.onsuccess = (e) => resolve(e.target.result);
56                getReq.onerror = () => resolve(null);
57            };
58
59            req.onerror = () => resolve(null);
60        });
61
62        if (deviceData && deviceData.device) {
63            device = deviceData.device.toString();
64        } else {
65            if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i
66                .test(navigator.userAgent)) {
67                device = '4';
68            }
69
70            saveDeviceTokenToIndexedDB(token, device);
71        }
72
73        const lastVerify = await idbGet('kayumanis', 'lastVerifyTokenAt');
74        const nowVerify = Date.now();
75        if (!lastVerify || nowVerify - lastVerify > 30000) {
76            await fetch('https://kayumanis.detik.com/api/verify/', {
77                method: 'POST',
78                headers: { 'Content-Type': 'application/json' },
79                body: JSON.stringify({
80                    token,
81                    application: config.application,
82                    device,
83                    notif_id: id
84                })
85            });
86
87            await idbSet('kayumanis', 'lastVerifyTokenAt', nowVerify);
88        } 
89    } catch (e) {
90        console.error('foreground verify error:', e);
91    }
92
93    notification.onclick = async (event) => {
94        event.preventDefault();
95        notification.close();
96        window.open(url, '_blank');
97
98        try {
99            const formData = new FormData();
100            formData.append('id', id);
101            formData.append('token', token);
102            formData.append('app', app);
103            formData.append('platform', device);
104
105            await fetch('https://kayumanis.detik.com/api/app_open/', {
106                method: 'POST',
107                body: formData
108            });
109        } catch (e) {
110            console.error('app_open error:', e);
111        }
112    };
113});
114
115function requestToken() {
116    getToken(messaging, {vapidKey: vapidKey})
117        .then((currentToken) => {
118        if (currentToken) {
119          sendTokenToServer(currentToken);
120        } else {
121          // Show permission request.
122          console.log('No registration token available. Request permission to generate one.');
123          setTokenSentToServer(false);
124        }
125    }).catch((err) => {
126        console.log('An error occurred while retrieving token. ', err);
127        setTokenSentToServer(false);
128        requestToken();
129    });
130}
131
132function sendTokenToServer(currentToken) {
133    if (!isTokenSentToServer()) {
134        console.log("Sending token to server...");
135        sendTokenToAppsDev(currentToken);
136        setTokenSentToServer(true);
137    } else {
138        console.log("Token already sent to server so won't send it again " + "unless it changes");
139    }
140}
141
142function sendTokenToAppsDev(currentToken) {
143    let url = "https://kayumanis.detik.com/api/media/";
144    let method = "POST";
145
146    let device = 3;
147    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
148        device = 4;
149    }
150
151    let postData = new FormData();
152    postData.append("application", config.application);
153    postData.append("token", currentToken);
154    postData.append("device", device);
155
156    let uv = getCookieNotif("__dtma");
157    if (uv !== "") {
158        postData.append("uv", uv);
159    }
160
161    let async = true;
162    let request = new XMLHttpRequest();
163    request.withCredentials = true;
164    request.onload = function () {
165        let status = request.status;
166        let data = request.responseText;
167    };
168    request.open(method, url, async);
169    request.send(postData);
170
171    setCookieNotif('__fcm_token', currentToken);
172
173    saveDeviceTokenToIndexedDB(currentToken, device);
174}
175
176function isTokenSentToServer() {
177    if (window.localStorage.getItem("sentToServer") == 1) {
178        return true;
179    }
180    return false;
181}
182
183function setTokenSentToServer(sent) {
184    window.localStorage.setItem("sentToServer", sent ? 1 : 0);
185
186    if (!sent) {
187        deleteDeviceFromIndexedDB();
188    }
189}
190
191function requestPermission() {
192    console.log('Requesting permission...');
193    Notification.requestPermission().then((permission) => {
194        if (permission === 'granted') {
195            requestToken();
196            console.log("Notification permission granted.");
197        } else {
198            console.log('Unable to get permission to notify.');
199        }
200    });
201}
202
203function deleteTokenFromFirebase() {
204    getToken(messaging, {vapidKey: vapidKey})
205        .then((currentToken) => {
206        deleteToken(messaging).then(() => {
207            console.log('Token deleted.', currentToken);
208            setTokenSentToServer(false);
209        }).catch((err) => {
210            console.log('Unable to delete token. ', err);
211            setTokenSentToServer(false);
212        });
213    }).catch((err) => {
214        console.log("Error retrieving Instance ID token. ", err);
215        setTokenSentToServer(false);
216    });
217}
218
219function getCookieNotif(cname) {
220    var name = cname + "=";
221    var decodedCookie = decodeURIComponent(document.cookie);
222    var ca = decodedCookie.split(";");
223    for (var i = 0; i < ca.length; i++) {
224        var c = ca[i];
225        while (c.charAt(0) == " ") {
226            c = c.substring(1);
227        }
228        if (c.indexOf(name) == 0) {
229            return c.substring(name.length, c.length);
230        }
231    }
232    return "";
233}
234
235function setCookieNotif(name, value, days) {
236    var expires = "";
237    if (days) {
238        var date = new Date();
239        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
240        expires = "; expires=" + date.toUTCString();
241    }
242    document.cookie = name + "=" + (value || "") + expires + "; path=/";
243}
244
245function resendToken() {
246    const lastValidation = localStorage.getItem("lastTokenValidationAt");
247    const now = Date.now();
248    if (lastValidation && now - parseInt(lastValidation) < 86400000) {
249       return;
250    }
251
252   getToken(messaging, {vapidKey: vapidKey})
253       .then(function (currentToken) {
254       if (!currentToken) {
255           setTokenSentToServer(false);
256           return;
257       }
258
259       var platform = 3;
260       if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
261           platform = 4;
262       }
263       $.post("https://kayumanis.detik.com/api/validation/", {
264           token: currentToken,
265           device: platform,
266           application: config.application
267       }).done(function (msg, _, jqXHR) {
268           if (jqXHR.status === 202) {
269               localStorage.setItem("lastTokenValidationAt", Date.now().toString());
270           } else {
271               deleteTokenFromFirebase();
272               deleteDeviceFromIndexedDB();
273
274               localStorage.removeItem("lastTokenValidationAt"); 
275           }
276       });
277   });
278}
279
280
281function initNotif() {
282    if (isTokenSentToServer()) {
283        resendToken();
284    } else {
285        requestPermission();
286    }
287}
288
289initNotif();
290
291function saveDeviceTokenToIndexedDB(currentToken, device) {
292    let requestIndexDb = indexedDB.open('device-token-database', 1);
293
294    try {
295        requestIndexDb.onupgradeneeded = function(event) {
296            let db = event.target.result;
297            db.createObjectStore('device-token-store', { keyPath: 'id' });
298        }
299
300        requestIndexDb.onsuccess = function(event) {
301            let db = event.target.result;
302            let transaction = db.transaction('device-token-store', 'readwrite');
303            let objectStore = transaction.objectStore('device-token-store');
304            let key = "device-token";
305            objectStore.add ({'id': key, token: currentToken, device: device});
306        }
307
308        requestIndexDb.onerror = function(event) {
309            console.log("Error opening indexedDB: ", event);
310        }
311    } catch (e) {
312        console.log("Cannot save device to indexedDB", e);
313    }
314}
315
316function deleteDeviceFromIndexedDB() {
317    let requestIndexDb = indexedDB.open('device-token-database', 1);
318    try {
319        requestIndexDb.onupgradeneeded = function(event) {
320            let db = event.target.result;
321            db.createObjectStore('device-token-store', { keyPath: 'id' });
322        }
323
324        requestIndexDb.onsuccess = function(event) {
325            let db = event.target.result;
326            let transaction = db.transaction('device-token-store', 'readwrite');
327            let objectStore = transaction.objectStore('device-token-store');
328            objectStore.delete("device-token");
329        }
330
331        requestIndexDb.onerror = function(event) {
332            console.log("Error opening indexedDB: ", event);
333        }
334    } catch (e) {
335        console.log("Cannot delete device from indexedDB", e);
336    }
337}
338
339function isMobileDevice() {
340    return /Mobi|Android|iPad|iPhone|iPod|IEMobile|Opera Mini/i.test(navigator.userAgent);
341}
342
343if (isMobileDevice()) {
344document.querySelector('#btn_pnf').addEventListener('click', () => { // add a click event listener
345    requestPermission();
346});
347} else {
348document.querySelector('#yes-notif').addEventListener('click', () => { // add a click event listener
349    requestPermission();
350});
351}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.