Create Multiple Jabber Client Echo Bot - node.js

Hai Stackoverflowers,
i had try so many ways to fix my problem and i end up with stack over flow
Programming Language:
Typescript
my main goals:
create Client Class as many as i want and can turn on and turn off the Client, the client will be as Bot that echo text from the friendlist
I use node-xmpp-client Library :
https://github.com/chris-rock/node-xmpp-client
My Code :
import * as Client from 'node-xmpp-client'; // Jabber Helper
export class TerminalJabber {
private ter;
private client;
constructor(ter: any) {
this.ter = ter;
this.client = new Client({
jid: this.ter.settings.username,
password: this.ter.settings.password,
});
}
public turnOn(){
// Turn on Jabber
this.client.on('online', () => {
console.log('online');
const stanza = new Client.Element('presence', { })
.c('show').t('chat').up()
.c('status').t('Happily echoing your <message/> stanzas');
this.client.send(stanza);
});
this.client.on('stanza', (stanza) => {
// Message come here and will echo from here
});
// Catch error
this.client.on('error', (e) => {
console.log('------>', e);
});
}
// Turn Off Jabber
public turnOff () {
// Turn Off Jabber
this.client.end();
return true;
}
}
The Problem is, The Bot Can Start, but never will be disconnect when i call a new class and turnOn() and turnOff().
How I call My code:
// Hit URL
/turnOn/:terId
// Hit URL
app.router.get(/turnOn/:id, turnOnController); // for turn On
app.router.get(/turnOff/:id, turnOfController); // for turn Off
TurnOnController(){
// Get data from database using id
const data = Query ~ ;
const terminal = new TerminalId(data)
terminal.turnOn();
}
TurnOffController(){
// Get data from database using id
const data = Query ~ ;
const terminal = new TerminalID(data)
terminal.turnOff();
}
Maybe you have a solution of my problems ?
have been thinking and read so many post about xmpp, but i cant solve this things,
Please help
sincerely,
Thank you

You need to call the turnOff method on the terminal instance before you create new one.
This also means you need to have access to the instance from both controllers.
var terminals = {};
function turnOnController(){
var id = getIdSomehow();
terminal[id] = new TerminalId(data);
terminal[id].turnOn();
}
function turnOffController(){
var id = getIdSomehow();
if (terminal[id])
terminal[id].turnOff();
}

Related

Web3.js pair contract events.Swap not correctly subscribing to swap event

