Skip to content

Commit ad7d682

Browse files
committed
Update help text and configuration handling; replace static values with dynamic placeholders for gong, vote, and flush limits
1 parent 36476a5 commit ad7d682

File tree

2 files changed

+84
-167
lines changed

2 files changed

+84
-167
lines changed

helpText.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Current commands!
22
=== === === === === === ===
33
`add` *text* : add song to the queue and start playing if idle. Will start with a fresh queue.
44
`addalbum` *text* : add an album to the queue and start playing if idle. Will start with a fresh queue.
5-
`bestof` : *text* : add topp 10 tracks by the artist
5+
`bestof` : *text* : add top 10 tracks by the artist
66
`status` : show current status of Sonos
77
`current` : list current track
88
`search` *text* : search for a track, does NOT add it to the queue
@@ -12,10 +12,10 @@ Current commands!
1212
`append` *text* : append a song to the previous playlist and start playing the same list again.
1313
`vote` *number* : vote for a track to be played next!!! :rocket:
1414
`votecheck` : how many votes there are currently, as well as who has voted.
15-
`gong` : current track is bad! *5* gongs will skip the track
15+
`gong` : current track is bad! *{{gongLimit}}* gongs will skip the track
1616
`gongcheck` : how many gong votes there are currently, as well as who has gonged.
17-
`voteimmune` *number* : vote to make the current track immune to gong. *3* votes will make it immune
18-
`flushvote` : vote to flush the queue. *4* votes will flush the queue :toilet:
17+
`voteimmune` *number* : vote to make the current track immune to gong. *{{voteLimit}}* votes will make it immune
18+
`flushvote` : vote to flush the queue. *{{flushVoteLimit}}* votes will flush the queue :toilet:
1919
`upnext` : show the next track to be played
2020
`volume` : view current volume
2121
`list` : list current queue

index.js

Lines changed: 80 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,10 +1057,22 @@ function _help(input, channel) {
10571057
const adminMessage = fs.readFileSync(helpTextPathAdmin, 'utf8');
10581058
let message = fs.readFileSync(helpTextPath, 'utf8');
10591059

1060+
// Read configuration values
1061+
const gongLimit = config.get('gongLimit');
1062+
const voteLimit = config.get('voteLimit');
1063+
const flushVoteLimit = config.get('flushVoteLimit');
1064+
const maxVolume = config.get('maxVolume');
1065+
1066+
// Replace placeholders in help text
1067+
message = message.replace(/{{gongLimit}}/g, gongLimit);
1068+
message = message.replace(/{{voteLimit}}/g, voteLimit);
1069+
message = message.replace(/{{flushVoteLimit}}/g, flushVoteLimit);
1070+
message = message.replace(/{{maxVolume}}/g, maxVolume);
1071+
10601072
if (channel === global.adminChannel) {
10611073
message += '\n' + adminMessage;
10621074
}
1063-
_slackMessage(message, channel)
1075+
_slackMessage(message, channel);
10641076
}
10651077

10661078
function _play(input, channel, userName, state) {
@@ -1788,49 +1800,19 @@ function _status(channel, state) {
17881800
})
17891801
}
17901802

