All files ocrController.ts

0% Statements 0/52
0% Branches 0/30
0% Functions 0/2
0% Lines 0/50

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121                                                                                                                                                                                                                                                 
import { Request, Response } from 'express';
import axios from 'axios';
import { OcrStatusResponse } from '@deliverables.org/types';
import { queryByPrefix } from '@deliverables.org/database';
import Multer from 'multer';
interface MulterRequest extends Request {
    file: Express.Multer.File;
}
 
const AZURE_ENDPOINT = process.env.AZURE_OCR_ENDPOINT as string;
const AZURE_KEY = process.env.AZURE_OCR_KEY as string;
 
 
export const testLocalOcr = async (req: Request, res: Response): Promise<void> => {
    try {
        const file = (req as MulterRequest).file;
        const { complexId } = req.body;
 
        if (!file || !file.buffer) {
            res.status(400).json({ error: 'No image uploaded.' });
            return;
        }
 
        if (!complexId) {
            res.status(400).json({ error: 'complexId is required.' });
            return;
        }
 
        const imageBuffer = file.buffer;
 
        const response = await axios.post(
            `${AZURE_ENDPOINT}/vision/v3.2/read/analyze`,
            imageBuffer,
            {
                headers: {
                    'Content-Type': 'application/octet-stream',
                    'Ocp-Apim-Subscription-Key': AZURE_KEY,
                },
            }
        );
 
        const operationLocation = response.headers['operation-location'];
        if (!operationLocation) {
            res.status(400).json({ error: 'No operation-location returned from Azure OCR.' });
            return;
        }
 
        let result = null;
        for (let i = 0; i < 10; i++) {
            await new Promise((resolve) => setTimeout(resolve, 1000));
            const statusResponse = await axios.get<OcrStatusResponse>(operationLocation, {
                headers: {
                    'Ocp-Apim-Subscription-Key': AZURE_KEY,
                },
            });
 
            const data = statusResponse.data;
            if (data.status === 'failed') {
                res.status(400).json({ error: 'Azure OCR failed to process the image.' });
                return;
            }
 
            if (data.status === 'succeeded' && data.analyzeResult) {
                result = data.analyzeResult.readResults;
                break;
            }
        }
 
        if (!result) {
            res.status(504).json({ error: 'Azure OCR timed out waiting for results.' });
            return;
        }
 
        const lines: string[] = [];
        for (const page of result) {
            for (const line of page.lines) {
                lines.push(line.text);
            }
        }
 
        const fullText = lines.join('\n').toLowerCase();
 
        // Fetch users for the complex
        const usersResult = await queryByPrefix({
            TableName: "Deliverables",
            PK: `COMPLEX#${complexId}`,
            SKPrefix: "USER#"
        });
 
        const users = usersResult.Items || [];
        let foundUser = null;
 
        // Simple name matching
        for (const user of users) {
            if (user.name && fullText.includes(user.name.toLowerCase())) {
                foundUser = {
                    name: user.name,
                    flat_number: user.unitNumber || user.address, // Assuming address or unitNumber holds flat info
                    id: user.id
                };
                break; // Stop at first match for now
            }
        }
 
        res.json({
            extracted: foundUser, // Can be null if no user found
            allLines: lines,
        });
    } catch (error: any) {
        if (error?.response && error?.isAxiosError) {
            res.status(500).json({
                error: 'OCR request failed',
                details: error.response?.data,
            });
        } else if (!res.headersSent) {
            console.error("OCR Error:", error);
            res.status(500).json({ error: 'Internal server error during OCR processing.' });
        }
    }
};