@langchain/community
Version:
Third-party integrations for LangChain.js
390 lines (389 loc) • 14.6 kB
JavaScript
import { Client, TextChannel, GatewayIntentBits, ChannelType, } from "discord.js";
import { getEnvironmentVariable } from "@langchain/core/utils/env";
import { Tool } from "@langchain/core/tools";
/**
* A tool for retrieving messages from a discord channel using a bot.
* It extends the base Tool class and implements the _call method to
* perform the retrieve operation. Requires an bot token which can be set
* in the environment variables, and a limit on how many messages to retrieve.
* The _call method takes the discord channel ID as the input argument.
* The bot must have read permissions to the given channel. It returns the
* message content, author, and time the message was created for each message.
*/
export class DiscordGetMessagesTool extends Tool {
static lc_name() {
return "DiscordGetMessagesTool";
}
constructor(fields) {
super();
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: "discord-get-messages"
});
Object.defineProperty(this, "description", {
enumerable: true,
configurable: true,
writable: true,
value: `A discord tool. useful for reading messages from a discord channel.
Input should be the discord channel ID. The bot should have read
permissions for the channel.`
});
Object.defineProperty(this, "botToken", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "messageLimit", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
const { botToken = getEnvironmentVariable("DISCORD_BOT_TOKEN"), messageLimit = 10, client, } = fields ?? {};
if (!botToken) {
throw new Error("Environment variable DISCORD_BOT_TOKEN missing, but is required for DiscordGetMessagesTool.");
}
this.client =
client ??
new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});
this.botToken = botToken;
this.messageLimit = messageLimit;
}
/** @ignore */
async _call(input) {
try {
await this.client.login(this.botToken);
const channel = (await this.client.channels.fetch(input));
if (!channel) {
return "Channel not found.";
}
const messages = await channel.messages.fetch({
limit: this.messageLimit,
});
await this.client.destroy();
const results = messages.map((message) => ({
author: message.author.tag,
content: message.content,
timestamp: message.createdAt,
})) ?? [];
return JSON.stringify(results);
}
catch (err) {
await this.client.destroy();
return "Error getting messages.";
}
}
}
/**
* A tool for retrieving all servers a bot is a member of. It extends the
* base `Tool` class and implements the `_call` method to perform the retrieve
* operation. Requires a bot token which can be set in the environment
* variables.
*/
export class DiscordGetGuildsTool extends Tool {
static lc_name() {
return "DiscordGetGuildsTool";
}
constructor(fields) {
super();
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: "discord-get-guilds"
});
Object.defineProperty(this, "description", {
enumerable: true,
configurable: true,
writable: true,
value: `A discord tool. Useful for getting a list of all servers/guilds the bot is a member of. No input required.`
});
Object.defineProperty(this, "botToken", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
const { botToken = getEnvironmentVariable("DISCORD_BOT_TOKEN"), client } = fields ?? {};
if (!botToken) {
throw new Error("Environment variable DISCORD_BOT_TOKEN missing, but is required for DiscordGetGuildsTool.");
}
this.client =
client ??
new Client({
intents: [GatewayIntentBits.Guilds],
});
this.botToken = botToken;
}
/** @ignore */
async _call(_input) {
try {
await this.client.login(this.botToken);
const guilds = await this.client.guilds.fetch();
await this.client.destroy();
const results = guilds.map((guild) => ({
id: guild.id,
name: guild.name,
createdAt: guild.createdAt,
})) ?? [];
return JSON.stringify(results);
}
catch (err) {
await this.client.destroy();
return "Error getting guilds.";
}
}
}
/**
* A tool for retrieving text channels within a server/guild a bot is a member
* of. It extends the base `Tool` class and implements the `_call` method to
* perform the retrieve operation. Requires a bot token which can be set in
* the environment variables. The `_call` method takes a server/guild ID
* to get its text channels.
*/
export class DiscordGetTextChannelsTool extends Tool {
static lc_name() {
return "DiscordGetTextChannelsTool";
}
constructor(fields) {
super();
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: "discord-get-text-channels"
});
Object.defineProperty(this, "description", {
enumerable: true,
configurable: true,
writable: true,
value: `A discord tool. Useful for getting a list of all text channels in a server/guild. Input should be a discord server/guild ID.`
});
Object.defineProperty(this, "botToken", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
const { botToken = getEnvironmentVariable("DISCORD_BOT_TOKEN"), client } = fields ?? {};
if (!botToken) {
throw new Error("Environment variable DISCORD_BOT_TOKEN missing, but is required for DiscordGetTextChannelsTool.");
}
this.client =
client ??
new Client({
intents: [GatewayIntentBits.Guilds],
});
this.botToken = botToken;
}
/** @ignore */
async _call(input) {
try {
await this.client.login(this.botToken);
const guild = await this.client.guilds.fetch(input);
const channels = await guild.channels.fetch();
await this.client.destroy();
const results = channels
.filter((channel) => channel?.type === ChannelType.GuildText)
.map((channel) => ({
id: channel?.id,
name: channel?.name,
createdAt: channel?.createdAt,
})) ?? [];
return JSON.stringify(results);
}
catch (err) {
await this.client.destroy();
return "Error getting text channels.";
}
}
}
/**
* A tool for sending messages to a discord channel using a bot.
* It extends the base Tool class and implements the _call method to
* perform the retrieve operation. Requires a bot token and channelId which can be set
* in the environment variables. The _call method takes the message to be
* sent as the input argument.
*/
export class DiscordSendMessagesTool extends Tool {
static lc_name() {
return "DiscordSendMessagesTool";
}
constructor(fields) {
super();
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: "discord-send-messages"
});
Object.defineProperty(this, "description", {
enumerable: true,
configurable: true,
writable: true,
value: `A discord tool useful for sending messages to a discod channel.
Input should be the discord channel message, since we will already have the channel ID.`
});
Object.defineProperty(this, "botToken", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "channelId", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
const { botToken = getEnvironmentVariable("DISCORD_BOT_TOKEN"), channelId = getEnvironmentVariable("DISCORD_CHANNEL_ID"), client, } = fields ?? {};
if (!botToken) {
throw new Error("Environment variable DISCORD_BOT_TOKEN missing, but is required for DiscordSendMessagesTool.");
}
if (!channelId) {
throw new Error("Environment variable DISCORD_CHANNEL_ID missing, but is required for DiscordSendMessagesTool.");
}
this.client =
client ??
new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});
this.botToken = botToken;
this.channelId = channelId;
}
/** @ignore */
async _call(message) {
try {
await this.client.login(this.botToken);
const channel = (await this.client.channels.fetch(this.channelId));
if (!channel) {
throw new Error("Channel not found");
}
if (!(channel.constructor === TextChannel)) {
throw new Error("Channel is not text channel, cannot send message");
}
await channel.send(message);
await this.client.destroy();
return "Message sent successfully.";
}
catch (err) {
await this.client.destroy();
return "Error sending message.";
}
}
}
/**
* A tool for searching for messages within a discord channel using a bot.
* It extends the base Tool class and implements the _call method to
* perform the retrieve operation. Requires an bot token which can be set
* in the environment variables, and the discord channel ID of the channel.
* The _call method takes the search term as the input argument.
* The bot must have read permissions to the given channel. It returns the
* message content, author, and time the message was created for each message.
*/
export class DiscordChannelSearchTool extends Tool {
static lc_name() {
return "DiscordChannelSearchTool";
}
constructor(fields) {
super();
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: "discord_channel_search_tool"
});
Object.defineProperty(this, "description", {
enumerable: true,
configurable: true,
writable: true,
value: `A discord toolkit. Useful for searching for messages
within a discord channel. Input should be the search term. The bot
should have read permissions for the channel.`
});
Object.defineProperty(this, "botToken", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "channelId", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
const { botToken = getEnvironmentVariable("DISCORD_BOT_TOKEN"), channelId = getEnvironmentVariable("DISCORD_CHANNEL_ID"), client, } = fields ?? {};
if (!botToken) {
throw new Error("Environment variable DISCORD_BOT_TOKEN missing, but is required for DiscordChannelSearchTool.");
}
if (!channelId) {
throw new Error("Environment variable DISCORD_CHANNEL_ID missing, but is required for DiscordChannelSearchTool.");
}
this.client =
client ??
new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});
this.botToken = botToken;
this.channelId = channelId;
}
/** @ignore */
async _call(searchTerm) {
try {
await this.client.login(this.botToken);
const channel = (await this.client.channels.fetch(this.channelId));
if (!channel) {
return "Channel not found";
}
const messages = await channel.messages.fetch();
await this.client.destroy();
const filtered = messages.filter((message) => message.content.toLowerCase().includes(searchTerm.toLowerCase()));
const results = filtered.map((message) => ({
author: message.author.tag,
content: message.content,
timestamp: message.createdAt,
})) ?? [];
return JSON.stringify(results);
}
catch (err) {
await this.client.destroy();
return "Error searching through channel.";
}
}
}