sources/new-forum-thread-message/new-forum-thread-message.mjs
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; import maxBy from "lodash.maxby"; import constants from "../../common/constants.mjs"; import common from "../common/common.mjs"; import sampleEmit from "./test-event.mjs"; export default { ...common, key: "discord_bot-new-forum-thread-message", name: "New Forum Thread Message", description: "Emit new event for each forum thread message posted. Note that your bot must have the `MESSAGE_CONTENT` privilege intent to see the message content. [See the documentation](https://discord.com/developers/docs/topics/gateway#message-content-intent).", type: "source", version: "1.0.0", dedupe: "unique", props: { ...common.props, db: "$.service.db", timer: { type: "$.interface.timer", default: { intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, }, }, forumId: { propDefinition: [ common.props.discord, "channelId", ({ guildId }) => ({ guildId, allowedChannels: [ constants.CHANNEL_TYPES.GUILD_FORUM, ], }), ], label: "Forum Id", description: "Select the forum you want to watch.", }, ignoreBotMessages: { type: "boolean", label: "Ignore Bot Messages", description: "Set to `true` to only emit messages NOT from the configured Discord bot", optional: true, }, }, hooks: { async deploy() { if (this.ignoreBotMessages) { const { id } = await this.getBotProfile(); this._setBotId(id); } }, }, methods: { ...common.methods, getChannel(id) { return this.discord._makeRequest({ path: `/channels/${id}`, }); }, }, async run({ $ }) { let lastMessageIDs = this._getLastMessageIDs(); const botId = this.ignoreBotMessages ? this._getBotId() : null; const { threads } = await this.discord.listThreads({ $, guildId: this.guildId, }); const forumThreads = threads.reduce((acc, curr) => { return curr.parent_id === this.forumId ? [ ...acc, curr, ] : acc; }, []); for (const channel of forumThreads) { let lastMessageID; let messages = []; const channelId = channel.id; if (!lastMessageIDs[channelId]) { messages = await this.discord.getMessages({ $, channelId, params: { limit: 25, }, }); lastMessageID = messages.length ? maxBy(messages, (message) => message.id).id : 1; } else { let newMessages = []; do { newMessages = await this.discord.getMessages({ $, channelId, params: { after: lastMessageIDs[channelId], }, }); messages = messages.concat(newMessages); lastMessageID = newMessages.length ? maxBy(newMessages, (message) => message.id).id : lastMessageIDs[channelId]; lastMessageIDs[channelId] = lastMessageID; } while (newMessages.length); } lastMessageIDs[channelId] = lastMessageID; if (!messages.length) { console.log(`No new messages in thread ${channelId}`); continue; } if (botId) { messages = messages.filter((message) => message.author.id !== botId); } console.log(`${messages.length} new messages in thread ${channelId}`); messages = await Promise.all(messages.map(async (message) => ({ ...message, thread: await this.getChannel(message.channel_id), }))); const { available_tags: availableTags = [] } = await this.getChannel(this.forumId); for (const message of messages) { if (!message.thread.applied_tags) { message.thread.applied_tags = []; } message.thread.applied_tags = message.thread.applied_tags.map((tagId) => ({ ...availableTags.find(({ id }) => id === tagId), })); } messages.reverse().forEach((message) => { this.$emit(message, { id: message.id, summary: `A new message with Id: ${message.id} was posted in forum thread ${channelId}.`, ts: Date.parse(message.timestamp), }); }); } this._setLastMessageIDs(lastMessageIDs); }, sampleEmit, };