feat: Enable unfurling comments in Slack (#6716)
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
import { t } from "i18next";
|
import { t } from "i18next";
|
||||||
import Router from "koa-router";
|
import Router from "koa-router";
|
||||||
import escapeRegExp from "lodash/escapeRegExp";
|
import escapeRegExp from "lodash/escapeRegExp";
|
||||||
|
import queryString from "query-string";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { IntegrationService, IntegrationType } from "@shared/types";
|
import { IntegrationService, IntegrationType } from "@shared/types";
|
||||||
|
import parseDocumentSlug from "@shared/utils/parseDocumentSlug";
|
||||||
import {
|
import {
|
||||||
AuthenticationError,
|
AuthenticationError,
|
||||||
InvalidRequestError,
|
InvalidRequestError,
|
||||||
@@ -19,8 +21,10 @@ import {
|
|||||||
Integration,
|
Integration,
|
||||||
IntegrationAuthentication,
|
IntegrationAuthentication,
|
||||||
AuthenticationProvider,
|
AuthenticationProvider,
|
||||||
|
Comment,
|
||||||
} from "@server/models";
|
} from "@server/models";
|
||||||
import SearchHelper from "@server/models/helpers/SearchHelper";
|
import SearchHelper from "@server/models/helpers/SearchHelper";
|
||||||
|
import { can } from "@server/policies";
|
||||||
import { APIContext } from "@server/types";
|
import { APIContext } from "@server/types";
|
||||||
import { safeEqual } from "@server/utils/crypto";
|
import { safeEqual } from "@server/utils/crypto";
|
||||||
import { opts } from "@server/utils/i18n";
|
import { opts } from "@server/utils/i18n";
|
||||||
@@ -78,16 +82,38 @@ router.post(
|
|||||||
const unfurls = {};
|
const unfurls = {};
|
||||||
|
|
||||||
for (const link of event.links) {
|
for (const link of event.links) {
|
||||||
const id = link.url.slice(link.url.lastIndexOf("/") + 1);
|
const documentId = parseDocumentSlug(link.url);
|
||||||
const doc = await Document.findByPk(id);
|
if (documentId) {
|
||||||
if (!doc || doc.teamId !== user.teamId) {
|
const doc = await Document.findByPk(documentId, { userId: user.id });
|
||||||
continue;
|
|
||||||
|
if (doc && can(user, "read", doc)) {
|
||||||
|
const commentId = queryString.parse(
|
||||||
|
link.url.split("?")[1]
|
||||||
|
)?.commentId;
|
||||||
|
|
||||||
|
if (commentId) {
|
||||||
|
const comment = await Comment.findByPk(commentId as string);
|
||||||
|
if (!comment) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unfurls[link.url] = {
|
||||||
|
title: t(`Comment by {{ author }} on "{{ title }}"`, {
|
||||||
|
author: comment.createdBy.name,
|
||||||
|
title: doc.title,
|
||||||
|
...opts(user),
|
||||||
|
}),
|
||||||
|
text: comment.toPlainText(),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
unfurls[link.url] = {
|
||||||
|
title: doc.title,
|
||||||
|
text: doc.getSummary(),
|
||||||
|
color: doc.collection?.color,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unfurls[link.url] = {
|
|
||||||
title: doc.title,
|
|
||||||
text: doc.getSummary(),
|
|
||||||
color: doc.collection?.color,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Slack.post("chat.unfurl", {
|
await Slack.post("chat.unfurl", {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Node } from "prosemirror-model";
|
||||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||||
import {
|
import {
|
||||||
DataType,
|
DataType,
|
||||||
@@ -9,7 +10,9 @@ import {
|
|||||||
DefaultScope,
|
DefaultScope,
|
||||||
} from "sequelize-typescript";
|
} from "sequelize-typescript";
|
||||||
import type { ProsemirrorData } from "@shared/types";
|
import type { ProsemirrorData } from "@shared/types";
|
||||||
|
import ProsemirrorHelper from "@shared/utils/ProsemirrorHelper";
|
||||||
import { CommentValidation } from "@shared/validations";
|
import { CommentValidation } from "@shared/validations";
|
||||||
|
import { schema } from "@server/editor";
|
||||||
import Document from "./Document";
|
import Document from "./Document";
|
||||||
import User from "./User";
|
import User from "./User";
|
||||||
import ParanoidModel from "./base/ParanoidModel";
|
import ParanoidModel from "./base/ParanoidModel";
|
||||||
@@ -71,6 +74,11 @@ class Comment extends ParanoidModel<
|
|||||||
@ForeignKey(() => Comment)
|
@ForeignKey(() => Comment)
|
||||||
@Column(DataType.UUID)
|
@Column(DataType.UUID)
|
||||||
parentCommentId: string;
|
parentCommentId: string;
|
||||||
|
|
||||||
|
public toPlainText() {
|
||||||
|
const node = Node.fromJSON(schema, this.data);
|
||||||
|
return ProsemirrorHelper.toPlainText(node, schema);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Comment;
|
export default Comment;
|
||||||
|
|||||||
@@ -970,6 +970,7 @@
|
|||||||
"Get rich previews of {{ appName }} links shared in Slack and use the <em>{{ command }}</em> slash command to search for documents without leaving your chat.": "Get rich previews of {{ appName }} links shared in Slack and use the <em>{{ command }}</em> slash command to search for documents without leaving your chat.",
|
"Get rich previews of {{ appName }} links shared in Slack and use the <em>{{ command }}</em> slash command to search for documents without leaving your chat.": "Get rich previews of {{ appName }} links shared in Slack and use the <em>{{ command }}</em> slash command to search for documents without leaving your chat.",
|
||||||
"This will remove the Outline slash command from your Slack workspace. Are you sure?": "This will remove the Outline slash command from your Slack workspace. Are you sure?",
|
"This will remove the Outline slash command from your Slack workspace. Are you sure?": "This will remove the Outline slash command from your Slack workspace. Are you sure?",
|
||||||
"Connect {{appName}} collections to Slack channels. Messages will be automatically posted to Slack when documents are published or updated.": "Connect {{appName}} collections to Slack channels. Messages will be automatically posted to Slack when documents are published or updated.",
|
"Connect {{appName}} collections to Slack channels. Messages will be automatically posted to Slack when documents are published or updated.": "Connect {{appName}} collections to Slack channels. Messages will be automatically posted to Slack when documents are published or updated.",
|
||||||
|
"Comment by {{ author }} on \"{{ title }}\"": "Comment by {{ author }} on \"{{ title }}\"",
|
||||||
"How to use {{ command }}": "How to use {{ command }}",
|
"How to use {{ command }}": "How to use {{ command }}",
|
||||||
"To search your workspace use {{ command }}. \nType {{ command2 }} help to display this help text.": "To search your workspace use {{ command }}. \nType {{ command2 }} help to display this help text.",
|
"To search your workspace use {{ command }}. \nType {{ command2 }} help to display this help text.": "To search your workspace use {{ command }}. \nType {{ command2 }} help to display this help text.",
|
||||||
"Post to Channel": "Post to Channel",
|
"Post to Channel": "Post to Channel",
|
||||||
|
|||||||
Reference in New Issue
Block a user