Chat and Commands
These calls go to the shard that owns the bot. The bot has to be running in this process and past Events.Ready. For a bot that is only online in the cloud, use the HTTP client.
Party chat and whispers
await bot.send('hello party');
await bot.whisper('epic-account-id', 'hello');
await bot.party.send('same as bot.send');whisper takes an Epic account id or display name. The recipient has to be a friend. Incoming chat is an event, not a poll. message.reply uses the same channel the message arrived on.
fnlb.on(Events.PartyMemberMessage, async (message) => {
await message.reply(`you said ${message.content}`);
});
fnlb.on(Events.FriendMessage, async (message) => {
await message.reply('got your whisper');
});Commands
bot.runCommand runs a bot command as the account owner. The name has no prefix. This does not go through the cloud API.
const reply = await bot.runCommand('outfit', ['renegade']);
console.log(reply.content, reply.success);
await bot.runCommand('emote', 'wave');
await bot.runCommand('emote', ['wave'], 'en');args is a string or a string array. locale defaults to the bot's locale. The result is a SdkCommandResult:
| Field | Meaning |
|---|---|
content | Text the command would have sent back. |
success | False when the command replied with an error. |
format | 0 neutral, 1 success, 2 info, 3 warn, 4 error. |
botName | The bot's FNLB nickname. |
Cosmetic changes you want as a direct call, without a command reply, are party.setOutfit and the other member methods in Bots and parties. Use runCommand when you want the same path as a chat command, including its checks and reply text. The same command on a bot that is not in this process is fnlb.api.bots.commands.run. See HTTP client. The cloud result uses ApiCommandResult, which has the same content and format fields.
fnlb.on(Events.PartyMemberMessage, async (message) => {
if (!message.content.startsWith('!outfit ')) return;
const name = message.content.slice('!outfit '.length);
const reply = await message.bot.runCommand('outfit', [name]);
await message.reply(reply.content);
});Friends
const { onlineFriends, offlineFriends } = await bot.friends();
const { incomingFriends, outgoingFriends } = await bot.pendingFriends();
await bot.acceptFriend(incomingFriends[0].id);
await bot.declineFriend('epic-account-id');
await bot.addFriend('DisplayName');
await bot.removeFriend('epic-account-id');
await bot.block('epic-account-id');
await bot.unblock('epic-account-id');
const joinable = onlineFriends.filter((friend) => friend.isJoinable);friends() returns ApiFriends: onlineFriends and offlineFriends. An online friend has id, displayName, isJoinable, and status. pendingFriends() returns ApiPendingFriends: incomingFriends and outgoingFriends. acceptFriend and declineFriend take the Epic account id from that list. declineFriend also cancels an outgoing request. addFriend and removeFriend take an Epic account id or display name. block and unblock use the same id. unblock only works for an account that is already on the block list. removeFriend also drops a pending request. Events.FriendRequest fires when someone sends a request, so you do not have to poll pendingFriends() for that case. See Events. The HTTP routes api.bots.friends.list and api.bots.users.blocked read the same kind of data for a bot that is connected in the cloud. They do not add, remove, or block. Those writes are the local methods above.
Reference
| Call | Symbol |
|---|---|
| Party chat | Bot.send |
| Whisper | Bot.whisper |
| Reply | Message.reply |
| Local command | Bot.runCommand |
| Add a friend | Bot.addFriend |
| Block | Bot.block |