feat: tính năng chia sẻ khẩn cấp
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
const loadScript = (src: string): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (document.querySelector(`script[src="${src}"]`)) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = () => resolve();
|
||||
script.onerror = () => reject(new Error(`Failed to load script ${src}`));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
};
|
||||
|
||||
const loadModerationLibraries = async () => {
|
||||
// Load TensorFlow first
|
||||
await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs');
|
||||
// Load models after tfjs is available
|
||||
await Promise.all([
|
||||
loadScript('https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface'),
|
||||
loadScript('https://cdn.jsdelivr.net/npm/nsfwjs@2.4.0/dist/bundle.js')
|
||||
]);
|
||||
};
|
||||
|
||||
export const processImageModeration = async (file: File): Promise<{ file: File; blocked: boolean }> => {
|
||||
try {
|
||||
const settingsRes = await fetch('/api/v1/moderation/settings');
|
||||
if (!settingsRes.ok) return { file, blocked: false };
|
||||
const settings = await settingsRes.json();
|
||||
const { blockNsfw, blurFaces } = settings;
|
||||
|
||||
if (!blockNsfw && !blurFaces) {
|
||||
return { file, blocked: false };
|
||||
}
|
||||
|
||||
await loadModerationLibraries();
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const img = new Image();
|
||||
img.onload = async () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
resolve({ file, blocked: false });
|
||||
return;
|
||||
}
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
if (blockNsfw) {
|
||||
try {
|
||||
const nsfwModel = await (window as any).nsfwjs.load();
|
||||
const predictions = await nsfwModel.classify(canvas);
|
||||
const pornOrHentai = predictions.find((p: any) => p.className === 'Porn' || p.className === 'Hentai');
|
||||
const pornProb = pornOrHentai ? pornOrHentai.probability : 0;
|
||||
if (pornProb > 0.5) {
|
||||
resolve({ file, blocked: true });
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('NSFW validation error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
let modified = false;
|
||||
if (blurFaces) {
|
||||
try {
|
||||
const blazefaceModel = await (window as any).blazeface.load();
|
||||
const predictions = await blazefaceModel.estimateFaces(canvas, false);
|
||||
if (predictions && predictions.length > 0) {
|
||||
modified = true;
|
||||
predictions.forEach((prediction: any) => {
|
||||
const startX = prediction.topLeft[0];
|
||||
const startY = prediction.topLeft[1];
|
||||
const endX = prediction.bottomRight[0];
|
||||
const endY = prediction.bottomRight[1];
|
||||
const width = endX - startX;
|
||||
const height = endY - startY;
|
||||
|
||||
const faceCanvas = document.createElement('canvas');
|
||||
faceCanvas.width = width;
|
||||
faceCanvas.height = height;
|
||||
const faceCtx = faceCanvas.getContext('2d');
|
||||
if (faceCtx) {
|
||||
faceCtx.drawImage(canvas, startX, startY, width, height, 0, 0, width, height);
|
||||
ctx.filter = 'blur(15px)';
|
||||
ctx.drawImage(faceCanvas, startX, startY, width, height);
|
||||
ctx.filter = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Face blur error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
canvas.toBlob((blob) => {
|
||||
if (blob) {
|
||||
const processedFile = new File([blob], file.name, { type: file.type });
|
||||
resolve({ file: processedFile, blocked: false });
|
||||
} else {
|
||||
resolve({ file, blocked: false });
|
||||
}
|
||||
}, file.type);
|
||||
} else {
|
||||
resolve({ file, blocked: false });
|
||||
}
|
||||
};
|
||||
img.onerror = () => {
|
||||
resolve({ file, blocked: false });
|
||||
};
|
||||
img.src = URL.createObjectURL(file);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Image moderation failed:', err);
|
||||
return { file, blocked: false };
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user