I am trying to run a section of (nodejs using Web3.js) code whenever a swap occurs on a given pair contract (qPair is the pair contract derived from Quickswap's router contract (Polygon blockchain) and sPair is the same pair contract derived from Sushiswap's router contract (also Polygon blockchain)) but the code doesn't work as intended when implented as a class. I have it working in one file, but when I try to create a class for crypto pairs, the code wont work.
Here is the working code:
const main = async () => {
qPair = await getPairContract(quickswapFactoryContract, token0.address, token1.address)
sPair = await getPairContract(sushiswapFactoryContract, token0.address, token1.address)
/* The below code is listening for a swap event on the Quickswap exchange. When a swap event is
detected, the code checks the price of the token pair on Quickswap and compares it to the price
of the token pair on Sushiswap. If the price on Quickswap is higher than the price on Sushiswap, the
code will execute a trade on Quickswap. If the price on Sushiswap is higher than the price on
Quickswap, the code will execute a trade on Uniswap. */
qPair.events.Swap({}, async () => {
console.log("qPair activated")
/*
*
* Do stuff here
*
*/
})
/* The below code is listening for an event on the Sushiswap contract. When the event is detected,
the code will check the price of the token pair and determine if there is an arbitrage
opportunity. If there is an arbitrage opportunity, the code will execute the trade. */
sPair.events.Swap({}, async () => {
console.log("sPair activated")
/*
*
* Do stuff here
*
*/
})
console.log("Waiting for swap event...")
}
And here is the code that doesn't work:
const main = async () => {
qPair1 = new cryptoPair(<same token details as before go here>)
sPair1 = new cryptoPair(<same token details as before go here>)
qPair1.pairContract.events.Swap({}, async () => {
// The code here activates once (after main() reaches the bottom) and never again
})
sPair1.pairContract.events.Swap({}, async () => {
// The code here activates once (after main() reaches the bottom) and never again
})
console.log("waiting for swap event")
} // Once the debugger reaches here, the two "async" console logs activate
The class has the same code as the "working" code but instead would just do this._pairContract = await getPairContract() and then return that variable using a getter function.
Here is the (nonworking) class code:
module.exports = class cryptoPair {
constructor(token0Address, token0Decimals, token1Address, token1Decimals, factory) {
this._token0Address = token0Address;
this._token0Decimals = token0Decimals;
this._token1Address = token1Address;
this._token1Decimals = token1Decimals;
this._factory = factory;
}
// Setter functions
set token0(web3Token) {
this._token0 = web3Token;
}
set token1(web3Token) {
this._token1 = web3Token;
}
set token0Contract(web3Contract) {
this._token0Contract = web3Contract;
}
set token1Contract(web3Contract) {
this._token1Contract = web3Contract;
}
// Getter functions
get token0Address() {
return this._token0Address;
}
get token1Address() {
return this._token1Address;
}
get factory() {
return this._factory;
}
get token0Contract() {
return this._token0Contract;
}
get token1Contract() {
return this._token1Contract;
}
get token0() {
return this._token0;
}
get pairContract() {
return this._pairContract;
}
// The following two functions are nearly identically defined in the "working code"
// But instead don't use the "this.variableName" syntax
async defineTokens(t0Address, t0Decimals, t1Address, t1Decimals) {
try {
this._token0Contract = new web3.eth.Contract(IERC20.abi, t0Address)
this._token1Contract = new web3.eth.Contract(IERC20.abi, t1Address)
const t0Symbol = await this._token0Contract.methods.symbol().call()
const t0Name = await this._token0Contract.methods.name().call()
this._token0 = new Token(
ChainId.POLYGON,
t0Address,
t0Decimals,
t0Symbol,
t0Name
)
const t1Symbol = await this._token1Contract.methods.symbol().call()
const t1Name = await this._token1Contract.methods.name().call()
this._token1 = new Token(
ChainId.POLYGON,
t1Address,
t1Decimals,
t1Symbol,
t1Name
)
} catch (err) {
// For some reason, I keep getting the error "hex data is odd-length" in the
// class but not when this same code is outside of a class
console.log("Token creation failed, retrying...")
this.defineTokens(this._token0Address, this._token0Decimals, this._token1Address, this._token1Decimals)
}
}
async definePairContract() {
this._pairAddress = await this._factory.methods.getPair(this._token0Address, this._token1Address).call();
this._pairContract = new web3.eth.Contract(IUniswapV2Pair.abi, this._pairAddress);
}
}
To reiterate, the "working code" runs the inner code of the async events.Swap() code whenever a swap is triggered, but the same code when implemented as a class does not work. Is this because of the use of classes? Or did I make a mistake somewhere? Thanks in advance!
I fixed the issue. Of course, the issue was outside of the code provided where I defined web3. The working way defined it as:
web3 = new Web3(`wss://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`)
whereas the incorrect class was defining it as
provider = new HDWalletProvider({
privateKeys: [process.env.DEPLOYMENT_ACCOUNT_KEY],
providerOrUrl: `wss://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`
})
web3 = new Web3(provider)

what is the best way or pattern to create a Wrapper class to abstract the use of RabbitMQ in node js

