Skip to content

Commit

Permalink
feat(services): Normalize services
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Crespi committed Mar 24, 2020
1 parent cf01bc6 commit 9e07b8c
Show file tree
Hide file tree
Showing 15 changed files with 370 additions and 346 deletions.
92 changes: 70 additions & 22 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Client, Embed, Guild, Member, Message, TextChannel } from 'eris';
import i18n from 'i18n';
import moment, { Moment } from 'moment';

import { Cache } from './framework/cache/Cache';
import { GuildSettingsCache } from './framework/cache/GuildSettingsCache';
import { MemberSettingsCache } from './framework/cache/MemberSettingsCache';
import { PermissionsCache } from './framework/cache/PermissionsCache';
Expand All @@ -14,6 +15,7 @@ import { MessagingService } from './framework/services/Messaging';
import { PremiumService } from './framework/services/PremiumService';
import { RabbitMqService } from './framework/services/RabbitMq';
import { SchedulerService } from './framework/services/Scheduler';
import { IMService } from './framework/services/Service';
import { InviteCodeSettingsCache } from './invites/cache/InviteCodeSettingsCache';
import { InvitesCache } from './invites/cache/InvitesCache';
import { LeaderboardCache } from './invites/cache/LeaderboardCache';
Expand Down Expand Up @@ -60,6 +62,8 @@ export interface ClientOptions {
}

