• bark.js
  • //
    //  bark.js
    //  UptimeKuma
    //
    //  Created by Lakr Aream on 2021/10/24.
    //  Copyright © 2021 Lakr Aream. All rights reserved.
    //
    
    const NotificationProvider = require("./notification-provider");
    const { DOWN, UP } = require("../../src/util");
    const { default: axios } = require("axios");
    
    // bark is an APN bridge that sends notifications to Apple devices.
    
    const barkNotificationAvatar = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png";
    const successMessage = "Successes!";
    
    class Bark extends NotificationProvider {
        name = "Bark";
    
        /**
         * @inheritdoc
         */
        async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
            let barkEndpoint = notification.barkEndpoint;
    
            // check if the endpoint has a "/" suffix, if so, delete it first
            if (barkEndpoint.endsWith("/")) {
                barkEndpoint = barkEndpoint.substring(0, barkEndpoint.length - 1);
            }
    
            if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === UP) {
                let title = "UptimeKuma Monitor Up";
                return await this.postNotification(notification, title, msg, barkEndpoint);
            }
    
            if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
                let title = "UptimeKuma Monitor Down";
                return await this.postNotification(notification, title, msg, barkEndpoint);
            }
    
            if (msg != null) {
                let title = "UptimeKuma Message";
                return await this.postNotification(notification, title, msg, barkEndpoint);
            }
        }
    
        /**
         * Add additional parameter for Bark v1 endpoints.
         * Leads to better on device styles (iOS 15 optimized)
         * @param {BeanModel} notification Notification to send
         * @returns {string} Additional URL parameters
         */
        additionalParameters(notification) {
            // set icon to uptime kuma icon, 11kb should be fine
            let params = "?icon=" + barkNotificationAvatar;
            // grouping all our notifications
            if (notification.barkGroup != null) {
                params += "&group=" + notification.barkGroup;
            } else {
                // default name
                params += "&group=" + "UptimeKuma";
            }
            // picked a sound, this should follow system's mute status when arrival
            if (notification.barkSound != null) {
                params += "&sound=" + notification.barkSound;
            } else {
                // default sound
                params += "&sound=" + "telegraph";
            }
            return params;
        }
    
        /**
         * Check if result is successful
         * @param {object} result Axios response object
         * @returns {void}
         * @throws {Error} The status code is not in range 2xx
         */
        checkResult(result) {
            if (result.status == null) {
                throw new Error("Bark notification failed with invalid response!");
            }
            if (result.status < 200 || result.status >= 300) {
                throw new Error("Bark notification failed with status code " + result.status);
            }
        }
    
        /**
         * Send the message
         * @param {BeanModel} notification Notification to send
         * @param {string} title Message title
         * @param {string} subtitle Message
         * @param {string} endpoint Endpoint to send request to
         * @returns {Promise<string>} Success message
         */
        async postNotification(notification, title, subtitle, endpoint) {
            let result;
            if (notification.apiVersion === "v1" || notification.apiVersion == null) {
                // url encode title and subtitle
                title = encodeURIComponent(title);
                subtitle = encodeURIComponent(subtitle);
                const params = this.additionalParameters(notification);
                result = await axios.get(`${endpoint}/${title}/${subtitle}${params}`);
            } else {
                result = await axios.post(`${endpoint}/push`, {
                    title,
                    body: subtitle,
                    icon: barkNotificationAvatar,
                    sound: notification.barkSound || "telegraph", // default sound is telegraph
                    group: notification.barkGroup || "UptimeKuma", // default group is UptimeKuma
                });
            }
            this.checkResult(result);
            if (result.statusText != null) {
                return "Bark notification succeed: " + result.statusText;
            }
            // because returned in range 200 ..< 300
            return successMessage;
        }
    }
    
    module.exports = Bark;