19
loading...
This website collects cookies to deliver better user experience
$ createdb zoom-summarizer
$ createuser -P -s -e zoom_summarizer_user
DATABASE_URL = 'postgresql://zoom-summarizer-user@localhost:5432/zoom-summarizer'
$ npm i
$ npx prisma migrate dev --name init
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();
// CREATE
const createUser = async (email, password, name) => {
const result = await prisma.user.create({
data: {
email,
password,
name,
},
});
return result;
};
module.exports = {
createUser,
};
const db = require("./db/db");
const bcrypt = require("bcrypt");
const jwtService = require("jsonwebtoken");
const express = require("express");
const app = express();
app.use(express.json());
app.get(`/`, async (req, res) => {
res.json({ success: true, data: "Hello World!" });
});
app.post("/signup", async (req, res) => {
const { email, password, name } = req.body;
if (!email || !password || !name) {
res.status(400).json({
success: false,
error: "Email, password and name are required.",
});
return;
}
try {
// hash password
const salt = await bcrypt.genSalt(Number(process.env.SALT_ROUNDS));
const passwordHash = await bcrypt.hash(password, salt);
// create user
const response = await db.createUser(email, passwordHash, name);
res.json({ success: true, data: response });
} catch (e) {
console.log(e);
res.status(409).json({
success: false,
error: "Email account already registered.",
});
}
});
{
"email": "[email protected]",
"password": "123",
"name": "Guillermo"
}
const jwt = require("jsonwebtoken");
const getJWT = async (id, email) => {
try {
return jwt.sign(
{
email,
id,
},
process.env.JWT_SECRET,
{
expiresIn: Number(process.env.JWT_EXPIRE_TIME),
}
);
} catch (e) {
throw new Error(e.message);
}
};
const authorize = (req, res, next) => {
// middleware to check if user is logged in
try {
const token = req.headers.authorization.split(" ")[1];
jwt.verify(token, process.env.JWT_SECRET);
next();
} catch (error) {
res.status(401).json({ success: false, error: "Authentication failed." });
}
};
module.exports = {
getJWT,
authorize,
};
const jwtService = require("jsonwebtoken");
const jwtLib = require("./lib/jwt");
// READ
const getSingleUserByEmail = async (email) => {
const user = await prisma.user.findFirst({
where: { email },
});
return user;
};
module.exports = {
createUser,
getSingleUserByEmail
};
app.post("/signin", async (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
res
.status(400)
.json({ success: false, error: "Email and password are required." });
return;
}
try {
// Find user record
const user = await db.getSingleUserByEmail(email);
if (!user) {
res.status(401).json({ success: false, error: "Authentication failed." });
return;
}
// securely compare passwords
const match = await bcrypt.compare(password, user.password);
if (!match) {
res.status(401).json({ success: false, error: "Authentication failed." });
return;
}
// get jwt
const jwtToken = await jwtLib.getJWT(user.id, user.email);
// send jwt and user id to store in local storage
res
.status(200)
.json({ success: true, data: { jwt: jwtToken, id: user.id } });
} catch (e) {
console.log(e);
res.status(500).json({
success: false,
error: `Authentication failed.`,
});
}
});
const AWS = require("aws-sdk");
s3 = new AWS.S3({ apiVersion: "2006-03-01" });
const uploadFile = async (file) => {
const params = {
Bucket: process.env.AWS_S3_BUCKET_NAME,
Key: file.name,
Body: file.data,
};
try {
const stored = await s3.upload(params).promise();
return stored;
} catch (e) {
console.log(e);
throw new Error(e.message);
}
};
module.exports = {
uploadFile,
};
const PDF = require("pdfkit");
const generatePdf = (title, text, terms, res) => {
const pdf = new PDF({ bufferPages: true });
let buffers = [];
pdf.on("data", buffers.push.bind(buffers));
pdf.on("end", () => {
let pdfData = Buffer.concat(buffers);
res
.writeHead(200, {
"Content-Length": Buffer.byteLength(pdfData),
"Content-Type": "application/pdf",
"Content-disposition": `attachment;filename=${title}.pdf`,
})
.end(pdfData);
});
pdf.font("Times-Roman").fontSize(20).text(title, {
align: "center",
paragraphGap: 20,
});
pdf.font("Times-Roman").fontSize(12).text(text, {
lineGap: 20,
});
if (terms) {
const termsArr = terms.results.sort((a, b) => b.rank - a.rank);
const cleanedTerms = termsArr.map((term) => term.text);
pdf.font("Times-Roman").fontSize(16).text("Key Terms", {
align: "center",
paragraphGap: 20,
});
pdf
.font("Times-Roman")
.fontSize(12)
.list(cleanedTerms, { listType: "numbered" });
}
pdf
.fillColor("gray")
.fontSize(12)
.text(
"Transcript provided by AssemblyAI ",
pdf.page.width - 200,
pdf.page.height - 25,
{
lineBreak: false,
align: "center",
}
);
pdf.end();
};
module.exports = {
generatePdf,
};
const createRecording = async (name, s3Key, transcriptId, email) => {
const result = await prisma.recording.create({
data: {
name,
s3Key,
transcriptId,
user: {
connect: {
email,
},
},
},
});
return result;
};
const getSingleUserById = async (id) => {
const user = await prisma.user.findFirst({
where: { id },
});
return user;
};
module.exports = {
createUser,
createRecording,
getSingleUserByEmail,
getSingleUserById,
};
const db = require("./db/db");
const jwtLib = require("./lib/jwt");
const awsLib = require("./lib/aws");
const pdfLib = require("./lib/pdf");
const fetch = require("node-fetch");
const bcrypt = require("bcrypt");
const express = require("express");
const fileUpload = require("express-fileupload");
const cors = require("cors");
const { response } = require("express");
const app = express();
app.use(cors());
app.use(express.json());
app.use(fileUpload());
.
.
.
app.post("/upload", jwtLib.authorize, async (req, res) => {
const { id } = req.body;
if (!id) {
return res
.status(400)
.json({ success: false, error: "You must provide the user id." });
}
if (!req.files || Object.keys(req.files).length === 0) {
return res
.status(400)
.json({ success: false, error: "No files were uploaded." });
}
try {
const file = req.files.uploadedFile;
// upload to s3
const uploadedFile = await awsLib.uploadFile(file);
const { Location, key } = uploadedFile;
const body = {
audio_url: Location,
auto_highlights: true,
};
// call aai api
const response = await fetch(process.env.ASSEMBLYAI_API_URL, {
method: "POST",
body: JSON.stringify(body),
headers: {
authorization: process.env.ASSEMBLYAI_API_KEY,
"content-type": "application/json",
},
});
const result = await response.json();
if (result.error) {
console.log(result);
res.status(500).json({
success: false,
error: "There was an error uploading your file.",
});
return;
}
// get user email
const user = await db.getSingleUserById(Number(id));
const { email } = user;
// save transcript id to db
const recording = await db.createRecording(
file.name,
key,
result.id,
email
);
res.status(200).json({ success: true, data: recording });
} catch (e) {
console.log(e);
res.status(500).json({
success: false,
error: "There was an error uploading your file.",
});
}
});
const getSingleRecording = async (transcriptId) => {
const recording = await prisma.recording.findFirst({
where: {
transcriptId,
},
});
return recording;
};
module.exports = {
createUser,
createRecording,
getSingleUserByEmail,
getSingleUserById,
getSingleRecording,
};
app.post("/generate-pdf", jwtLib.authorize, async (req, res) => {
const { transcriptId } = req.body;
if (!transcriptId) {
return res
.status(400)
.json({ success: false, error: "You must provide the transcript id." });
}
try {
const url = process.env.ASSEMBLYAI_API_URL + "/" + transcriptId;
const response = await fetch(url, {
method: "GET",
headers: {
authorization: process.env.ASSEMBLYAI_API_KEY,
"content-type": "application/json",
},
});
const result = await response.json();
if (result.error) {
console.log(result);
res.status(500).json({
success: false,
error: "There was an error retrieving your recording.",
});
return;
}
const { text, auto_highlights_result } = result;
const recordingRecord = await db.getSingleRecording(transcriptId);
const { name } = recordingRecord;
pdfLib.generatePdf("Transcript", text, auto_highlights_result, res);
} catch (e) {
console.log(e);
res.status(500).json({
success: false,
error: "There was an error retrieving your recordings.",
});
}
});
19