Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 11 additions & 35 deletions application/batchjobs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,21 @@
/* eslint-disable no-console, no-process-exit */
import "jc-backend/configure.js";
import "jc-backend/initWinston.js";

import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js";

import userstore from "jc-backend/lib/users/userstore.js";
import mailtransport from "jc-backend/lib/mailsender/mailtransport.js";
import sendMailsNightly from "./sendMailsNightly.js";
import MailMessage from "jc-shared/mail/mailMessage.js";
import User from "jc-shared/user/user.js";

const receiver = "leider";
import { informAdmin, JobType } from "./sendMailToAdmin.js";

function closeAndExit(err?: Error): void {
if (err) {
// eslint-disable-next-line no-console
console.log("Error in nightjob...");
// eslint-disable-next-line no-console
console.log(err.message);
console.error("Error in nightjob...");
console.error(err.message);
} else {
// eslint-disable-next-line no-console
console.log("Terminating nightjob...");
}
// eslint-disable-next-line no-process-exit
process.exit();
}

async function informAdmin(err?: Error, counter?: number) {
if (!err && !counter) {
return closeAndExit(err);
}
try {
const user = userstore.forId(receiver) as User;
const message = new MailMessage({
subject: "[B-O Jazzclub] Mails sent",
});
message.body = `${counter} nightly Mails for Presse have been sent.

${err ? "Es gibt Fehler! " + err.message + "\n\n" + err : ""}`;
message.to = [{ name: user.name, address: user.email }];
await mailtransport.sendMail(message);
closeAndExit();
} catch (e) {
return closeAndExit(e as Error);
}
}
// eslint-disable-next-line no-console
console.log("Starting nightjob...");

const now = new DatumUhrzeit();
Expand All @@ -62,9 +33,14 @@ async function run() {
sendMailsNightly.checkBar(now),
]);

informAdmin(undefined, results[0] as number);
const jobtypes: JobType[] = ["Presse", "Fluegel", "Photo", "TextFehlt", "Kasse", "Programmheft", "Staff", "Bar"];

const typedResults = results.map((each, index) => ({ type: jobtypes[index], each }));

await Promise.all(typedResults.map(informAdmin));
closeAndExit();
} catch (e) {
informAdmin(e as Error);
closeAndExit(e as Error);
}
}
run();
54 changes: 54 additions & 0 deletions application/batchjobs/src/sendMailToAdmin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* eslint-disable no-console */

import userstore from "jc-backend/lib/users/userstore.js";
import MailMessage from "jc-shared/mail/mailMessage.js";
import mailtransport from "jc-backend/lib/mailsender/mailtransport.js";
import { JobResult } from "./sendMailsNightly.js";
import compact from "lodash/compact.js";

const receiver = "leider";

export type JobType = "Programmheft" | "Presse" | "Kasse" | "Bar" | "Photo" | "Fluegel" | "TextFehlt" | "Staff";

export async function informAdmin({ type, each }: { type: JobType; each: JobResult }) {
const infosCompacted = Array.isArray(each.result) ? compact(each.result) : compact([each.result]);

if (each === undefined || (!infosCompacted.length && !each.error)) {
console.log(`nothing happened for JobType "${type}"`);
return;
}
const user = userstore.forId(receiver);
if (!user) {
console.error("User not found");
return;
}
user.email = "nadreas.leidig@jazzclub.de";

if (each.error) {
console.error(`error occurred while informing ${each.error}`);
}

const infos = infosCompacted.map(({ accepted, rejected, response, envelope }) => ({
accepted,
rejected,
response,
envelope,
}));
const count = infos.length;

const message = new MailMessage({
subject: `[${each.error ? "ERROR" : "INFO"} B-O Jazzclub] Mails sent for jobtype "${type}"`,
});
message.to = [{ name: user.name, address: user.email }];
message.body = `${count} nightly Mails for jobtype "${type}" have been sent.

${
each.error
? `Es gibt Fehler! ${each.error.message}

${each.error}`
: `Informationen zu den gesendeten E-Mails:
${"\n```\n" + JSON.stringify(infos, null, 2) + "\n```"}`
}`;
return mailtransport.sendMail(message);
}
15 changes: 10 additions & 5 deletions application/batchjobs/src/sendMailsForProgrammheft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import store from "jc-backend/lib/programmheft/kalenderstore.js";
import mailtransport from "jc-backend/lib/mailsender/mailtransport.js";
import MailMessage from "jc-shared/mail/mailMessage.js";
import User from "jc-shared/user/user.js";
import { JobResult } from "./sendMailsNightly.js";
import userstore from "jc-backend/lib/users/userstore.js";

