| import axios from 'axios'; |
| import { Readable } from 'stream'; |
|
|
| export function normalizeCommand(text: string): string { |
| return text |
| .trim() |
| .toLowerCase() |
| .replace(/[.,!?;:]+$/, "") |
| .toUpperCase(); |
| } |
|
|
| export function detectIntent(text: string): 'YES' | 'NO' | 'UNKNOWN' { |
| const normalized = text.trim().toLowerCase().replace(/[.,!?;:]+$/, ""); |
| const yesWords = ['oui', 'ouais', 'wi', 'waaw', 'yes', 'yep', 'ok', 'd’accord', 'daccord', 'da’accord']; |
| const noWords = ['non', 'déet', 'deet', 'no', 'nah', 'nein']; |
|
|
| if (yesWords.some(w => normalized.includes(w))) return 'YES'; |
| if (noWords.some(w => normalized.includes(w))) return 'NO'; |
| return 'UNKNOWN'; |
| } |
|
|
| export function levenshteinDistance(a: string, b: string): number { |
| const matrix: number[][] = []; |
| for (let i = 0; i <= b.length; i++) matrix[i] = [i]; |
| for (let j = 0; j <= a.length; j++) matrix[0][j] = j; |
|
|
| for (let i = 1; i <= b.length; i++) { |
| for (let j = 1; j <= a.length; j++) { |
| if (b.charAt(i - 1) === a.charAt(j - 1)) { |
| matrix[i][j] = matrix[i - 1][j - 1]; |
| } else { |
| matrix[i][j] = Math.min( |
| matrix[i - 1][j - 1] + 1, |
| matrix[i][j - 1] + 1, |
| matrix[i - 1][j] + 1 |
| ); |
| } |
| } |
| } |
| return matrix[b.length][a.length]; |
| } |
|
|
| export function isFuzzyMatch(text: string, target: string, threshold = 0.8): boolean { |
| const normalized = text.trim().toUpperCase(); |
| const tar = target.toUpperCase(); |
| if (normalized === tar) return true; |
| if (normalized.includes(tar) || tar.includes(normalized)) return true; |
|
|
| const distance = levenshteinDistance(normalized, tar); |
| const maxLength = Math.max(normalized.length, tar.length); |
| const similarity = 1 - distance / maxLength; |
| return similarity >= threshold; |
| } |
|
|
|
|
|
|
| |
| |
| |
| |
| |
| |
| export async function downloadMedia( |
| mediaId: string, |
| accessToken: string |
| ): Promise<{ stream: Readable; mimeType: string; fileSize: number }> { |
| |
| const metaRes = await axios.get( |
| `https://graph.facebook.com/${process.env.META_GRAPH_API_VERSION || 'v22.0'}/${mediaId}`, |
| { headers: { Authorization: `Bearer ${accessToken}` } } |
| ); |
| const { url, mime_type, file_size } = metaRes.data; |
|
|
| if (!url) throw new Error(`[downloadMedia] No URL returned for media ${mediaId}`); |
|
|
| |
| const mediaRes = await axios.get(url, { |
| headers: { Authorization: `Bearer ${accessToken}` }, |
| responseType: 'stream', |
| timeout: 30_000 |
| }); |
|
|
| return { |
| stream: mediaRes.data, |
| mimeType: mime_type || 'application/octet-stream', |
| fileSize: file_size || 0 |
| }; |
| } |
|
|