Skip to content

Instantly share code, notes, and snippets.

@adrum
Forked from rfletcher/app.js
Last active December 31, 2023 07:01
Show Gist options
  • Save adrum/e33f5f240fecc7e41c3d90325d0fce6d to your computer and use it in GitHub Desktop.
Save adrum/e33f5f240fecc7e41c3d90325d0fce6d to your computer and use it in GitHub Desktop.
A simple bridge between iMessage and Home Assistant's conversation component
const HomeAssistant = require( 'homeassistant' );
const Pino = require( 'pino' );
const config = require( 'config' );
const hass = new HomeAssistant( config.get( 'home_assistant' ) );
const imessage = require( 'osa-imessage' );
const logger = Pino();
// TODO package this better
const bridge = {
handleMessage: function( sender, text ) {
logger.info( `from ${sender}: ${text}` );
hass.services._post( '/conversation/process', null, {
text: text
} )
.then( res => {
imessage.send( sender, res.speech.plain.speech );
} )
.catch( err => {
logger.error( err );
imessage.send( sender, "Sorry, something broke" );
} );
}
}
imessage.listen().on( 'message', ( msg ) => {
if ( msg.fromMe ) {
logger.warn( `ignoring message from myself: ${msg.text}` );
return;
}
if ( ! config.get( 'allowed_senders' ).includes( msg.handle ) ) {
logger.warn( `ignoring message from unknown sender: ${msg.handle}: ${msg.text}` );
return;
}
bridge.handleMessage( msg.handle, msg.text );
} );
// Setup notify service
if (config.notify.port) {
const express = require('express');
const app = express();
app.use(express.json());
app.post('/notify', async function(req, res){
const to = req.body.to
let message = req.body.message;
if (req.body.title) message = `${req.body.title}\n${message}`
// Check auth
if (config.notify.token) {
const token = (req.body.token || req.query.token || req.headers['authorization'] || '').replace('Bearer ', '').replace('Token ', '');
if (token != config.notify.token) {
logger.error( `unauthorized send: ${message} : ${e}` );
return res.status(403).json({error: 'Unauthorized'});
}
}
logger.info(`${JSON.stringify(req.body)}`)
// Send to imessage
try {
await imessage.send( to, message );
logger.error( `sent message: ${to} : ${message}` );
} catch(e) {
logger.error( `error sending: ${message} : ${e}` );
return res.status(500).json({error: 'iMessage Error'});
}
res.status(200).json({status: true})
})
var server = app.listen(config.notify.port, function () {
var host = server.address().address
var port = server.address().port
console.log("Home Assistant iMessage Notify Service listening at http://%s:%s", host, port)
})
}
---
allowed_senders:
- "me@example.com"
home_assistant:
host: "http://<your home assistant host or ip>"
port: 8123
token: "<your home assistant token>"
notify:
port: 8124
token: "<your imessage notify token>"
# Include this in your Home Assistant configuration.yaml
notify:
- name: imessage
platform: rest
resource: http://<your mac ip or hostname>:8124/notify
method: 'POST_JSON'
headers:
Authorization: Token <your imessage notify token>
title_param_name: 'title'
data_template:
to: '+15551236789'
{
"name": "imessage-home-assistant",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start": "node app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"dependencies": {
"config": "3.0.1",
"express": "^4.16.4",
"homeassistant": "0.2.0",
"js-yaml": "3.12.1",
"osa-imessage": "2.4.2",
"pino": "5.11.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment