GithubHelp home page GithubHelp logo

fusebot's Introduction

Welcome to Fusebot!

Fusebot is the simplest way to quickly develop custom Slash Commands for Discord and Slack. Fusebot gives you a Node.js and npm development environment and takes care of running, scaling, and securing your Slash Commands. All you need to bring is your code and imagination.

Fusebot for Slack and Discord

You interact with Fusebot using the /fusebot Slash Command from Discord or Slack. It enables you to open a browser-based Node.js and npm development environment to implement any number of custom commands. Once created, the commands can be invoked by anyone in your Slack workspace or Discord guild.

Fusebot was created for developers by developers at fusebit.io and is free to use. We hope you enjoy it!

Table of contents

Installing Fusebot
Code your first command
Interacting with Fusebot
Command code samples
Programming model
  Receiving data from Slack or Discord
  Managing secrets and configuration
  Sending messages back to Slack or Discord
  Using storage
Support

Installing Fusebot

  1. Download Fusebot on Discord or Slack
  2. Run /fusebot coin DOGE to test command

If you see the current value of dogecoin, then Fusebot is successfully installed! Let's move on to coding our first command.

Code your first command

Now that you have Fusebot installed and you tested the /fusebot coin command, let's get started on building your first custom command. Let's build a command to search reddit. It is best to do development on a desktop browser as you will have more room to work with tabs and copy/paste code.

  1. Type /fusebot edit reddit and hit enter

image

  1. Click the "click here" link

image

Your browser will open a window like this:

image

You are looking at the Fusebot command editor that allows you to implement the logic behind the reddit command or any command you build. You can write any Node.js code here and use all public npm modules by declaring them in package.json. After you save the code, you can invoke it from Slack or Discord using the /fusebot reddit Slash Command.

  1. Open this command.js file in another tab

image

  1. Copy and paste the entire command.js file file content into the command.js file in the web editor.

Copy:

image

Paste:

image

  1. Click the save icon in the top left of the web editor

image

  1. Return back to Slack or Discord to test out your new reddit command

/fusebot reddit node API

This command will search for "API" in the node subreddit.

image

BOOM! You've built your first custom command with Fusebot. Check out other examples below and start coding today.

Interacting with Fusebot

If you are wondering about all of the ways to interact with manage your custom slash commands, just run:

/fusebot help

This is what you can do with Fusebot:

/fusebot ls list custom commands in your workspace

/fusebot edit {command} create or edit a custom command

/fusebot rm {command} remove a command

/fusebot feedback {your-feedback} tell us what you think (leave contact if expecting response)

/fusebot {command} [arguments] run a custom command

Command samples

With the power of Node.js and npm, the sky is the limit. What are you going to build today?

Programming model

The function exported from command.js is the entry point to your Slash Command implementation. The ctx parameter contains the details of the event generated by Slack or Discord and a few useful methods described below.

At the time your code executes, we have already done the Slack or Discord signature validation for you, so you can focus on the task at hand. Also, we have responded to Slack, so you are not subject to the 3 second execution limit those platforms impose.

module.export = async (ctx) => {
  await ctx.client.send(`Hello ${ctx.body.userName}!`);
};

Using package.json you can specify a dependency on any public npm module and then use it code.

{
  "engines": {
    "node": ">= 14"
  },
  "dependencies": {
    "superagent": "6.1.0"
  }
}

ctx.body

The ctx.body contains the payload describing the event received from Slack or Discord. It is normalized between the two systems to facilite reusing the same code.

{
  "teamId": "TDFBLCJV9",
  "channelId": "DFNE1FG2E",
  "userId": "UFN96HN1J",
  "userName": "tomek",
  "text": "hello arg1 arg2 arg3",
  "args": ["arg1", "arg2", "arg3"],
  "native": {
    /* native event received from Slack or Discord */
  }
}

The ctx.body.args contains tokenized arguments the caller passed to your Slash Command. For example, if the command name is hello, calling /fusebot hello arg1 arg2 arg3 would result in the ctx.body.args value shown above.

The ctx.body.native represents the native event received from Slack or Discord. Check the Slack event schema or the Discord event schema for details.

ctx.configuration

The ctx.configuration property provides access to the key/value pairs you define in the Configuration section of the editor. These values are stored encrypted at rest and are a convenient way of providing any secrets or API keys to your code.

// In Configuration:
// MY_KEY=SOME_VALUE
const key = ctx.configuration.MY_KEY;
// key is "SOME_VALUE"

ctx.client

The ctx.client provides a way to send messages back to Slack or Discord. You can send multiple messages during a single invocation of your Slash Command.

ctx.client.send

The ctx.client.send asynchronous method sends a text message back to Slack or Discord. The message is visible to anyone in the channel the Slash Command was invoked in. You can use Slack markup, or Discord markup to format the message, respectively:

Remember to wait for the asynchronous method to complete:

await ctx.client.send(`Hello, ${ctx.body.userName}!`);

ctx.client.sendEphemeral

Works similarly to ctx.client.send, but the message will only be visible to the person who invoked the Slash Command.

ctx.storage

The ctx.storage offers access to a simple persistent storage solution. Think about it as local storage, only in the cloud.

ctx.storage.get

Returns a named document or undefined if no document is stored under the specified name:

const item = await ctx.storage.get("my_data");
// item is:
// {
//    data: { ...object you previously stored... },
//    etag: "{etag}"
// }

The etag property describes the version of the item in storage which can be used in the call to ctx.storage.put to detect and prevent conflicting, concurrent writes.

You can omit the document name to read the default document.

ctx.storage.put

Upserts a named document:

const item = {
    data: { ...whatever object you want to store... },
    etag: "{etag}"  // optional
};
await ctx.storage.put(item, "my_data")

If you specify the etag property (usually by obtaining it from a prior ctx.storage.get call), and the document in storage has changed since then, the call will fail with an exception indicating a conflict. If you don't specify the etag property, any data in storage will be forcefuly overwritten.

You can omit the document name to write to the default document.

ctx.storage.list

The ctx.storage.list returns the list of existing documents:

const result = await ctx.storage.list();
// result is
// {
//   items: [ { storageKey: "{storageKey1}" }, ... ],
//   next: "{continuation-token}" // optional
// }

If you organize your documents in a hierarchy using the / character as segment delimiter, you can also list only the documents underneath a particular segment of the hierarchy:

const result = await ctx.storage.list("/a/b");

If the result.next property is present, there are more results which can be obtained with a subsequent call to the API:

const next;
const result = await ctx.storage.list("/a/b", { next });

You can limit the maximum number of results returned using the limit parameter:

const result = await ctx.storage.list("/a/b", { limit: 10 });

ctx.storage.delete

The ctx.storage.delete deletes an item from storage:

await ctx.storage.delete("my_data");

If you organize your documents in a hierarchy using the / character as segment delimiter, you can also delete an entire branch of documents with a single call:

// Existing documents:
// /a/b/c/d
// /a/b/e/f
// /a/b/
// /a/g/h/i
await ctx.storage.delete("/a/b", true, true);
// Documents after delete:
// /a/b/
// /a/g/h/i

NOTE Deleteing /a/b recursively deletes all documents underneath /a/b but not /a/b itself.

NOTE The two true parameters are not a typo - they are intended to prevent accidental deletion of the entire storage.

Support

You can share your thoughts or ask questions using /fusebot feedback command, contacting the Fusebit team.

fusebot's People

Contributors

matthewzhaocc avatar pchng avatar tjanczuk avatar yavorg avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.