UNPKG

leetcode-fetcher-cli

Version:

A CLi Application for local fetching of leetcode problems

269 lines (268 loc) 11 kB
"use strict"; /** * @author Riccardo La Marca * * @brief State-releated Commands: * - save [Save the current state into a json file] * - load [Load a saved state from a json file] * - set [Set the value of a variable in the state] * - unset [Reset the value of a variable in the state] * - show [Shows the current state (non-sensitive information)] */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.show_command = exports.load_command = exports.save_command = exports.unset_command = exports.set_command = void 0; const formatter_1 = require("../utils/formatter"); const general_1 = require("../utils/general"); const printer_1 = require("../utils/printer"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const constants_1 = __importDefault(require("../constants")); const chalk_1 = __importDefault(require("chalk")); const ConstructRegex = (name, vars, unset) => { const prefix = (0, formatter_1.FormatString)("^{0}", name); const regex_str = vars.map((value) => { const name_val = "(" + value.name + ")"; return (0, formatter_1.FormatString)("(?:\\s+{0})?", (unset || false) ? name_val : value.match); }).reduce((prev, curr) => (prev + curr)); return new RegExp(prefix + regex_str); }; const SetCommand = async (data, state) => { // Check that there is something not undefined if (data.every((x) => (x === undefined))) { console.error(chalk_1.default.redBright("Command formatted uncorrectly.")); return state; } // Take the variables that are being set by the command const keys = Object.keys(state.variables); for (let index = 0; index < data.length; index++) { if (data[index] === undefined) continue; const key = keys[index]; const _type = state.variables[key].type; state.variables[key].value = (_type === "s") ? data[index] : Number.parseInt(data[index]); } return state; }; // Set Command - Set the value of a variables exports.set_command = { group: 'State', name: 'Set Command', command: 'set', syntax: ConstructRegex('set', Object.values(constants_1.default.APP.APP_VARIABLES)), callback: SetCommand, help: 'set [VAR <value> ...] - Sets the value of a specific variable.\n' + 'To inspect which variables and values for each of them use the\n' + '`show` command. Notice that, if multiple values needs to be set\n' + 'the order in which they appear in the command must be the same\n' + 'as shown in the `show` command.\n' }; const UnsetCommand = async (data, state) => { // If no values are passed then all variables are resetted const condition = data.every((x) => (x === undefined)); if (condition) data = Object.keys(state.variables); for (let key in data) { if (key === undefined) continue; state.variables[key].value = state.variables[key].default; } return state; }; // Unset Command - Set variables to their default value exports.unset_command = { group: 'State', name: 'Unset Command', command: 'unset', syntax: ConstructRegex('unset', Object.values(constants_1.default.APP.APP_VARIABLES), true), callback: UnsetCommand, help: 'unset [VAR1 VAR2 ...] - Unset a variable by bringing back to its\n' + 'default value. Notice that the same rules of `set` holds here.\n' + 'If no variables are specified, consider resetting all of them.\n' }; const SaveCommand = async (data, state) => { if (data.length < 1) { console.error(chalk_1.default.redBright("Missing the target filename")); return state; } // Check if the flag to save also the login credentials is true let cookies = null; let userLogin = null; let profile = null; if (state.variables['SAVE_LOGIN'].value === 1 && state.userLogin !== undefined) { const result = await (0, general_1.RequestPassword)(state.userLogin); if (result) { cookies = state.cookies; userLogin = state.userLogin; profile = state.profile; } } else { cookies = state.cookies; userLogin = state.userLogin; profile = state.profile; } // Select the data to save into the json file const content_data = { lastCommand: state.lastCommand || null, fetchedProblems: state.fetchedProblems || null, selectedUser: state.selectedUser || null, userLogin: userLogin || null, profile: profile || null, cookies: cookies || null, variables: Object.values(state.variables).map((x) => ({ name: x.name, value: x.value })) }; const filename = data[0]; // Take the filename from the data const content = JSON.stringify(content_data, null, 2); // Check if the parent path of the filename exists const parent = path.dirname(filename); if (!fs.existsSync(parent)) { if (fs.mkdirSync(parent, 0o777) === undefined) { console.error(chalk_1.default.redBright("Impossible to create parent path of provided file")); return state; } } fs.writeFileSync(filename, content); console.log("Current state saved into:", chalk_1.default.blueBright(filename)); return state; }; // Save command - Save the state into a json file exports.save_command = { group: 'State', name: 'Save State Command', command: 'save', syntax: /^save\s+([\w/\.\-]+\.json)$/, callback: SaveCommand, help: 'save FILEPATH - Saves the current state into a json file\n' }; const IfNullUndefined = (data) => { if (data) return data; return undefined; }; const LoadCommand = async (data, state) => { if (data.length < 1) { console.error(chalk_1.default.redBright("Missing the target filename")); return state; } const filename = data[0]; // Check that the provided file exists if (!fs.existsSync(filename)) { console.error(chalk_1.default.redBright(`File ${filename} does not exists`)); return state; } const content = fs.readFileSync(filename, { encoding: 'utf-8' }); const content_data = JSON.parse(content); // Modify the state with the loaded informations state.lastCommand = IfNullUndefined(content_data.lastCommand); state.fetchedProblems = IfNullUndefined(content_data.fetchedProblems); state.selectedUser = IfNullUndefined(content_data.selectedUser); state.userLogin = IfNullUndefined(content_data.userLogin); state.profile = IfNullUndefined(content_data.profile); state.cookies = IfNullUndefined(content_data.cookies); let counter = 0; for (const key of Object.keys(state.variables)) { state.variables[key].value = content_data.variables[counter].value; counter++; } console.log("Loaded state from:", chalk_1.default.blueBright(filename)); return state; }; // Load command - load the state from a json file exports.load_command = { group: 'State', name: 'Load State Command', command: 'load', syntax: /^load\s+([\w/\.\-]+\.json)$/, callback: LoadCommand, help: 'load FILEPATH - Load the state from a json file\n' }; const ShowCommand = async (data, state) => { const sensitive = (data.length > 0) && data[0] === 'sensitive' && state.cookies !== undefined; let validation_result = true; if (sensitive && state.userLogin !== undefined) { validation_result = await (0, general_1.RequestPassword)(state.userLogin); } if (!validation_result) { console.error(chalk_1.default.redBright("Cannot show sensitive informations.")); return state; } // Shows some variables and informations about the state console.log("STATE INFORMATIONS\n------------------"); console.log("Last Command:", state.lastCommand); console.log("Logged-in User:", state.selectedUser); console.log("Watching Question ID:", state.watchQuestionId); if (state.fetchedProblems) { console.log(""); await (0, printer_1.PrintProblemsSummary)(state.fetchedProblems, state.variables); } else { console.log("Total Problems:", state.fetchedProblems); } if (sensitive && validation_result) { console.log("\nSENSITIVE STATE INFORMATIONS\n------------------"); console.log("Leetcode Cookies: "); console.log(` LEETCODE_SESSION = ${state.cookies?.LEETCODE_SESSION}`); console.log(` csrftoken = ${state.cookies?.csrftoken}`); console.log(` messages = ${state.cookies?.messages}`); console.log(""); console.log("User credentials: "); console.log(` Username: ${state.userLogin?.username}`); console.log(` Hash: ${state.userLogin?.password}`); console.log(` Salt: ${state.userLogin?.salt}`); } console.log("\nVARIABLES\n---------"); Object.values(state.variables).forEach((value, idx) => { console.log((0, formatter_1.FormatString)("{0} => {1} <{2} ({3})>", value.name, value.value.toString(), value.desc, value.values)); }); console.log(""); return state; }; // Show Command - shows some informations of the app state exports.show_command = { group: 'State', name: 'Show Command', command: 'show', syntax: /^show(?:\s(sensitive))$/, callback: ShowCommand, help: 'show [SENSITIVE] - Shows values and informations about the state.\n' };