1791-
// Ensure the _debug function is defined
1803+
1804+
17921805
async function _debug(channel, userName) {
17931806
_logUserAction(userName, 'debug');
17941807
var url = 'http://' + sonosIp + ':1400/xml/device_description.xml';
17951808

1796-
// Function to get the IP address of the machine (Docker container if inside Docker)
1797-
function getIPAddress() {
1798-
const interfaces = os.networkInterfaces();
1799-
for (const name of Object.keys(interfaces)) {
1800-
for (const iface of interfaces[name]) {
1801-
if (iface.family === 'IPv4' && !iface.internal) {
1802-
return iface.address;
1803-
}
1804-
}
1805-
}
1806-
return 'IP address not found';
1807-
}
1808-
1809-
// Improved function to check if running inside Docker
1810-
function isRunningInDocker() {
1811-
try {
1812-
// Check if running in Docker by inspecting /proc/1/cgroup and the presence of .dockerenv
1813-
const cgroup = fs.readFileSync('/proc/1/cgroup', 'utf8');
1814-
if (cgroup.includes('docker')) {
1815-
return true;
1816-
}
1817-
} catch (err) {
1818-
// Ignore errors, continue to next check
1819-
}
1820-
1821-
try {
1822-
// Check if .dockerenv file exists (another indication of being inside Docker)
1823-
if (fs.existsSync('/.dockerenv')) {
1824-
return true;
1825-
}
1826-
} catch (err) {
1827-
// Ignore errors
1809+
function maskSensitiveInfo(value) {
1810+
if (typeof value === 'string' && value.length > 6) {
1811+
return value.slice(0, 3) + '--xxx-MASKED-xxx--' + value.slice(-3);
18281812
}
1829-
1830-
return false; // Default to not inside Docker if all checks fail
1813+
return value;
18311814
}
18321815

1833-
// Function to get the host's IP address if running inside Docker
18341816
function getHostIPAddress() {
18351817
try {
18361818
const result = fs.readFileSync('/proc/net/route', 'utf8');
@@ -1853,7 +1835,6 @@ async function _debug(channel, userName) {
18531835
}
18541836
}
18551837

1856-
// Helper function to convert hex IP from /proc/net/route to a readable IP address
18571838
function hexToIp(hex) {
18581839
return [
18591840
parseInt(hex.slice(6, 8), 16),
@@ -1863,25 +1844,36 @@ async function _debug(channel, userName) {
18631844
].join('.');
18641845
}
18651846

1866-
const isDocker = isRunningInDocker(); // Improved check for Docker environment
1847+
const isRunningInDocker = () => {
1848+
try {
1849+
const cgroup = fs.readFileSync('/proc/1/cgroup', 'utf8');
1850+
if (cgroup.includes('docker')) {
1851+
return true;
1852+
}
1853+
} catch (err) {}
1854+
1855+
try {
1856+
if (fs.existsSync('/.dockerenv')) {
1857+
return true;
1858+
}
1859+
} catch (err) {}
1860+
1861+
return false;
1862+
};
1863+
1864+
const isDocker = isRunningInDocker();
18671865

18681866
if (isDocker) {
1869-
// Check if IP is defined in the environment
1870-
// Get the IP address from the configuration
1871-
console.log('IP Address from config:', ipAddress);
18721867
if (!ipAddress) {
1873-
// Log error and set a default value for IP
18741868
const warningMessage = 'Make sure you have configured IP in the config.json';
18751869
logger.error(warningMessage);
1876-
ipAddress = warningMessage; // Set the value of IP to the warning message
1870+
ipAddress = warningMessage;
18771871
}
18781872
} else {
1879-
ipAddress = getIPAddress(); // IP of the machine if not in Docker
1873+
ipAddress = getIPAddress();
18801874
}
18811875

1882-
const dockerIPAddress = isDocker ? getHostIPAddress() : null; // Host IP if running inside Docker
1883-
1884-
// Define nodeVersion outside the if block
1876+
const dockerIPAddress = isDocker ? getHostIPAddress() : null;
18851877
const nodeVersion = JSON.stringify(process.versions);
18861878

18871879
xmlToJson(url, async function (err, data) {
@@ -1890,86 +1882,35 @@ async function _debug(channel, userName) {
18901882
logger.error('Error occurred ' + err);
18911883
sonosInfo = 'SONOS device is offline or not responding.';
18921884
} else {
1893-
logger.info('BuildNumber of SlackONOS: ', buildNumber);
1894-
logger.info('Platform: ', process.platform);
1895-
logger.info('Node version: ', process.version);
1896-
logger.info('Node dependencies: ', process.versions);
1897-
1898-
// Log Sonos information
1899-
logger.info(data.root.device[0].modelDescription);
1900-
logger.info(data.root.device[0].softwareVersion);
1901-
logger.info(data.root.device[0].displayName);
1902-
logger.info(data.root.device[0].hardwareVersion);
1903-
logger.info(data.root.device[0].apiVersion);
1904-
logger.info(data.root.device[0].roomName);
1905-
logger.info(data.root.device[0].friendlyName);
1906-
logger.info(data.root.device[0].modelNumber);
1907-
logger.info(data.root.device[0].serialNum);
1908-
logger.info(data.root.device[0].MACAddress);
1909-
19101885
sonosInfo =
19111886
'\n*Sonos Info*' +
1912-
'\nFriendly Name: ' + (data.root.device[0].friendlyName) +
1913-
'\nRoom Name: ' + (data.root.device[0].roomName) +
1914-
'\nDisplay Name: ' + (data.root.device[0].displayName) +
1915-
'\nModel Description: ' + (data.root.device[0].modelDescription) +
1916-
'\nModelNumber: ' + (data.root.device[0].modelNumber) +
1917-
'\nSerial Number: ' + (data.root.device[0].serialNum) +
1918-
'\nMAC Address: ' + (data.root.device[0].MACAddress) +
1919-
'\nSW Version: ' + (data.root.device[0].softwareVersion) +
1920-
'\nHW Version: ' + (data.root.device[0].hardwareVersion) +
1921-
'\nAPI Version: ' + (data.root.device[0].apiVersion);
1887+
'\nFriendly Name: ' + data.root.device[0].friendlyName;
19221888
}
19231889

1924-
// Get memory usage
19251890
const memoryUsage = process.memoryUsage();
1926-
const formattedMemoryUsage = `
1927-
*Memory Usage*:
1928-
RSS: ${Math.round(memoryUsage.rss / 1024 / 1024)} MB
1929-
Heap Total: ${Math.round(memoryUsage.heapTotal / 1024 / 1024)} MB
1930-
Heap Used: ${Math.round(memoryUsage.heapUsed / 1024 / 1024)} MB
1931-
External: ${Math.round(memoryUsage.external / 1024 / 1024)} MB
1932-
Array Buffers: ${Math.round(memoryUsage.arrayBuffers / 1024 / 1024)} MB
1933-
`;
1934-
1935-
// Get uptime
1936-
const uptime = process.uptime();
1937-
const formattedUptime = `
1938-
*Uptime*: ${Math.floor(uptime / 60)} minutes ${Math.floor(uptime % 60)} seconds
1939-
`;
1940-
1941-
// Get network interfaces
1942-
const networkInterfaces = os.networkInterfaces();
1943-
const formattedNetworkInterfaces = Object.entries(networkInterfaces).map(([name, addresses]) => {
1944-
return addresses.map(addr => `${name}: ${addr.address}`).join('\n');
1945-
}).join('\n');
1946-
1947-
// Get disk usage (example for Unix-like systems)
1948-
const diskUsage = execSync('df -h /').toString();
1949-
const formattedDiskUsage = `
1950-
*Disk Usage*:
1951-
${diskUsage}
1952-
`;
1953-
1954-
1955-
1956-
// Read configuration values only from config.json
1957-
const configKeys = Object.keys(config.stores.file.store); // Access only the file-based store
1958-
const configValues = configKeys.map(key => `${key}: ${config.get(key)}`).join('\n');
1959-
1960-
// Debug log for verification
1961-
logger.info('DEBUG -- Config values from config.json: ' + configValues);
1962-
1963-
// Ensure environment variables are handled separately
1964-
const envVars = `
1965-
*Environment Variables*:
1966-
NODE_VERSION: ${process.env.NODE_VERSION || 'not set'}
1967-
HOSTNAME: ${process.env.HOSTNAME || 'not set'}
1968-
YARN_VERSION: ${process.env.YARN_VERSION || 'not set'}
1969-
HOME: ${process.env.HOME || 'not set'}
1970-
PATH: ${process.env.PATH}
1971-
PWD: ${process.env.PWD}
1972-
`;
1891+
const formattedMemoryUsage = `\n*Memory Usage*:\n RSS: ${Math.round(memoryUsage.rss / 1024 / 1024)} MB`;
1892+
1893+
const envVars = `\n*Environment Variables*:\n NODE_VERSION: ${process.env.NODE_VERSION || 'not set'}\n HOSTNAME: ${process.env.HOSTNAME || 'not set'}\n YARN_VERSION: ${process.env.YARN_VERSION || 'not set'}`;
1894+
1895+
const sensitiveKeys = ['token', 'spotifyClientId', 'spotifyClientSecret', 'openaiApiKey'];
1896+
const configKeys = Object.keys(config.stores.file.store);
1897+
const configValues = configKeys
1898+
.map(key => {
1899+
const value = config.get(key);
1900+
return sensitiveKeys.includes(key) ? `${key}: ${maskSensitiveInfo(value)}` : `${key}: ${value}`;
1901+
})
1902+
.join('\n');
1903+
1904+
// Identify missing configuration values
1905+
const defaultConfig = config.stores.defaults.store;
1906+
const missingConfigValues = Object.keys(defaultConfig)
1907+
.filter(key => !configKeys.includes(key))
1908+
.map(key => {
1909+
const value = defaultConfig[key].value || defaultConfig[key];
1910+
return value === 'literal' ? null : `${key}: ${value}`;
1911+
})
1912+
.filter(line => line !== null) // Remove excluded entries
1913+
.join('\n');
19731914

19741915
const blocks = [
19751916
{
@@ -2012,16 +1953,6 @@ ${diskUsage}
20121953
{
20131954
type: 'divider'
20141955
},
2015-
{
2016-
type: 'section',
2017-
text: {
2018-
type: 'mrkdwn',
2019-
text: formattedUptime
2020-
}
2021-
},
2022-
{
2023-
type: 'divider'
2024-
},
20251956
{
20261957
type: 'section',
20271958
text: {
@@ -2032,45 +1963,30 @@ ${diskUsage}
20321963
{
20331964
type: 'divider'
20341965
},
2035-
{
2036-
type: 'section',
2037-
text: {
2038-
type: 'mrkdwn',
2039-
text: '*Network Interfaces*\n' + formattedNetworkInterfaces
2040-
}
2041-
},
2042-
{
2043-
type: 'divider'
2044-
},
2045-
{
2046-
type: 'section',
2047-
text: {
2048-
type: 'mrkdwn',
2049-
text: formattedDiskUsage
2050-
}
2051-
},
2052-
{
2053-
type: 'divider'
2054-
},
20551966
{
20561967
type: 'section',
20571968
text: {
20581969
type: 'mrkdwn',
20591970
text: '*Configuration Values*\n' + configValues
20601971
}
2061-
},
2062-
{
2063-
type: 'divider'
2064-
},
2065-
{
2066-
type: 'section',
2067-
text: {
2068-
type: 'mrkdwn',
2069-
text: envVars
2070-
}
20711972
}
20721973
];
20731974

1975+
if (missingConfigValues) {
1976+
blocks.push(
1977+
{
1978+
type: 'divider'
1979+
},
1980+
{
1981+
type: 'section',
1982+
text: {
1983+
type: 'mrkdwn',
1984+
text: '*Missing Configuration Values*\n' + missingConfigValues
1985+
}
1986+
}
1987+
);
1988+
}
1989+
20741990
const message = {
20751991
channel: channel,
20761992
blocks: blocks
@@ -2089,6 +2005,7 @@ ${diskUsage}
20892005

20902006

20912007

2008+
20922009
async function _blacklist(input, channel, userName) {
20932010
_logUserAction(userName, 'blacklist');
20942011
if (channel !== global.adminChannel) {

0 commit comments

Comments
 (0)