# framecord

> A Discord bot framework made by Sana Rinomi.

Latest version **1.2.4** (published 2020-09-11) · MIT license · 0 weekly downloads

## Install

```sh
npm install framecord
pnpm add framecord
yarn add framecord
bun add framecord
```

## Health

**Score 5/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: insecure dependencies; abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.2.4 |
| Published | 2020-09-11 |
| First published | 2020-04-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Node | >=12.0.0 |
| Dependencies | 7 |
| Unpacked size | 42.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 4 |
| Author | Amelia Rose Aldridge |
| Maintainers | sanarinomi |
| Keywords | Framework, Discord, EZ |

## Links

- npm: https://www.npmjs.com/package/framecord
- Repository: https://github.com/SanaRinomi/FrameCord
- Homepage: https://github.com/SanaRinomi/FrameCord#readme
- Issues: https://github.com/SanaRinomi/FrameCord/issues
- npm.io page: https://npm.io/package/framecord

## Dependencies (7)

- [moment](https://npm.io/package/moment.md) ^2.27.0
- [erlpack](https://npm.io/package/erlpack.md) github:discordapp/erlpack
- [fs-extra](https://npm.io/package/fs-extra.md) ^9.0.1
- [zlib-sync](https://npm.io/package/zlib-sync.md) ^0.1.7
- [bufferutil](https://npm.io/package/bufferutil.md) ^4.0.1
- [discord.js](https://npm.io/package/discord.js.md) ^12.3.1
- [utf-8-validate](https://npm.io/package/utf-8-validate.md) ^5.0.2

## Alternatives

- [@sveltejs/kit](https://npm.io/package/@sveltejs/kit.md) — 2.2M weekly downloads
- [@tangle-network/brand](https://npm.io/package/@tangle-network/brand.md) — 10.0K weekly downloads
- [seneca](https://npm.io/package/seneca.md) — 7.4K weekly downloads
- [@bsb/base](https://npm.io/package/@bsb/base.md) — 7.2K weekly downloads
- [@modern-js/plugin-swc](https://npm.io/package/@modern-js/plugin-swc.md) — 3.4K weekly downloads

## Recent versions

- 1.2.4 (latest) — 2020-09-11
- 1.2.3 — 2020-08-19
- 1.2.2 — 2020-07-20
- 1.2.1 — 2020-06-25
- 1.2.0 — 2020-06-08
- 1.1.18 — 2020-06-01
- 1.1.17 — 2020-05-29
- 1.1.16 — 2020-05-26
- 1.1.15 — 2020-05-26
- 1.1.14 — 2020-05-25
- 1.1.13 — 2020-05-25
- 1.1.12 — 2020-05-21
- 1.1.11 — 2020-05-19
- 1.1.10 — 2020-05-19
- 1.1.9 — 2020-05-02
- … 20 more at https://npm.io/package/framecord/versions

## README

# FrameCord
A Discord bot framework made by Sana Rinomi.

Install via NPM: `npm i -s framecord`

## Index
* [Setting up a Bot](#setting-up-a-bot)
  * [Adding Commands](#adding-commands)
    * [Adding Commands: Method 1](#adding-commands-method-1)
    * [Adding Commands: Method 2](#adding-commands-method-2)
* [Nodes](#nodes)
  * [Node](#node)
  * [Data Node](#data-node)
  * [Root Node](#root-node)
  * [Command Node](#command-node)

## Setting up a Bot
To get your bot up up and running is rather simple!
We create a `Client` and then we use the `login()` function to start the bot!

```javascript
const {Client} = require("framecord");

let client = new Client("Discord bot token", "d", function(client) { console.log(`Logged in as ${client.discordCli.user.tag}`); });

client.login();
```

### Adding Commands
To add commands to our bot, we need to first create a [`Node`](#node)! This node can be be a simple [`Node`](#node) or it could also be a [`DataNode`](#data-node).
This node will be the base we will call commands from, and there can be multiple!

In this example we will use a `DataNode` with the ID of `!` and add it to our client.
```javascript
const {Client, Nodes} = require("framecord");

let client = new Client("Discord bot token", "d", function(client) { console.log(`Logged in as ${client.discordCli.user.tag}`); });

let Base = new Nodes.DataNode("!");

client.registerNode(Base);

client.login();
```

Now we can add our command, which to do so, we will create a new [`CommandNode`](#command-node).
And as an example, we will make a command that closes our program.

Here's how we create a command:
```javascript
const {Client, Nodes} = require("framecord");

let client = new Client("Discord bot token", "d", function(client) { console.log(`Logged in as ${client.discordCli.user.tag}`); });

let Base = new Nodes.DataNode("!");
let Exit = new Nodes.CommandNode("exit", (cli, command, msg) => {
    msg.reply("See you later!").then(() => {
        cli.exit();
    });
});

client.registerNode(Base);

client.login();
```

There are 2 ways we can add the command node to our client:
* Using `addChild(Node)`
* Using the client method `registerNode(Node, String)` with a path

Each one has their own benefits, so choose according to what you want to do.
You can also use both methods at the same time, so a hybrid approach is possible.

#### Adding Commands: Method 1
This example shows the use of `addChild(Node)`:
```javascript
const {Client, Nodes} = require("framecord");

let client = new Client("Discord bot token", "d", function(client) { console.log(`Logged in as ${client.discordCli.user.tag}`); });

let Base = new Nodes.DataNode("!");
let Exit = new Nodes.CommandNode("exit", (cli, command, msg) => {
    msg.reply("See you later!").then(() => {
        cli.exit();
    });
});

Base.addChild(Exit);
client.registerNode(Base);

client.login();
```

This method is easier to implement, since you directly add your node to the parent using [`Node`](#node)'s `addChild(Node)` method without having to worry if the parent exists.

#### Adding Commands: Method 2
This example shows the use of your client's `registerNode(Node, String)` method using a path:
```javascript
const {Client, Nodes} = require("framecord");

let client = new Client("Discord bot token", "d", function(client) { console.log(`Logged in as ${client.discordCli.user.tag}`); });

let Base = new Nodes.DataNode("!");
let Exit = new Nodes.CommandNode("exit", (cli, command, msg) => {
    msg.reply("See you later!").then(() => {
        cli.exit();
    });
});

client.registerNode(Base);
client.registerNode(Exit, "!");

client.login();
```

With this method, you have to make sure your parent node is already registered, the path is exactly like how you'd call a command within Discord just without the prefix.
Like in this example, we want to register a node to our base `!`, in Discord our path would be `e!` while the path within the client itself would just be `!`.
A few more examples:
* `e!foo` => `!foo`
* `e!foo bar` => `!foo bar`

Be aware that `registerNode(Node, String)` uses the same method as `executeNode(String)` which is used to call commands.
Which means that registering something to `!foo bar doesntexist` would register to node `bar`, and `doesntexist` would be returned as a command argument.

This method works great for modular bots, with code that's loaded in dynamically.

## Nodes
You can find all the nodes under `Nodes` in FrameCord:
```javascript
const {Nodes} = require("framecord");
```

These are the nodes available by default with FrameCord:

### Node
Type: `blank`. This node is our base node, and every other node is going to be based off of it.

#### Constructor
| Value | Description | Type | Default |
| ----- | ----------- | ---- | ------- |
| id | ID of the node | String | `null` |

#### Variables
| Variable | Type | Read-Only |
| -------- | ---- | --------- |
| Type | String | Yes |
| ID | String | Yes |
| Parent | Node | No |
| Children | Array | No |
| HasChildren | Boolean | Yes |
| FirstChild | Node | Yes |
| LastChild | Node | Yes |

#### Methods
| Method | Description | Return Value |
|------- | ----------- | ------------ |
| addChild(Node) | Adds a child node to the current node. Errors if child with same ID is present! | `null` |
| getChild() | Gets a child from the current node. Returns `null` if that child doesn't exist. | Node or `null` |
| removeChild(String) | Removes any child with the ID specified.* | `null` |
| removeChildren() | Removes all children from the current node. | `null` |
| delete() | Calls `removeChildren()` and sets all data stored within to `null`. | `null` |
| equals(Node) | Returns `true` if the IDs and Types match between the current node and the one passed, `false` if not. | Boolean |
| toBlankNode() | Returns a new `Node` instance with the same `ID` and `Children` as the current node. | Node of type `blank` |
| clone() | Returns a new `Node` of the same type with the same values. | Node of same type |

* Removing children will call the `delete()` function of the children.

### Data Node
`DataNode` extends [`Node`](#node).

Type: `data`. This node adds basic data such as `Name`. `Description`, `Tags` and `IsNSFW` to `Node`.

#### Constructor
| Value | Description | Type | Default |
| ----- | ----------- | ---- | ------- |
| id | ID of the node | String | `null` |
| data | Object with the values `name`, `desc`, `tags[]` and `nsfw` | JSON or JS Object | `{name: "", desc: "", tags: [], nsfw: false}` |

#### Variables
| Variable | Type | Read-Only |
| -------- | ---- | --------- |
| Name | String | Yes |
| Description | String | Yes |
| Tags | Array | Yes |
| IsNSFW | Boolean | Yes |

#### Methods
| Method | Description | Return Value |
|------- | ----------- | ------------ |
| toDataNode() | Same function as `toBlankNode()`, but includes the values `Name`, `Description`, `Tags` and `IsNSFW` | Node of type `data` |
| `static` toDataNode(Node, {name: "", desc: "", tags: [], nsfw: false}) | Same function as `toBlankNode()`, but includes the values `Name`, `Description`, `Tags` and `IsNSFW` | Node of type `data` |

### Root Node
`RootNode` extends [`Node`](#node).

Type: `root`. This node includes a bunch of methods related to finding and retrieving nodes, and creating command variables.
Used mainly by a `Client` instance.

#### Constructor
| Value | Description | Type | Default |
| ----- | ----------- | ---- | ------- |
| id | ID of the node | String | `null` |

#### Methods
| Method | Description | Return Value |
|------- | ----------- | ------------ |
| getRegex(Boolean = `true`) | Returns a regular expression, mainly to separate out the prefix, from the base node and from the command node | RegExp |
| getCommandObj(String) | Creates a command object from a string. | Command Obj: `{prefix, values: [], commands: [], args: []}` |
| crawl(String or CommandObj) | Crawls the tree to return in search of an appropriate node. If a string is passes, it will be turned into a CommandObj. Returns `null` if nothing could be found. | {Node, CommandObj} or `null` |
| `static` toRootNode(Node) | Same function as `toBlankNode()`. | Node of type `root` |

### Command Node
`CommandNode` extends [`DataNode`](#data-node).

Type: `command`. This node adds basic data such as `Name`. `Description`, `Tags` and `IsNSFW` to `Node`.

#### Constructor
| Value | Description | Type | Default |
| ----- | ----------- | ---- | ------- |
| id | ID of the node | String | `null` |
| call | Function to call when executing command | Function | `null` |
| data | Object with the values `name`, `desc`, `tags[]` and `nsfw` | JSON or JS Object | `{name: "", desc: "", tags: [], nsfw: false}` |

#### Variables
| Variable | Type | Read-Only |
| -------- | ---- | --------- |
| Call | Function | No |

#### Methods
| Method | Description | Return Value |
|------- | ----------- | ------------ |
| execute() | Executes `Call` as long as bot has `SEND_MESSAGES` privilages, else calls `command.botPermissionFail` event. If IsNSFW is `true`, then checks if in NSFW channel in Discord servers, if fails, calls `command.notInNSFW` event. | `null` |
| toCommandNode() | Same function as `toDataNode()`, but includes the `Call` value. | Node of type `data` |
| `static` toCommandNode(Node, callFunc, {name: "", desc: "", tags: [], nsfw: false}) | Same function as `toDataNode()`, but includes the `Call` value. | Node of type `command` |

---
_Source: https://npm.io/package/framecord · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
