the variable changes for all Telegraf.js users - javascript

I am developing a language selection function for my telegram bot written in telegraf.js, language variable changes for all users and this needs to be fixed
bot.start(async (ctx) => await ctx.reply("Выберете язык / Choose language: ",{
reply_markup:{
inline_keyboard:[
[ { text: "🇷🇺 Русский", callback_data: "ru" }, { text: "🇺🇸 English", callback_data: "en" } ],
]
}
}))
let lang;
bot.action('ru',() => lang = "ru");
bot.action('en',() => lang = "en");
i tried adding acync/await in various places but it did not help

Related

discord bot problem embed thumbnail attachment

I am not very experienced in javascript and I have a problem to display my attached image.
when someone type #1 bot send an embed with caracteristics and i want post the image too !
I don't know if I formatted it wrong or if I should load the image first. So the image is my local folder in the same directory as my index.js file
I had problems with color too! I didn't manage to modify it! I didn't manage to modify it
I would have liked to be able to change the color of the name title or description but I don't know if it's possible my tests were unsuccessful
Could you help me a little bit please? Here is my code. Thanks in advance.
const { token, prefix } = require('../config.json');
const Discord = require('discord.js');
const client = new Discord.Client();
// Listen to the Bot being ready
client.once('ready', () => onClientReady());
function onClientReady()
{
// Listen to Messages in the channel
client.on('message', (message) => onMessageReceived(message));
}
// Upon a message being received, handle how we interact
function onMessageReceived(message)
{
if(message.author.bot) return;
if (message.content.toLowerCase().includes('#1'))
message.channel.send({ embed: {
color: 3447003,
title: "SpaceShips #1 New_York",
url: "http://google.com",
description: "RANK: 74 / SCORE: 121",
Thumbnail: (url="attachment://000793.jpg"),
fields: [{
name: "__**POWER**__",
value: "A-G 0: **39**",
"inline": true
},
{
name: "__**POWER**__",
value: "E-W: **76**",
"inline": true
},
{
name: "__**AUTONOMY**__",
value: "EY-W Nrg: **74**",
"inline": true
},
{
name: "__**AUTONOMY**__",
value: "B-P 0 Nrg: **73**",
"inline": true
},
{
name: "__**DISPLACEMENT**__",
value: "L-A: **79**",
"inline": true
},
{
name: "__**DISPLACEMENT**__",
value: "3D-V: **67**",
"inline": true
},
{
name: "__**SPECIALS**__",
value: "EM-W: **34**",
"inline": true
},
{
name: "__**SPECIALS**__",
value: "3D-W: **42**",
"inline": true
}
],
}
});
}
client.login(token);
If your working with python, and just want to send an image, try this:
await channel.send(file=discord.File('my_image.png'))
You may simply add an image value to the embed object you're sending like so:
message.channel.send({ embed: {
color: 3447003,
title: "SpaceShips #1 New_York",
url: "http://google.com",
description: "RANK: 74 / SCORE: 121",
thumbnail: {
url: "attachment://000793.jpg"
},
}
}); // Removed fields to clear up the clutter, you may add them like before!
As far as color is concerned it's a RGB value you may Google up the value for the colour you like and replace it!
If you want only send the image then here i suppose (Node.Js)
const path = require('path');
const Discord = require('discord.js');
let pic = path.resolve('test.jpg')
// the picture, if you console.log it will send the path of the file for example mine /src/image/test.jpg
message.channel.send(new Discord.MessageAttachment(pic))
In fact it isn't possible in local to put an image in a embed... we only can put attach file...
Si I used an web link and hosted my images on a server and it works!
Thanks for your help.

Is there a way of making "embed pages" with Object-based embeds? (Discord.js)

