Skip to content

Commit

Permalink
🚀 Release v1.0.0-alpha.2
Browse files Browse the repository at this point in the history
📩 Merge: Update changes.
  • Loading branch information
john-bv committed Feb 6, 2021
2 parents 24b6d0a + 14e307b commit 34c10f2
Show file tree
Hide file tree
Showing 43 changed files with 1,421 additions and 242 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# This workflow will install Deno and run tests across stable builds on Windows, Ubuntu and macOS.
# For more information see: https://github.com/denolib/setup-deno

name: Tests

on:
push:
branches: [master, dev]
pull_request:
branches: [master, dev]

jobs:
test:
runs-on: ${{ matrix.os }} # runs a test on Ubuntu and Windows

strategy:
matrix:
deno: ["v1.x"] # "nightly"
os: [windows-latest, ubuntu-latest]

steps:
- uses: actions/checkout@v2
- uses: denolib/setup-deno@v2
with:
deno-version: ${{ matrix.deno }} # tests across multiple Deno versions

- name: Cache Module
run: deno cache mod.ts

- name: Run Tests
run: deno test -A
env:
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
126 changes: 124 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,128 @@ This code is licensed under **GNU General Public License v3**.
AssistantLib is a powerful, extensible framework to create a bot quickly, and easily.
This framework is currently being developed and will be used for **Assistant Bot**.

### Why use AssistantLib?
- It uses Typescript's powerful type system to write simple, type-safe, and elegant code
- Object Oriented
- Created with completely type safe code
- Zero third-party dependencies
- Only uses the latest version of Deno standard library
- Benchmarks with incredible gateway speeds
- 250-500 m/s gateway login speeds!
- Enhanced for speed and memory
- Uses 10-15x less memory that Node.JS libraries!
- Includes multiple developer utilities such as live module reloader and a CLI
- Optimal API Coverage
- Has full fledged slash (/) command support
- The first library (if not one of the first) to implement slash commands!
- Empowers the developer! What do we mean? We've made Assistant as extensible as possible to make sure it can suit the developers needs whenever they need to extends features
- Create custom websocket handlers
- Create custom REST API Handlers
- Create custom structures
- Create custom collectors
- Create custom caching environments (do I hear Mongo and Redis?)

### API
**DataStores:** Datastores are stores that handle runtime data, such as client.guilds
#### Special Code Examples

Get a command directly from a message!
```ts
client.on('message', (msg: Message) => {
const commandName = msg.getCommand("!");
});
```

Elegant collector syntax!
```ts
client.on('message', (msg: Message) => {
const commandName = msg.getCommand("!");
switch(commandName) {
case 'collect': {
const msgs = new MessageCollector(client, {limit: 10});
// Asynchronously iterate over
// incoming messages!
for await (const message of msgs) {
console.log("NEW MESSAGE!!", message);
}
}
}
});

```

Complete client configuration!
```ts
const CACHE_CAP = 1000;
const client = new Client({
sharding: {
useDiscord: false,
},
connection: {
emitPayloads: false,
autoReconnect: true,
compress: false,
maxReconnectTries: 1,
maxResumeTries: 1,
respectDiscordGateway: true,
timeout: 1000
},
intents: Intents.all().parse(),
cache: {
limit: CACHE_CAP,
}
}, new RuntimeManager(CACHE_CAP));
```

Use the advanced CLI to create project boilerplates in mere milliseconds
```ps1
deno install -A -f -n ast https://raw.githubusercontent.com/Assistant-Bot/Lib/dev/src/util/cli.ts
# Then use the following to create a boilerplate
ast gen MyEpicBot TOKEN
```

Use the advanced Command and Module API without writing any command handling code from scratch!
```ts
const client = new Client();

class AdminPermission extends Permission {
public constructor() {
super('generic.permission.admin', 100);
}

public can(msg: Message, member: Member) {
return member.permissions.has('administrator');
}
}

class AdminCommand extends Command {
public constructor() {
super('admin', 'generic.command.admin', 'An admin command!');
this.permissions = [new AdminPermission()];
this.aliases = ['adm', 'a']
}

public async onRun(client: Client, msg: Message, args: string[]) {
msg.reply('An admin command!')
}
}

const commandHandler = new CommandHandler(client, {prefix: "!"});
commandHandler.registerModule(new Module('Admin', [new AdminCommand()], [new AdminPermission()], true));
```

