import { IContainer } from '../common/types' ; import { Kernel } from '../bootstrap/kernel' ; import fs from 'fs' ; import { Listener } from './listener' ; import { Store } from '../common/store' ; import express , { Express } from 'express' ; import Server from 'http' ; import { Plugin } from '../common/plugin' ; import path from 'path' ; export class Bot { private _kernel ! : Kernel ; private _listener ! : Listener ; private _webServer ! : Express ; public container ! : IContainer ; private _webServerInstance : Server . Server | undefined ; constructor ( ) { this . _initialise ( ) ; } private _initialise ( ) { this . _kernel = new Kernel ( ) ; this . container = this . _kernel . getContainer ( ) ; this . _listener = new Listener ( this . container ) ; this . _webServer = express ( ) ; } private _loadAndRun ( ) { this . _registerPlugins ( ) ; this . _registerJobs ( ) ; this . _registerStores ( ) ; this . _registerWebServer ( ) ; } private _registerPlugins ( ) { this . container . pluginService . reset ( ) ; const pluginFolder = path . join ( __dirname , '/plugins' ) ; fs . readdir ( pluginFolder , ( _err , files ) => { files . forEach ( async ( file ) => { if ( ! file . endsWith ( '.ts' ) && ! file . endsWith ( '.js' ) ) { return ; } const pluginInstance = await import ( `./plugins/${ file }` ) ; try { const plugin = new pluginInstance . default ( this . container ) ; if ( ! ( plugin instanceof Plugin ) ) { this . container . loggerService . error ( `${ file } has a default export, but it is not of type Plugin` ) ; return ; } this . container . pluginService . register ( plugin ) ; } catch ( err ) { this . container . loggerService . warn ( `${ file } doesn't have a default export of type Plugin!` ) ; } } ) ; } ) ; } private _registerJobs ( ) { this . container . jobService . reset ( ) ; const jobs = this . container . jobService . jobs ; for ( const job of jobs ) { this . container . jobService . register ( job , this . container ) ; } } private _registerStores ( ) { this . container . storeService . reset ( ) ; this . container . storeService . stores . forEach ( ( store ) => { this . container . storeService . register ( store ) ; } ) ; } private _registerWebServer ( ) { this . _resetWebServer ( ) ; const defaultPort = 3000 ; this . _webServerInstance = this . _webServer . listen ( process . env . WEBSERVER_PORT ?? defaultPort , ( ) => this . container . loggerService . info ( 'Webserver is now running' ) ) ; this . _webServer . get ( '/health' , ( _ , res ) => res . send ( 'OK' ) ) ; } private _resetWebServer ( ) { this . _webServerInstance ?. close ( ( err ) => { if ( err ) { this . container . loggerService . error ( 'While closing webServerInstance: ' + err ) ; } } ) ; } public async run ( ) { while ( true ) { try { this . container . loggerService . info ( 'Loading and running Bot...' ) ; this . _loadAndRun ( ) ; this . container . loggerService . info ( 'Bot loaded. Sleeping thread until error.' ) ; while ( true ) { const waiting = new Promise ( ( resolve ) => setTimeout ( resolve , 1000000000 ) ) ; await waiting ; } } catch ( e ) { console . log ( 'here' ) ; console . log ( e ) ; this . container . loggerService . error ( 'Bot crashed with error: ' + e ) ; this . _initialise ( ) ; } } } }