summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.json33
-rw-r--r--.prettierignore3
-rw-r--r--.travis.yml4
-rw-r--r--FEDERATION.md30
-rw-r--r--docker-compose.yml24
-rwxr-xr-xsrc/routes.js972
-rw-r--r--tsconfig.json6
7 files changed, 523 insertions, 549 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
index f1e3d15..d3fb99f 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,18 +1,17 @@
{
- "env": {
- "browser": true,
- "es6": true,
- "node": true
- },
- "extends": "eslint:recommended",
- "globals": {
- "Atomics": "readonly",
- "SharedArrayBuffer": "readonly"
- },
- "parserOptions": {
- "ecmaVersion": 2018,
- "sourceType": "module"
- },
- "rules": {
- }
-} \ No newline at end of file
+ "env": {
+ "browser": true,
+ "es6": true,
+ "node": true
+ },
+ "extends": "eslint:recommended",
+ "globals": {
+ "Atomics": "readonly",
+ "SharedArrayBuffer": "readonly"
+ },
+ "parserOptions": {
+ "ecmaVersion": 2018,
+ "sourceType": "module"
+ },
+ "rules": {}
+}
diff --git a/.prettierignore b/.prettierignore
index 2ca284f..96fa736 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,3 +1,4 @@
dist
public
-views \ No newline at end of file
+views
+pnpm-lock.yaml \ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index cdf8b48..d6fe659 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ language: shell
os: linux
services:
- - docker
+ - docker
script:
- - ./test.sh \ No newline at end of file
+ - ./test.sh
diff --git a/FEDERATION.md b/FEDERATION.md
index fde2d2d..4c3a10b 100644
--- a/FEDERATION.md
+++ b/FEDERATION.md
@@ -6,18 +6,18 @@ This document is meant to be a reference for all the ActivityPub federation-rela
To keep things simple, sometimes you will see things formatted like `Create/Note` or `Delete/Event` or `Undo/Follow`. The thing before the slash is the Activity, and the thing after the slash is the Object inside the Activity, in an `object` property. So these are to be read as follows:
-* `Create/Note`: a `Create` activity containing a `Note` in the `object` field
-* `Delete/Event`: a `Delete` activity containing an `Event` in the `object` field
-* `Undo/Follow`: an `Undo` activity containing a `Follow` in the `object` field
+- `Create/Note`: a `Create` activity containing a `Note` in the `object` field
+- `Delete/Event`: a `Delete` activity containing an `Event` in the `object` field
+- `Undo/Follow`: an `Undo` activity containing a `Follow` in the `object` field
When the word "broadcast" is used in this document, it means to send an Activity to individual inbox of each of the followers of a given Actor.
This document has four main sections:
-* __Federation philosophy__ lays out the general model of how this is intended to federate
-* __General Actor information__ contains the basics of what to expect from our `Actor` objects
-* __Inbox behavior__ lists every incoming ActivityPub activity that the server recognizes, and tells you what it does in response to that activity, including any other ActivityPub activities it sends back out.
-* __Activities triggered from the web app__ tells you what circumstances on the web application cause the server to emit ActivityPub activities. (For example, when an event is updated via the web application, it lets all the ActivityPub followers know that the event has been updated.)
+- **Federation philosophy** lays out the general model of how this is intended to federate
+- **General Actor information** contains the basics of what to expect from our `Actor` objects
+- **Inbox behavior** lists every incoming ActivityPub activity that the server recognizes, and tells you what it does in response to that activity, including any other ActivityPub activities it sends back out.
+- **Activities triggered from the web app** tells you what circumstances on the web application cause the server to emit ActivityPub activities. (For example, when an event is updated via the web application, it lets all the ActivityPub followers know that the event has been updated.)
Please note: there is an unfortunate collision between the English language and the ActivityPub spec that can make this document confusing. When this document uses the word 'event' with a lowercase-e and not in monospace, it refers to the thing that is being tracked in gathio: events that are being organized. When this document uses the word `Event` with a capital E and in monospace, it refers to the [`Event` object defined in the ActivityStreams Vocabulary spec](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event).
@@ -37,7 +37,7 @@ Every event has an Actor. The Actor looks like this:
```json
{
- "@context":[
+ "@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
],
@@ -50,12 +50,12 @@ Every event has an Actor. The Actor looks like this:
"summary": "<p><p>DESCRIPTION</p>\n</p><p>Location: LOCATION.</p><p>Starting DATETIME (human readable).</p>",
"name": "EVENTNAME",
"featured": "https://DOMAIN/EVENTID/featured",
- "publicKey":{
+ "publicKey": {
"id": "https://DOMAIN/EVENTID#main-key",
"owner": "https://DOMAIN/EVENTID",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nOURPUBLICKEY\n-----END PUBLIC KEY-----\n"
},
- "icon":{
+ "icon": {
"type": "Image",
"mediaType": "image/jpg",
"url": "https://DOMAIN/events/EVENTID.jpg"
@@ -85,7 +85,7 @@ When the server receives a `Follow` Activity, it grabs the `actor` property on t
Assuming we can find the Actor object, then we emit an `Accept` Activity back to the server, containing the full `Follow` that we just parsed. This lets the other server know that we have fully processed the follow request.
-After this, we *also* send a `Create` Activity to the actor's inbox, containing an `Event` object with the information for this event. This is, at the moment, future compatibility for servers that consume `Event` objects. This is sent as a "direct message", directly to the inbox with no `cc` field and not addressing the public timeline.
+After this, we _also_ send a `Create` Activity to the actor's inbox, containing an `Event` object with the information for this event. This is, at the moment, future compatibility for servers that consume `Event` objects. This is sent as a "direct message", directly to the inbox with no `cc` field and not addressing the public timeline.
And finally we send the user a `Create` Activity containing a `Question` object. The `Question` is an invitation to RSVP to the event. Mastodon renders this as a poll to the user, which lets them send back to us a "Yes" RSVP directly from their client UI should they so choose. This is also sent as a "direct message". Some clients like Friendica, simply ignore `Question` objects, which is fine since the user can use built-in RSVP function of Friendica to RSVP anyway (see below).
@@ -102,13 +102,13 @@ The plan is to have this support two ways to RSVP:
1. The user answers the `Question` sent out to the prospective attendee in the form of a `Create/Note` in the style of Mastodon polls. This is mostly a hack for implementations like Mastodon that don't have vocabulary built in to RSVP to `Event`s.
2. The user sends a `Accept/Event` or `Undo/Accept/Event` back to our server. This is for implementations like Friendica that support `Event` and do things like automatically render incoming events in their UI with an RSVP interface. We currently don't accept `Reject/Event` or `TentativeAccept/Event` because gathio has no concept of a "Maybe" or "No" RSVP. It probably should have that in the future, at which case we could meaningfully parse this stuff.
-__The `Question` method__
+**The `Question` method**
If the inbox gets a `Create/Note`, there is a chance that this is a response to a `Question` that we sent a user. So the first thing we do is check its `inReplyTo` property. If it matches the id of a `Question` we sent this user, and this user is still following us, then we fetch the user's profile info. This is to make sure we have their newest `preferredUsername` in their `Actor` object (falling back to `name` and then `actor`), which we will honor as the name we display on the RSVP. We then add this person to our database as an attendee of the event.
Next we confirm that the user has RSVPed. We do this by sending them a `Create/Note` via direct message. The note tells them they RSVPed, and gives them a URL they can click on to instantly un-RSVP if they need to.
-__The `Accept/Event` method__
+**The `Accept/Event` method**
If the inbox gets an `Accept/Event`, then it assumes this is an affirmative RSVP from the actor who sent it. We check to see if the `id` of the `Event` matches the `id` of an `Event` that we sent ot this actor. If it does, then it must be a valid, affirmative RSVP. We then get the `preferredUsername` or `name` from the actor object, and add that actor to the database as an attendee. TODO: support either object URI or embedded object here.
@@ -126,7 +126,7 @@ Since a user can comment on the event via ActivityPub, they should be able to de
### Incoming private messages
-*TODO*: If someone tries to DM the event, we need to reply with a message like "Sorry, this service only supports posting public messages to the event page. Try contacting the event organizer directly if you need to have a private conversation."
+_TODO_: If someone tries to DM the event, we need to reply with a message like "Sorry, this service only supports posting public messages to the event page. Try contacting the event organizer directly if you need to have a private conversation."
## Activities triggered from the web app
@@ -144,7 +144,7 @@ And finally we send an `Update/Event` out with the new event details in the `Eve
### Delete event
-When an event is deleted by its administrator, or the event has been deleted due to it being one week after the event has ended, we send a `Delete/Actor` out to followers. This lets followers know that the event has been deleted, and their server should remove its profile from their database. (On Mastodon this results in an automatic "unfollow", which is good because we want people's follow counts to go back to normal after an event is over and has been deleted.)
+When an event is deleted by its administrator, or the event has been deleted due to it being one week after the event has ended, we send a `Delete/Actor` out to followers. This lets followers know that the event has been deleted, and their server should remove its profile from their database. (On Mastodon this results in an automatic "unfollow", which is good because we want people's follow counts to go back to normal after an event is over and has been deleted.)
We also send a `Delete/Event` out to followers. For an application like Friendica, this removes the event from the calendar of a follower.
diff --git a/docker-compose.yml b/docker-compose.yml
index 44026c8..334bc3d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,16 +1,16 @@
-version: '3'
+version: "3"
volumes:
- mongodb_data_db:
+ mongodb_data_db:
services:
- gathio:
- build: .
- links:
- - mongo
- ports:
- - 3000:3000
- mongo:
- image: mongo:latest
- volumes:
- - mongodb_data_db:/data/db \ No newline at end of file
+ gathio:
+ build: .
+ links:
+ - mongo
+ ports:
+ - 3000:3000
+ mongo:
+ image: mongo:latest
+ volumes:
+ - mongodb_data_db:/data/db
diff --git a/src/routes.js b/src/routes.js
index 052446c..0d59b65 100755
--- a/src/routes.js
+++ b/src/routes.js
@@ -937,46 +937,44 @@ router.post("/newevent", async (req, res) => {
addToLog("createEvent", "success", "Event " + eventID + "created");
// Send email with edit link
if (req.body.creatorEmail && sendEmails) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/createevent.handlebars",
- {
- eventID,
- editToken,
- siteName,
- siteLogo,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: req.body.creatorEmail,
- from: {
- name: siteName,
- email: contactEmail,
- address: contactEmail,
- },
- subject: `${siteName}: ${req.body.eventName}`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/createevent.handlebars",
+ {
+ eventID,
+ editToken,
+ siteName,
+ siteLogo,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: req.body.creatorEmail,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ address: contactEmail,
+ },
+ subject: `${siteName}: ${req.body.eventName}`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
// If the event was added to a group, send an email to any group
// subscribers
@@ -989,49 +987,47 @@ router.post("/newevent", async (req, res) => {
return [current.email, ...acc];
}, []);
subscribers.forEach((emailAddress) => {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/eventgroupupdated.handlebars",
- {
- siteName,
- siteLogo,
- domain,
- eventID: req.params.eventID,
- eventGroupName: eventGroup.name,
- eventName: event.name,
- eventID: event.id,
- eventGroupID: eventGroup.id,
- emailAddress: encodeURIComponent(emailAddress),
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: emailAddress,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: New event in ${eventGroup.name}`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/eventgroupupdated.handlebars",
+ {
+ siteName,
+ siteLogo,
+ domain,
+ eventID: req.params.eventID,
+ eventGroupName: eventGroup.name,
+ eventName: event.name,
+ eventID: event.id,
+ eventGroupID: eventGroup.id,
+ emailAddress: encodeURIComponent(emailAddress),
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: emailAddress,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: New event in ${eventGroup.name}`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
});
});
}
@@ -1098,46 +1094,44 @@ router.post("/importevent", (req, res) => {
addToLog("createEvent", "success", "Event " + eventID + " created");
// Send email with edit link
if (creatorEmail && sendEmails) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/createevent.handlebars",
- {
- eventID,
- editToken,
- siteName,
- siteLogo,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: req.body.creatorEmail,
- from: {
- name: siteName,
- email: contactEmail,
- address: contactEmail,
- },
- subject: `${siteName}: ${importedEventData.summary}`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/createevent.handlebars",
+ {
+ eventID,
+ editToken,
+ siteName,
+ siteLogo,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: req.body.creatorEmail,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ address: contactEmail,
+ },
+ subject: `${siteName}: ${importedEventData.summary}`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
res.writeHead(302, {
Location: "/" + eventID + "?e=" + editToken,
@@ -1199,46 +1193,44 @@ router.post("/neweventgroup", (req, res) => {
);
// Send email with edit link
if (req.body.creatorEmail && sendEmails) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/createeventgroup.handlebars",
- {
- eventGroupID,
- editToken,
- siteName,
- siteLogo,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: req.body.creatorEmail,
- from: {
- name: siteName,
- email: contactEmail,
- address: contactEmail,
- },
- subject: `${siteName}: ${req.body.eventGroupName}`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/createeventgroup.handlebars",
+ {
+ eventGroupID,
+ editToken,
+ siteName,
+ siteLogo,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: req.body.creatorEmail,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ address: contactEmail,
+ },
+ subject: `${siteName}: ${req.body.eventGroupName}`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
res.writeHead(302, {
Location: "/group/" + eventGroupID + "?e=" + editToken,
@@ -1469,46 +1461,44 @@ router.post("/editevent/:eventID/:editToken", (req, res) => {
.map((o) => o.email);
if (attendeeEmails.length) {
console.log("Sending emails to: " + attendeeEmails);
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/editevent.handlebars",
- {
- diffText,
- eventID: req.params.eventID,
- siteName,
- siteLogo,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: attendeeEmails,
- from: {
- name: siteName,
- email: contactEmail,
- address: contactEmail,
- },
- subject: `${siteName}: ${event.name} was just edited`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.sendMultiple(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/editevent.handlebars",
+ {
+ diffText,
+ eventID: req.params.eventID,
+ siteName,
+ siteLogo,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: attendeeEmails,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ address: contactEmail,
+ },
+ subject: `${siteName}: ${event.name} was just edited`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.sendMultiple(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
} else {
console.log("Nothing to send!");
}
@@ -1788,45 +1778,43 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => {
.map((o) => o.email);
if (attendeeEmails.length) {
console.log("Sending emails to: " + attendeeEmails);
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/deleteevent.handlebars",
- {
- siteName,
- siteLogo,
- domain,
- eventName: event.name,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: attendeeEmails,
- from: {
- name: siteName,
- email: contactEmail,
- address: contactEmail,
- },
- subject: `${siteName}: ${event.name} was deleted`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.sendMultiple(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/deleteevent.handlebars",
+ {
+ siteName,
+ siteLogo,
+ domain,
+ eventName: event.name,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: attendeeEmails,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ address: contactEmail,
+ },
+ subject: `${siteName}: ${event.name} was deleted`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.sendMultiple(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
} else {
console.log("Nothing to send!");
}
@@ -2111,45 +2099,43 @@ router.post("/attendevent/:eventID", async (req, res) => {
);
if (sendEmails) {
if (req.body.attendeeEmail) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/addeventattendee.handlebars",
- {
- eventID: req.params.eventID,
- siteName,
- siteLogo,
- domain,
- removalPassword: req.body.removalPassword,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: req.body.attendeeEmail,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: You're RSVPed to ${event.name}`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/addeventattendee.handlebars",
+ {
+ eventID: req.params.eventID,
+ siteName,
+ siteLogo,
+ domain,
+ removalPassword: req.body.removalPassword,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: req.body.attendeeEmail,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: You're RSVPed to ${event.name}`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
}
res.redirect(`/${req.params.eventID}`);
@@ -2187,44 +2173,42 @@ router.post("/unattendevent/:eventID", (req, res) => {
);
if (sendEmails) {
if (req.body.attendeeEmail) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/unattendevent.handlebars",
- {
- eventID: req.params.eventID,
- siteName,
- siteLogo,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: req.body.attendeeEmail,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: You have been removed from an event`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/unattendevent.handlebars",
+ {
+ eventID: req.params.eventID,
+ siteName,
+ siteLogo,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: req.body.attendeeEmail,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: You have been removed from an event`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
}
res.writeHead(302, {
@@ -2269,43 +2253,41 @@ router.get("/oneclickunattendevent/:eventID/:attendeeID", (req, res) => {
if (sendEmails) {
// currently this is never called because we don't have the email address
if (req.body.attendeeEmail) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/removeeventattendee.handlebars",
- {
- eventName: req.params.eventName,
- siteName,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: req.body.attendeeEmail,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: You have been removed from an event`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/removeeventattendee.handlebars",
+ {
+ eventName: req.params.eventName,
+ siteName,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: req.body.attendeeEmail,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: You have been removed from an event`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
}
res.writeHead(302, {
@@ -2341,44 +2323,42 @@ router.post("/removeattendee/:eventID/:attendeeID", (req, res) => {
if (sendEmails) {
// currently this is never called because we don't have the email address
if (req.body.attendeeEmail) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/removeeventattendee.handlebars",
- {
- eventName: req.params.eventName,
- siteName,
- siteLogo,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: req.body.attendeeEmail,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: You have been removed from an event`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/removeeventattendee.handlebars",
+ {
+ eventName: req.params.eventName,
+ siteName,
+ siteLogo,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: req.body.attendeeEmail,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: You have been removed from an event`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
}
res.writeHead(302, {
@@ -2420,46 +2400,44 @@ router.post("/subscribe/:eventGroupID", (req, res) => {
eventGroup.subscribers.push(subscriber);
eventGroup.save();
if (sendEmails) {
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/subscribed.handlebars",
- {
- eventGroupName: eventGroup.name,
- eventGroupID: eventGroup.id,
- emailAddress: encodeURIComponent(subscriber.email),
- siteName,
- siteLogo,
- domain,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: subscriber.email,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: You have subscribed to an event group`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.send(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/subscribed.handlebars",
+ {
+ eventGroupName: eventGroup.name,
+ eventGroupID: eventGroup.id,
+ emailAddress: encodeURIComponent(subscriber.email),
+ siteName,
+ siteLogo,
+ domain,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: subscriber.email,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: You have subscribed to an event group`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.send(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
}
return res.redirect(`/group/${eventGroup.id}`);
})
@@ -2557,45 +2535,43 @@ router.post("/post/comment/:eventID", (req, res) => {
.map((o) => o.email);
if (attendeeEmails.length) {
console.log("Sending emails to: " + attendeeEmails);
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/addeventcomment.handlebars",
- {
- siteName,
- siteLogo,
- domain,
- eventID: req.params.eventID,
- commentAuthor: req.body.commentAuthor,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: attendeeEmails,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: New comment in ${event.name}`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.sendMultiple(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/addeventcomment.handlebars",
+ {
+ siteName,
+ siteLogo,
+ domain,
+ eventID: req.params.eventID,
+ commentAuthor: req.body.commentAuthor,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: attendeeEmails,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: New comment in ${event.name}`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.sendMultiple(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
} else {
console.log("Nothing to send!");
}
@@ -2671,45 +2647,43 @@ router.post("/post/reply/:eventID/:commentID", (req, res) => {
.map((o) => o.email);
if (attendeeEmails.length) {
console.log("Sending emails to: " + attendeeEmails);
- req.app
- .get("hbsInstance")
- .renderView(
- "./views/emails/addeventcomment.handlebars",
- {
- siteName,
- siteLogo,
- domain,
- eventID: req.params.eventID,
- commentAuthor: req.body.replyAuthor,
- cache: true,
- layout: "email.handlebars",
- },
- function (err, html) {
- const msg = {
- to: attendeeEmails,
- from: {
- name: siteName,
- email: contactEmail,
- },
- subject: `${siteName}: New comment in ${event.name}`,
- html,
- };
- switch (mailService) {
- case "sendgrid":
- sgMail.sendMultiple(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- case "nodemailer":
- nodemailerTransporter.sendMail(msg).catch((e) => {
- console.error(e.toString());
- res.status(500).end();
- });
- break;
- }
+ req.app.get("hbsInstance").renderView(
+ "./views/emails/addeventcomment.handlebars",
+ {
+ siteName,
+ siteLogo,
+ domain,
+ eventID: req.params.eventID,
+ commentAuthor: req.body.replyAuthor,
+ cache: true,
+ layout: "email.handlebars",
+ },
+ function (err, html) {
+ const msg = {
+ to: attendeeEmails,
+ from: {
+ name: siteName,
+ email: contactEmail,
+ },
+ subject: `${siteName}: New comment in ${event.name}`,
+ html,
+ };
+ switch (mailService) {
+ case "sendgrid":
+ sgMail.sendMultiple(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
+ case "nodemailer":
+ nodemailerTransporter.sendMail(msg).catch((e) => {
+ console.error(e.toString());
+ res.status(500).end();
+ });
+ break;
}
- );
+ }
+ );
} else {
console.log("Nothing to send!");
}
diff --git a/tsconfig.json b/tsconfig.json
index 9d7b7ab..04519ef 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -16,7 +16,7 @@
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"moduleResolution": "nodenext",
- "skipLibCheck": true,
+ "skipLibCheck": true
},
- "include": ["src/**/*"],
-} \ No newline at end of file
+ "include": ["src/**/*"]
+}