// ----------------------------------------------------------------- // CONFIG // ----------------------------------------------------------------- const cols = process.stdout.columns // const rows = process.stdout.rows const maxStatLength = Math.floor(cols / 4) const statNameSpacing = 5 const beforeRowSpace = 13 const coloredWords = { red: ['lred', 'thanks'], cyan: [ 'getveteranpw', 'pwrequest', 'getpw', 'availablepws', 'login', 'logout', ], green: [ 'manual', 'todos', 'allquestions', 'subjectbrowser', 'contribute', 'feedback', 'ranklist', 'allqr', 'possibleAnswers', ], blue: ['isadding', 'ask'], magenta: [ 'donate', 'tiszai', 'install', 'irc', 'discord', 'postfeedback', 'votetodo', 'registerscript', 'quickvote', ], } const filterFromDailyStats = [ 'savedQuestions', 'sio/f', 'sound/', '/img/', '.php', 'favicon', 'robots.txt', 'ads.txt', '/f/', '.git', ] // ----------------------------------------------------------------- const fs = require('fs') // eslint-disable-line const dir = process.argv[2] if (!dir) { console.log('No params') process.exit() } function getDayIndex(offset) { if (!offset) { offset = 0 } const date = new Date() if (offset) { date.setDate(date.getDate() + offset) } return ( date.getFullYear() + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2) ) } function hr(char) { console.log(C('blue') + getLetterNTimes(char || '-', cols) + C()) } function printHeader(text) { hr() console.log(C('green') + text + C()) hr() } function C(color) { if (color !== undefined) { color = color.toLowerCase() } if (color === 'redbg') { return '\x1b[41m' } if (color === 'bluebg') { return '\x1b[44m' } if (color === 'green') { return '\x1b[32m' } if (color === 'red') { return '\x1b[31m' } if (color === 'yellow') { return '\x1b[33m' } if (color === 'blue') { return '\x1b[34m' } if (color === 'magenta') { return '\x1b[35m' } if (color === 'cyan') { return '\x1b[36m' } return '\x1b[0m' } function readJSON(name) { return JSON.parse(fs.readFileSync(name, 'utf8')) } function tail(text, number) { const splitedText = text.split('\n') return splitedText.slice(Math.max(splitedText.length - number, 1)).join('\n') } function head(text, number) { return text .split('\n') .slice(0, number) .join('\n') } function countLinesMatching(text, toMatch) { let count = 0 text.split('\n').forEach((line) => { if (line.includes(toMatch.toLowerCase())) { count++ } }) return count } function readFile(name) { return fs.readFileSync(name, 'utf8') } function getLetterNTimes(letter, number) { let res = '' while (res.length < number) { res += letter } return res } function pCols(cols, rowTitles, colorNames, firstRowColor, showDiff) { // console.log(cols) let maxLength = 0 Object.keys(cols).forEach((key) => { if (cols[key].length > maxLength) { maxLength = cols[key].length } }) for (let i = 0; i < maxLength; i++) { const row = [] const lastItems = [] Object.keys(cols) .reverse() .forEach((key) => { const val = cols[key] if (!val[i]) { return } lastItems.push(val[i]) const keyName = val[i].name || val[i] let slicedName = keyName.slice(0, maxStatLength) const toColor = colorNames ? Object.keys(coloredWords).reduce((acc, key) => { const colorArray = coloredWords[key] const includes = colorArray.some((colorableIdName) => { return keyName .toLowerCase() .includes(colorableIdName.toLowerCase()) }) if (includes) { return key } return acc }, '') : false const sep = (i + 1) % 5 === 0 ? '.' : ' ' while (slicedName.length < maxStatLength) { slicedName = slicedName + sep } let ammount = val[i].val ? val[i].val.toString() : '' while (ammount.length < 4) { ammount = ammount + ' ' } if (toColor) { row.push(C(toColor) + slicedName + ' ' + ammount + C()) } else { row.push(slicedName + ' ' + ammount) } }) // ROW TITLE --------------------------------------------------- let currRowTitle = rowTitles && rowTitles[i] ? rowTitles[i] : getLetterNTimes(' ', beforeRowSpace) while (currRowTitle.length < beforeRowSpace) { currRowTitle = currRowTitle + ' ' } currRowTitle = C('blue') + currRowTitle + C() // COLORING ---------------------------------------------------- let res = '' if (firstRowColor && i === 0) { res = currRowTitle + C('green') + row.join(getLetterNTimes(' ', statNameSpacing)) + C() } else { res = currRowTitle + row.join(getLetterNTimes(' ', statNameSpacing)) } // SHOW DIFF --------------------------------------------------- if (showDiff && i !== 0) { let diff = lastItems[lastItems.length - 1] - lastItems[lastItems.length - 2] if (diff > 0) { diff = '+' + diff.toString() } res += C('blue') + diff + C() } console.log(res) } } // ------------------------------------------------------------------------------ printHeader('Daily stats') const dailyStats = readJSON(`${dir}stats/vstats`) function preProcessDailyStats(obj) { const formatted = Object.keys(obj).reduce((acc, key) => { const includes = filterFromDailyStats.some((keyword) => { return key.toLowerCase().includes(keyword.toLowerCase()) }) if (!includes) { acc.push({ name: key, val: obj[key] }) } return acc }, []) return formatted.sort((a, b) => { if (a.name > b.name) { return 1 } else if (a.name < b.name) { return -1 } else { return 0 } }) } pCols( [ preProcessDailyStats(dailyStats[getDayIndex()]), preProcessDailyStats(dailyStats[getDayIndex(-1)]), preProcessDailyStats(dailyStats[getDayIndex(-2)]), ], null, true ) // ------------------------------------------------------------------------------ printHeader('User id test solving') const userIdTestSolving = readJSON(`${dir}stats/idvstats`) function preProcessUIdTestSolving(obj, minLength) { if (!obj) { return '0' } if (minLength) { return Object.keys(obj) .filter((key) => { return obj[key] > minLength }) .length.toString() } else { return Object.keys(obj).length.toString() } } pCols( [ ['Today', preProcessUIdTestSolving(userIdTestSolving[getDayIndex()])], ['Yesterday', preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-1)])], [ 'Before yesterday', preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-2)]), ], ], null, false, 'green' ) // ------------------------------------------------------------------------------ printHeader('User id requests') const clientIdTestSolving = readJSON(`${dir}stats/uvstats`) pCols( [ [ 'Today', preProcessUIdTestSolving(clientIdTestSolving[getDayIndex()]), preProcessUIdTestSolving(clientIdTestSolving[getDayIndex()], 2), ], [ 'Yesterday', preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-1)]), preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-1)], 2), ], [ 'Before Yesterday', preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-2)]), preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-2)], 2), ], ], ['', 'All', 'More than 2'], false, 'green' ) // ------------------------------------------------------------------------------ printHeader('Daily data count') const dailyDataCount = readFile(`${dir}stats/dailyDataCount`) printLastDataCount([ JSON.parse(head(tail(dailyDataCount, 1), 1)), JSON.parse(head(tail(dailyDataCount, 2), 1)), JSON.parse(head(tail(dailyDataCount, 3), 1)), ]) function printLastDataCount(data) { const res = [['Today'], ['Yesterday'], ['Before yesterday']] data.forEach((dataCount, i) => { res[i].push(dataCount.userCount.toString()) res[i].push(dataCount.subjectCount.toString()) res[i].push(dataCount.questionCount.toString()) }) pCols(res, ['', 'Users', 'Subjects', 'Questions'], false, 'green', true) } // ------------------------------------------------------------------------------ printHeader('Daily script install / update check count') const todaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex()}`) const yesterdaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex(-1)}`) const beforeYesterdaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex(-2)}`) const installs = [ [ 'Today', countLinesMatching(todaysLogs, '?install').toString(), countLinesMatching(todaysLogs, '?up').toString(), ], [ 'Yesterday', countLinesMatching(yesterdaysLogs, '?install').toString(), countLinesMatching(yesterdaysLogs, '?up').toString(), ], [ 'Before yesterday', countLinesMatching(beforeYesterdaysLogs, '?install').toString(), countLinesMatching(beforeYesterdaysLogs, '?up').toString(), ], ] pCols(installs, ['', 'Installs', 'Updates'], false, 'green')