159 lines
4.8 KiB
JavaScript
159 lines
4.8 KiB
JavaScript
|
import { knexOwner as knex } from './knex.js';
|
||
|
import promiseProps from '../utils/promise-props.js';
|
||
|
import { HttpError } from './errors.js';
|
||
|
|
||
|
function curateAlert(alert, context = {}) {
|
||
|
return {
|
||
|
id: alert.id,
|
||
|
notify: alert.notify,
|
||
|
email: alert.email,
|
||
|
createdAt: alert.created_at,
|
||
|
and: {
|
||
|
fields: alert.all,
|
||
|
actors: alert.all_actors,
|
||
|
tags: alert.all_tags,
|
||
|
entities: alert.all_entities,
|
||
|
matches: alert.all_tags,
|
||
|
},
|
||
|
actors: context.actors?.map((actor) => ({
|
||
|
id: actor.actor_id,
|
||
|
name: actor.actor_name,
|
||
|
slug: actor.actor_slug,
|
||
|
})) || [],
|
||
|
tags: context.tags?.map((tag) => ({
|
||
|
id: tag.tag_id,
|
||
|
name: tag.tag_name,
|
||
|
slug: tag.tag_slug,
|
||
|
})) || [],
|
||
|
entities: context.entities?.map((entity) => ({
|
||
|
id: entity.entity_id,
|
||
|
name: entity.entity_name,
|
||
|
slug: entity.entity_slug,
|
||
|
type: entity.type,
|
||
|
})) || [],
|
||
|
matches: context.matches?.map((match) => ({
|
||
|
id: match.id,
|
||
|
property: match.property,
|
||
|
expression: match.expression,
|
||
|
})) || [],
|
||
|
};
|
||
|
}
|
||
|
|
||
|
export async function fetchAlerts(user) {
|
||
|
const {
|
||
|
alerts,
|
||
|
actors,
|
||
|
tags,
|
||
|
entities,
|
||
|
matches,
|
||
|
} = await promiseProps({
|
||
|
alerts: knex('alerts')
|
||
|
.where('user_id', user.id),
|
||
|
actors: knex('alerts_actors')
|
||
|
.select('alerts_actors.*', 'actors.name as actor_name', 'actors.slug as actor_slug')
|
||
|
.leftJoin('alerts', 'alerts.id', 'alerts_actors.alert_id')
|
||
|
.leftJoin('actors', 'actors.id', 'alerts_actors.actor_id')
|
||
|
.where('alerts.user_id', user.id),
|
||
|
tags: knex('alerts_tags')
|
||
|
.select('alerts_tags.*', 'tags.name as tag_name', 'tags.slug as tag_slug')
|
||
|
.leftJoin('alerts', 'alerts.id', 'alerts_tags.alert_id')
|
||
|
.leftJoin('tags', 'tags.id', 'alerts_tags.tag_id')
|
||
|
.where('alerts.user_id', user.id),
|
||
|
entities: knex('alerts_entities')
|
||
|
.select('alerts_entities.*', 'entities.name as entity_name', 'entities.slug as entity_slug', 'entities.type as entity_type')
|
||
|
.leftJoin('alerts', 'alerts.id', 'alerts_entities.alert_id')
|
||
|
.leftJoin('entities', 'entities.id', 'alerts_entities.entity_id')
|
||
|
.where('alerts.user_id', user.id),
|
||
|
matches: knex('alerts_matches')
|
||
|
.select('alerts_matches.*')
|
||
|
.leftJoin('alerts', 'alerts.id', 'alerts_matches.alert_id')
|
||
|
.where('alerts.user_id', user.id),
|
||
|
});
|
||
|
|
||
|
const curatedAlerts = alerts.map((alert) => curateAlert(alert, {
|
||
|
actors: actors.filter((actor) => actor.alert_id === alert.id),
|
||
|
tags: tags.filter((tag) => tag.alert_id === alert.id),
|
||
|
entities: entities.filter((entity) => entity.alert_id === alert.id),
|
||
|
matches: matches.filter((match) => match.alert_id === alert.id),
|
||
|
}));
|
||
|
|
||
|
return curatedAlerts;
|
||
|
}
|
||
|
|
||
|
export async function createAlert(alert, reqUser) {
|
||
|
if (!reqUser) {
|
||
|
throw new HttpError('You are not authenthicated', 401);
|
||
|
}
|
||
|
|
||
|
if ((!alert.actors || alert.actors.length === 0) && (!alert.tags || alert.tags.length === 0) && (!alert.entities || alert.entities.length === 0) && (!alert.matches || alert.matches.length === 0)) {
|
||
|
throw new HttpError('Alert must contain at least one actor, tag or entity', 400);
|
||
|
}
|
||
|
|
||
|
if (alert.matches?.some((match) => !match.property || !match.expression)) {
|
||
|
throw new HttpError('Match must define a property and an expression', 400);
|
||
|
}
|
||
|
|
||
|
const [{ id: alertId }] = await knex('alerts')
|
||
|
.insert({
|
||
|
user_id: reqUser.id,
|
||
|
notify: alert.notify,
|
||
|
email: alert.email,
|
||
|
all: alert.all,
|
||
|
all_actors: alert.allActors,
|
||
|
all_entities: alert.allEntities,
|
||
|
all_tags: alert.allTags,
|
||
|
all_matches: alert.allMatches,
|
||
|
})
|
||
|
.returning('id');
|
||
|
|
||
|
await Promise.all([
|
||
|
alert.actors?.length > 0 && knex('alerts_actors').insert(alert.actors.map((actorId) => ({
|
||
|
alert_id: alertId,
|
||
|
actor_id: actorId,
|
||
|
}))),
|
||
|
alert.tags?.length > 0 && knex('alerts_tags').insert(alert.tags.map((tagId) => ({
|
||
|
alert_id: alertId,
|
||
|
tag_id: tagId,
|
||
|
}))),
|
||
|
alert.matches?.length > 0 && knex('alerts_matches').insert(alert.matches.map((match) => ({
|
||
|
alert_id: alertId,
|
||
|
property: match.property,
|
||
|
expression: match.expression,
|
||
|
}))),
|
||
|
alert.stashes?.length > 0 && knex('alerts_stashes').insert(alert.stashes.map((stashId) => ({
|
||
|
alert_id: alertId,
|
||
|
stash_id: stashId,
|
||
|
}))),
|
||
|
alert.entities?.length > 0 && knex('alerts_entities').insert(alert.entities.map((entityId) => ({
|
||
|
alert_id: alertId,
|
||
|
entity_id: entityId,
|
||
|
})).slice(0, alert.allEntities ? 1 : Infinity)), // one scene can never match multiple entities in AND mode
|
||
|
]);
|
||
|
|
||
|
return alertId;
|
||
|
}
|
||
|
|
||
|
export async function removeAlert(alertId, reqUser) {
|
||
|
await knex('alerts')
|
||
|
.where('id', alertId)
|
||
|
.where('user_id', reqUser.id)
|
||
|
.delete();
|
||
|
}
|
||
|
|
||
|
export async function updateNotification(notificationId, updatedNotification, reqUser) {
|
||
|
await knex('notifications')
|
||
|
.where('id', notificationId)
|
||
|
.where('user_id', reqUser.id)
|
||
|
.update({
|
||
|
seen: updatedNotification.seen,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
export async function updateNotifications(updatedNotification, reqUser) {
|
||
|
await knex('notifications')
|
||
|
.where('user_id', reqUser.id)
|
||
|
.update({
|
||
|
seen: updatedNotification.seen,
|
||
|
});
|
||
|
}
|