Skip to content

Commit

Permalink
🎉 now for real the initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
XanderD99 committed Nov 2, 2020
1 parent c6856e3 commit 0c94a49
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 3 deletions.
58 changes: 58 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
42 changes: 41 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
@@ -1 +1,41 @@
# Commando FaunaDBProvider
# Commando FaunaDBProvider

## About

[Commando](https://github.com/Gawdl3y/discord.js-commando) is the official framework for [discord.js](https://github.com/hydrabolt/discord.js). To make connected your Faunadb to your bot a bit easier I "remade" the sqliteProvider from the framework to use FaunaDB.

## Installation

This installs the faunadb package and this package.

```bash
# With NPM
npm install --save faunadb commando-provider-faundb
```

## Usage

Below is an example on how to use it with [faunadb](https://github.com/fauna/faunadb-js) (recommended).

Creating a new provider will create a new collection called `guilds` in your database and also create a new index `guild_by_id`.

- The collection is to store all the data.
- The index is so that we can query based on the guilds id do not have to store the id given by FaunaDB.

```js
const { Client } = requrie('faunadb');
const FaunaProvider = require('commando-provider-faunadb');

...

client.setProvider(
new FaunaProvider(new Client({ secret: '<you-secret-database-key>' }))
);


...
```

## License

MIT © [XanderD99](https://github.com/XanderD99)
203 changes: 203 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
const { SettingProvider } = require('discord.js-commando');
const { query } = require('faunadb');

const {
Update,
Select,
Get,
Match,
Index,
Remove,
Lambda,
Documents,
Collection: FaunaCollection,
Map,
Paginate,
CreateIndex,
Exists,
CreateCollection,
Create,
} = query;

module.exports = class FaunaProvider extends SettingProvider {
constructor(db, name) {
super();

this.db = db;
this.client = null;

this.settings = new Map();
this.listeners = new Map();
}

async init(client) {
this.client = client;
if (!(await this.db.query(Exists(FaunaCollection('guilds'))))) {
await this.db.query(CreateCollection({ name: 'guilds' }));
}
if (!(await this.db.query(Exists(Index('guild_by_id'))))) {
await this.db.query(CreateIndex({ name: 'guild_by_id', source: FaunaCollection('guilds'), terms: [{ field: ['data', 'id'] }] }));
}

// this could take a while if it is a big collection
const guilds = (await this.db.query(Map(
Paginate(Documents(FaunaCollection('guilds'))),
Lambda((x) => Get(x)),
))).data;

guilds.forEach(({ data }) => {
const guild = data.id !== '0' ? data.id : 'global';
const settings = data;
this.settings.set(guild, settings);
if (guild !== 'global' && !client.guilds.cache.has(guild)) return;
this.setupGuild(guild, settings);
});

this.listeners
.set('commandPrefixChange', (guild, prefix) => this.set(guild.id, 'prefix', prefix))
.set('commandStatusChange', (guild, command, enabled) => this.set(guild.id, `cmd-${command.name}`, enabled))
.set('groupStatusChange', (guild, group, enabled) => this.set(guild.id, `grp-${group.id}`, enabled))
.set('guildCreate', (guild) => {
const settings = this.settings.get(guild.id);
if (!settings) return;
this.setupGuild(guild.id, settings);
})
.set('commandRegister', (command) => {
this.settings.forEach(([id, settings]) => {
if (id !== 'global' && !client.guilds.cache.has(id)) return;
const guild = client.guilds.cache.get(id);
this.setupGuildCommand(guild, command, settings);
});
})
.set('groupRegister', (group) => {
this.settings.forEach(([guild, settings]) => {
if (guild !== 'global' && !client.guilds.cache.has(guild)) return;
this.setupGuildGroup(client.guilds.cache.get(guild), group, settings);
});
});

Array.from(this.listeners).forEach(([event, listener]) => client.on(event, listener));
}

async destroy() {
Array.from(this.listeners)
.forEach(([event, listener]) => this.client.removeListener(event, listener));
this.listeners.clear();
}

async get(guild, key, defVal) {
const settings = this.settings.get(guild);
if (settings) {
return typeof settings[key] !== 'undefined' ? settings[key] : defVal;
}

return defVal;
}

async createOrUpdate(guildID, settings) {
if ((await this.db.query(Exists(Match(Index('guild_by_id'), guildID.toString()))))) {
return this.db.query(
Update(
Select(['ref'], Get(Match(Index('guild_by_id'), guildID.toString()))),
{ data: { id: guildID, ...settings } },
),
);
}

return this.db.query(
Create(FaunaCollection('guilds'), { data: { id: guildID, ...settings } }),
);
}

async set(guild, key, val) {
const guildId = guild;
let settings = this.settings.get(guildId);
if (!settings) {
settings = {};
this.settings.set(guildId, settings);
}
settings[key] = val;
await this.createOrUpdate(guildId !== 'global' ? guildId : 0, settings);
if (guild === 'global') this.updateOtherShards(key, val);
return val;
}

async remove(guild, key) {
const guildId = guild;
const settings = this.settings.get(guildId);
if (!settings || typeof settings[key] === 'undefined') return undefined;

const val = settings[key];
settings[key] = undefined;
await this.createOrUpdate(guildId !== 'global' ? guildId : 0, settings);
if (guildId === 'global') this.updateOtherShards(key, undefined);
return val;
}

async clear(guild) {
const guildID = guild;
if (!this.settings.has(guildID)) return;
this.settings.delete(guildID);
await this.db.query(
Remove(
Select(['ref'], Get(Match(Index('guild_by_id'), guildID !== 'global' ? guildID : 0))),
1,
'create',
),
);
}

setupGuild(guildId, settings) {
if (typeof guildId !== 'string') throw new TypeError('The guild must be a guild ID or "global".');
const guild = this.client.guilds.cache.get(guildId) || null;

// Load the command prefix
if (typeof settings.prefix !== 'undefined') {
if (guild) guild._commandPrefix = settings.prefix;
else this.client._commandPrefix = settings.prefix;
}

// Load all command/group statuses
(Array.from(this.client.registry.commands.values()))
.forEach((command) => this.setupGuildCommand(guild, command, settings));
(Array.from(this.client.registry.groups.values()))
.forEach((group) => this.setupGuildGroup(guild, group, settings));
}

// eslint-disable-next-line class-methods-use-this
setupGuildCommand(guild, command, settings) {
if (typeof settings[`cmd-${command.name}`] === 'undefined') return;
if (guild) {
if (!guild._commandsEnabled) guild._commandsEnabled = {};
guild._commandsEnabled[command.name] = settings[`cmd-${command.name}`];
} else {
command._globalEnabled = settings[`cmd-${command.name}`];
}
}

// eslint-disable-next-line class-methods-use-this
setupGuildGroup(guild, group, settings) {
if (typeof settings[`grp-${group.id}`] === 'undefined') return;
if (guild) {
if (!guild._groupsEnabled) guild._groupsEnabled = {};
guild._groupsEnabled[group.id] = settings[`grp-${group.id}`];
} else {
group._globalEnabled = settings[`grp-${group.id}`];
}
}

updateOtherShards(key, val) {
if (!this.client.shard) return;
this.client.shard.broadcastEval(`
const ids = [${this.client.shard.ids.join(',')}];
if(!this.shard.ids.some(id => ids.includes(id)) && this.provider && this.provider.settings) {
let global = this.provider.settings.get('global');
if(!global) {
global = {};
this.provider.settings.set('global', global);
}
global[${JSON.stringify(key)}] = ${typeof val !== 'undefined' ? JSON.stringify(val) : 'undefined'};
}
`);
}
}
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "commando-provider-faunadb",
"version": "1.0.0",
"version": "1.0.1",
"description": "a FaunaDB provider for Discord.js Commando framework",
"main": "index.js",
"scripts": {
Expand All @@ -21,5 +21,9 @@
"bugs": {
"url": "https://gitlab.com/npm7/commando-provider-faunadb/issues"
},
"homepage": "https://gitlab.com/npm7/commando-provider-faunadb#readme"
"homepage": "https://gitlab.com/npm7/commando-provider-faunadb#readme",
"peerDependencies": {
"discord.js-commando": "^0.9.0",
"mongodb": "^3.0"
}
}

0 comments on commit 0c94a49

Please sign in to comment.