This commit is contained in:
2024-05-13 17:28:13 +05:00
commit 1ff3fb351d
166 changed files with 10288 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
PORT=3003
MONGO_URI=mongodb://root:p62Z!ZatgY25@194.26.138.94:27017/
JWT_SECRET=yDcdWJgvlj2bJAuovYfQHTvtc3U9xQPw
+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+10
View File
@@ -0,0 +1,10 @@
module.exports = {
apps: [
{
name: "graff.estate-server:3003",
exec_mode: "cluster",
script: "yarn",
args: "start",
},
],
};
+34
View File
@@ -0,0 +1,34 @@
{
"name": "server",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "nodemon src/index.ts",
"build": "npx tsc",
"start": "node dist/index.js"
},
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-sslify": "^1.2.0",
"mongoose": "^8.0.1",
"multer": "^1.4.5-lts.1",
"nodemailer": "^6.9.7",
"sharp": "^0.32.6",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/cors": "^2.8.15",
"@types/express": "^4.17.20",
"@types/express-sslify": "^1.2.5",
"@types/multer": "^1.4.11",
"@types/node": "^20.8.10",
"@types/nodemailer": "^6.4.14",
"@types/uuid": "^9.0.7",
"nodemon": "^3.0.1",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.2.2"
}
}
+16
View File
@@ -0,0 +1,16 @@
import { connect } from "mongoose";
async function connectDB() {
try {
await connect(process.env.MONGO_URI!, { dbName: "estate" });
console.log("MongoDB connected...");
} catch (error) {
if (error instanceof Error) {
console.error(error.message);
}
process.exit(1);
}
}
export default connectDB;
+25
View File
@@ -0,0 +1,25 @@
import "dotenv/config";
import connectDB from "./config/db";
import express, { json } from "express";
import cors from "cors";
import mailRoute from "./routes/mail";
import projectRoute from "./routes/projects";
import uploadRoute from "./routes/upload";
import getRegionNameRoute from "./routes/getRegionName";
connectDB();
const app = express();
const port = process.env.PORT || 3003;
app.use(json());
app.use(cors({ origin: "*" }));
app.use("/mail", mailRoute);
app.use("/projects", projectRoute);
app.use("/upload", uploadRoute);
app.use("/getRegionName", getRegionNameRoute);
app.listen(port, () => {
console.log(`Server is listening on port ${port}`);
});
+32
View File
@@ -0,0 +1,32 @@
import { Schema, model } from "mongoose";
const mailSchema = new Schema(
{
fullname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
phone: {
type: String,
},
request: {
type: String,
},
referer: {
type: String,
},
},
{
timestamps: true,
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
const Mail = model("Mail", mailSchema);
export default Mail;
+42
View File
@@ -0,0 +1,42 @@
import { Schema, model } from "mongoose";
const projectSchema = new Schema(
{
name: {
type: String,
required: true,
},
company: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
image: {
type: String,
required: true,
},
stage: {
type: Number,
default: 1,
},
releaseDate: {
type: Date,
required: true,
},
devices: {
type: Array,
},
},
{
timestamps: true,
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
const Project = model("Project", projectSchema);
export default Project;
+31
View File
@@ -0,0 +1,31 @@
import { Router } from "express";
import fs from "fs";
const router = Router();
router.get("/", async (req, res) => {
const ip = req.headers["x-forwarded-for"];
try {
const { countryCode, region, regionName }: any = await (
await fetch(`http://ip-api.com/json/${ip}?lang=ru`)
).json();
if (countryCode === "RU") {
fs.appendFileSync(
"./log.txt",
`${countryCode}-${region} (${regionName})\n`
);
}
res.json({ regionName });
} catch (error) {
if (error instanceof Error) {
res.json({ error: error.message });
}
}
});
const getRegionNameRoute = router;
export default getRegionNameRoute;
+57
View File
@@ -0,0 +1,57 @@
import { Router } from "express";
import Mail from "../models/Mail";
import nodemailer from "nodemailer";
const router = Router();
router.post("/", async (req, res) => {
try {
const referer = req.headers.referer;
const { fullname, email, phone, request } = req.body;
await Mail.create({ fullname, email, phone, request, referer });
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "mail.netangels.ru",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "test@graff.tech", // generated ethereal user
pass: "ZmL0pKiDFWUyCDMq", // generated ethereal password
},
});
// send mail with defined transport object
let info = await transporter.sendMail({
from: email, // sender address
to: "info@graff.tech", // list of receivers
subject: "Заявка с сайта graff.estate", // Subject line
text: `
Имя Фамилия: ${fullname}
Email: ${email}
Телефон: ${phone}
Текст запроса: ${request}
`, // plain text body
html: `<div>
<p>Имя: ${fullname}</p>
<p>Email: ${email}</p>
<p>Телефон: ${phone}</p>
<p>Текст запроса: ${request}</p>
</div>`, // html body
});
console.log(info);
console.log(req.body);
res.json({ ok: 1 });
} catch (error) {
console.log(error);
res.json({ error: 1 });
}
});
const mailRoute = router;
export default mailRoute;
+70
View File
@@ -0,0 +1,70 @@
import { Router } from "express";
import Project from "../models/Project";
const router = Router();
router.get("/", async (_req, res) => {
try {
const projects = await Project.find().sort({ releaseDate: -1 });
return res.json(projects);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.get("/:id", async (req, res) => {
try {
const project = await Project.findById(req.params.id);
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.post("/", async (req, res) => {
try {
const project = await Project.create(req.body);
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.put("/:id", async (req, res) => {
try {
const project = await Project.findByIdAndUpdate(req.params.id, req.body, {
upsert: true,
new: true,
});
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.delete("/:id", async (req, res) => {
try {
const project = await Project.findByIdAndDelete(req.params.id);
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
const projectRoute = router;
export default projectRoute;
+78
View File
@@ -0,0 +1,78 @@
import { Router } from "express";
import multer, { memoryStorage } from "multer";
import sharp from "sharp";
import fs from "fs";
import path from "path";
import { v4 as uuidv4 } from "uuid";
const router = Router();
const upload = multer({
dest: "uploads/",
storage: memoryStorage(),
fileFilter: (_req, file, cb) => {
if (file.mimetype.split("/")[0] === "image") {
cb(null, true);
} else {
cb(new Error("Only images are allowed!"));
}
},
});
router.get("/", (_req, res) => {
res.json({ ok: 1 });
});
router.get("/:filename", (req, res) => {
res.sendFile(`${path.resolve("uploads")}/${req.params.filename}`);
});
router.get("/:file", (req, res) => {
const fileName = req.params.file;
console.log(fileName);
try {
const readStream = fs.createReadStream(
`${path.join(__dirname, "uploads")}/${fileName}`
);
console.log(readStream);
readStream.pipe(res);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.post("/", upload.single("file"), async (req, res) => {
if (!req.file) {
return res.json({ error: "req.file" });
}
try {
const filename = `${uuidv4()}.jpg`;
await sharp(req.file.buffer)
.resize({
width: 728,
height: 728,
fit: "inside",
withoutEnlargement: true,
})
.jpeg({ quality: 90 })
.toFile(`uploads/${filename}`);
return res.json({ file: filename });
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
const uploadRoute = router;
export default uploadRoute;
+18
View File
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "CommonJS",
"moduleResolution": "Node",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true
},
"ts-node": {
"transpileOnly": true
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

+1497
View File
File diff suppressed because it is too large Load Diff