"use strict"; const cl = global.botanLoader; const Dragonfly = global.Dragonfly; const EventEmitter = require( "events" ).EventEmitter; const Client = cl.load( "botansx.modular.redisclient" ); const rand = cl.load( "botansx.utils.random" ); const SessConf = cl.load( "config.all" ).sx.modular.session; class SessionEventArgs { constructor( message ) { this.message = message; } } class Session extends EventEmitter { static create( args ) { if( !args ) args = []; return new Session( args[0], args[1] ); } constructor( hash, prefix, noIdReset ) { super(); var _self = this; if( hash && prefix ) hash = hash.replace( new RegExp( "^" + prefix + "\\." ), "" ); prefix = prefix ? prefix + "." : ""; this.id = prefix + hash; this.ready = false; this.exists = false; Client.HGETALL( this.id, function( err, obj ) { if( err ) throw err; if( _self.exists = !!obj.length ) { _self.__sess = {}; for( var i = 0, l = obj.length; i < l; i += 2 ) { _self.__sess[obj[i]] = obj[ i + 1 ]; } } // Auto reset the session id if no match else if( !noIdReset ) { _self.id = prefix + rand.uuid(); } _self.ready = true; _self.emit( "ready", _self ); } ); this.__sess = {}; this.__emitOk = ( e, m ) => { _self.__emit( e, "set", new SessionEventArgs( m ) ); }; } __emit( err, EventName, SessionArgs ) { if( err ) throw err; this.emit( EventName || "set", this, SessionArgs ); } // Spawn session with specified id spawn( expire, handler ) { var ttl = ( expire === undefined ? SessConf.ttl : expire ) + 0; this.__sess[ "lifespan" ] = ttl; var _self = this; Client.compatExec( Client.multi() .HSET( this.id, "spawn", new Date().getTime() ) .HSET( this.id, "lifespan", ttl ) .EXPIRE( this.id, ttl ) , ( data, err ) => ( handler || this.__emitOk)( err, data ) ); } destroy( handler ) { this.__sess = {}; Client.DEL( this.id, handler || this.__emitOk ); } set( dict, handler ) { var chain = Client.multi(); for( let k in dict ) { var v = dict[k]; this.__sess[ k ] = v; chain = chain.HSET( this.id, k, v ); } Client.compatExec( chain, handler || this.__emitOk ); } get( name ) { return this.__sess[ name ]; } // Get value asynchronously aget( name, handler ) { var _self = this; Client.HGET( this.id, name , function( err, rep ) { _self.__emitOk( err ); _self.__sess[ name ] = rep; handler && handler( rep ); } ); } remove( name ) { delete this.__sess[ name ]; Client.HDEL( this.id, name, this.__emitOk ); } expire( seconds ) { // expire > lifespan > SessConf.ttl var ttl = ( seconds === undefined ? ( ( this.__sess[ "lifespan" ] === undefined ) ? SessConf.ttl : this.__sess[ "lifespan" ] ) : seconds ) + 0 ; this.__sess[ "lifespan" ] = ttl; Client.compatExec( Client.multi() .HSET( this.id, "lifespan", ttl ) .EXPIRE( this.id, ttl ) , this.__emitOk ); } } Session.SessionEventArgs = SessionEventArgs; module.exports = Session;