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.' });
}
}
};
|