so I'm using RabbitMQ for some Projects and i noticed that i ll use some duplicate code all the Time that's why i decided to make a Wrapper Class or Interface that have some function to use RabbitMQ direct without repeating the code all the time. i began to do this yesterday and i already had some Problems since i wanted to use OOP and Javascript can be complicated when using OOP (at least i think so)
I began with creating a class IRAbbitMQ with function init to initialize a connection and create a channel, i knew that i cant use nested classes so instead i wanted to use Factory functions, i tried to make the connection and channel a part of the class IRabbitMQ properties but i dont know why that gave me undefined when i create an instance of it
class IRabbitMQ {
constructor() {
this.init(rabbitMQServer); // rabbitMQServer for example 'localhost//5672'
}
// establish a Connection to RAbbitMQ Server
async init(host) {
try {
let connection = await amqplib.connect(host);
let channel = await connection.createChannel();
channel.prefetch(1);
console.log(' [x] Awaiting RPC requests');
this.connection = connection;
this.channel = channel;
}
catch(err) {
console.error(err);
}
}
// Close the Connection with RabbitMQ
closeConnection() {
this.connection.close();
}
log() {
console.log(this.connection);
}
EventPublisher() {
function init(IRabbit, publisherName) {
if(!IRabbit.connection) {
throw new Error('Create an Instance of IRabbitMQ to establish a Connection');
}
let ch = IRabbit.channel;
console.log(ch);
}
return {
init : init
}
}
}
var r = new IRabbitMQ();
r.log();
when i run the code the output is undefined, i dont know why since i m initializing the connection and channel properties in the init function and then called that function in the constructor so that should be initialized when i create an object of the Wrapper class. i wanted also to take some advices from you wether it is good to use classes or is there any other better way to create a Wrapper class or Interface for RabbitMQ to make it easy to use it and not have to duplicate Code.
Not really an answer, but I was able to successfully log the connection with this example code. I trimmed out other code to just focus on the .log() part that was logging a undefined.
Code is far from perfect, but works at least
const amqplib = require('amqplib');
class IRabbitMQ {
constructor() { }
async init(host) {
try {
const connection = await amqplib.connect(host);
const channel = await connection.createChannel();
channel.prefetch(1);
console.log(' [x] Awaiting RPC requests');
this.connection = connection;
this.channel = channel;
}catch(err) {
console.error(err);
}
}
log() {
console.log(this.connection);
}
}
async function createInstance(){
const instance = new IRabbitMQ();
try {
await instance.init('amqp://localhost');
}catch (e) {
throw new Error('OOPS!');
}
return instance;
}
async function runLogic() {
const r = await createInstance();
r.log();
}
runLogic().catch(console.log);
Just comment if you'd want me to give additional advice/tips, but this seems to work for me.

Scope in NodeJS / Firebase promise

I'm trying to develop a NodeJS app connecting to Firebase. I can connect successfully, but I'm unable to figure how to manage the scope in the then call.
I'm using NodeJS 6.9.2
My test implementation looks like this:
const EventEmitter = require('events');
const fb = require('firebase')
class FireGateway extends EventEmitter {
constructor() {
super();
if ( this.instance ) {
return this.instance;
}
// INIT
var fbConfig = {
apiKey: "xxxxx",
authDomain: "xxxxx.firebaseapp.com",
databaseURL: "https://xxxxx.firebaseio.com/"
};
fb.initializeApp(fbConfig)
this.instance = this;
this.testvar = "aaa";
}
login() {
fb.auth().signInWithEmailAndPassword ("email", "pwd")
.catch(function(error) {
// Handle Errors here.
}).then( function(onresolve, onreject) {
if (onresolve) {
console.log(this.testvar);
// "Cannot read property 'testvar' of undefined"
this.emit('loggedin');
// error as well
}
})
}
}
module.exports = FireGateway;
------
...
var FireGateway = require('./app/fireGateway');
this.fireGW = new FireGateway();
this.fireGW.login();
....
Any idea how can I manage it?
The callback passed to then is being called asynchronously from another context, so the this doesn't correspond to the instantiated object.
Using ES6 arrow functions you can keep your object context, since an arrow function does not create its own this context.
By the way, the syntax you are using in the then method is not correct, then accepts two callbacks with one argument each one. Check the syntax here.
The catch before the then is not necessary as well I think, it would make more sense to put it at the end.
It would be something like this:
login() {
fb.auth().signInWithEmailAndPassword("email", "pwd")
.then(
(onResolve) => {
console.log(this.testvar);
this.emit('loggedin');
},
(onReject) = > {
// error handling goes here
});
}
On the other hand, it seems login method is doing an asynchronous operation, so you might want to wait for it to finish in your code. I would make the login method return a Promise, so you can wait for it outside:
login() {
return fb.auth().signInWithEmailAndPassword("email", "pwd")
...
}

Wait for Node constructor to connect to api before issuing commands

