Skip to content

Commit 39f8e1d

Browse files
authored
Merge pull request #4825 from coralproject/feat/ext-notifications-send-site-story
send the site and story info to external notifications
2 parents 1f9fea3 + 09af401 commit 39f8e1d

File tree

6 files changed

+87
-47
lines changed

6 files changed

+87
-47
lines changed

server/src/core/server/graph/context.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ export default class GraphContext {
159159

160160
this.externalNotifications = new ExternalNotificationsService(
161161
this.config,
162-
this.logger,
163-
this.mongo
162+
this.logger
164163
);
165164

166165
this.notifications = new InternalNotificationContext(

server/src/core/server/graph/mutators/Comments.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,12 @@ export const Comments = (ctx: GraphContext) => ({
119119
commentRevisionID,
120120
}: GQLCreateCommentReactionInput) =>
121121
createReaction(
122-
ctx.mongo,
123-
ctx.redis,
124-
ctx.config,
125-
ctx.i18n,
126-
ctx.cache,
127-
ctx.broker,
128-
ctx.tenant,
122+
ctx,
129123
ctx.user!,
130124
{
131125
commentID,
132126
commentRevisionID,
133127
},
134-
ctx.externalNotifications,
135128
ctx.now
136129
),
137130
removeReaction: ({

server/src/core/server/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,7 @@ class Server {
262262

263263
const externalNotifications = new ExternalNotificationsService(
264264
this.config,
265-
logger,
266-
this.mongo
265+
logger
267266
);
268267

269268
// Create the Job Queue.

server/src/core/server/services/comments/actions.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
import { getLatestRevision } from "coral-server/models/comment/helpers";
2626
import { retrieveSite } from "coral-server/models/site";
2727
import { Tenant } from "coral-server/models/tenant";
28-
import { retrieveUser, User } from "coral-server/models/user";
2928
import { isSiteBanned } from "coral-server/models/user/helpers";
3029
import { AugmentedRedis } from "coral-server/services/redis";
3130
import {
@@ -36,12 +35,13 @@ import { Request } from "coral-server/types/express";
3635

3736
import { GQLCOMMENT_FLAG_REPORTED_REASON } from "coral-server/graph/schema/__generated__/types";
3837

38+
import GraphContext from "coral-server/graph/context";
39+
import { User } from "coral-server/models/user";
3940
import {
4041
publishCommentFlagCreated,
4142
publishCommentReactionCreated,
4243
} from "../events";
4344
import { I18n } from "../i18n";
44-
import { ExternalNotificationsService } from "../notifications/externalService";
4545
import { submitCommentAsSpam } from "../spam";
4646

4747
export type CreateAction = CreateActionInput;
@@ -312,18 +312,22 @@ export type CreateCommentReaction = Pick<
312312
>;
313313

314314
export async function createReaction(
315-
mongo: MongoContext,
316-
redis: AugmentedRedis,
317-
config: Config,
318-
i18n: I18n,
319-
cache: DataCache,
320-
broker: CoralEventPublisherBroker,
321-
tenant: Tenant,
315+
context: GraphContext,
322316
author: User,
323317
input: CreateCommentReaction,
324-
externalNotifications: ExternalNotificationsService,
325318
now = new Date()
326319
) {
320+
const {
321+
mongo,
322+
redis,
323+
i18n,
324+
cache,
325+
config,
326+
broker,
327+
tenant,
328+
externalNotifications,
329+
} = context;
330+
327331
const { comment, action } = await addCommentAction(
328332
mongo,
329333
redis,
@@ -359,14 +363,25 @@ export async function createReaction(
359363
if (externalNotifications.active()) {
360364
const reccingUser = author;
361365
const reccedUser = comment.authorID
362-
? await retrieveUser(mongo, comment.tenantID, comment.authorID)
366+
? await context.loaders.Users.user.load(comment.authorID)
363367
: null;
364368

365-
if (reccedUser) {
369+
const story = await context.loaders.Stories.find.load({
370+
id: comment.storyID,
371+
});
372+
373+
const site =
374+
story && story.siteID
375+
? await context.loaders.Sites.site.load(story.siteID)
376+
: null;
377+
378+
if (reccedUser && story && site) {
366379
await externalNotifications.createRec({
367380
from: reccingUser,
368381
to: reccedUser,
369382
comment,
383+
story,
384+
site,
370385
});
371386
}
372387
}

server/src/core/server/services/notifications/externalService.ts

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import Logger from "bunyan";
22
import { Config } from "coral-server/config";
3-
import { MongoContext } from "coral-server/data/context";
43
import { Comment, getLatestRevision } from "coral-server/models/comment";
5-
import { getURLWithCommentID, retrieveStory } from "coral-server/models/story";
4+
import { Site } from "coral-server/models/site";
5+
import { getURLWithCommentID, Story } from "coral-server/models/story";
66
import { User } from "coral-server/models/user";
77
import { convert } from "html-to-text";
88
import fetch from "node-fetch";
@@ -12,16 +12,22 @@ const ProfileType = "Coral";
1212

1313
// From Coral input types
1414

15-
interface CreateReplyInput {
15+
interface CreateReplyParams {
1616
from: User;
1717
to: User;
18+
19+
story: Readonly<Story>;
20+
site: Readonly<Site>;
1821
parent: Comment;
1922
reply: Comment;
2023
}
2124

22-
interface CreateRecInput {
25+
interface CreateRecParams {
2326
from: User;
2427
to: User;
28+
29+
story: Readonly<Story>;
30+
site: Readonly<Site>;
2531
comment: Comment;
2632
}
2733

@@ -33,6 +39,17 @@ enum NotificationType {
3339
CoralReply = "CoralReply",
3440
}
3541

42+
interface StoryInput {
43+
id: string;
44+
title: string;
45+
url: string;
46+
}
47+
48+
interface SiteInput {
49+
id: string;
50+
name: string;
51+
}
52+
3653
interface ExternalUserProfile {
3754
id: string;
3855
type: string;
@@ -43,7 +60,7 @@ interface ExternalUserProfile {
4360
ssoIds?: string[];
4461
}
4562

46-
interface CommentPayload {
63+
interface CommentInput {
4764
id: string;
4865
storyId: string;
4966
snippet?: string | null;
@@ -64,11 +81,9 @@ export class ExternalNotificationsService {
6481
private url?: string | null;
6582
private apiKey?: string | null;
6683
private logger: Logger;
67-
private mongo: MongoContext;
6884

69-
constructor(config: Config, logger: Logger, mongo: MongoContext) {
85+
constructor(config: Config, logger: Logger) {
7086
this.logger = logger;
71-
this.mongo = mongo;
7287

7388
this.url = config.get("external_notifications_api_url");
7489
this.apiKey = config.get("external_notifications_api_key");
@@ -101,13 +116,11 @@ export class ExternalNotificationsService {
101116
}
102117
}
103118

104-
private async commentToPayload(comment: Comment): Promise<CommentPayload> {
105-
const story = await retrieveStory(
106-
this.mongo,
107-
comment.tenantID,
108-
comment.storyID
109-
);
110-
const url = story ? getURLWithCommentID(story.url, comment.id) : null;
119+
private async commentToInput(
120+
comment: Comment,
121+
story: Story
122+
): Promise<CommentInput> {
123+
const url = getURLWithCommentID(story.url, comment.id);
111124

112125
return {
113126
id: comment.id,
@@ -117,7 +130,22 @@ export class ExternalNotificationsService {
117130
};
118131
}
119132

120-
public async createRec(input: CreateRecInput) {
133+
private storyToInput(story: Story): StoryInput {
134+
return {
135+
id: story.id,
136+
title: story.metadata?.title ?? "",
137+
url: story.url,
138+
};
139+
}
140+
141+
private siteToInput(site: Site): SiteInput {
142+
return {
143+
id: site.id,
144+
name: site.name,
145+
};
146+
}
147+
148+
public async createRec(input: CreateRecParams) {
121149
if (!this.active()) {
122150
return;
123151
}
@@ -128,8 +156,9 @@ export class ExternalNotificationsService {
128156
type: NotificationType.CoralRec,
129157
from: this.userToExternalProfile(input.from),
130158
to: this.userToExternalProfile(input.to),
131-
storyId: input.comment.storyID,
132-
comment: this.commentToPayload(input.comment),
159+
story: this.storyToInput(input.story),
160+
site: this.siteToInput(input.site),
161+
comment: this.commentToInput(input.comment, input.story),
133162
};
134163

135164
return await this.send(data);
@@ -143,7 +172,7 @@ export class ExternalNotificationsService {
143172
return false;
144173
}
145174

146-
public async createReply(input: CreateReplyInput) {
175+
public async createReply(input: CreateReplyParams) {
147176
if (!this.active()) {
148177
return;
149178
}
@@ -154,9 +183,10 @@ export class ExternalNotificationsService {
154183
type: NotificationType.CoralReply,
155184
from: this.userToExternalProfile(input.from),
156185
to: this.userToExternalProfile(input.to),
157-
storyId: input.parent.storyID,
158-
comment: await this.commentToPayload(input.parent),
159-
reply: await this.commentToPayload(input.reply),
186+
story: this.storyToInput(input.story),
187+
site: this.siteToInput(input.site),
188+
comment: await this.commentToInput(input.parent, input.story),
189+
reply: await this.commentToInput(input.reply, input.story),
160190
};
161191

162192
return await this.send(data);

server/src/core/server/stacks/createComment.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,12 +454,16 @@ export default async function create(
454454
? await retrieveUser(mongo, parent.tenantID, parent.authorID)
455455
: null;
456456

457-
if (repliedToUser) {
457+
const site = await retrieveSite(mongo, tenant.id, story.siteID!);
458+
459+
if (repliedToUser && site) {
458460
await externalNotifications.createReply({
459461
from: replyingUser,
460462
to: repliedToUser,
461463
parent,
462464
reply: comment,
465+
story,
466+
site,
463467
});
464468
}
465469
}

0 commit comments

Comments
 (0)