integrate node-telegram-bot-api with nlp.js QnA - javascript

I'm creating a telegram bot. I want to integrate nlp.js to have a QnA.
At the moment I have this code:
#!/usr/bin/env node
const TelegramBot = require('node-telegram-bot-api');
const process = require('process');
const path = require('path');
const { dockStart } = require('#nlpjs/basic');
const axios = require('axios').default;
//const qnaFile = path.dirname()
let chatId;
let currentUser;
let incomingMessage;
let response;
let dock;
let nlp;
// replace the value below with the Telegram token you receive from #BotFather
const token = process.env.TELEGRAM_BOT_TOKEN || '5252802474:AA';
// Create a bot that uses 'polling' to fetch new updates
const bot = new TelegramBot(token, {polling: true});
bot.onText(/\/echo(.+)/, async (msg, match) => {
// 'msg' is the received Message from Telegram
// 'match' is the result of executing the regexp above on the text content
// of the message
//const chatId = msg.chat.id;
console.log(`CONSOLE LOG onText: \n ${match, msg}`);
});
bot.on('message', async (msg) => {
chatId = msg.chat.id;
currentUser = msg.from.first_name;
incomingMessage = msg.text;
dock = await dockStart();
const nlp = await dock.get('nlp');
await nlp.train();
response = await nlp.process('en', incomingMessage);
// Listen for any kind of message. There are different kinds of messages.
console.log(response);
console.log(msg);
// send a message to the chat acknowledging receipt of their message
await bot.sendMessage(chatId, `${response.answer}`);
});
How I can add new intents and utterances by using the user input incoming messages? From the documentation of the libary I don't see any reference about dynamically updating the corpus file?

Related

discord.js v12.5.1 direct message a user by id - not in async form

