Tạo liên kết chia sẻ lên social

This commit is contained in:
2026-06-09 08:24:21 +07:00
parent fadfb6ba09
commit e6071a050d
4 changed files with 115 additions and 10 deletions
+62
View File
@@ -229,6 +229,68 @@ router.get('/scenes', optionalAuth, async (req, res) => {
}
});
/**
* @route GET /api/share/:sceneId
* @desc Endpoint tạo trang trung gian hỗ trợ hiển thị ảnh thumbnail trên Facebook/Zalo (Open Graph)
*/
router.get('/share/:sceneId', optionalAuth, async (req, res) => {
try {
const scene = await Scene.findById(req.params.sceneId).populate('assetId');
if (!scene) return res.status(404).send('Không tìm thấy Scene');
// Kiểm tra quyền truy cập (sử dụng logic đồng bộ với các route khác)
const isTokenValid = scene.shareToken && (!scene.shareTokenExpires || new Date() < scene.shareTokenExpires);
const userEmail = req.user ? req.user.email : null;
const hasAccess =
scene.privacy === 'public' ||
(scene.privacy === 'member' && req.user && (scene.sharedWith.includes(req.user._id) || (userEmail && scene.sharedEmails.includes(userEmail)))) ||
(req.user && scene.createdBy.toString() === req.user._id.toString()) ||
(scene.privacy === 'shared' && req.query.token === scene.shareToken && isTokenValid);
if (!hasAccess) return res.status(403).send('Bạn không có quyền xem liên kết này hoặc liên kết đã hết hạn');
// Xây dựng các thông số Open Graph
const protocol = req.headers['x-forwarded-proto'] || req.protocol;
const host = req.get('host');
const siteUrl = `${protocol}://${host}`;
const assetId = scene.assetId?._id || scene.assetId;
const thumbUrl = `${siteUrl}/api/assets/view/${assetId}${req.query.token ? '?token=' + req.query.token : ''}`;
// Trả về HTML chứa Meta Tags và Script chuyển hướng
const html = `
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>${scene.name}</title>
<meta property="og:title" content="${scene.name}" />
<meta property="og:description" content="${scene.description || 'Khám phá tour 3D thực tế ảo sinh động'}" />
<meta property="og:image" content="${thumbUrl}" />
<meta property="og:image:secure_url" content="${thumbUrl}" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:url" content="${siteUrl}${req.originalUrl}" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="${scene.name}" />
<meta name="twitter:description" content="${scene.description || 'Khám phá tour 3D thực tế ảo sinh động'}" />
<meta name="twitter:image" content="${thumbUrl}" />
<script>
// Tự động chuyển hướng người dùng về ứng dụng chính (SPA) kèm tham số
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get('token');
window.location.href = "/?sceneId=${scene._id}" + (token ? "&token=" + token : "");
</script>
</head>
<body style="background:#000; color:#fff; display:flex; align-items:center; justify-content:center; height:100vh; font-family:sans-serif;">
<p>Đang mở tour 3D của bạn...</p>
</body>
</html>`;
res.send(html);
} catch (error) {
res.status(500).send('Internal Server Error');
}
});
/**
* @route GET /api/scenes/:id
* @desc Get single scene detail (respecting privacy rules)