diff --git a/keyserver/src/creators/message-report-creator.js b/keyserver/src/creators/message-report-creator.js new file mode 100644 --- /dev/null +++ b/keyserver/src/creators/message-report-creator.js @@ -0,0 +1,87 @@ +// @flow + +import bots from 'lib/facts/bots'; +import { createMessageReply } from 'lib/shared/message-utils'; +import { messageTypes } from 'lib/types/message-types'; +import type { RawMessageInfo } from 'lib/types/message-types'; +import type { ServerThreadInfo } from 'lib/types/thread-types'; +import { promiseAll } from 'lib/utils/promises'; + +import { createCommbotThread } from '../bots/commbot'; +import { fetchPersonalThreadID } from '../fetchers/thread-fetchers'; +import { fetchUsername } from '../fetchers/user-fetchers'; +import { createBotViewer } from '../session/bots'; +import type { Viewer } from '../session/viewer'; +import createMessages from './message-creator'; + +const { commbot } = bots; + +async function getCommbotThreadID(userID: string): Promise { + let commbotThreadID = await fetchPersonalThreadID(userID, commbot.userID); + if (!commbotThreadID) { + commbotThreadID = createCommbotThread(userID); + } + return commbotThreadID; +} + +async function createMessageReport( + viewer: Viewer, + reportedMessage: ?RawMessageInfo, + reportedThread: ?ServerThreadInfo, + recipientID: string, +) { + const promises = {}; + promises.viewerUsername = fetchUsername(viewer.id); + promises.commbotThreadID = getCommbotThreadID(recipientID); + + const reportedMessageAuthorID = reportedMessage?.creatorID; + if (reportedMessageAuthorID) { + promises.reportedMessageAuthor = fetchUsername(reportedMessageAuthorID); + } + + const reportedMessageText = + reportedMessage?.type === 0 ? reportedMessage.text : null; + + const { + viewerUsername, + commbotThreadID, + reportedMessageAuthor, + } = await promiseAll(promises); + + const reportMessage = getCommbotMessage( + viewerUsername, + reportedMessageAuthor, + reportedThread?.name, + reportedMessageText, + ); + const time = Date.now(); + await createMessages(createBotViewer(commbot.userID), [ + { + type: messageTypes.TEXT, + threadID: commbotThreadID, + creatorID: commbot.userID, + time, + text: reportMessage, + }, + ]); +} + +function getCommbotMessage( + reporterUsername: ?string, + messageAuthorUsername: ?string, + threadName: ?string, + message: ?string, +): string { + reporterUsername = reporterUsername ?? '[null]'; + const messageAuthor = messageAuthorUsername + ? `${messageAuthorUsername}’s` + : 'this'; + const thread = threadName ? `chat titled "${threadName}"` : 'chat'; + const reply = message ? createMessageReply(message) : 'non-text message'; + return ( + `user ${reporterUsername} reported ${messageAuthor} message in ${thread}\n` + + reply + ); +} + +export default createMessageReport; diff --git a/keyserver/src/fetchers/thread-fetchers.js b/keyserver/src/fetchers/thread-fetchers.js --- a/keyserver/src/fetchers/thread-fetchers.js +++ b/keyserver/src/fetchers/thread-fetchers.js @@ -7,6 +7,7 @@ getCommunity, } from 'lib/shared/thread-utils'; import { hasMinCodeVersion } from 'lib/shared/version-utils'; +import type { RawMessageInfo, MessageInfo } from 'lib/types/message-types'; import { threadTypes, type ThreadType, @@ -240,6 +241,17 @@ return threads[0]?.id.toString(); } +async function serverThreadInfoFromMessageInfo( + message: ?RawMessageInfo | MessageInfo, +): Promise { + const threadID = message?.threadID; + if (threadID) { + const threads = await fetchServerThreadInfos(SQL`t.id = ${threadID}`); + return threads.threadInfos[threadID]; + } + return null; +} + export { fetchServerThreadInfos, fetchThreadInfos, @@ -249,4 +261,5 @@ determineThreadAncestry, personalThreadQuery, fetchPersonalThreadID, + serverThreadInfoFromMessageInfo, }; diff --git a/lib/types/message-report-types.js b/lib/types/message-report-types.js new file mode 100644 --- /dev/null +++ b/lib/types/message-report-types.js @@ -0,0 +1,5 @@ +// @flow + +export type MessageReportCreationRequest = { + +messageID: string, +};