Sorry if the question title is a tad ambiguous, but I'm not entirely sure how to word it.
I'm writing an NPM module that talks to a json-rpc api - this is the current setup.
// The module
function MyModule(config) {
// do some connection stuff here
connected = true
}
MyModule.prototype.sendCommand = function() {
if(connected) {
// do command
} else {
// output an error
}
}
module.exports = MyModule;
// The script interacting with the module
var MyModule = require('./MyModule');
var config = {
// config stuff
};
var mod = new MyModule(config);
var mod.sendCommand;
The command won't send, as at this point it hasn't connected, I assume this is due to NodeJS' asynchronous, non-blocking architecture and that I perhaps need to use promises to wait for a response from the API, where would I implement this? Do I do it in my module or do I do it in the script interacting with the module?
You will need to use either a callback or promises or something like that to indicate when the connection is complete so you can then use the connection in further code that is started via that callback.
Though it is generally not considered the best practice to do asynchronous stuff in a constructor, it can be done:
function MyModule(config, completionCallback) {
// do some connection stuff here
connected = true
completionCallback(this);
}
var mod = new MyModule(config, function(mod) {
// object has finished connecting
// further code can run here that uses the connection
mod.sendCommand(...);
});
A more common design pattern is to not put the connecting in the constructor, but to add a method just for that:
function MyModule(config) {
}
MyModule.prototype.connect = function(fn) {
// code here that does the connection and calls
// fn callback when connected
}
var mod = new MyModule(config);
mod.connect(function() {
// object has finished connecting
// further code can run here that uses the connection
mod.sendCommand(...);
});
don't use promises, use node's programming model where you don't "call functions" but you "call functions with a result handler for dealing with the data once it's actually available":
MyModule.prototype.sendCommand = function(handler) {
if(connected) {
// run stuff, obtain results, send that on:
handler(false, result);
} else {
// output an error, although really we should
// just try to connect if we're not, and say
// there's an error only when it actually fails.
handler(new Error("ohonoes"));
}
}
and then you call the function as
var MyModule = require('./MyModule');
var mod = ...
mod.sendCommand(function(err, result) {
// we'll eventually get here, at which point:
if (err) { return console.error(err); }
run();
more();
code();
withResult(result);
});

How to access instance variables anywhere in the class for node.js

I am working on a node.js application with postgresql, using the express framework. I am trying to follow MVC as much as possible.
I want to generate query results in a model class and then pass them to a controller class. That controller class is actually defined in the routes, so that controller class can take the results and pass them as http response.
This is my database helper class, i.e. the model class. My problem is at the listener at the very end of the class.
exports.DatabaseHelper = function()
{
var allVenues;
var client;
var customEventEmitter;
this.init = function()
{
this.customEventEmitter = new events.EventEmitter();
client = new pg.Client(
{
host:'localhost',
port:5432,
database:'postgres',
user:'postgres',
password:'password'
});
}
this.getVenuesWithEvents = function(searchParams)
{
allVenues = new Array();
var query_for_venues;
this.init();
client.connect();
client.addListener("error",function()
{
sys.puts("postgresql interface error");
});
query_for_venues = client.query("select id, name, location, latitude, longitude, category_generalized from venues");
query_for_venues.addListener("row",function(row)
{
//some code
});
query_for_venues.addListener("end",function(result)
{
this.customEventEmitter.emit("data",allVenues);
//////////////////////////////////////////////////////////
//this line shows error....'this' refers to the query object so customEventEmitter is undefined
//customEventEmitter is my idea of sharing the query results to my controller class.
//but I cannot do this becasue of this error
console.log("after emission");
});
}
}
How can I access the customEventEmitter instance variable from within the listener?
Just remove this from your init function:
this.customEventEmitter = new events.EventEmitter();
So you'll have:
customEventEmitter = new events.EventEmitter();
And in your listener just emit the emitter without this as follows:
query_for_venues.addListener("end",function(result){
customEventEmitter.emit("data",allVenues);
console.log("after emission");
});
let me show you a nice trick.
you could change custom
var customEventEmitter;
to
this.customEventEmitter =null;
at the top of the function. then you can call
var self = this;
outside of the query function. then inside the query function you reference the outer "this" with self.
as in:
self.customEventEmitter.emit()
the methodology I just described is standard.

Resources