Secure environment variable storage!
```ts
const env = new EnvStore();
env.set("API_KEY", "12345678910");
// !eval env
// Oh no! I evalled my env variable!
// Don't fear it's hashed in a UInt8Array

// Also!
const env2 = new EnvStore();
env2.set("API_KEY", "12345678910");
console.log(env.get("API_KEY") === env2.get("API_KEY"));
// Returns false!
// New salts (numbers used to hash)
// are made everyone EnvStore instance!
```
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,5 @@ export * as Async from './src/util/Async.ts';
export { default as Collection } from './src/util/Collection.ts';
export { default as Embed } from './src/util/Embed.ts';
export { default as Intents } from './src/util/Intents.ts';
export { default as Queue } from './src/util/Queue.ts';
export { default as Queue } from './src/util/Queue.ts';
export { default as MessageCollector } from './src/util/collectors/MessageCollector.ts';
93 changes: 78 additions & 15 deletions src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*/
import { EventEmitter, GenericFunction, WrappedFunction } from 'https://deno.land/std@0.78.0/node/events.ts';
import { EventEmitter, GenericFunction, WrappedFunction } from 'https://deno.land/std@0.85.0/node/events.ts';
import DataManager from "./data/DataManager.ts";
import type DataStore from "./data/DataStore.ts";
import type { GatewayResponseBot, RoleData, VoiceState } from "./net/common/Types.ts";
import type { GatewayResponseBot, PresenceOptions, RoleData, VoiceState } from "./net/common/Types.ts";
import DiscordRequestHandler from "./net/rest/DiscordRequestHandler.ts";
import Endpoints, { GATEWAY_URL } from "./net/rest/Endpoints.ts";
import RequestHandler, { RequestHandlerOptions } from "./net/rest/RequestHandler.ts";
Expand All @@ -30,11 +30,14 @@ import type Emoji from "./structures/guild/Emoji.ts";
import type Guild from "./structures/guild/Guild.ts";
import type Invite from "./structures/guild/Invite.ts";
import type Member from "./structures/guild/Member.ts";
import Presence from "./structures/guild/Presence.ts";
import type Role from "./structures/guild/Role.ts";
import TextChannel from "./structures/guild/TextChannel.ts";
import type Message from "./structures/Message.ts";
import Application from "./structures/oauth/Application.ts";
import type User from "./structures/User.ts";
import Collection from "./util/Collection.ts";
import Intents, { IntentTypes } from "./util/Intents.ts";

/**
* Events emitted when recieved from the websocket.
Expand Down Expand Up @@ -95,40 +98,40 @@ export interface ClientOptions {
/**
* Whether or not to reconnect if disconnected.
*/
autoReconnect: boolean;
autoReconnect?: boolean;

/**
* Amount of attempts to reconnect
*/
maxReconnectTries: number;
maxReconnectTries?: number;

/**
* Amount of attempts to resume the session from discord.
*/
maxResumeTries: number;
maxResumeTries?: number;

/**
* Whether or not to compress data from discord
*/
compress: boolean;
compress?: boolean;

/**
* The amount of time until the client auto disconnects;
* If no response to discord is recieved.
*/
timeout: number;
timeout?: number;

/**
* Whether or not to respect discord response to connecting through the bot gateway.
* This should be "true" if you want to shard, or cluster
*/
respectDiscordGateway: boolean;
respectDiscordGateway?: boolean;