export class EmailEvent {
Expand Down Expand Up @@ -76,16 +77,20 @@ async function sendMail(eventsForToday: EmailEvent[]) {
return Promise.all(messages.map(mailtransport.sendMail));
}

export function eventsToSend(aDatumUhrzeit: DatumUhrzeit, events?: Event[]): EmailEvent[] {
function eventsToSend(aDatumUhrzeit: DatumUhrzeit, events?: Event[]): EmailEvent[] {
const result = (events ?? []).filter((e) => e.users.length).map((e) => new EmailEvent(e));
return result.filter((e) => e.shouldSendOn(aDatumUhrzeit));
}

export async function remindForProgrammheft(now: DatumUhrzeit = new DatumUhrzeit()) {
export async function remindForProgrammheft(now: DatumUhrzeit = new DatumUhrzeit()): Promise<JobResult> {
const current = store.getCurrentKalender(now);
const next = store.getNextKalender(now);
if (!current && !next) {
return;
try {
if (!current && !next) {
return {};
}
return { result: await sendMail(eventsToSend(now, current?.events).concat(eventsToSend(now, next?.events))) };
} catch (e) {
return { error: e as Error };
}
return sendMail(eventsToSend(now, current?.events).concat(eventsToSend(now, next?.events)));
}
20 changes: 11 additions & 9 deletions application/batchjobs/src/sendMailsForRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import VeranstaltungFormatter from "jc-shared/veranstaltung/VeranstaltungFormatt
import Veranstaltung from "jc-shared/veranstaltung/veranstaltung.js";
import MailMessage from "jc-shared/mail/mailMessage.js";
import formatMailAddresses from "jc-shared/mail/formatMailAddresses.js";
import { JobResult } from "./sendMailsNightly.js";

const logger = loggers.get("application");

let counter = 0;

function isSendable(ver: Veranstaltung): boolean {
return ver.presse.checked && ver.kopf.confirmed && (ver.isVermietung ? (ver as Vermietung).brauchtPresse : true);
}
Expand All @@ -39,11 +38,10 @@ ${selected
const mailAddress = MailMessage.formatEMailAddress(rule.name, rule.email);
logger.info(`Email Adresse für Presseregeln: ${formatMailAddresses([mailAddress])}`);
mailmessage.to = [mailAddress];
counter++;
return mailtransport.sendMail(mailmessage);
}

export async function loadRulesAndProcess(now: DatumUhrzeit) {
export async function loadRulesAndProcess(now: DatumUhrzeit): Promise<JobResult> {
async function processRule(rule: MailRule) {
const startAndEndDay = rule.startAndEndDay(now);

Expand All @@ -54,13 +52,17 @@ export async function loadRulesAndProcess(now: DatumUhrzeit) {
vermietungenFilter: isSendable,
});

if (zuSendende.length !== 0) {
if (zuSendende.length) {
return sendMail(zuSendende, rule, now);
}
}

const rules = mailstore.all();
const relevantRules = rules.filter((rule) => rule.shouldSend(now));
await relevantRules.map(processRule);
return counter;
try {
const rules = mailstore.all();
const relevantRules = rules.filter((rule) => rule.shouldSend(now));
const infos = await Promise.all(relevantRules.map(processRule));
return { result: infos };
} catch (error) {
return { error: error as Error };
}
}
18 changes: 11 additions & 7 deletions application/batchjobs/src/sendMailsKasseFehlt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Users from "jc-shared/user/users.js";
import usersService from "jc-backend/lib/users/usersService.js";
import MailMessage from "jc-shared/mail/mailMessage.js";
import formatMailAddresses from "jc-shared/mail/formatMailAddresses.js";
import { JobResult } from "./sendMailsNightly.js";

const logger = loggers.get("application");

Expand Down Expand Up @@ -55,15 +56,18 @@ ${konzerte
return mailtransport.sendMail(message);
}

export async function checkKasse(now: DatumUhrzeit) {
export async function checkKasse(now: DatumUhrzeit): Promise<JobResult> {
const start = now;
const end = start.plus({ tage: 7 }); // Eine Woche im Voraus

const konzerte = store.byDateRangeInAscendingOrder(start, end);
const zuSendende = konzerte.filter((konzert) => kasseFehlt(konzert));
if (zuSendende.length === 0) {
return;
} else {
return sendMail(zuSendende);
try {
const konzerte = store.byDateRangeInAscendingOrder(start, end);
const zuSendende = konzerte.filter((konzert) => kasseFehlt(konzert));
if (zuSendende.length) {
return { result: await sendMail(zuSendende) };
}
return {};
} catch (error) {
return { error: error as Error };
}
}
3 changes: 3 additions & 0 deletions application/batchjobs/src/sendMailsNightly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { loadRulesAndProcess } from "./sendMailsForRules.js";
import { remindForProgrammheft } from "./sendMailsForProgrammheft.js";
import { checkStaff } from "./sendMailsStaffReminder.js";
import { checkBar } from "./sendMailsNightlyBar.js";
import * as SMTPTransport from "nodemailer/lib/smtp-transport/index.js";

export type JobResult = { result?: (SMTPTransport.SentMessageInfo | undefined)[] | SMTPTransport.SentMessageInfo; error?: Error };

export default {
loadRulesAndProcess,
Expand Down
79 changes: 42 additions & 37 deletions application/batchjobs/src/sendMailsNightlyBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,58 @@ import Veranstaltung from "jc-shared/veranstaltung/veranstaltung.js";
import Vermietung from "jc-shared/vermietung/vermietung.js";
import MailMessage from "jc-shared/mail/mailMessage.js";
import formatMailAddresses from "jc-shared/mail/formatMailAddresses.js";
import { JobResult } from "./sendMailsNightly.js";

const logger = loggers.get("application");

export async function checkBar(now: DatumUhrzeit) {
const name = conf.barName;
const email = conf.barEmail;
const subject = "Jazzclub Bar Termine";
const firstLine = "## An folgenden Terminen haben wir Veranstaltungen im Jazzclub:";
export async function checkBar(now: DatumUhrzeit): Promise<JobResult> {
try {
const name = conf.barName;
const email = conf.barEmail;
const subject = "Jazzclub Bar Termine";
const firstLine = "## An folgenden Terminen haben wir Veranstaltungen im Jazzclub:";

if (now.wochentag !== 0) {
// Sonntag
return;
}
if (!name || !email) {
return;
}
const start = now;
const end = start.plus({ wochen: 8 }); // Acht Wochen im Voraus
const filterFunction = (ver: Veranstaltung) => {
const typOk = !ver.isVermietung ? !ver.kopf.eventTyp.startsWith("DryJam") : (ver as Vermietung).brauchtBar;
return ver.kopf.ort === "Jazzclub" && ver.kopf.confirmed && typOk;
};
const zuSendende = byDateRangeInAscendingOrder({
from: start,
to: end,
konzerteFilter: filterFunction,
vermietungenFilter: filterFunction,
});
if (zuSendende.length === 0) {
return;
}
if (now.wochentag !== 0) {
// Sonntag
return {};
}
if (!name || !email) {
return {};
}
const start = now;
const end = start.plus({ wochen: 8 }); // Acht Wochen im Voraus
const filterFunction = (ver: Veranstaltung) => {
const typOk = !ver.isVermietung ? !ver.kopf.eventTyp.startsWith("DryJam") : (ver as Vermietung).brauchtBar;
return ver.kopf.ort.includes("Jazzclub") && ver.kopf.confirmed && typOk;
};
const zuSendende = byDateRangeInAscendingOrder({
from: start,
to: end,
konzerteFilter: filterFunction,
vermietungenFilter: filterFunction,
});
if (zuSendende.length === 0) {
return {};
}

const markdownToSend = `${firstLine}
const markdownToSend = `${firstLine}

---
${zuSendende
.map((konzert) => `${konzert.datumForDisplayShort} bis ${konzert.endDatumUhrzeit.format("LT")} - ${konzert.kopf.titelMitPrefix}`)
.join("\n\n---\n")}`;

const message = new MailMessage({
subject: subject,
});
message.body = markdownToSend;
const message = new MailMessage({
subject: subject,
});
message.body = markdownToSend;

const adminAddresses = usersService.emailsAllerAdmins();
logger.info(`Email Adressen für ${subject}: ${formatMailAddresses(adminAddresses)}`);
message.to = MailMessage.formatEMailAddressCommaSeparated(name, email);
message.bcc = adminAddresses;
return mailtransport.sendMail(message);
const adminAddresses = usersService.emailsAllerAdmins();
logger.info(`Email Adressen für ${subject}: ${formatMailAddresses(adminAddresses)}`);
message.to = MailMessage.formatEMailAddressCommaSeparated(name, email);
message.bcc = adminAddresses;
return { result: await mailtransport.sendMail(message) };
} catch (error) {
return { error: error as Error };
}
}
Loading