info.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. const { Errors, colors, allOfType } = require("svcorelib");
  2. const { join, resolve } = require("path");
  3. const { getEnv, getProp } = require("../src/env");
  4. const parseJokes = require("../src/parseJokes");
  5. const languages = require("../src/languages");
  6. const translate = require("../src/translate");
  7. const settings = require("../settings");
  8. const { readdir } = require("fs-extra");
  9. const col = colors.fg;
  10. const { exit } = process;
  11. /** @typedef {import("svcorelib").Stringifiable} Stringifiable */
  12. /** @typedef {import("./types").SubmissionInfoResult} SubmissionInfoResult */
  13. /** @typedef {import("../src/types/languages").LangCode} LangCode */
  14. async function run()
  15. {
  16. try
  17. {
  18. try
  19. {
  20. await languages.init();
  21. await translate.init();
  22. await parseJokes.init();
  23. }
  24. catch(err)
  25. {
  26. console.log(`\n${col.red}Error while initializing:${col.rst}${err instanceof Error ? `${err.message}\n${err.stack}` : `\n${err.toString()}`}\n`);
  27. exit(1);
  28. }
  29. /**
  30. * Decorates an array value with colors and other stuff
  31. * @param {Stringifiable[]} val
  32. */
  33. const n = val => {
  34. const ln = val.length;
  35. const lhs = `(${ln > 0 ? "" : col.yellow}${val.length}${col.rst})`;
  36. const rhs = `${col.green}${val.join(`${col.rst}, ${col.green}`)}${col.rst}`;
  37. return `${lhs}: ${rhs}`;
  38. };
  39. /**
  40. * Decorates a value with colors and other stuff
  41. * @param {number|string} val
  42. */
  43. const v = val => {
  44. const valCol = typeof val === "number" ? (val > 0 ? col.green : col.yellow) : col.green;
  45. const value = Array.isArray(val) && allOfType(val, "string") ? val.join(`${col.rst}, ${valCol}`) : val;
  46. return ` ${valCol}${value}${col.rst}`;
  47. };
  48. const { jokes, subm, http } = await getInfo("submissions");
  49. /** The lines that get printed to the console to display JokeAPI's info */
  50. const lines = [
  51. `${col.blue}${settings.info.name}${col.rst} v${settings.info.version} [${getEnv(true)}] - Info`,
  52. ``,
  53. `${col.blue}Jokes:${col.rst}`,
  54. ` Total amount: ${v(jokes.totalAmt)}`,
  55. ` Joke languages ${n(jokes.languages)}`,
  56. ``,
  57. `${col.blue}Submissions:${col.rst}`,
  58. ` Amount: ${v(subm.amount)}`,
  59. ` Languages ${n(subm.languages)}`,
  60. ``,
  61. `${col.blue}HTTP Server:${col.rst}`,
  62. ` Port: ${v(http.port)}`,
  63. ` BaseURL: ${v(http.baseUrl)}`,
  64. ];
  65. process.stdout.write(`\n${lines.join("\n")}\n\n`);
  66. exit(0);
  67. }
  68. catch(err)
  69. {
  70. console.log(`\n${col.red}Error while displaying info:${col.rst}${err instanceof Error ? `${err.message}\n${err.stack}` : `\n${err.toString()}`}\n`);
  71. exit(1);
  72. }
  73. }
  74. /**
  75. * Returns all information about JokeAPI
  76. */
  77. async function getInfo()
  78. {
  79. const { allJokes } = parseJokes;
  80. /** @type {LangCode[]} */
  81. const jokeLangs = Object.keys(allJokes.getJokeCountPerLang());
  82. const { submCount, submLangs } = await getSubmissionInfo();
  83. return {
  84. /** Internal jokes */
  85. jokes: {
  86. totalAmt: allJokes._jokeCount,
  87. languages: jokeLangs,
  88. },
  89. /** Joke submissions */
  90. subm: {
  91. amount: submCount,
  92. languages: submLangs,
  93. },
  94. /** HTTP server */
  95. http: {
  96. port: getProp("httpPort"),
  97. baseUrl: getProp("baseUrl"),
  98. },
  99. // ...
  100. }
  101. }
  102. /**
  103. * Resolves with some info about the submissions JokeAPI has received
  104. * @returns {Promise<SubmissionInfoResult, Error>}
  105. */
  106. function getSubmissionInfo()
  107. {
  108. return new Promise(async (res, rej) => {
  109. try
  110. {
  111. const submBasePath = resolve(settings.jokes.jokeSubmissionPath);
  112. const langs = await readdir(submBasePath);
  113. const submFolders = langs.map(lang => join(submBasePath, lang));
  114. const submissionFiles = [];
  115. for await(const folder of submFolders)
  116. (await readdir(folder))
  117. .forEach(file => submissionFiles.push(file));
  118. return res({
  119. submCount: submissionFiles.length,
  120. submLangs: langs,
  121. });
  122. }
  123. catch(err)
  124. {
  125. return rej(err);
  126. }
  127. });
  128. }
  129. //#SECTION on execute
  130. (() => {
  131. try
  132. {
  133. if(!process.stdin.isTTY)
  134. throw new Errors.NoStdinError("The process doesn't have an stdin channel to read input from");
  135. else
  136. run();
  137. }
  138. catch(err)
  139. {
  140. console.error(`${col.red}${err.message}${col.rst}\n${err.stack}\n`);
  141. exit(0);
  142. }
  143. })();