diff options
author | alyssaf16 <alyssa_feinberg@brown.edu> | 2024-10-15 12:19:38 -0400 |
---|---|---|
committer | alyssaf16 <alyssa_feinberg@brown.edu> | 2024-10-15 12:19:38 -0400 |
commit | 63d1731bb675b71c20c0e460cf50ef9d674a6c08 (patch) | |
tree | 2dcb0ce2842f0fc77e065b35aacba64171f14360 /src/server/ApiManagers/FlashcardManager.ts | |
parent | bb8fe2933154c6db70cfe5da1e890535bc9012d4 (diff) |
flashcard move to server
Diffstat (limited to 'src/server/ApiManagers/FlashcardManager.ts')
-rw-r--r-- | src/server/ApiManagers/FlashcardManager.ts | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/server/ApiManagers/FlashcardManager.ts b/src/server/ApiManagers/FlashcardManager.ts new file mode 100644 index 000000000..fd7c42437 --- /dev/null +++ b/src/server/ApiManagers/FlashcardManager.ts @@ -0,0 +1,161 @@ +/** + * @file FlashcardManager.ts + * @description This file defines the FlashcardManager class, responsible for managing API routes + * related to flashcard creation and manipulation. It provides functionality for handling file processing, + * running Python scripts in a virtual environment, and managing dependencies. + */ + +import { spawn } from 'child_process'; +import * as fs from 'fs'; +import * as path from 'path'; +import { Method } from '../RouteManager'; +import ApiManager, { Registration } from './ApiManager'; + +/** + * Runs a Python script using the provided virtual environment and passes file and option arguments. + * @param {string} venvPath - Path to the virtual environment. + * @param {string} scriptPath - Path to the Python script. + * @param {string} [file] - Optional file to pass to the Python script. + * @param {string} [drag] - Optional argument to control drag mode. + * @param {string} [smart] - Optional argument to control smart mode. + * @returns {Promise<string>} - Resolves with the output from the Python script, or rejects on error. + */ +function runPythonScript(venvPath: string, scriptPath: string, file?: string, drag?: string, smart?: string): Promise<string> { + return new Promise((resolve, reject) => { + const pythonPath = process.platform === 'win32' ? path.join(venvPath, 'Scripts', 'python.exe') : path.join(venvPath, 'bin', 'python3'); + + const tempFilePath = path.join(__dirname, `temp_data.txt`); // Unique temp file name + + if (file) { + // Write the raw file data to the temp file without conversion + fs.writeFileSync(tempFilePath, file, 'utf8'); + } + + const pythonProcess = spawn( + pythonPath, + [scriptPath, file ? tempFilePath : undefined, drag, smart].filter(arg => arg !== undefined) + ); + + let pythonOutput = ''; + let stderrOutput = ''; + + pythonProcess.stdout.on('data', data => { + pythonOutput += data.toString(); + }); + + pythonProcess.stderr.on('data', data => { + stderrOutput += data.toString(); + }); + + pythonProcess.on('close', code => { + if (code === 0) { + resolve(pythonOutput); + } else { + reject(`Python process exited with code ${code}: ${stderrOutput}`); + } + }); + }); +} + +/** + * Installs Python dependencies using pip in the specified virtual environment. + * @param {string} venvPath - Path to the virtual environment. + * @param {string} requirementsPath - Path to the requirements.txt file. + * @returns {Promise<void>} - Resolves when dependencies are successfully installed, rejects on failure. + */ +function installDependencies(venvPath: string, requirementsPath: string): Promise<void> { + return new Promise((resolve, reject) => { + const pipPath = process.platform === 'win32' ? path.join(venvPath, 'Scripts', 'pip.exe') : path.join(venvPath, 'bin', 'pip3'); + + const installProcess = spawn(pipPath, ['install', '-r', requirementsPath]); + + installProcess.stdout.on('data', data => { + console.log(`pip stdout: ${data}`); + }); + + installProcess.stderr.on('data', data => { + console.error(`pip stderr: ${data}`); + }); + + installProcess.on('close', code => { + if (code !== 0) { + reject(`Failed to install dependencies. Exit code: ${code}`); + } else { + resolve(); + } + }); + }); +} + +/** + * Creates a new Python virtual environment. + * @param {string} venvPath - Path to the virtual environment that will be created. + * @returns {Promise<void>} - Resolves when the virtual environment is successfully created, rejects on failure. + */ +function createVirtualEnvironment(venvPath: string): Promise<void> { + return new Promise((resolve, reject) => { + const createVenvProcess = spawn('python3', ['-m', 'venv', venvPath]); + + createVenvProcess.on('close', code => { + if (code !== 0) { + reject(`Failed to create virtual environment. Exit code: ${code}`); + } else { + resolve(); + } + }); + }); +} + +/** + * Manages the creation of the virtual environment, installation of dependencies, and running of the Python script. + * @param {string} [file] - Optional file data to be processed by the Python script. + * @param {string} [drag] - Optional argument controlling drag mode. + * @param {string} [smart] - Optional argument controlling smart mode. + * @returns {Promise<string>} - Resolves with the Python script output, or rejects on failure. + */ +async function manageVenvAndRunScript(file?: string, drag?: string, smart?: string): Promise<string> { + const venvPath = path.join(__dirname, '../flashcard/venv'); // Virtual environment path + const requirementsPath = path.join(__dirname, '../flashcard/requirements.txt'); + const pythonScriptPath = path.join(__dirname, '../flashcard/labels.py'); + console.log('venvPath:', venvPath); + + // Check if the virtual environment exists + if (!fs.existsSync(path.join(venvPath, 'bin', 'python3')) && !fs.existsSync(path.join(venvPath, 'Scripts', 'python.exe'))) { + await createVirtualEnvironment(venvPath); + + await installDependencies(venvPath, requirementsPath); + } + + return runPythonScript(venvPath, pythonScriptPath, file, drag, smart); +} + +/** + * FlashcardManager class responsible for managing API routes related to flashcard functionality. + * It initializes API routes for handling YouTube subscriptions and label creation using a Python backend. + */ +export default class FlashcardManager extends ApiManager { + /** + * Initializes the API routes for the FlashcardManager class. + * @param {Registration} register - The registration function for defining API routes. + */ + protected initialize(register: Registration): void { + register({ + method: Method.POST, + subscription: '/labels', + secureHandler: async ({ req, res }) => { + const { file, drag, smart } = req.body; + + try { + // Run the Python process + const result = await manageVenvAndRunScript(file, drag, smart); + res.status(200).send({ result }); + } catch (error) { + console.error('Error initiating document creation:', error); + res.status(500).send({ + error: 'Failed to initiate document creation', + }); + } + }, + }); + } +} |