export interface ClientCacheObject {
[key: string]: Cache<any>;

inviteCodes: InviteCodeSettingsCache;
invites: InvitesCache;
leaderboard: LeaderboardCache;
Expand All @@ -74,6 +78,23 @@ export interface ClientCacheObject {
reactionRoles: ReactionRoleCache;
}

export interface ClientServiceObject {
[key: string]: IMService;

database: DatabaseService;
rabbitmq: RabbitMqService;
message: MessagingService;
moderation: ModerationService;
scheduler: SchedulerService;
commands: CommandsService;
captcha: CaptchaService;
invites: InvitesService;
music: MusicService;
tracking: TrackingService;
premium: PremiumService;
management: ManagementService;
}

export class IMClient extends Client {
public version: string;
public config: any;
Expand All @@ -83,13 +104,16 @@ export class IMClient extends Client {
public settings: BotSettingsObject;
public hasStarted: boolean = false;

public db: DatabaseService;
public cache: ClientCacheObject;

public rabbitmq: RabbitMqService;
public shardId: number;
public shardCount: number;

public service: ClientServiceObject;
private startingServices: IMService[];
public cache: ClientCacheObject;

// Service shortcuts
public db: DatabaseService;
public rabbitmq: RabbitMqService;
public msg: MessagingService;
public mod: ModerationService;
public scheduler: SchedulerService;
Expand All @@ -100,6 +124,7 @@ export class IMClient extends Client {
public tracking: TrackingService;
public premium: PremiumService;
public management: ManagementService;
// End service shortcuts

public startedAt: Moment;
public gatewayConnected: boolean;
Expand Down Expand Up @@ -157,7 +182,21 @@ export class IMClient extends Client {
this.shardId = shardId;
this.shardCount = shardCount;

this.db = new DatabaseService(this);
this.service = {
database: new DatabaseService(this),
rabbitmq: new RabbitMqService(this),
message: new MessagingService(this),
moderation: new ModerationService(this),
scheduler: new SchedulerService(this),
commands: new CommandsService(this),
captcha: new CaptchaService(this),
invites: new InvitesService(this),
tracking: new TrackingService(this),
music: new MusicService(this),
premium: new PremiumService(this),
management: new ManagementService(this)
};
this.startingServices = Object.values(this.service);
this.cache = {
inviteCodes: new InviteCodeSettingsCache(this),
invites: new InvitesCache(this),
Expand All @@ -172,17 +211,20 @@ export class IMClient extends Client {
music: new MusicCache(this),
reactionRoles: new ReactionRoleCache(this)
};
this.rabbitmq = new RabbitMqService(this);
this.msg = new MessagingService(this);
this.mod = new ModerationService(this);
this.scheduler = new SchedulerService(this);
this.cmds = new CommandsService(this);
this.captcha = new CaptchaService(this);
this.invs = new InvitesService(this);
this.tracking = new TrackingService(this);
this.music = new MusicService(this);
this.premium = new PremiumService(this);
this.management = new ManagementService(this);

// Setup service shortcuts
this.db = this.service.database;
this.rabbitmq = this.service.rabbitmq;
this.msg = this.service.message;
this.mod = this.service.moderation;
this.scheduler = this.service.scheduler;
this.cmds = this.service.commands;
this.captcha = this.service.captcha;
this.invs = this.service.invites;
this.music = this.service.music;
this.tracking = this.service.tracking;
this.premium = this.service.premium;
this.management = this.service.management;

this.on('ready', this.onClientReady);
this.on('guildCreate', this.onGuildCreate);
Expand All @@ -199,8 +241,7 @@ export class IMClient extends Client {

public async init() {
// Services
await this.cmds.init();
await this.rabbitmq.init();
await Promise.all(Object.values(this.service).map((s) => s.init()));
}

public async waitForStartupTicket() {
Expand All @@ -209,7 +250,7 @@ export class IMClient extends Client {
() => console.log(`Waiting for ticket since ${Math.floor(process.uptime() - start)} seconds...`),
10000
);
await this.rabbitmq.waitForStartupTicket();
await this.service.rabbitmq.waitForStartupTicket();
clearInterval(interval);
}

Expand All @@ -219,9 +260,8 @@ export class IMClient extends Client {
return;
}

// Setup services that require all guilds
await this.premium.init();
await this.scheduler.init();
// This is for convenience, the services could also subscribe to 'ready' event on client
await Promise.all(Object.values(this.service).map((s) => s.onClientReady()));

this.hasStarted = true;

Expand Down Expand Up @@ -324,6 +364,14 @@ export class IMClient extends Client {
this.activityInterval = setInterval(() => this.setActivity(), 1 * 60 * 1000);
}

public serviceStartupDone(service: IMService) {
this.startingServices = this.startingServices.filter((s) => s !== service);
if (this.startingServices.length === 0) {
console.log(`All services ready, returning start ticket`);
this.rabbitmq.endStartup().catch((err) => console.error(err));
}
}

private async onGuildCreate(guild: Guild): Promise<void> {
const channel = await this.getDMChannel(guild.ownerID);
const dbGuild = await this.db.getGuild(guild.id);
Expand Down
27 changes: 11 additions & 16 deletions src/framework/services/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { promises, statSync } from 'fs';
import i18n from 'i18n';
import { basename, resolve } from 'path';

import { IMClient } from '../../client';
import { guildDefaultSettings } from '../../settings';
import { GuildPermission } from '../../types';
import { Command, Context } from '../commands/Command';
import { BooleanResolver } from '../resolvers';

import { IMService } from './Service';

const CMD_DIRS = [
resolve(__dirname, '../commands'),
resolve(__dirname, '../../invites/commands'),
Expand All @@ -21,20 +22,10 @@ const ID_REGEX: RegExp = /^(?:<@!?)?(\d+)>? ?(.*)$/;
const RATE_LIMIT = 1; // max commands per second
const COOLDOWN = 5; // in seconds

export class CommandsService {
private client: IMClient;

public commands: Command[];
private cmdMap: Map<string, Command>;
private commandCalls: Map<string, { last: number; warned: boolean }>;

public constructor(client: IMClient) {
this.client = client;

this.commands = [];
this.cmdMap = new Map();
this.commandCalls = new Map();
}
export class CommandsService extends IMService {
public commands: Command[] = [];
private cmdMap: Map<string, Command> = new Map();
private commandCalls: Map<string, { last: number; warned: boolean }> = new Map();

public async init() {
console.log(`Loading commands...`);
Expand Down Expand Up @@ -88,9 +79,13 @@ export class CommandsService {
await Promise.all(CMD_DIRS.map((dir) => loadRecursive(dir)));

console.log(`Loaded \x1b[32m${this.commands.length}\x1b[0m commands!`);
}

// Attach events
public async onClientReady() {
// Attach events after the bot is ready
this.client.on('messageCreate', this.onMessage.bind(this));

await super.onClientReady();
}

public async onMessage(message: Message) {
Expand Down
Loading

0 comments on commit 9e07b8c

Please sign in to comment.