You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
4.9 KiB
160 lines
4.9 KiB
/**
|
|
* @module flitter-gotify/src/unit/NotifyUnit
|
|
*/
|
|
const Unit = require('libflitter/Unit')
|
|
const ncp = require('ncp')
|
|
const path = require('path')
|
|
|
|
/**
|
|
* Unit providing a service for sending Gotify notifications to grouped channels.
|
|
* @extends module:libflitter/Unit~Unit
|
|
*/
|
|
class NotifyUnit extends Unit {
|
|
/**
|
|
* Get the services required by this unit.
|
|
* @type {Array<string>}
|
|
*/
|
|
static get services() {
|
|
return [...super.services, 'configs', 'output']
|
|
}
|
|
|
|
/**
|
|
* Get the name of the service provided by this unit: 'notify'
|
|
* @type {string}
|
|
*/
|
|
static get name() {
|
|
return 'notify'
|
|
}
|
|
|
|
/**
|
|
* The URL to the Gotify host. False if unset.
|
|
* @type {string|boolean}
|
|
*/
|
|
host = false
|
|
|
|
/**
|
|
* Mapping of group names to array of Gotify app keys.
|
|
* @type {object}
|
|
*/
|
|
groups = {}
|
|
|
|
/**
|
|
* Instantiate the service. Optionally, provide an instance of Axios to use.
|
|
* @param {axios} [axios = null] - reference to the Axios library. Normally, don't set this. Used for testing.
|
|
*/
|
|
constructor(axios = null) {
|
|
super()
|
|
this.axios = axios ? axios : require('axios').default
|
|
}
|
|
|
|
/**
|
|
* Initialize the unit. Attempts to load in the 'notify' config.
|
|
* @param {module:libflitter/app/FlitterApp~FlitterApp} app
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async go(app) {
|
|
const notify = this.configs.get('notify')
|
|
if ( notify && notify.host && notify.groups ) {
|
|
this.host = notify.host
|
|
this.groups = notify.groups
|
|
} else {
|
|
this.output.warn('Missing config for flitter-gotify. The service will not initialize.')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deploy the config template for this service.
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async deploy() {
|
|
const package_dir = __dirname
|
|
function do_copy(from, to) {
|
|
return new Promise(
|
|
(resolve, reject) => {
|
|
ncp(from, to, (error) => {
|
|
if (error) reject(error)
|
|
|
|
resolve()
|
|
})
|
|
}
|
|
)
|
|
}
|
|
|
|
this.output.info('Deploying notify config from '+path.resolve(package_dir, '../deploy/config'))
|
|
await do_copy(path.resolve(package_dir, '../deploy/config'), this.app.directories.configs)
|
|
}
|
|
|
|
/**
|
|
* Send a notification to the configured channel.
|
|
* @param {string} title
|
|
* @param {string} message
|
|
* @param {number} [priority = 5] - the Gotify priority
|
|
* @param {string} [channel = 'default'] - the name of the configured channel group
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async send(title, message, priority = 5, channel = 'default') {
|
|
const group = this.get_group_or_fail(channel)
|
|
const promises = group.map(x => this.send_one(x, title, message, priority))
|
|
await Promise.all(promises)
|
|
}
|
|
|
|
/**
|
|
* Send a notification to a single app key.
|
|
* @param {string} token - the Gotify app key
|
|
* @param {string} title
|
|
* @param {string} message
|
|
* @param {number} [priority = 5]
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async send_one(token, title, message, priority = 5) {
|
|
return this.send_raw(token, {title, message, priority})
|
|
}
|
|
|
|
/**
|
|
* Send a raw POST request to the message endpoint for the specified token.
|
|
* @param {string} token - the Gotify app key
|
|
* @param {object} data - POST data
|
|
* @returns {Promise<axios/Response>}
|
|
*/
|
|
async send_raw(token, data = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
this.axios.post(this.get_message_endpoint(token), data).then(response => {
|
|
resolve(response)
|
|
}).catch(e => reject(e))
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Get the fully-qualified URL to the message endpoint for the given token.
|
|
* @param {string} token - the Gotify app key
|
|
* @returns {string}
|
|
*/
|
|
get_message_endpoint(token) {
|
|
return `${this.host}${this.host.endsWith('/') ? '' : '/'}message?token=${token}`
|
|
}
|
|
|
|
/**
|
|
* Get the app keys for the configured notification channel group.
|
|
* @param {string} group - the configured group name
|
|
* @returns {Array<string>|undefined} - array of Gotify app keys
|
|
*/
|
|
get_group_config(group = 'default') {
|
|
if ( this.host && this.groups && this.groups[group] && Array.isArray(this.groups[group]) ) {
|
|
return this.groups[group].filter(Boolean)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Same as get_group_config, but throw an error if we don't have a config for the specified group.
|
|
* @param {string} group - the configured group name
|
|
* @returns {Array<string>} - array of Gotify app keys
|
|
*/
|
|
get_group_or_fail(group) {
|
|
const config = this.get_group_config(group)
|
|
if ( !config ) throw new Error(`Cannot push notification to group ${group}: invalid or missing configuration.`)
|
|
return config
|
|
}
|
|
}
|
|
|
|
module.exports = exports = NotifyUnit
|