Skip to content

Instantly share code, notes, and snippets.

@simone-sanfratello
Last active March 11, 2019 10:08
Show Gist options
  • Save simone-sanfratello/119682185edaff6a992d1ea5f371556e to your computer and use it in GitHub Desktop.
Save simone-sanfratello/119682185edaff6a992d1ea5f371556e to your computer and use it in GitHub Desktop.
mute spotify on matching title
{
"list": [
"spotify",
"meer info",
"consegna gratuita",
"scopri di pi",
"advertisement",
"ascolta adesso",
"power it",
"hits unlimited",
]
}
#!/usr/bin/env node
// @todo check apt install pulseaudio alsa-utils
const cprocess = require('child_process')
const fs = require('fs')
const path = require('path')
const os = require('os')
const util = require('util')
const DEFAULT_CONFIG = '{"list": ["advertisement"]}'
const DEFAULT_CONFIG_FILE = path.join(os.homedir(), 'mute-spoty.cfg.js')
const DEFAULT_TIMER = 2500
const HOSTNAME = os.hostname()
const COMMAND = {
TEST: 'wmctrl -lx',
GET_TITLE: 'wmctrl -lx | grep spotify.Spotify',
CHANNELS: 'pactl list sink-inputs',
MUTE: 'pactl set-sink-input-mute %s 1',
UNMUTE: 'pactl set-sink-input-mute %s 0',
MUTE_ALL: 'amixer -D pulse sset Master mute',
UNMUTE_ALL: 'amixer -D pulse sset Master unmute'
}
if (process.argv.includes('-h') || process.argv.includes('--help')) {
console.log(process.argv[1], '[-v] verbose')
console.log('[-t] [timer ms] polling timer check; default ', DEFAULT_TIMER)
console.log('[-s] [config file] config file; default ', DEFAULT_CONFIG_FILE)
console.log('example', process.argv[1], '-v -t 1500')
process.exit(0)
}
const verbose = process.argv.indexOf('-v') > 0
const timer = process.argv.indexOf('-t') > 0 ? process.argv[process.argv.indexOf('-t') + 1] || DEFAULT_TIMER : DEFAULT_TIMER
const configFile = process.argv.indexOf('-s') > 0 ? process.argv[process.argv.indexOf('-s') + 1] || DEFAULT_CONFIG_FILE : DEFAULT_CONFIG_FILE
const loadConfig = function () {
return new Promise((resolve, reject) => {
try {
fs.readFile(configFile, 'utf8', (err, content) => {
if (err) {
return reject(err)
}
const _list = JSON.parse(content).list
log('load config file', configFile, _list)
resolve(_list)
})
} catch (e) {
reject(e)
}
})
}
const createConfig = function () {
return new Promise((resolve, reject) => {
try {
fs.writeFile(configFile, DEFAULT_CONFIG, 'utf8', (err, content) => {
if (err) {
return reject(err)
}
log('create config file', configFile)
resolve([])
})
} catch (e) {
reject(e)
}
})
}
const getChannel = async function () {
const _channels = await exec(COMMAND.CHANNELS)
const _channel = _channels.split('Sink Input #').find((channel) => {
return channel.includes('spotify') || channel.includes('Spotify')
})
return _channel.split('\n')[0]
}
const log = function (...args) {
if (!verbose) {
return
}
console.log.apply(null, args)
}
const exec = function (cmd) {
return new Promise((resolve, reject) => {
cprocess.exec(cmd, (err, stdout, stderr) => {
if (err) {
// console.error('error on', cmd, err)
return reject(err)
}
resolve(stdout)
})
})
}
const main = async function () {
let banList
try {
await exec(COMMAND.TEST)
} catch (e) {
console.error('wmctrl not installed')
console.info('sudo apt install wmctrl')
process.exit(-1)
}
try {
banList = await loadConfig()
} catch (error) {
banList = await createConfig()
}
fs.watch(configFile, async () => {
try {
banList = await loadConfig()
} catch (e) {
console.error(e)
banList = []
}
})
let _isMute, _now, _channel
let _mute, _unmute
setInterval(async () => {
let _out
try {
_out = await exec(COMMAND.GET_TITLE)
} catch (e) {
log('spotify is not running')
return
}
if (!_channel && !_mute) {
try {
_channel = await getChannel()
log('spotify channel is', _channel)
_mute = util.format(COMMAND.MUTE, _channel)
_unmute = util.format(COMMAND.UNMUTE, _channel)
} catch (e) {
log('unable to find spotify channel, mute all sound')
_mute = COMMAND.MUTE_ALL
_unmute = COMMAND.MUTE_ALL
}
}
try {
const _title = _out.substr(_out.indexOf(HOSTNAME) + HOSTNAME.length).trim()
const _match = _title.toLocaleLowerCase()
for (const _ban of banList) {
if (_match.indexOf(_ban) !== -1) {
if (!_isMute) {
log('(mute) ban:', _title)
await exec(_mute)
_isMute = true
}
return
}
}
if (_title !== _now) {
log('now playing:', _title)
_now = _title
}
if (_isMute) {
log('(unmute)')
await exec(_unmute)
_isMute = false
}
} catch (e) {
console.error(e)
process.exit(-1)
}
}, timer)
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment