feat: first commit
						commit
						b96b05ad83
					
				| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
{
 | 
			
		||||
  "extends": ["@commitlint/config-conventional"]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
/node_modules
 | 
			
		||||
.env
 | 
			
		||||
/public/*
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
#!/usr/bin/env sh
 | 
			
		||||
. "$(dirname -- "$0")/_/husky.sh"
 | 
			
		||||
 | 
			
		||||
npx commitlint --edit 
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
require('dotenv').config()
 | 
			
		||||
require('express-async-errors')
 | 
			
		||||
 | 
			
		||||
// express 
 | 
			
		||||
const express = require('express')
 | 
			
		||||
const app = express()
 | 
			
		||||
 | 
			
		||||
// rest of the packages
 | 
			
		||||
const morgan = require('morgan')
 | 
			
		||||
// const fileUpload = require('express-fileupload')
 | 
			
		||||
 | 
			
		||||
const rateLimiter = require('express-rate-limit')
 | 
			
		||||
 | 
			
		||||
// Swagger
 | 
			
		||||
const swaggerUI = require('swagger-ui-express')
 | 
			
		||||
const YAML = require('yamljs')
 | 
			
		||||
const swaggerDocument = YAML.load('./swagger.yaml') 
 | 
			
		||||
 | 
			
		||||
const helmet = require('helmet')
 | 
			
		||||
const xss = require('xss-clean')
 | 
			
		||||
const cors = require('cors')  
 | 
			
		||||
 
 | 
			
		||||
// routers   
 | 
			
		||||
const apiPricingRouter = require('./routes/apiPriceRoute')
 | 
			
		||||
 | 
			
		||||
const notFoundMiddlware = require('./middleware/not-found')
 | 
			
		||||
// const errorHandlerMiddleware = require('./middleware/error-handler')
 | 
			
		||||
 | 
			
		||||
//middleware
 | 
			
		||||
app.set('trust proxy', 1)
 | 
			
		||||
app.use(rateLimiter({
 | 
			
		||||
    windowMs: 15 * 60 * 1000,
 | 
			
		||||
    max: 60,
 | 
			
		||||
}))
 | 
			
		||||
 
 | 
			
		||||
// Security packages
 | 
			
		||||
app.use(helmet())
 | 
			
		||||
app.use(cors())
 | 
			
		||||
app.use(xss())
 | 
			
		||||
 | 
			
		||||
app.use(morgan('tiny'))
 | 
			
		||||
app.use(express.json())
 | 
			
		||||
 
 | 
			
		||||
// app.use(fileUpload())
 | 
			
		||||
 | 
			
		||||
app.get('/', (req, res) => {
 | 
			
		||||
    res.send('<h1>Billing API</h1><a href="/api-docs">Documentation</a>')
 | 
			
		||||
}) 
 | 
			
		||||
 | 
			
		||||
app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerDocument))
 | 
			
		||||
  
 | 
			
		||||
app.use('/api/v1/billing', apiPricingRouter)
 | 
			
		||||
 | 
			
		||||
app.use(notFoundMiddlware)
 | 
			
		||||
// app.use(errorHandlerMiddleware)
 | 
			
		||||
 | 
			
		||||
const port = process.env.PORT || 3000
 | 
			
		||||
 | 
			
		||||
app.listen(port, console.log(`Listening on port: ${port}...`))
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,128 @@
 | 
			
		|||
const { StatusCodes } = require("http-status-codes")
 | 
			
		||||
const API_Pricing = require("../models/API_Pricing.js")
 | 
			
		||||
const {
 | 
			
		||||
    mustContainProperties,
 | 
			
		||||
    calculateApiUsage,
 | 
			
		||||
} = require('../utils')
 | 
			
		||||
const API_Usage = require("../models/API_Usage.js")
 | 
			
		||||
const billingSumUsage = require("../utils/billingSumUsage.js")
 | 
			
		||||
const moment = require('moment')
 | 
			
		||||
 | 
			
		||||
const setApiPricing = async (req, res) => {
 | 
			
		||||
 | 
			
		||||
    const { provider, product, currency, price, billingBy, billingUnit, type } = req.body
 | 
			
		||||
 | 
			
		||||
    mustContainProperties(req, ['provider',
 | 
			
		||||
        'product',
 | 
			
		||||
        'price',
 | 
			
		||||
        'billingBy',
 | 
			
		||||
        'billingUnit'])
 | 
			
		||||
 | 
			
		||||
    const apiPricing = await API_Pricing.create({
 | 
			
		||||
        provider: provider.trim().toLowerCase(),
 | 
			
		||||
        product: product.trim().toLowerCase(),
 | 
			
		||||
        currency,
 | 
			
		||||
        price,
 | 
			
		||||
        billingBy,
 | 
			
		||||
        billingUnit,
 | 
			
		||||
        type
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    res.status(StatusCodes.OK).json({ apiPricing })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const registerUsage = async (req, res) => {
 | 
			
		||||
    const { 
 | 
			
		||||
        provider,
 | 
			
		||||
        product,
 | 
			
		||||
        usage,
 | 
			
		||||
        callerId, 
 | 
			
		||||
        companyId,
 | 
			
		||||
        quantityOfOperationAttempts,
 | 
			
		||||
        chosenOperation,
 | 
			
		||||
        requestLogsOpenAI,
 | 
			
		||||
        responseErrorLogsOpenAI,
 | 
			
		||||
        quantityOfCallsToFalconFlowAPI,
 | 
			
		||||
        requestLogsFalconFlowAPI,
 | 
			
		||||
        responseErrorLogsFalconFlowAPI,
 | 
			
		||||
    } = req.body
 | 
			
		||||
 | 
			
		||||
    mustContainProperties(req, [
 | 
			
		||||
        'companyId',
 | 
			
		||||
        'callerId',
 | 
			
		||||
        'quantityOfOperationAttempts',
 | 
			
		||||
        'chosenOperation',
 | 
			
		||||
        'requestLogsOpenAI',
 | 
			
		||||
        // 'responseErrorLogsOpenAI',
 | 
			
		||||
        'quantityOfCallsToFalconFlowAPI',
 | 
			
		||||
        'requestLogsFalconFlowAPI',
 | 
			
		||||
        // 'responseErrorLogsFalconFlowAPI',
 | 
			
		||||
        'provider',
 | 
			
		||||
        'product',
 | 
			
		||||
        'usage',
 | 
			
		||||
    ])  
 | 
			
		||||
 | 
			
		||||
    const apiPricing = await API_Pricing.findOne({
 | 
			
		||||
        provider: provider.trim().toLowerCase(),
 | 
			
		||||
        product: product.trim().toLowerCase(),
 | 
			
		||||
    })
 | 
			
		||||
  
 | 
			
		||||
    if (apiPricing) {  
 | 
			
		||||
 | 
			
		||||
        const { price, billingBy, billingUnit } = apiPricing  
 | 
			
		||||
 | 
			
		||||
        const apiUsage = await API_Usage.create({
 | 
			
		||||
            provider: provider.trim().toLowerCase(),
 | 
			
		||||
            product: product.trim().toLowerCase(), 
 | 
			
		||||
            callerId, 
 | 
			
		||||
            quantityOfOperationAttempts,
 | 
			
		||||
            chosenOperation,
 | 
			
		||||
            requestLogsOpenAI,
 | 
			
		||||
            responseErrorLogsOpenAI,
 | 
			
		||||
            quantityOfCallsToFalconFlowAPI,
 | 
			
		||||
            requestLogsFalconFlowAPI,
 | 
			
		||||
            responseErrorLogsFalconFlowAPI,  
 | 
			
		||||
            usage,
 | 
			
		||||
            price,
 | 
			
		||||
            billingBy,
 | 
			
		||||
            billingUnit, 
 | 
			
		||||
            companyId,
 | 
			
		||||
            total_cost: calculateApiUsage(price, billingUnit, usage, billingBy)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        return res.status(StatusCodes.OK).json({ apiUsage })
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    res.status(StatusCodes.NOT_FOUND).json({ msg: `Price not found for ${product} in the API Pricing table` })
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const getUsage = async (req, res) => {
 | 
			
		||||
 | 
			
		||||
    const { startDate, endDate, companyId, } = req.body
 | 
			
		||||
 | 
			
		||||
    mustContainProperties(req, ['startDate', 'endDate', 'companyId'])
 | 
			
		||||
 | 
			
		||||
    const total = await billingSumUsage(startDate, endDate, companyId)
 | 
			
		||||
 | 
			
		||||
    if (total) {
 | 
			
		||||
        const usage = await API_Usage.find({
 | 
			
		||||
            createdAt: {
 | 
			
		||||
                $gte: moment(startDate, 'YYYY-MM-DD').startOf('day').toDate(),
 | 
			
		||||
                $lte: moment(endDate, 'YYYY-MM-DD').endOf('day').toDate()
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        return res.status(StatusCodes.OK).json({ usage, total })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return res.status(StatusCodes.NOT_FOUND).json({})
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    setApiPricing,
 | 
			
		||||
    registerUsage,
 | 
			
		||||
    getUsage
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
const User = require('../models/User')
 | 
			
		||||
const { StatusCodes } = require('http-status-codes')
 | 
			
		||||
const CustomError = require('../errors')
 | 
			
		||||
 | 
			
		||||
const { attachCookiesToResponse, createTokenUser } = require('../utils')
 | 
			
		||||
 | 
			
		||||
const register = async (req, res) => {
 | 
			
		||||
 | 
			
		||||
    const { email, name, password } = req.body
 | 
			
		||||
 | 
			
		||||
    const emailAlreadyExists = await User.findOne({ email })
 | 
			
		||||
    if (emailAlreadyExists) {
 | 
			
		||||
        throw new CustomError.BadRequestError('Email already exists')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // first register user is an admin
 | 
			
		||||
    const isFirstAccount = await User.countDocuments({}) === 0
 | 
			
		||||
 | 
			
		||||
    const role = isFirstAccount ? 'admin' : 'user'
 | 
			
		||||
 | 
			
		||||
    const user = await User.create({ name, email, password, role })
 | 
			
		||||
 | 
			
		||||
    const tokenUser = createTokenUser(user)
 | 
			
		||||
 | 
			
		||||
    attachCookiesToResponse({ res, user: tokenUser })
 | 
			
		||||
 | 
			
		||||
    res.status(StatusCodes.CREATED).json({ user: tokenUser })
 | 
			
		||||
}
 | 
			
		||||
const login = async (req, res) => {
 | 
			
		||||
    const { email, password } = req.body
 | 
			
		||||
 | 
			
		||||
    if (!email || !password) {
 | 
			
		||||
        throw new CustomError.BadRequestError('Please provide email and password')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const user = await User.findOne({ email })
 | 
			
		||||
 | 
			
		||||
    if (!user) {
 | 
			
		||||
        throw new CustomError.UnauthenticatedError('Ivalid Credentials')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const isPasswordCorret = await user.comparePassword(password)
 | 
			
		||||
 | 
			
		||||
    if (!isPasswordCorret) {
 | 
			
		||||
        throw new CustomError.UnauthenticatedError('Ivalid Credentials')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    const tokenUser = {
 | 
			
		||||
        name: user.name,
 | 
			
		||||
        userId: user._id,
 | 
			
		||||
        role: user.role
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    attachCookiesToResponse({ res, user: tokenUser })
 | 
			
		||||
 | 
			
		||||
    res.status(StatusCodes.OK).json({ user: tokenUser })
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
const logout = async (req, res) => {
 | 
			
		||||
    res.cookie('token', 'logout', {
 | 
			
		||||
        httpOnly: true,
 | 
			
		||||
        expires: new Date(Date.now())
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    res.status(StatusCodes.OK).json({
 | 
			
		||||
        msg: 'user logged out!'
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    register,
 | 
			
		||||
    login,
 | 
			
		||||
    logout
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
const mongoose = require('mongoose')
 | 
			
		||||
 | 
			
		||||
const connectDB = async () => {
 | 
			
		||||
  await mongoose.connect(process.env.DB_MONGO_URL, { dbName: process.env.DB_MONGO_NAME })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
connectDB().catch((err) => console.log(err))
 | 
			
		||||
module.exports = mongoose
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
const { StatusCodes } = require('http-status-codes');
 | 
			
		||||
const CustomAPIError = require('./custom-api');
 | 
			
		||||
 | 
			
		||||
class BadRequestError extends CustomAPIError {
 | 
			
		||||
  constructor(message) {
 | 
			
		||||
    super(message);
 | 
			
		||||
    this.statusCode = StatusCodes.BAD_REQUEST;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = BadRequestError;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
class CustomAPIError extends Error {
 | 
			
		||||
  constructor(message) {
 | 
			
		||||
    super(message)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = CustomAPIError
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
const CustomAPIError = require('./custom-api');
 | 
			
		||||
const UnauthenticatedError = require('./unauthenticated');
 | 
			
		||||
const NotFoundError = require('./not-found');
 | 
			
		||||
const BadRequestError = require('./bad-request');
 | 
			
		||||
const UnauthorizedError = require('./unauthorized');
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  CustomAPIError,
 | 
			
		||||
  UnauthenticatedError,
 | 
			
		||||
  NotFoundError,
 | 
			
		||||
  BadRequestError,
 | 
			
		||||
  UnauthorizedError,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
const { StatusCodes } = require('http-status-codes');
 | 
			
		||||
const CustomAPIError = require('./custom-api');
 | 
			
		||||
 | 
			
		||||
class NotFoundError extends CustomAPIError {
 | 
			
		||||
  constructor(message) {
 | 
			
		||||
    super(message);
 | 
			
		||||
    this.statusCode = StatusCodes.NOT_FOUND;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = NotFoundError;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
const { StatusCodes } = require('http-status-codes');
 | 
			
		||||
const CustomAPIError = require('./custom-api');
 | 
			
		||||
 | 
			
		||||
class UnauthenticatedError extends CustomAPIError {
 | 
			
		||||
  constructor(message) {
 | 
			
		||||
    super(message);
 | 
			
		||||
    this.statusCode = StatusCodes.UNAUTHORIZED;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = UnauthenticatedError;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
const { StatusCodes } = require('http-status-codes');
 | 
			
		||||
const CustomAPIError = require('./custom-api');
 | 
			
		||||
 | 
			
		||||
class UnauthorizedError extends CustomAPIError {
 | 
			
		||||
  constructor(message) {
 | 
			
		||||
    super(message);
 | 
			
		||||
    this.statusCode = StatusCodes.FORBIDDEN;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = UnauthorizedError;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
const CustomError = require('../errors') 
 | 
			
		||||
 | 
			
		||||
const authorization = async (req, res, next) => { 
 | 
			
		||||
 | 
			
		||||
    const authHeader = req.headers.authorization
 | 
			
		||||
 | 
			
		||||
    if (!authHeader) {
 | 
			
		||||
        throw new CustomError.BadRequestError('Authorization not found into header!')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const [, token] = authHeader.split(" "); 
 | 
			
		||||
 | 
			
		||||
    if (!token) {
 | 
			
		||||
        throw new CustomError.BadRequestError('Authorization token not found into header!')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (token != process.env.TOKEN){
 | 
			
		||||
        throw new CustomError.UnauthorizedError('Authorization token Invalid')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    next() 
 | 
			
		||||
     
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const authorizePermissions = (...roles) => {
 | 
			
		||||
 | 
			
		||||
    return (req, res, next) => {
 | 
			
		||||
 | 
			
		||||
        if (!roles.includes(req.user.role)) {
 | 
			
		||||
            throw new CustomError.UnauthorizedError('Unauthorized do access to this routes')
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        next()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    authorization,
 | 
			
		||||
    authorizePermissions,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
const { StatusCodes } = require('http-status-codes');
 | 
			
		||||
const errorHandlerMiddleware = (err, req, res, next) => {
 | 
			
		||||
  let customError = {
 | 
			
		||||
    // set default
 | 
			
		||||
    statusCode: err.statusCode || StatusCodes.INTERNAL_SERVER_ERROR,
 | 
			
		||||
    msg: err.message || 'Something went wrong try again later',
 | 
			
		||||
  };
 | 
			
		||||
  if (err.name === 'ValidationError') {
 | 
			
		||||
    customError.msg = Object.values(err.errors)
 | 
			
		||||
      .map((item) => item.message)
 | 
			
		||||
      .join(',');
 | 
			
		||||
    customError.statusCode = 400;
 | 
			
		||||
  }
 | 
			
		||||
  if (err.code && err.code === 11000) {
 | 
			
		||||
    customError.msg = `Duplicate value entered for ${Object.keys(
 | 
			
		||||
      err.keyValue
 | 
			
		||||
    )} field, please choose another value`;
 | 
			
		||||
    customError.statusCode = 400;
 | 
			
		||||
  }
 | 
			
		||||
  if (err.name === 'CastError') {
 | 
			
		||||
    customError.msg = `No item found with id : ${err.value}`;
 | 
			
		||||
    customError.statusCode = 404;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return res.status(customError.statusCode).json({ msg: customError.msg });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = errorHandlerMiddleware;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
const notFound = (req, res) => res.status(404).send('Route does not exist')
 | 
			
		||||
 | 
			
		||||
module.exports = notFound
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
[
 | 
			
		||||
  { "languageCode": "af-ZA" },
 | 
			
		||||
  { "languageCode": "ar-XA" },
 | 
			
		||||
  { "languageCode": "bg-BG" },
 | 
			
		||||
  { "languageCode": "bn-IN" },
 | 
			
		||||
  { "languageCode": "ca-ES" },
 | 
			
		||||
  { "languageCode": "cmn-CN" },
 | 
			
		||||
  { "languageCode": "cmn-TW" },
 | 
			
		||||
  { "languageCode": "cs-CZ" },
 | 
			
		||||
  { "languageCode": "da-DK" },
 | 
			
		||||
  { "languageCode": "de-DE" },
 | 
			
		||||
  { "languageCode": "el-GR" },
 | 
			
		||||
  { "languageCode": "en-AU" },
 | 
			
		||||
  { "languageCode": "en-GB" },
 | 
			
		||||
  { "languageCode": "en-IN" },
 | 
			
		||||
  { "languageCode": "en-US" },
 | 
			
		||||
  { "languageCode": "es-ES" },
 | 
			
		||||
  { "languageCode": "es-US" },
 | 
			
		||||
  { "languageCode": "eu-ES" },
 | 
			
		||||
  { "languageCode": "fi-FI" },
 | 
			
		||||
  { "languageCode": "fil-PH" },
 | 
			
		||||
  { "languageCode": "fr-CA" },
 | 
			
		||||
  { "languageCode": "fr-FR" },
 | 
			
		||||
  { "languageCode": "gl-ES" },
 | 
			
		||||
  { "languageCode": "gu-IN" },
 | 
			
		||||
  { "languageCode": "he-IL" },
 | 
			
		||||
  { "languageCode": "hi-IN" },
 | 
			
		||||
  { "languageCode": "hu-HU" },
 | 
			
		||||
  { "languageCode": "id-ID" },
 | 
			
		||||
  { "languageCode": "is-IS" },
 | 
			
		||||
  { "languageCode": "it-IT" },
 | 
			
		||||
  { "languageCode": "ja-JP" },
 | 
			
		||||
  { "languageCode": "kn-IN" },
 | 
			
		||||
  { "languageCode": "ko-KR" },
 | 
			
		||||
  { "languageCode": "lt-LT" },
 | 
			
		||||
  { "languageCode": "lv-LV" },
 | 
			
		||||
  { "languageCode": "ml-IN" },
 | 
			
		||||
  { "languageCode": "mr-IN" },
 | 
			
		||||
  { "languageCode": "ms-MY" },
 | 
			
		||||
  { "languageCode": "nb-NO" },
 | 
			
		||||
  { "languageCode": "nl-BE" },
 | 
			
		||||
  { "languageCode": "nl-NL" },
 | 
			
		||||
  { "languageCode": "pa-IN" },
 | 
			
		||||
  { "languageCode": "pl-PL" },
 | 
			
		||||
  { "languageCode": "pt-BR" },
 | 
			
		||||
  { "languageCode": "pt-PT" },
 | 
			
		||||
  { "languageCode": "ro-RO" },
 | 
			
		||||
  { "languageCode": "ru-RU" },
 | 
			
		||||
  { "languageCode": "sk-SK" },
 | 
			
		||||
  { "languageCode": "sr-RS" },
 | 
			
		||||
  { "languageCode": "sv-SE" },
 | 
			
		||||
  { "languageCode": "ta-IN" },
 | 
			
		||||
  { "languageCode": "te-IN" },
 | 
			
		||||
  { "languageCode": "th-TH" },
 | 
			
		||||
  { "languageCode": "tr-TR" },
 | 
			
		||||
  { "languageCode": "uk-UA" },
 | 
			
		||||
  { "languageCode": "vi-VN" },
 | 
			
		||||
  { "languageCode": "yue-HK" }
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
[
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Wavenet-A",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  },
 | 
			
		||||
  { "name": "pt-BR-Wavenet-B", "ssmlGender": "MALE", "languageCode": "pt-BR" },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Wavenet-C",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Standard-A",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  },
 | 
			
		||||
  { "name": "pt-BR-Standard-B", "ssmlGender": "MALE", "languageCode": "pt-BR" },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Standard-C",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Neural2-A",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  },
 | 
			
		||||
  { "name": "pt-BR-Neural2-B", "ssmlGender": "MALE", "languageCode": "pt-BR" },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Neural2-C",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Standard-A",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  },
 | 
			
		||||
  { "name": "pt-BR-Standard-B", "ssmlGender": "MALE", "languageCode": "pt-BR" },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pt-BR-Standard-C",
 | 
			
		||||
    "ssmlGender": "FEMALE",
 | 
			
		||||
    "languageCode": "pt-BR"
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
const mongoose = require('../db/connect')
 | 
			
		||||
 | 
			
		||||
const { Schema } = mongoose
 | 
			
		||||
 | 
			
		||||
const apiPricing = new Schema({    
 | 
			
		||||
    provider: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    product: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    currency: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        enum: ['dollar', 'real',],
 | 
			
		||||
        default: 'dollar'
 | 
			
		||||
    },
 | 
			
		||||
    price: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true
 | 
			
		||||
    },
 | 
			
		||||
    billingBy:{
 | 
			
		||||
        type: String,
 | 
			
		||||
        enum: ['minute', 'character', 'token'],
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    billingUnit:{
 | 
			
		||||
        type: Number,
 | 
			
		||||
        required: true
 | 
			
		||||
    },
 | 
			
		||||
    type: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        enum: ['input', 'output',], 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}, { timestamps: true })
 | 
			
		||||
 
 | 
			
		||||
const API_Pricing = mongoose.model('API_Pricing', apiPricing)
 | 
			
		||||
 | 
			
		||||
module.exports = API_Pricing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
const mongoose = require('../db/connect')
 | 
			
		||||
 | 
			
		||||
const { Schema } = mongoose
 | 
			
		||||
 | 
			
		||||
const apiUsage = new Schema({
 | 
			
		||||
    companyId: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    callerId: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    quantityOfOperationAttempts: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    chosenOperation: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    requestLogsOpenAI: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    responseErrorLogsOpenAI: {
 | 
			
		||||
        type: String, 
 | 
			
		||||
    },
 | 
			
		||||
    quantityOfCallsToFalconFlowAPI: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    requestLogsFalconFlowAPI: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    responseErrorLogsFalconFlowAPI: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    provider: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    product: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true,
 | 
			
		||||
    },    
 | 
			
		||||
    usage: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true
 | 
			
		||||
    },
 | 
			
		||||
    price: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true
 | 
			
		||||
    },
 | 
			
		||||
    billingBy: {
 | 
			
		||||
        type: String, 
 | 
			
		||||
        required: true,
 | 
			
		||||
    },
 | 
			
		||||
    billingUnit: {
 | 
			
		||||
        type: Number,
 | 
			
		||||
        required: true
 | 
			
		||||
    },     
 | 
			
		||||
    total_cost: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        required: true
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
}, { timestamps: true })
 | 
			
		||||
 
 | 
			
		||||
const API_Usage = mongoose.model('API_Usage', apiUsage)
 | 
			
		||||
 | 
			
		||||
module.exports = API_Usage
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "sentiment_api",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "main": "app.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "node app.js",
 | 
			
		||||
    "dev": "nodemon app.js"
 | 
			
		||||
  },
 | 
			
		||||
  "author": "",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@google-cloud/language": "^6.1.0",
 | 
			
		||||
    "@google-cloud/speech": "^6.0.2",
 | 
			
		||||
    "@google-cloud/storage": "^7.4.0",
 | 
			
		||||
    "@google-cloud/text-to-speech": "^5.0.1",
 | 
			
		||||
    "axios": "^1.7.2",
 | 
			
		||||
    "bcryptjs": "^2.4.3",
 | 
			
		||||
    "bull": "^4.15.1",
 | 
			
		||||
    "cookie-parser": "^1.4.5",
 | 
			
		||||
    "cors": "^2.8.5",
 | 
			
		||||
    "dotenv": "^10.0.0",
 | 
			
		||||
    "express": "^4.17.1",
 | 
			
		||||
    "express-async-errors": "^3.1.1",
 | 
			
		||||
    "express-fileupload": "^1.2.1",
 | 
			
		||||
    "express-mongo-sanitize": "^2.1.0",
 | 
			
		||||
    "express-rate-limit": "^5.4.1",
 | 
			
		||||
    "fluent-ffmpeg": "^2.1.2",
 | 
			
		||||
    "google-gax": "^4.0.5",
 | 
			
		||||
    "google-proto-files": "^4.0.0",
 | 
			
		||||
    "google-protobuf": "^3.21.2",
 | 
			
		||||
    "helmet": "^4.6.0",
 | 
			
		||||
    "http-status-codes": "^2.3.0",
 | 
			
		||||
    "joi": "^17.4.0",
 | 
			
		||||
    "moment": "^2.30.1",
 | 
			
		||||
    "mongoose": "^7.8.0",
 | 
			
		||||
    "morgan": "^1.10.0",
 | 
			
		||||
    "multer": "^1.4.5-lts.1",
 | 
			
		||||
    "openai": "^4.52.7",
 | 
			
		||||
    "protobufjs": "^7.2.5",
 | 
			
		||||
    "swagger-ui-express": "^4.1.6",
 | 
			
		||||
    "validator": "^13.6.0",
 | 
			
		||||
    "xss-clean": "^0.1.1",
 | 
			
		||||
    "yamljs": "^0.3.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@commitlint/cli": "^17.7.2",
 | 
			
		||||
    "@commitlint/config-conventional": "^17.7.0",
 | 
			
		||||
    "husky": "^8.0.3",
 | 
			
		||||
    "nodemon": "^2.0.9"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
const express = require('express')
 | 
			
		||||
const router = express.Router()
 | 
			
		||||
const { authorization, } = require('../middleware/authentication') 
 | 
			
		||||
const { setApiPricing, registerUsage, getUsage} = require('../controllers/apiUsagePricing')
 | 
			
		||||
 | 
			
		||||
router.route('/create').post(authorization, setApiPricing)  
 | 
			
		||||
router.route('/usage').post(authorization, registerUsage)
 | 
			
		||||
router.route('/report').post(authorization, getUsage)  
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = router
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,99 @@
 | 
			
		|||
openapi: 3.0.0
 | 
			
		||||
info:
 | 
			
		||||
  title: Billing API
 | 
			
		||||
  description: This API describes the endpoints to register the use of external APIs.
 | 
			
		||||
  contact: {}
 | 
			
		||||
  version: '1.0'
 | 
			
		||||
servers:
 | 
			
		||||
- url: http://localhost:6001/api/v1/billing
 | 
			
		||||
  variables: {}
 | 
			
		||||
paths:
 | 
			
		||||
  /usage:
 | 
			
		||||
    post:
 | 
			
		||||
      tags:
 | 
			
		||||
      - APIUsage
 | 
			
		||||
      summary: Set usage
 | 
			
		||||
      operationId: setUsage
 | 
			
		||||
      parameters: []
 | 
			
		||||
      requestBody:
 | 
			
		||||
        description: ''
 | 
			
		||||
        content:
 | 
			
		||||
          application/json:
 | 
			
		||||
            schema:
 | 
			
		||||
              type: object
 | 
			
		||||
              properties:
 | 
			
		||||
                companyId:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Company identifier
 | 
			
		||||
                  example: "1"
 | 
			
		||||
                callerId:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Identifier of the person who made the call
 | 
			
		||||
                  example: "17988310949"
 | 
			
		||||
                quantityOfOperationAttempts:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Number of attempts to perform the operation made by the person who made the call
 | 
			
		||||
                  example: "2"
 | 
			
		||||
                chosenOperation:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Operation chosen by the person who made the call
 | 
			
		||||
                  example: "unblokUser"
 | 
			
		||||
                requestLogsOpenAI:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Response logs of requests made to openai
 | 
			
		||||
                  example: "{}"
 | 
			
		||||
                responseErrorLogsOpenAI:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Openai error request response logs
 | 
			
		||||
                  example: "{}"
 | 
			
		||||
                quantityOfCallsToFalconFlowAPI:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Number of requests made to third-party api
 | 
			
		||||
                  example: "2"
 | 
			
		||||
                requestLogsFalconFlowAPI:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Response logs of requests made to third-party api
 | 
			
		||||
                  example: "{}"
 | 
			
		||||
                responseErrorLogsFalconFlowAPI:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Third-party api error request response logs
 | 
			
		||||
                  example: "{}"
 | 
			
		||||
                provider:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Identifier of the organization providing the AI solution
 | 
			
		||||
                  example: "openai"
 | 
			
		||||
                product:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: Product provided by the organization that is providing AI solution
 | 
			
		||||
                  example: "whisper"
 | 
			
		||||
                usage:
 | 
			
		||||
                  type: integer
 | 
			
		||||
                  description: "Using the API. The product Whisper should be sent in seconds"
 | 
			
		||||
                  example: 15
 | 
			
		||||
              required:
 | 
			
		||||
                - companyId
 | 
			
		||||
                - callerId
 | 
			
		||||
                - quantityOfOperationAttempts
 | 
			
		||||
                - chosenOperation
 | 
			
		||||
                - requestLogsOpenAI 
 | 
			
		||||
                - quantityOfCallsToFalconFlowAPI
 | 
			
		||||
                - requestLogsFalconFlowAPI 
 | 
			
		||||
                - provider
 | 
			
		||||
                - product
 | 
			
		||||
                - usage
 | 
			
		||||
        required: true
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: ''
 | 
			
		||||
          headers: {}
 | 
			
		||||
      deprecated: false
 | 
			
		||||
      security:
 | 
			
		||||
      - bearer: []
 | 
			
		||||
components:
 | 
			
		||||
  securitySchemes:
 | 
			
		||||
    bearer:
 | 
			
		||||
      type: http
 | 
			
		||||
      scheme: bearer
 | 
			
		||||
security: []
 | 
			
		||||
tags: 
 | 
			
		||||
- name: APIUsage
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,216 @@
 | 
			
		|||
openapi: 3.0.0
 | 
			
		||||
info:
 | 
			
		||||
  title: Natural Language API Google
 | 
			
		||||
  description: This API describes the endpoints and parameters to use resources from Google Cloud API.
 | 
			
		||||
  contact: {}
 | 
			
		||||
  version: '1.0'
 | 
			
		||||
servers:
 | 
			
		||||
- url: http://localhost:6001/api/v1/nl
 | 
			
		||||
  variables: {}
 | 
			
		||||
paths:
 | 
			
		||||
  /upload-audio-to-transcript:
 | 
			
		||||
    post:
 | 
			
		||||
      tags:
 | 
			
		||||
      - Speech to text async
 | 
			
		||||
      summary: Speech to text job
 | 
			
		||||
      operationId: Speechtotextjob
 | 
			
		||||
      parameters: []
 | 
			
		||||
      requestBody:
 | 
			
		||||
        content:
 | 
			
		||||
          multipart/form-data:
 | 
			
		||||
            encoding: {}
 | 
			
		||||
            schema:
 | 
			
		||||
              required:
 | 
			
		||||
              - audio 
 | 
			
		||||
              type: object
 | 
			
		||||
              properties:
 | 
			
		||||
                audio:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  format: binary
 | 
			
		||||
                languageCode:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  description: 'If not provided, the default will be: pt-BR'
 | 
			
		||||
                  example: pt-BR
 | 
			
		||||
        required: false
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: ''
 | 
			
		||||
          headers: {}
 | 
			
		||||
      deprecated: false
 | 
			
		||||
      security:
 | 
			
		||||
      - bearer: []
 | 
			
		||||
  /query-job-status:
 | 
			
		||||
    get:
 | 
			
		||||
      tags:
 | 
			
		||||
      - Speech to text async
 | 
			
		||||
      summary: Speech to text job process
 | 
			
		||||
      operationId: Speechtotextjobprocess
 | 
			
		||||
      parameters:
 | 
			
		||||
      - name: operationName
 | 
			
		||||
        in: query
 | 
			
		||||
        description: 'The job id returned after uploading the audio file that will be transcribed.'
 | 
			
		||||
        required: true
 | 
			
		||||
        style: form
 | 
			
		||||
        explode: true
 | 
			
		||||
        schema:
 | 
			
		||||
          type: integer
 | 
			
		||||
          format: int64
 | 
			
		||||
          example: 2993135803178989324
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: ''
 | 
			
		||||
          headers: {}
 | 
			
		||||
      deprecated: false
 | 
			
		||||
      security:
 | 
			
		||||
      - bearer: []
 | 
			
		||||
  /speech-to-text:
 | 
			
		||||
    post:
 | 
			
		||||
      tags:
 | 
			
		||||
      - Speech to text sync
 | 
			
		||||
      summary: Speech to text
 | 
			
		||||
      operationId: Speechtotext
 | 
			
		||||
      parameters: []
 | 
			
		||||
      requestBody:
 | 
			
		||||
        content:
 | 
			
		||||
          multipart/form-data:
 | 
			
		||||
            encoding: {}
 | 
			
		||||
            schema:
 | 
			
		||||
              required:
 | 
			
		||||
              - audio 
 | 
			
		||||
              type: object
 | 
			
		||||
              properties:
 | 
			
		||||
                audio:
 | 
			
		||||
                  type: string
 | 
			
		||||
                  format: binary
 | 
			
		||||
                languageCode:
 | 
			
		||||
                  description: 'If not provided, the default will be: pt-BR'
 | 
			
		||||
                  type: string 
 | 
			
		||||
                  example: pt-BR
 | 
			
		||||
        required: false
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: ''
 | 
			
		||||
          headers: {}
 | 
			
		||||
      deprecated: false
 | 
			
		||||
      security:
 | 
			
		||||
      - bearer: []
 | 
			
		||||
  /sentiment:
 | 
			
		||||
    post:
 | 
			
		||||
      tags:
 | 
			
		||||
      - Sentiment
 | 
			
		||||
      summary: Get sentiment
 | 
			
		||||
      operationId: Getsentiment
 | 
			
		||||
      parameters: []
 | 
			
		||||
      requestBody:
 | 
			
		||||
        description: ''
 | 
			
		||||
        content:
 | 
			
		||||
          application/json:
 | 
			
		||||
            schema:
 | 
			
		||||
              allOf:
 | 
			
		||||
              - $ref: '#/components/schemas/GetsentimentRequest'
 | 
			
		||||
              - example:
 | 
			
		||||
                  text: Toda vez a mesma coisa ja to cansado de ficar ligando pra resolver esses problemas de conexão!
 | 
			
		||||
            example:
 | 
			
		||||
              text: Toda vez a mesma coisa ja to cansado de ficar ligando pra resolver esses problemas de conexão!
 | 
			
		||||
        required: true
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: ''
 | 
			
		||||
          headers: {}
 | 
			
		||||
      deprecated: false
 | 
			
		||||
      security:
 | 
			
		||||
      - bearer: []
 | 
			
		||||
  /text-to-speech:
 | 
			
		||||
    get:
 | 
			
		||||
      tags:
 | 
			
		||||
      - Text to speech
 | 
			
		||||
      summary: Text to speech
 | 
			
		||||
      operationId: Texttospeech
 | 
			
		||||
      parameters:
 | 
			
		||||
      - name: text
 | 
			
		||||
        in: query
 | 
			
		||||
        description: ''
 | 
			
		||||
        required: true
 | 
			
		||||
        style: form
 | 
			
		||||
        explode: true
 | 
			
		||||
        schema:
 | 
			
		||||
          type: string
 | 
			
		||||
          example: Vela branca na enxurrada la vou eu de léo em léo, se o navio é pequeno do tamanho de um chapeu, não importa a volta ao mundo, é viagem de brinquedo em um barquinho de papel.
 | 
			
		||||
      - name: voice_name
 | 
			
		||||
        in: query
 | 
			
		||||
        description: ''
 | 
			
		||||
        required: false
 | 
			
		||||
        style: form
 | 
			
		||||
        explode: true
 | 
			
		||||
        schema:
 | 
			
		||||
          type: string
 | 
			
		||||
          example: pt-BR-Wavenet-C
 | 
			
		||||
      - name: voice_gender
 | 
			
		||||
        in: query
 | 
			
		||||
        description: ''
 | 
			
		||||
        required: false
 | 
			
		||||
        style: form
 | 
			
		||||
        explode: true
 | 
			
		||||
        schema:
 | 
			
		||||
          type: string
 | 
			
		||||
          example: FEMALE
 | 
			
		||||
      - name: languageCode
 | 
			
		||||
        in: query
 | 
			
		||||
        description: ''
 | 
			
		||||
        required: false
 | 
			
		||||
        style: form
 | 
			
		||||
        explode: true
 | 
			
		||||
        schema:
 | 
			
		||||
          type: string
 | 
			
		||||
          example: pt-BR
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: ''
 | 
			
		||||
          headers: {}
 | 
			
		||||
      deprecated: false
 | 
			
		||||
      security:
 | 
			
		||||
      - bearer: []
 | 
			
		||||
  /voice-config:
 | 
			
		||||
    get:
 | 
			
		||||
      tags:
 | 
			
		||||
      - Text to speech
 | 
			
		||||
      summary: Get voice config
 | 
			
		||||
      operationId: Getvoiceconfig
 | 
			
		||||
      parameters:
 | 
			
		||||
      - name: languageCode
 | 
			
		||||
        in: query
 | 
			
		||||
        description: ''
 | 
			
		||||
        required: false
 | 
			
		||||
        style: form
 | 
			
		||||
        explode: true
 | 
			
		||||
        schema:
 | 
			
		||||
          type: string
 | 
			
		||||
          example: pt-Br
 | 
			
		||||
      responses:
 | 
			
		||||
        '200':
 | 
			
		||||
          description: ''
 | 
			
		||||
          headers: {}
 | 
			
		||||
      deprecated: false
 | 
			
		||||
      security: []
 | 
			
		||||
components:
 | 
			
		||||
  schemas:
 | 
			
		||||
    GetsentimentRequest:
 | 
			
		||||
      title: GetsentimentRequest
 | 
			
		||||
      required:
 | 
			
		||||
      - text
 | 
			
		||||
      type: object
 | 
			
		||||
      properties:
 | 
			
		||||
        text:
 | 
			
		||||
          type: string
 | 
			
		||||
      example:
 | 
			
		||||
        text: Toda vez a mesma coisa ja to cansado de ficar ligando pra resolver esses problemas de conexão!
 | 
			
		||||
  securitySchemes:
 | 
			
		||||
    bearer:
 | 
			
		||||
      type: http
 | 
			
		||||
      scheme: bearer
 | 
			
		||||
security: []
 | 
			
		||||
tags:
 | 
			
		||||
- name: Speech to text async
 | 
			
		||||
- name: Speech to text sync
 | 
			
		||||
- name: Sentiment
 | 
			
		||||
- name: Text to speech
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
const multer = require('multer')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
//Destination to store the file
 | 
			
		||||
const audioStorage = multer.diskStorage({
 | 
			
		||||
    destination: function (req, file, cb) {
 | 
			
		||||
        cb(null, `public/uploads`)
 | 
			
		||||
    },
 | 
			
		||||
    filename: function (req, file, cb) {
 | 
			
		||||
        cb(null, Date.now() + String(Math.floor(Math.random() * 1000)) + path.extname(file.originalname))
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const audioUpload = multer({
 | 
			
		||||
    storage: audioStorage,
 | 
			
		||||
    fileFilter(req, file, cb) {
 | 
			
		||||
        if (!file.originalname.match(/\.(mp3|wav|ogg|flac|aac|wma|m4a|mp4|webm|opus|mpeg)$/i)) {
 | 
			
		||||
            return cb(new Error('Invalid file type. Send only an audio file!'))
 | 
			
		||||
        }
 | 
			
		||||
        cb(undefined, true)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
module.exports = audioUpload 
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
const moment = require('moment')
 | 
			
		||||
const API_Usage = require("../models/API_Usage.js")
 | 
			
		||||
 | 
			
		||||
async function billingSumUsage(startDate, endDate, companyId) {
 | 
			
		||||
    try {
 | 
			
		||||
        const start = moment(startDate, 'YYYY-MM-DD').startOf('day').toDate()
 | 
			
		||||
        const end = moment(endDate, 'YYYY-MM-DD').endOf('day').toDate()
 | 
			
		||||
 | 
			
		||||
        const result = await API_Usage.aggregate([
 | 
			
		||||
            {
 | 
			
		||||
                $match: {
 | 
			
		||||
                    createdAt: {
 | 
			
		||||
                        $gte: start,
 | 
			
		||||
                        $lte: end
 | 
			
		||||
                    },
 | 
			
		||||
                    companyId
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                $group: {
 | 
			
		||||
                    _id: null,
 | 
			
		||||
                    total: {
 | 
			
		||||
                        $sum: {
 | 
			
		||||
                            $toDouble: "$price"  
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        ])
 | 
			
		||||
 | 
			
		||||
        if (result.length > 0) {
 | 
			
		||||
            return result[0].total
 | 
			
		||||
        } else {
 | 
			
		||||
            return 0
 | 
			
		||||
        }
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        console.error('Error calculating sum of prices:', error) 
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = billingSumUsage
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
function calculateApiUsage(price, billingUnit, usage, billingBy) {
 | 
			
		||||
  let _billingUnit = +billingUnit
 | 
			
		||||
 | 
			
		||||
  if (billingBy == 'minute')
 | 
			
		||||
    _billingUnit = 60 * _billingUnit 
 | 
			
		||||
 | 
			
		||||
  const total_cost = (+usage / _billingUnit) * parseFloat(price) 
 | 
			
		||||
 | 
			
		||||
  return total_cost.toFixed(10)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = calculateApiUsage
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
const audioUpload = require('./audioUpload') 
 | 
			
		||||
const mustContainProperties = require('./mustContainProperties') 
 | 
			
		||||
const calculateApiUsage = require('./calculateApiUsage') 
 | 
			
		||||
 | 
			
		||||
module.exports = { 
 | 
			
		||||
    audioUpload, 
 | 
			
		||||
    mustContainProperties,
 | 
			
		||||
    calculateApiUsage
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
const CustomError = require('../errors')
 | 
			
		||||
 | 
			
		||||
function mustContainProperties(req, requiredProperties) { 
 | 
			
		||||
    
 | 
			
		||||
    const missingProperties = requiredProperties.filter(prop => !req.body[prop])
 | 
			
		||||
 | 
			
		||||
    if (missingProperties.length > 0) {
 | 
			
		||||
        throw new CustomError.BadRequestError(`Missing properties: ${missingProperties.join(', ')}`)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = mustContainProperties
 | 
			
		||||
		Loading…
	
		Reference in New Issue