Express.js Integration
Intégrez YODI dans une application Express.js complète.
Installation
npm init -y
npm install express axios dotenv cors body-parser
Application Express Complète
app.js
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
require("dotenv").config();
const app = express();
// Middleware
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Routes
const translationRoutes = require("./routes/translation");
const analysisRoutes = require("./routes/analysis");
const communicationRoutes = require("./routes/communication");
const subscriptionRoutes = require("./routes/subscription");
app.use("/api/translate", translationRoutes);
app.use("/api/analyze", analysisRoutes);
app.use("/api/communication", communicationRoutes);
app.use("/api/subscription", subscriptionRoutes);
// Health check
app.get("/health", (req, res) => {
res.json({ status: "ok", service: "YODI API Wrapper" });
});
// Error handling
app.use((err, req, res, next) => {
console.error(" Erreur:", err);
res.status(err.status || 500).json({
error: err.message,
status: err.status || 500,
});
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(` Serveur démarré sur http://localhost:${PORT}`);
});
module.exports = app;
config/yodi.js
const axios = require("axios");
require("dotenv").config();
const yodiClient = axios.create({
baseURL: process.env.YODI_BASE_URL || "https://admin.yodi.tg/api",
headers: {
Authorization: `Bearer ${process.env.YODI_API_KEY}`,
"Content-Type": "application/json",
},
timeout: 10000,
});
// Interceptor pour les erreurs
yodiClient.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 429) {
console.warn(" Rate limited - implementing backoff");
}
return Promise.reject(error);
},
);
module.exports = yodiClient;
routes/translation.js
const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");
// POST /api/translate
router.post("/", async (req, res, next) => {
try {
const { text, targetLanguage, sourceLanguage } = req.body;
if (!text || !targetLanguage) {
return res.status(400).json({
error: "text et targetLanguage sont requis",
});
}
const response = await yodiClient.post("/ai/translate", {
text,
targetLanguage,
sourceLanguage,
});
res.json({
success: true,
data: response.data.data,
});
} catch (error) {
next(error);
}
});
// POST /api/translate/batch
router.post("/batch", async (req, res, next) => {
try {
const { texts, targetLanguage } = req.body;
if (!Array.isArray(texts) || !targetLanguage) {
return res.status(400).json({
error: "texts (array) et targetLanguage sont requis",
});
}
const results = [];
for (const text of texts) {
try {
const response = await yodiClient.post("/ai/translate", {
text,
targetLanguage,
});
results.push({
original: text,
translated: response.data.data.translated,
status: "success",
});
} catch (error) {
results.push({
original: text,
status: "failed",
error: error.message,
});
}
}
res.json({
success: true,
count: results.length,
results,
});
} catch (error) {
next(error);
}
});
module.exports = router;
routes/analysis.js
const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");
// POST /api/analyze
router.post("/", async (req, res, next) => {
try {
const { text } = req.body;
if (!text) {
return res.status(400).json({ error: "text est requis" });
}
const response = await yodiClient.post("/ai/analyze", { text });
res.json({
success: true,
data: response.data.data,
});
} catch (error) {
next(error);
}
});
// POST /api/analyze/sentiment
router.post("/sentiment", async (req, res, next) => {
try {
const { text } = req.body;
if (!text) {
return res.status(400).json({ error: "text est requis" });
}
const response = await yodiClient.post("/ai/analyze", { text });
const { sentiment } = response.data.data;
res.json({
success: true,
sentiment: {
label: sentiment.label,
confidence: sentiment.confidence,
percentage: Math.round(sentiment.confidence * 100),
},
});
} catch (error) {
next(error);
}
});
module.exports = router;
routes/communication.js
const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");
// POST /api/communication/sms
router.post("/sms", async (req, res, next) => {
try {
const { phone, input } = req.body;
if (!phone || !input) {
return res.status(400).json({
error: "phone et input sont requis",
});
}
const response = await yodiClient.post("/ai/sms/communication", {
phone,
input,
});
res.json({
success: true,
messageId: response.data.data.messageId,
});
} catch (error) {
next(error);
}
});
// POST /api/communication/call (Voice Call)
router.post("/call", async (req, res, next) => {
try {
const { phone, input } = req.body;
if (!phone || !input) {
return res.status(400).json({
error: "phone et input sont requis",
});
}
const response = await yodiClient.post("/ai/call/communication", {
phone,
input,
});
res.json({
success: true,
messageId: response.data.data.messageId,
});
} catch (error) {
next(error);
}
});
module.exports = router;
routes/subscription.js
const express = require("express");
const router = express.Router();
const yodiClient = require("../config/yodi");
// GET /api/subscription/plans
router.get("/plans", async (req, res, next) => {
try {
const response = await yodiClient.get("/subscription/plans");
res.json({
success: true,
plans: response.data.data,
});
} catch (error) {
next(error);
}
});
// GET /api/subscription/current
router.get("/current", async (req, res, next) => {
try {
const response = await yodiClient.get("/subscription/current");
res.json({
success: true,
subscription: response.data.data,
});
} catch (error) {
next(error);
}
});
module.exports = router;
Middleware Custom
middleware/auth.js
const authMiddleware = (req, res, next) => {
const apiKey = req.headers["x-api-key"];
if (!apiKey || apiKey !== process.env.APP_API_KEY) {
return res.status(401).json({ error: "API Key manquante ou invalide" });
}
next();
};
module.exports = authMiddleware;
Utilisez dans vos routes:
const authMiddleware = require("../middleware/auth");
router.post("/", authMiddleware, async (req, res) => {
// Votre logique...
});
middleware/rateLimit.js
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100, // Limite 100 requêtes par minute
message: "Trop de requêtes, veuillez réessayer plus tard",
standardHeaders: true,
legacyHeaders: false,
});
module.exports = limiter;
Utilisez dans app.js:
const rateLimit = require("./middleware/rateLimit");
app.use(rateLimit);
Tests avec Postman/cURL
Translation
curl -X POST http://localhost:3000/api/translate \
-H "Content-Type: application/json" \
-d '{
"text": "Hello world",
"targetLanguage": "fr"
}'
Analysis
curl -X POST http://localhost:3000/api/analyze/sentiment \
-H "Content-Type: application/json" \
-d '{
"text": "I love this service!"
}'
Send SMS
curl -X POST http://localhost:3000/api/communication/sms \
-H "Content-Type: application/json" \
-d '{
"phone": "+22890123456",
"input": "Bienvenue sur YODI!"
}'
Structure du Projet
yodi-api-wrapper/
├── app.js
├── package.json
├── .env
├── config/
│ └── yodi.js
├── routes/
│ ├── translation.js
│ ├── analysis.js
│ ├── communication.js
│ └── subscription.js
├── middleware/
│ ├── auth.js
│ └── rateLimit.js
└── models/
└── (optionnel: base de données)
Déploiement
Heroku
heroku create your-app-name
git push heroku main
heroku config:set YODI_API_KEY=your_key
Docker
Créez Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
Créez docker-compose.yml:
version: "3.8"
services:
app:
build: .
ports:
- "3000:3000"
environment:
- YODI_API_KEY=${YODI_API_KEY}
- NODE_ENV=production
Lancez:
docker-compose up
Exemple Complet: Platform de Support Client
// supportApp.js
const express = require("express");
const yodiClient = require("./config/yodi");
const app = express();
app.use(express.json());
class SupportPlatform {
async createTicket(customerData, issue) {
// 1. Analyser le problème
const analysis = await yodiClient.post("/ai/analyze", {
text: issue,
});
const { sentiment, confidence } = analysis.data.data;
const priority = sentiment === "negative" ? "high" : "normal";
// 2. Notifier le support team par SMS
await yodiClient.post("/ai/sms/communication", {
phone: process.env.SUPPORT_PHONE,
input: `Nouveau ticket ${priority}: ${issue.substring(0, 50)}`,
});
return {
ticketId: Math.random().toString(36).substr(2, 9),
priority,
sentiment,
};
}
async respondToTicket(ticketId, response) {
// Traduire la réponse automatiquement
const translated = await yodiClient.post("/ai/translate", {
text: response,
targetLanguage: "fr",
});
return translated.data.data.translatedText;
}
}
// Routes
const platform = new SupportPlatform();
app.post("/tickets", async (req, res) => {
try {
const ticket = await platform.createTicket(
req.body.customer,
req.body.issue,
);
res.json({ success: true, ticket });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post("/tickets/:id/respond", async (req, res) => {
try {
const response = await platform.respondToTicket(
req.params.id,
req.body.response,
);
res.json({ success: true, response });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log(" Support Platform sur http://localhost:3000");
});