38038-vm/backend/src/services/news_cards.js
2026-01-31 17:26:19 +00:00

159 lines
4.1 KiB
JavaScript

const db = require('../db/models');
const News_cardsDBApi = require('../db/api/news_cards');
const processFile = require("../middlewares/upload");
const ValidationError = require('./notifications/errors/validation');
const csv = require('csv-parser');
const axios = require('axios');
const config = require('../config');
const stream = require('stream');
module.exports = class News_cardsService {
static async create(data, currentUser) {
const transaction = await db.sequelize.transaction();
try {
await News_cardsDBApi.create(
data,
{
currentUser,
transaction,
},
);
await transaction.commit();
} catch (error) {
await transaction.rollback();
throw error;
}
};
static async scrapeUrl(url) {
try {
const response = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
},
timeout: 5000
});
const html = response.data;
// Basic extraction using regex for speed and simplicity without new dependencies
const titleMatch = html.match(/<meta property="og:title" content="([^"]+)"/) ||
html.match(/<title>([^<]+)<\/title>/);
const imageMatch = html.match(/<meta property="og:image" content="([^"]+)"/);
return {
title: titleMatch ? titleMatch[1].trim() : 'No title found',
imageUrl: imageMatch ? imageMatch[1] : null,
date: new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'long', year: 'numeric' }),
url
};
} catch (error) {
console.error('Scraping error:', error.message);
throw new Error('Failed to fetch news metadata');
}
}
static async bulkImport(req, res, sendInvitationEmails = true, host) {
const transaction = await db.sequelize.transaction();
try {
await processFile(req, res);
const bufferStream = new stream.PassThrough();
const results = [];
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
await new Promise((resolve, reject) => {
bufferStream
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', async () => {
console.log('CSV results', results);
resolve();
})
.on('error', (error) => reject(error));
})
await News_cardsDBApi.bulkImport(results, {
transaction,
ignoreDuplicates: true,
validate: true,
currentUser: req.currentUser
});
await transaction.commit();
} catch (error) {
await transaction.rollback();
throw error;
}
}
static async update(data, id, currentUser) {
const transaction = await db.sequelize.transaction();
try {
let news_cards = await News_cardsDBApi.findBy(
{id},
{transaction},
);
if (!news_cards) {
throw new ValidationError(
'news_cardsNotFound',
);
}
const updatedNews_cards = await News_cardsDBApi.update(
id,
data,
{
currentUser,
transaction,
},
);
await transaction.commit();
return updatedNews_cards;
} catch (error) {
await transaction.rollback();
throw error;
}
};
static async deleteByIds(ids, currentUser) {
const transaction = await db.sequelize.transaction();
try {
await News_cardsDBApi.deleteByIds(ids, {
currentUser,
transaction,
});
await transaction.commit();
} catch (error) {
await transaction.rollback();
throw error;
}
}
static async remove(id, currentUser) {
const transaction = await db.sequelize.transaction();
try {
await News_cardsDBApi.remove(
id,
{
currentUser,
transaction,
},
);
await transaction.commit();
} catch (error) {
await transaction.rollback();
throw error;
}
}
};