Last active
March 11, 2019 10:08
-
-
Save simone-sanfratello/119682185edaff6a992d1ea5f371556e to your computer and use it in GitHub Desktop.
mute spotify on matching title
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"list": [ | |
"spotify", | |
"meer info", | |
"consegna gratuita", | |
"scopri di pi", | |
"advertisement", | |
"ascolta adesso", | |
"power it", | |
"hits unlimited", | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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