S3 : add news

This commit is contained in:
2026-06-19 12:11:18 +03:30
parent 1c40eb958b
commit 99a9f9ace5
11 changed files with 1002 additions and 247 deletions
+46
View File
@@ -0,0 +1,46 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const NEWS_IMAGE_PREFIX = "uploads/images/news";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteNewsImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${NEWS_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${NEWS_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
NEWS_IMAGE_PREFIX,
getStoredImageName,
deleteNewsImage,
uploadProcessedImage,
};
+93
View File
@@ -0,0 +1,93 @@
const {
S3Client,
PutObjectCommand,
DeleteObjectCommand,
} = require("@aws-sdk/client-s3");
const config = {
bucket: process.env.BUCKET_NAME,
region: process.env.BUCKET_REGION || "us-west-2",
endpoint: process.env.PARSPACK_S3_ENDPOINT,
accessKeyId: process.env.BUCKET_ACCESS_KEY,
secretAccessKey: process.env.BUCKET_SECRET_KEY,
publicUrl: process.env.BUCKET_PUBLIC_URL || process.env.PARSPACK_S3_ENDPOINT,
};
let s3Client = null;
const isConfigured = () =>
Boolean(
config.bucket &&
config.endpoint &&
config.accessKeyId &&
config.secretAccessKey
);
const getClient = () => {
if (!isConfigured()) {
throw new Error("S3 storage is not configured");
}
if (!s3Client) {
s3Client = new S3Client({
region: config.region,
endpoint: config.endpoint,
credentials: {
accessKeyId: config.accessKeyId,
secretAccessKey: config.secretAccessKey,
},
forcePathStyle: true,
});
}
return s3Client;
};
const normalizeKey = (key) => key.replace(/^\/+/, "");
const getPublicUrl = (key) => {
const normalizedKey = normalizeKey(key);
const baseUrl = (config.publicUrl || config.endpoint).replace(/\/+$/, "");
return `${baseUrl}/${normalizedKey}`;
};
const uploadBuffer = async (
key,
buffer,
contentType = "application/octet-stream"
) => {
const normalizedKey = normalizeKey(key);
await getClient().send(
new PutObjectCommand({
Bucket: config.bucket,
Key: normalizedKey,
Body: buffer,
ContentType: contentType,
ACL: "public-read",
})
);
return {
key: normalizedKey,
url: getPublicUrl(normalizedKey),
};
};
const deleteObject = async (key) => {
const normalizedKey = normalizeKey(key);
await getClient().send(
new DeleteObjectCommand({
Bucket: config.bucket,
Key: normalizedKey,
})
);
};
module.exports = {
isConfigured,
getPublicUrl,
uploadBuffer,
deleteObject,
};
+12 -7
View File
@@ -1,18 +1,24 @@
const axios = require("axios");
const SMS_API_KEY = "QkkNxhyXZ6GtEf1soOTtikomO3mA4LaNQDH8mol8huDIwh00";
module.exports.sms = async (phoneNumber, message) => {
const smsService = new SmsService("QkkNxhyXZ6GtEf1soOTtikomO3mA4LaNQDH8mol8huDIwh00");
const smsService = new SmsService(SMS_API_KEY);
return smsService.sendMessage(phoneNumber, message);
};
/** Sends login/verification OTP via sms.ir template (verify endpoint). */
module.exports.sendOtpSms = async (phoneNumber, otp) => {
const smsService = new SmsService(SMS_API_KEY);
return smsService.sendOTPSms(otp, phoneNumber);
};
class SmsService {
constructor(apiKey) {
this.API_URL = "https://api.sms.ir/v1";
this.OTP_PATTERN = "83604";
this.OTP_PATTERN = "628767";
this.SMS_API_KEY = apiKey;
}
//******************************** */
//******************************** */
async sendMessage(phone, message) {
try {
@@ -32,7 +38,7 @@ class SmsService {
console.error("Error in sending SMS", error);
}
}
//******************************** */
async getLineNumber() {
try {
const { data } = await axios.get(`${this.API_URL}/line`, {
@@ -45,7 +51,6 @@ class SmsService {
console.error("Error in getting line number", error);
}
}
//******************************** */
async sendOTPSms(otp, phone) {
const smsData = {