I am using this as a example in a coding class I've started, and this section is about messaging on discord. So far, I have the following code from inhoLee's question's answers:
client.once('ready', () => {
client.users.get("userid").send("test");
}
And the following is my list of dependencies, as it matters:
const Discord = require('discord.js');
const { MessageEmbed, Message } = require('discord.js');
Discord.Constants.DefaultOptions.ws.properties.$browser = 'Discord Windows';
const { keep_alive } = require('./keep_alive');
const fs = require('fs');
const config = require('./config.json');
const CatLoggr = require('cat-loggr');
const client = new Discord.Client();
const log = new CatLoggr();
var request = require('request');
also it would be preferrable if the answers were not in a async/await
Client.users is a UserManager that contains cached Users.
UserManager.cache is a Collection, which is the key-value cache.
Collection.has(userid) checks if the cache has the user with the specified id.
UserManager.createDM(userid) returns a Promise that resolves to the created DMChannel.
DMChannel.send(msg) will send a message in the DMChannel.
if (client.users.cache.has(/*userid*/)) {
client.users.createDM(/*userid*/).then((dmchannel) => {
dmchannel.send("hi i'm a bot");
});
} else console.log("user not found");
This method does use asynchronous programming, but it does not use async/await as requested.
As far as I have seen there are multiple ways to do this, but this is the method I found after reading the Discord.js documentation.

Trying to use puppeteer inside async function inside async function which already has puppeteer

I'm trying to build telegram bot to parse page on use request. My parsing code works fine inside one async function, but completeky falls on its face if I try to put it inside another async function.
Here is the relevant code I have:
const puppeteer = require('puppeteer');
const fs = require('fs/promises');
const { Console } = require('console');
async function start(){
async function searcher(input) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const url = ; //here is a long url combining logic, that works fine
await page.goto(url);
const currentUrl = requestPage.url();
console.log(currentUrl); //returns nothing.
//here is some long parsing logic
await browser.close();
return combinedResult;
}
//here is a bot code
const { Telegraf } = require('telegraf');
const bot = new Telegraf('my bot ID');
bot.command('start', ctx => {
console.log(ctx.from);
bot.telegram.sendMessage(ctx.chat.id, 'Greatings message', {});
bot.telegram.sendMessage(ctx.chat.id, 'request prompt ', {});
})
bot.on('text', (ctx) => {
console.log(ctx.message.text);
const queryOutput = searcher(ctx.message.text);
bot.telegram.sendMessage(ctx.chat.id, queryOutput, {});
});
bot.launch()
}
start();
Here is an error message:
/Users/a.rassanov/Desktop/Fetch/node_modules/puppeteer/lib/cjs/puppeteer/common/Connection.js:218
return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the ${this._targetType} has been closed.`));
^
Error: Protocol error (Page.navigate): Session closed. Most likely the page has been closed.
I'm very new to this, and your help is really appriciated.

How to properly transfer Solana SOL using web3js via Phantom

Am working with Solana Blockchain. Am trying to transfer Solana SOL via Phantom. To this effect I used the code below which was found on Stack Overflow: source link
I already have Phantom installed in Chrome. When I run the code, it displays error:
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'toString')
I think its this line of code that is causing the error above
console.log("Public key of the emitter: ",provider.publicKey.toString());
Here is the Code
import * as web3 from '#solana/web3.js';
import * as splToken from '#solana/spl-token';
const getProvider = async () => {
if ("solana" in window) {
const provider = window.solana;
if (provider.isPhantom) {
console.log("Is Phantom installed? ", provider.isPhantom);
return provider;
}
} else {
window.open("https://www.phantom.app/", "_blank");
}
};
async function transferSOL() {
// Detecing and storing the phantom wallet of the user (creator in this case)
var provider = await getProvider();
console.log("Public key of the emitter: ",provider.publicKey.toString());
// Establishing connection
var connection = new web3.Connection(
web3.clusterApiUrl('devnet'),
);
// I have hardcoded my secondary wallet address here. You can take this address either from user input or your DB or wherever
var recieverWallet = new web3.PublicKey("CkiKLEa9eSEoG6CoTSuaahsF2WqNgArnvoCSbNZjJ7BQ");
// Airdrop some SOL to the sender's wallet, so that it can handle the txn fee
var airdropSignature = await connection.requestAirdrop(
provider.publicKey,
web3.LAMPORTS_PER_SOL,
);
// Confirming that the airdrop went through
await connection.confirmTransaction(airdropSignature);
console.log("Airdropped");
var transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: provider.publicKey,
toPubkey: recieverWallet,
lamports: web3.LAMPORTS_PER_SOL //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
}),
);
// Setting the variables for the transaction
transaction.feePayer = await provider.publicKey;
let blockhashObj = await connection.getRecentBlockhash();
transaction.recentBlockhash = await blockhashObj.blockhash;
// Transaction constructor initialized successfully
if(transaction) {
console.log("Txn created successfully");
}
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
// The signature is generated
let signature = await connection.sendRawTransaction(signed.serialize());
// Confirm whether the transaction went through or not
await connection.confirmTransaction(signature);
//Signature chhap diya idhar
console.log("Signature: ", signature);
}
You need to connect to the wallet. That part is missing
const getProvider = async () => {
if ("solana" in window) {
// opens wallet to connect to
await window.solana.connect();
const provider = window.solana;
if (provider.isPhantom) {
console.log("Is Phantom installed? ", provider.isPhantom);
return provider;
}
} else {
window.open("https://www.phantom.app/", "_blank");
}
};
I'm not sure if this is the best solution going ahead, but yours is a problem of the persistence of the phantom wallet after the user signs in. You'll have to go for front-end heavy solution for this. One of which is:
Assuming you are using React, use context APIs to persist the data about the wallet. Here is a rough guideline on how to do that by creating a file under the context folder in your project root:
import React, { createContext, useState} from "react";
export const WalletDataContext=createContext();
export const WalletDataContextProvider=(props)=>{
const [publicKey,setPublicKey]=useState(null);
const [wallet,setWallet]=useState(null);
return (
<WalletDataContext.Provider
value={{publicKey,setPublicKey,wallet,setWallet}}
>
{props.children}
</WalletDataContext.Provider>
)
}
Create a connectWallet function, something like this:
//import {WalletDataContext}
//import other stuff:
const {setPublicKey,setWallet}=useContext(WalletDataContext)
const connectWallet = async() {
const provider = await getProvider();
if(provider) {
await provider.connect();
let publicKey = "";
provider.on("connect", async () => {
setWallet(provider);
publicKey = provider.pubicKey.toString();
setPublicKey(publicKey);
/*
// more things that you would like to do here
*/
});
}
}
Make the following changes in your transferSOL function:
async function transferSOL() {
//Changes are only here, in the beginning
const phantomProvider = wallet;
if(!phantomProvider){
//Urge the user to sign in(connect) again
}
const pubKey = await phantomProvider.publicKey;
console.log("Public Key: ", pubKey);
// Establishing connection
var connection = new web3.Connection(
web3.clusterApiUrl('devnet'),
);
// I have hardcoded my secondary wallet address here. You can take this address either from user input or your DB or wherever
var recieverWallet = new web3.PublicKey("CkiKLEa9eSEoG6CoTSuaahsF2WqNgArnvoCSbNZjJ7BQ");
// Airdrop some SOL to the sender's wallet, so that it can handle the txn fee
var airdropSignature = await connection.requestAirdrop(
provider.publicKey,
web3.LAMPORTS_PER_SOL,
);
// Confirming that the airdrop went through
await connection.confirmTransaction(airdropSignature);
console.log("Airdropped");
var transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: provider.publicKey,
toPubkey: recieverWallet,
lamports: web3.LAMPORTS_PER_SOL //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
}),
);
// Setting the variables for the transaction
transaction.feePayer = await provider.publicKey;
let blockhashObj = await connection.getRecentBlockhash();
transaction.recentBlockhash = await blockhashObj.blockhash;
// Transaction constructor initialized successfully
if(transaction) {
console.log("Txn created successfully");
}
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
// The signature is generated
let signature = await connection.sendRawTransaction(signed.serialize());
// Confirm whether the transaction went through or not
await connection.confirmTransaction(signature);
//Signature or the txn hash
console.log("Signature: ", signature);
}
I think you problem is here:
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
// The signature is generated
let signature = await connection.sendRawTransaction(signed.serialize());
// Confirm whether the transaction went through or not
await connection.confirmTransaction(signature);
You sign using provider, but you send using connection, try change this:
const { signature } = await provider?.signAndSendTransaction(
transaction
);
await connection.getSignatureStatus(signature);
return signature;

UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message

I'm having an issue with sending a message to a Discord channel from a fetch.
I'm fetching Time Series Data from a REST API. I then want to send this data if a Discord user types a command.
Code:
require("dotenv").config();
const fetch = require("node-fetch");
const { Client } = require("discord.js");
const PREFIX = "!";
const getPrice = async (ticker) => {
let result = "test";
const request = await fetch(
`https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=${ticker}&interval=5min&apikey=${process.env.API_KEY}`
);
const response = await request.json();
const data = await response;
const obj = await data["Time Series (5min)"];
result = obj[Object.keys(obj)[0]];
return result;
};
client.on("message", (message) => {
if (message.author.bot) return;
if (message.content.startsWith(PREFIX)) {
const [command, ...args] = message.content
.trim()
.substring(PREFIX.length)
.split(/\s+/);
const result = getPrice(`${command.toUpperCase()}`);
message.channel.send(result);
}
});
I get the following error:
UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message
If you take a look at the following code and replace it with a console.log - it works. E.g
Original
message.channel.send(result);
Replace with
console.log(result)
Then it works:
{
'1. open': '119.0200',
'2. high': '119.0200',
'3. low': '119.0200',
'4. close': '119.0200',
'5. volume': '302'
}
I suspect it has something to do with Promises, maybe my understanding isn't up to scratch but I've read docs over and over and cannot make sense of it.
I believe the reason that result is empty is because by the time that method is called in the stack, the fetch has not come back with the data, and it attempts to send empty data.
How can I ensure that message.channel.send waits for my fetch to finish before being called?
getPrice is an async function that returns a promise. You need to await the result before you can send it:
client.on("message", async (message) => {
if (message.author.bot) return;
if (message.content.startsWith(PREFIX)) {
const [command, ...args] = message.content
.trim()
.substring(PREFIX.length)
.split(/\s+/);
const result = await getPrice(`${command.toUpperCase()}`);
message.channel.send(result);
}
});

How do I playback .m4s files. And turn them into a binary stream for a Discord Bot

I want to download the BBC radio 2 and stream it to a discord server. Each request is https://as-dash-uk-live.akamaized.net/pool_904/live/uk/bbc_radio_two/bbc_radio_two.isml/dash/bbc_radio_two-audio=320000-250636302.m4s However the Time stamp will change and they regularly delete content. I found a .dash file as well https://as-dash-uk-live.akamaized.net/pool_904/live/uk/bbc_radio_two/bbc_radio_two.isml/dash/bbc_radio_two-audio=320000.dash which is seems to request. However I can't find how to send it through a discord bot to a discord server. My code is
const axios = require('axios')
module.exports = {
play: async function (guild,message) {
const serverQueue = {};
const voiceChannel = message.member.voice.channel
serverQueue.connection = await voiceChannel.join();
plays(guild)
async function plays(guild) {
let data1 = new Date(1353439725);
let data2 = new Date(Date.now()/1000);
console.log(`https://as-dash-uk-live.akamaized.net/pool_904/live/uk/bbc_radio_two/bbc_radio_two.isml/dash/bbc_radio_two-audio=320000-${Math.floor((data2 - data1))-4000}.m4s`)
const dispatcher = serverQueue.connection.play((await axios.get(`https://as-dash-uk-live.akamaized.net/pool_904/live/uk/bbc_radio_two/bbc_radio_two.isml/dash/bbc_radio_two-audio=320000-${Math.floor((data2 - data1))-4000}.m4s`)).data)
.on('finish', () => {
console.log('Music ended!');
plays(guild);
return
})
.on('error', error => {
console.error(error);
plays(guild);
return
});
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
}
}
}
However no audio plays and the audio end event is always being called. Am I being really stupid or is there a way to do this.

Categories