I've been looking around for a way to make embed pages with discord.js but all of the tutorials I've seen are for a MessageEmbed. I would like to have some way to react to the embed and have it switch to the next.
This is my original code:
client.on('message', (message) => {
if (message.content.toLowerCase() == prefix + "help") {
const Embed = {
color: 0x91A6A6,
title: 'Help Menu. Page 1.',
author: {
name: 'KLSB',
icon_url: bot.user.avatarURL()
},
description: '\n How to use KLSB. \n',
fields: [
{
name: '!-help',
value: 'Opens a help menu.',
inline: true,
},
{
name: '!-cat',
value: 'Grabs a random cat picture from the internet.',
inline: true,
},
{
name: '!-dog',
value: 'Grabs a random dog picture from the internet.',
inline: true,
},
{
name: '!-panda',
value: 'Grabs a random panda picture from the internet.',
inline: true,
},
{
name: '!-bird',
value: 'Grabs a random panda picture from the internet.',
inline: true,
},
{
name: '!-meme',
value: 'Finds a meme from Reddit.',
inline: true,
},
{
name: '!-animememe',
value: 'Finds a anime meme from Reddit.',
inline: true,
},
{
name: '!-animalmeme',
value: 'Finds a animal meme from Reddit.',
inline: true,
},
{
name: '!-hug',
value: "Sends a hug through the internet!",
inline: true,
},
{
name: '!-8ball',
value: "As they say, it sees the future!",
inline: true,
},
],
};
message.channel.send({ embed: Embed });
}})
If anyone has some examples, please share them with me (and it would help if you could explain what's happening :D)
Yes, it is possible. The one I'm going to show you uses reaction collectors to control which page to go to. You can modify it accordingly to fit with your pages needs, but this is the basic gist.
I first set up an array called Pages that would be what you wrote in the description, you can add additional arrays accordingly for your titles and whatnot. I also have page set to one since that's the default page and it will be the counter of which page the user is currently on.
There's multiple steps to show how this works:
Create initial embed + send embed (which I see you have already done, but you'll need to modify it accordingly to fit with the pages array.
Then add the reactions (I chose :rewind: and :fast_forward:. Note: Do not simply just copy them from the Discord channel, as I have learned here.)
Then create two separate filters, one for each ReactionCollector. I've labeled mine isBackwards and isForwards accordingly.
Create a ReactionCollector for both forwards and backwards.
I've labeled mine backwards and forwards
Then inside of each event handler, I just shifted the page and the descriptions and whatnot, and edited the embed accordingly.
Note: The second reaction takes a while to load. I haven't found a function where you can put both embeds at the same time... so it might take a while for the second embed to pop up.
Code:
//pages is very flexible, as long as you change the array at the top you're set
let pages = ["Page one", "Page two", "Page three", "Page four"];
let page = 1;
if (message.content.startsWith("!embed")) {
const embed = new Discord.MessageEmbed()
.setColor(0xffffff) //sets color here
.setFooter(`Page ${page} of ${pages.length}`)
.setDescription(pages[page - 1])
message.channel.send(embed).then(msg => {
msg.react('⏪').then(r => {
msg.react('⏩');
//filters
const isBackwards = (reaction, user) => reaction.emoji.name === '⏪' && user.id === message.author.id;
const isForwards = (reaction, user) => reaction.emoji.name === '⏩' && user.id === message.author.id;
const backwards = msg.createReactionCollector(isBackwards);
const forwards = msg.createReactionCollector(isForwards);
backwards.on("collect", r => {
if (page === 1) return;
page--;
embed.setDescription(pages[page - 1]);
embed.setFooter(`Page ${page} of ${pages.length}`);
msg.edit(embed)
});
forwards.on("collect", r => {
if (page === pages.length) return;
page++;
embed.setDescription(pages[page - 1]);
embed.setFooter(`Page ${page} of ${pages.length}`);
msg.edit(embed)
});
});
});
}

React get array from MongoDB Stitch into react-bootstrap-table-next

I have a simple React app connected to MongoDB Stitch (Atlas) up and running, and am able to fetch some dummy data anonymously. I can display the array of data as text:
const {
Stitch,
RemoteMongoClient,
AnonymousCredential
} = require('mongodb-stitch-browser-sdk');
const client = Stitch.initializeDefaultAppClient('XXX-YYY');
const db = client.getServiceClient(RemoteMongoClient.factory, 'mongodb-atlas').db('vendor');
client.auth.loginWithCredential(new AnonymousCredential()).then(() =>
db.collection('vendor-item').find().asArray()
).then(docs => {
console.log("Found docs", docs);
const html = docs.map(docs => `
<div>${docs._id}</div>
<div>${docs.owner_id}</div>
<div>${docs.number}</div>`);
document.getElementById("comments").innerHTML = html;
}).catch(err => {
console.error(err)
});
And that displays as HTML as:
5e3dd30510807794cdef7968
5e3dac4310807794cde483f9
42
,
5e3dd30510807794cdef7978
5e3dd223340f9a51200f9192
42
,
5e3dd504ba978a97da4dc058
5e3dd503ba978a97da4dc020
42
However, I am trying to pull that data from the database and display it in a react-bootstrap-table-next table, which I have working out of the box, but also with different dummy data:
// dummy data
const data = [
{ id: 1, name: "Company 1", url: "http://www.google.com", loc:"san francisco, ca" },
{ id: 2, name: "Company 2", url: "http://www.bing.com", loc:"oakland, ca" }
];
const columns = [{
dataField: 'name',
text: 'Company'
}, {
dataField: 'url',
text: 'URL'
}, {
dataField: 'loc',
text: 'Location'
}];
Whereas I specifically need to combine the two methods and need the MongoDB array in the format that BootstrapTable is expecting, specifically as data={data} and columns={columns} as so:
<BootstrapTable
keyField="id"
data={data}
columns={columns}
striped
hover
condensed
bootstrap4
/>
I have already scoured the web for tutorials using "mongodb-stitch" and "react" and tried everything I could think of, with no luck.

Upload Intent function Dialogflow V2

I am trying to develop an API to upload the intent to Dialogflow V2. I have tried below snippet, which it is not working however if trying to communicate with Dialogflow it does work (detect intent)and does get a reply from the Dialogflow for queries.
PERMISSION
I AM & ADMIN > SERVICE ACCOUNTS > DIALOGFLOW ADMIN
ERROR
Error: 7 PERMISSION_DENIED: IAM permission 'dialogflow.entityTypes.create' on 'projects/dexter-47332/agent' denied.
BLOGS/ REFERENCES
Dialogflow easy way for authorization
https://github.com/dialogflow/dialogflow-nodejs-client-v2/blob/master/samples/resource.js#L26
https://www.npmjs.com/package/dialogflow
https://developers.google.com/apis-explorer/
https://cloud.google.com/docs/authentication/production
//------- keys.json (test 1)
{
"type": "service_account",
"project_id": "mybot",
"private_key_id": "123456asd",
"private_key": "YOURKEY",
"client_email": "yourID#mybot.iam.gserviceaccount.com",
"client_id": "098091234",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/yourID%40mybot.iam.gserviceaccount.com"
}
//--------------------- ** (test 2) ** ---------
let privateKey = 'key';
let clientEmail = "email";
let config = {
credentials: {
private_key: privateKey,
client_email: clientEmail
}
}
function createEntityTypes(projectId) {
// [START dialogflow_create_entity]
// Imports the Dialogflow library
const dialogflow = require('dialogflow');
// ******** Instantiates clients (Test 1)********
const entityTypesClient = new dialogflow.EntityTypesClient({
'keyFilename': './keys.json'
});
const intentsClient = new dialogflow.IntentsClient({
'keyFilename': './keys.json'
});
// ******** Instantiates clients (Test 2)********
const entityTypesClient = new dialogflow.EntityTypesClient(config);
const intentsClient = new dialogflow.IntentsClient(config);
// The path to the agent the created entity type belongs to.
const agentPath = intentsClient.projectAgentPath(projectId);
const promises = [];
// Create an entity type named "size", with possible values of small, medium
// and large and some synonyms.
const sizeRequest = {
parent: agentPath,
entityType: {
displayName: 'test',
kind: 'KIND_MAP',
autoExpansionMode: 'AUTO_EXPANSION_MODE_UNSPECIFIED',
entities: [{
value: 'small',
synonyms: ['small', 'petit']
},
{
value: 'medium',
synonyms: ['medium']
},
{
value: 'large',
synonyms: ['large', 'big']
},
],
},
};
promises.push(
entityTypesClient
.createEntityType(sizeRequest)
.then(responses => {
console.log('Created size entity type:');
logEntityType(responses[0]);
})
.catch(err => {
console.error('Failed to create size entity type ----->:', err);
})
);
}
createEntityTypes(projectId);
You can use JWT(JSON Web Tokens) for authenticating with service accounts like in this example
const serviceAccount = { }; // JSON key contents {"type": "service_account",...
const serviceAccountAuth = new google.auth.JWT({
email: serviceAccount.client_email,
key: serviceAccount.private_key,
scopes: 'https://www.googleapis.com/auth/calendar'
});
For more OAuth2.0 scopes for Google APIs you can see the full list here.
I encountered the same error. I corrected it by deleting the current service account and creating a new one and selected the "owner" option for the role.
The associated service-account has to have the role "Dialogflow API Admin" to be able to create intents and entities.
I think you must provide a name parameter there in the sizeRequest and make it equal to an empty string.
Take a look at the code snippet.
let request = {
parent: `projects/${PROJECID}/agent`,
entityType: {
name: '',
autoExpansionMode: 'AUTO_EXPANSION_MODE_DEFAULT',
displayName: 'size_type',
enableFuzzyExtraction: false,
entities: [
{
value: 'Big',
synonyms: ['big', 'large', 'huge']
},
{
value: 'Medium',
synonyms: ['medium', 'not big']
}
],
kind: 'KIND_MAP'
},
languageCode: 'en'
};
Please let me know if this helps.

Splitting an object by commas and then adding this to a hbs file

I'm trying to dynamically add buttons with their own links and titles. So in theory someone would be able to enter links (separated) by commas and their titles underneath (not the best solution but it's just for now). At the moment the page is showing up with 1 button with 2 links and 2 titles added to it (shown in screenshot)
router.js
router.get('/products/:permalinkSlug', async (req, res, next) => {
try {
const permalinkJob = req.params.permalinkSlug
const post = await postTools.getPostByPermalinkProducts(permalinkJob)
post.authorName = (await postTools.getAuthorById(post.author_id)).real_name
post.site_url = process.env.HOSTNAME
post.poster = {
"link": post.product_link.split(','),
"title": post.link_title.split(',')
}
HBS
{{#with poster}}
<a class="product_links_href" href="{{link}}" target="_blank">{{title}}</a>
{{/with}}
What's being returned
RowDataPacket {
id: 1,
name: null,
extract: null,
icon_image: null,
title: 'Product1',
permalink_slug: 'product1',
content: '<p>How can you two... Don\'t Google the question, Moss! Yeah, you need to turn it on... uh, the button turns it on. So, remember the new number! 0118 999! 88199, 9119 725! ... 3! Yeah, you need to turn it on... uh, the button turns it on. Hello? I\'ve had a bit of a tumble. Dear Sir stroke Madam, I am writing to inform you of a fire which has broken out at the premises of...</p>',
author_id: 1,
tags: '',
last_modified_date: 2018-07-09T09:47:09.000Z,
publish_date: 2018-07-06T08:30:12.000Z,
status: 'published',
feature_image: 33,
product_image: '49',
product_href: null,
undefined: null,
product_link: 'https://bbc.co.uk, https://google.com',
link_title: 'Discover more, Learn More',
authorName: 'Admin',
site_url: 'http://localhost:3000',
poster:
{ link: [ 'https://bbc.co.uk', ' https://google.com' ],
title: [ 'Discover more', ' Learn More' ] } }
You need to use the each helper to loop over the options, but it’ll be a bit awkward with the object of arrays that you have now. You should instead have an array of objects:
const SEPARATOR = /\s*,\s*/;
router.get('/products/:permalinkSlug', async (req, res, next) => {
try {
const permalinkJob = req.params.permalinkSlug;
const post = await postTools.getPostByPermalinkProducts(permalinkJob);
post.authorName = (await postTools.getAuthorById(post.author_id)).real_name
post.site_url = process.env.HOSTNAME
const links = post.product_link.split(SEPARATOR);
const titles = post.link_title.split(SEPARATOR);
const combined = links.map((link) => {
return {
link,
title: titles.shift(),
};
});
post.poster = combined;
Then your template can loop over these:
{{#each poster}}
<a class="product_links_href" href="{{this.link}}" target="_blank">{{this.title}}</a>
{{/each}}

Categories