/**
* Emits the "ws" event (when enabled)
*/
emitPayloads: boolean;
},
emitPayloads?: boolean;
};
cache: {
/**
* Should objects be cached in memory?
Expand Down Expand Up @@ -156,14 +159,15 @@ export interface ClientOptions {
* IE: Guild#roles, Member#roles, Guild#emojis
*/
subLimit?: number;
},
};
sharding: {
/**
* Whether or not to use discord recommended Sharding and Cluster count.
*/
useDiscord: boolean;
},
rest?: RequestHandlerOptions
rest?: RequestHandlerOptions;
intents?: IntentTypes[] | Number;
}

/**
Expand All @@ -180,6 +184,7 @@ export type ClientShardMode = 'Nodes' | 'Shards' | 'Clusters';

export default class Client extends EventEmitter {
public readonly options: ClientOptions;
public readonly intents: Intents;
public application: Application | null;
public requestHandler!: RequestHandler;
public discordHandler!: DiscordRequestHandler;
Expand Down Expand Up @@ -209,16 +214,20 @@ export default class Client extends EventEmitter {
},
sharding: {
useDiscord: false
}
},
intents: Intents.defaults().parse()
}

this.options = Object.assign(defaults, opts);
this.application = null;
this.intents = (this.options.intents instanceof Array) ? new Intents(this.options.intents) : Intents.from(this.options.intents as number);
Collection.MAX_SIZE = this.options.cache.subLimit || 300;

if (customStore) {
this.#dataManager = customStore;
}

Collection.MAX_SIZE = this.options.cache.limit ?? Infinity // Add this, IDK why but guild.members doesnt work w/out it
}

/**
Expand Down Expand Up @@ -251,7 +260,7 @@ export default class Client extends EventEmitter {
}

this.application = await this.resolveApplication();
this.#wsManager.connect(token);
this.#wsManager.connect(token, this.intents);
}

/**
Expand All @@ -263,6 +272,21 @@ export default class Client extends EventEmitter {
await this.#wsManager.close();
}

public async editStatus(opt: PresenceOptions) {
await this.ws.send({
op: 3,
d: {
since: opt.since ?? 0,
game: {
name: opt.game.name,
type: opt.game.type,
},
afk: opt.afk ?? false,
status: opt.status
}
})
}

/**
* Gets the oauth application from discord.
*/
Expand Down Expand Up @@ -337,7 +361,42 @@ export default class Client extends EventEmitter {
/**
* Emitted when (bulk) messages are deleted
*/
public on(event: "messageDeleteBulk", listener: (messages: (Message | string)[]) => any): this
public on(event: "messageDeleteBulk", listener: (messages: (Message | string)[]) => any): this;

/**
* Emitted when a reaction is added
*/
public on(event: "reactionAdd", listener: (message: Partial<Message> | Message, member: Partial<Member> | Member, emoji: Partial<Emoji> | Emoji) => any): this;

/**
* Emitted when a reaction is removed
*/
public on(event: "reactionRemove", listener: (message: Partial<Message> | Message, member: Partial<Member> | Member, emoji: Partial<Emoji> | Emoji) => any): this;

/**
* Emitted when all reactions are removed
*/
public on(event: "reactionRemoveAll", listener: (message: Partial<Message> | Message) => any): this;

/**
* Emitted when a specific emoji reaction is removed
*/
public on(event: "reactionRemoveEmoji", listener: (message: Partial<Message> | Message, member: Partial<Member> | Member, emoji: Partial<Emoji> | Emoji) => any): this;

/**
* Emitted when a presence is updated
*/
public on(event: "presenceUpdate", listener: (presence: Presence) => any): this;

/**
* Emitted when typing starts
*/
public on(event: "typingStart", listener: (member: Partial<Member> | Member, channel: TextChannel, timestamp: number) => any): this;

/**
* Emitted when a user is updated
*/
public on(event: "userUpdate", listener: (user: User) => any): this;

/**
* Emitted when a user is banned from a guild
Expand Down Expand Up @@ -476,6 +535,10 @@ export default class Client extends EventEmitter {
return this.#dataManager || null;
}

public get ws(): Connector {
return this.#wsManager;
}

/**
* Sets the data store (once).
*/
Expand Down
Loading

0 comments on commit 34c10f2

Please sign in to comment.