irc-radio-bot/index.js
2019-12-29 19:08:35 +01:00

177 lines
4.8 KiB
JavaScript

const radio = require('radio-stream')
const request = require('request')
const irc = require('irc-upd')
const Db = require('./libs/Db')
const models = require('./models').models
const Help = require('./libs/Help')
const ArtistSong = require('./libs/ArtistSong')
const When = require('./libs/When')
const Statistics = require('./libs/Statistics')
const List = require('./libs/List')
const allowedCommands = ['!artist', '!song', '!stats', '!when', '!help', '!notifications', '!list']
// Init des librairies
const db = new Db(models)
const artistSong = new ArtistSong(models)
const when = new When(models)
const stats = new Statistics(models)
const list = new List(models)
// Stockage du morceau en cours de lecture
let currentSong = {
artist: null,
title: null
}
let previousSong = {
artist: null,
title: null
}
// Initialisation du bot IRC
const bot = new irc.Client(process.env.IRC_SERVER, process.env.IRC_NICKNAME, {
userName: process.env.IRC_USER_NAME,
realName: process.env.IRC_REAL_NAME,
password: process.env.IRC_PASSWORD,
channels: [process.env.IRC_CHANNEL]
})
const checkCurrentSong = () => {
previousSong = currentSong
// Just for debug
console.info(`Now playing: ${currentSong.artist} - ${currentSong.title}`)
// Publish song on IRC channel
bot.say(process.env.IRC_CHANNEL, `${process.env.RADIO_ALIAS} : ${currentSong.artist} - ${currentSong.title}`)
// Save song for history
db.saveSong({
radio: process.env.RADIO_ALIAS,
artist: currentSong.artist,
title: currentSong.title
})
// Notify some people ?
artistSong.notify(botSay, process.env.IRC_CHANNEL, currentSong)
}
// Initialisation du stream radio
if (!process.env.STREAM_TYPE || process.env.STREAM_TYPE === 'radio') {
const stream = radio.createReadStream(process.env.STREAM_URL)
stream.on('connect', function () {
console.info('Radio Stream connected!')
console.info(stream.headers)
})
// Listener on new song
stream.on('metadata', function (data) {
let song = data.replace(/[^A-Za-z 0-9 .,?""!@#$%^&*()-_=+;:<>/\\|}{[\]`~]*/g, '')
song = song.substring(12, song.length - 1)
// Extract artist = title from song
const splitted = song.split(' - ')
const artist = splitted[0]
const title = splitted[1]
currentSong = {
title: title,
artist: artist
}
checkCurrentSong()
})
} else {
setInterval(() => {
request({
method: 'GET',
url: process.env.STREAM_URL
},
(error, response, body) => {
if (!error && response.statusCode === 200) {
const res = JSON.parse(body)
currentSong = {
title: res.title,
artist: res.artist
}
if (previousSong.title !== currentSong.title && previousSong.artist !== currentSong.artist) {
checkCurrentSong()
}
} else {
console.error('ERR:', error)
}
})
}, 4000)
}
// Gestion des erreurs du bot IRC
bot.addListener('error', function (message) {
console.error('ERR:', message)
})
/**
* Fonction permettant de publier un message sur IRC
* @param {String} where
* @param {String} what
*/
const botSay = (where, what) => {
bot.say(where, what)
}
/**
* Gestion des actions
* @param {String} where
* @param {String} message
* @param {String} from
*/
const actions = (where, message, from) => {
const exploded = message.split(' ')
// Le message publié est pour le bot
if (exploded[0].indexOf(process.env.IRC_NICKNAME) === 0) {
// Le message contient une commande
if (allowedCommands.indexOf(exploded[1]) !== -1) {
switch (exploded[1]) {
case '!artist':
case '!song':
artistSong.action(exploded[1].replace('!', ''), botSay, from, currentSong, exploded)
break
case '!help':
Help.show(botSay, where, exploded)
break
case '!when':
when.action(botSay, where, exploded)
break
case '!stats':
stats.action(botSay, where, exploded)
break
case '!list':
list.action(botSay, where, exploded)
break
default:
break
}
} else {
botSay(where, 'Commande inconnue, tape !help si tu es perdu')
}
}
}
// Listener for public message
bot.addListener(`message${process.env.IRC_CHANNEL}`, function (from, to, message) {
actions(process.env.IRC_CHANNEL, message.args.splice(1).join(' '), from)
})
// Listener for private message
bot.addListener('pm', function (from, to, message) {
actions(from, message.args.join(' '), from)
})
// Say hello!
if (process.env.SAY_HELLO && process.env.SAY_HELLO === 'true') {
bot.addListener('join', (channel, who) => {
// Welcome them in!
if (who !== process.env.IRC_NICKNAME) {
botSay(process.env.IRC_CHANNEL, 'Hello ' + who + '! Have a metal day! \\m/(-.-)\\m/')
}
})
}