I am creating a discord music bot. I want the bot to give output messages with embeds and reply to the user who used the command. Here's my code:
const { QueryType } = require('discord-player');
module.exports = {
name: 'play',
aliases: ['p'],
utilisation: '{prefix}play [song name/URL]',
voiceChannel: true,
async execute(client, message, args) {
if (!args[0]) return message.channel.send(`Please enter a valid search.`);
const res = await player.search(args.join(' '), {
requestedBy: message.member,
searchEngine: QueryType.AUTO
});
if (!res || !res.tracks.length) return message.channel.send(`No results found.`);
const queue = await player.createQueue(message.guild, {
metadata: message.channel
});
try {
if (!queue.connection) await queue.connect(message.member.voice.channel);
} catch {
await player.deleteQueue(message.guild.id);
return message.channel.send(`I can't join the voice channel.`);
}
await message.channel.send(`Loading your ${res.playlist ? 'playlist' : 'track'}...`);
res.playlist ? queue.addTracks(res.tracks) : queue.addTrack(res.tracks[0]);
if (!queue.playing) await queue.play();
},
};
I want to make it look like this
When I try to make axios.get request(url) for a small number of URLs it works successfully but when the number of URLs is large I get an errors from axios ( socket hang up - Client network socket disconnected before secure TLS connection was established - read ECONNRESET - connect ETIMEDOUT).
my code
I try to loop through this array
const links = [
{
title: 'title two',
newsLink: 'https://al-omana.net/details.php?id=158277',
imageLink: 'https://al-omana.net/media/imgs/news/25-09-2021-04-18-26.jpeg',
category: 'news',
rssId: 321,
selector: '.story_text p'
},
{
title: 'title one',
newsLink: 'https://al-omana.net/details.php?id=158277',
imageLink: 'https://al-omana.net/media/imgs/news/25-09-2021-04-18-26.jpeg',
category: 'news',
rssId: 123,
selector: '.story_text p'
},
... 1415 more items
]
and I try to extract the content by this function
async function scrapeContent(item) {
try {
let content = "";
const { data } = await axios.get(item.newsLink);
const $ = cheerio.load(data);
const listItems = $(item.selector);
listItems.each((_, item) => {
content += $(item).text();
});
return {
...item,
content: content.replace(/[\r\n\"\t]+/gm, "")
};
} catch (error) {
console.log({ in: "scrapeContent", message: error.message });
}
}
and this my execute function
async function scraper(links) {
try {
const promises = links.map(scrapeContent); // this loop axios requests
const newsContent = await Promise.all(promises);
console.log(newsContent);
} catch (error) {
console.log({ in: "scraper", message: error.message });
}
scraper(links);
Please help me
I have a problem with my API that sends metadata when called from my smart contract of website. Its NFT tokens and my database is postgres and API is node.js
The problem is when I mint 1 NFT metadata works perfect, but if I mint 2 or more it will only ever send 1 chunk of data? So only 1 NFT will mint properly and the rest with no data?
Do I need to set a loop function or delay? Does anyone have any experience with this?
Any help would be much appreciated.
Below is the code from the "controller" folder labeled "nft.js"
const models = require("../../models/index");
const path = require("path");
const fs = require("fs");
module.exports = {
create_nft: async (req, res, next) => {
try {
const dir = path.resolve(__dirname + `../../../data/traitsfinal.json`);
const readCards = fs.readFileSync(dir, "utf8");
const parsed = JSON.parse(readCards);
console.log("ya data ha final ??", parsed);
parsed.forEach(async (item) => {
// return res.json(item)
let newNft = await models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
});
});
return res.json({
data: "nft created",
error: null,
success: true,
});
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
get_nft: async (req, res, next) => {
try {
const { id } = req.params;
// console.log("id ?????????",id)
// console.log("type of ",typeof(id))
// const n=Number(id)
// console.log("type of ",typeof(id))
const nft = await models.NFT.findByPk(id);
if (!nft) {
throw new Error("Token ID invalid");
}
if (!nft.isMinted) {
throw new Error("Token not minted");
}
console.log(nft);
// }
const resObj = {
name: nft.name,
description: nft.description,
image: `https://gateway.pinata.cloud/ipfs/${nft.image}`,
attributes: [
{ trait_type: "background", value: `${nft.background}` },
{ trait_type: "body", value: `${nft.body}` },
{ trait_type: "mouth", value: `${nft.mouth}` },
{ trait_type: "eyes", value: `${nft.eyes}` },
{ trait_type: "tokenId", value: `${nft.tokenId}` },
{
display_type: "number",
trait_type: "Serial No.",
value: id,
max_value: 1000,
},
],
};
return res.json(resObj);
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
get_nft_all: async (req, res, next) => {
try {
// console.log("id ?????????",id)
// console.log("type of ",typeof(id))
// const n=Number(id)
// console.log("type of ",typeof(id))
const nft = await models.NFT.findAndCountAll({
limit: 10
});
// console.log(nft);
if (!nft) {
throw new Error("Token ID invalid");
}
// if (nft.isMinted) {
// throw new Error("Token not minted");
// }
// console.log(nft);
// }
var resObjarr = [];
for (var i = 0; i < nft.rows.length; i++) {
resObj = {
name: nft.rows[i].name,
description: nft.rows[i].description,
image: `https://gateway.pinata.cloud/ipfs/${nft.rows[i].image}`,
attributes: [
{ trait_type: "background", value: `${nft.rows[i].background}` },
{ trait_type: "body", value: `${nft.rows[i].body}` },
{ trait_type: "mouth", value: `${nft.rows[i].mouth}` },
{ trait_type: "eyes", value: `${nft.rows[i].eyes}` },
{ trait_type: "tokenId", value: `${nft.rows[i].tokenId}` },
{
display_type: "number",
trait_type: "Serial No.",
value: nft.rows[i].id,
max_value: 1000,
},
],
};
resObjarr.push(resObj);
}
console.log(JSON.stringify(resObjarr))
return res.json(resObjarr);
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
mint: async (req, res, next) => {
try {
const { id } = req.params;
const updated = await models.NFT.findByPk(id);
if (!updated) {
throw new Error("NFT ID invalid");
}
if (updated.isMinted) {
throw new Error("NFT Already minted");
}
updated.isMinted = true;
updated.save();
return res.json({
data: "Token minted successfully",
error: null,
success: true,
});
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
};
Below is from the routes folder.
const router = require("express").Router();
const auth=require("../middleware/auth")
const {
create_nft,
get_nft,
get_nft_all,
mint
} = require("../controller/nft");
router.post(
"/create",
create_nft
);
router.get(
"/metadata/:id",
get_nft
);
router.get(
"/metadata",
get_nft_all
);
router.put(
"/mint/:id",
mint
);
module.exports = router;
Looking your code,you may having some kind of asyncrhonous issue in this part:
parsed.forEach(async (item) => {
// return res.json(item)
let newNft = await models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
});
});
Because .forEach is a function to be used in synchronous context and NFT.create returns a promise (that is async). So things happens out of order.
So one approach is to process the data first and then perform a batch operation using Promise.all.
const data = parsed.map(item => {
return models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
})
})
const results = await Promise.all(data)
The main difference here is Promise.all resolves the N promises NFT.create in an async context in paralell. But if you are careful about the number of concurrent metadata that data may be too big to process in parallel, then you can use an async iteration provided by bluebird's Promise.map library.
const Promise = require('bluebird')
const data = await Promise.map(parsed, item => {
return models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
})
})
return data
i want collect news from different channels and echo them in a second channel, with the code i can read channels(not all but most).
I stuck now on the echo problem and have no clue about how i can do this, mtproto is completely new to me, thanks.
Im using the following code i have from another stackoverflow question.
const { MTProto, getSRPParams } = require('#mtproto/core');
const prompts = require('prompts');
const api_id = 'xxxxx';
const api_hash = 'xxxxx';
async function getPhone() {
return (await prompts({
type: 'text',
name: 'phone',
message: 'Enter your phone number:'
})).phone
}
async function getCode() {
// you can implement your code fetching strategy here
return (await prompts({
type: 'text',
name: 'code',
message: 'Enter the code sent:',
})).code
}
async function getPassword() {
return (await prompts({
type: 'text',
name: 'password',
message: 'Enter Password:',
})).password
}
const mtproto = new MTProto({
api_id,
api_hash,
});
function startListener() {
console.log('[+] starting listener')
mtproto.updates.on('updates', ({ updates }) => {
const newChannelMessages = updates.filter((update) => update._ === 'updateNewChannelMessage').map(({ message }) => message) // filter `updateNewChannelMessage` types only and extract the 'message' object
for (const message of newChannelMessages) {
// printing new channel messages
console.log(`[${message.to_id.channel_id}] ${message.message}`)
}
});
}
// checking authentication status
mtproto
.call('users.getFullUser', {
id: {
_: 'inputUserSelf',
},
})
.then(startListener) // means the user is logged in -> so start the listener
.catch(async error => {
// The user is not logged in
console.log('[+] You must log in')
const phone_number = await getPhone()
mtproto.call('auth.sendCode', {
phone_number: phone_number,
settings: {
_: 'codeSettings',
},
})
.catch(error => {
if (error.error_message.includes('_MIGRATE_')) {
const [type, nextDcId] = error.error_message.split('_MIGRATE_');
mtproto.setDefaultDc(+nextDcId);
return sendCode(phone_number);
}
})
.then(async result => {
return mtproto.call('auth.signIn', {
phone_code: await getCode(),
phone_number: phone_number,
phone_code_hash: result.phone_code_hash,
});
})
.catch(error => {
if (error.error_message === 'SESSION_PASSWORD_NEEDED') {
return mtproto.call('account.getPassword').then(async result => {
const { srp_id, current_algo, srp_B } = result;
const { salt1, salt2, g, p } = current_algo;
const { A, M1 } = await getSRPParams({
g,
p,
salt1,
salt2,
gB: srp_B,
password: await getPassword(),
});
return mtproto.call('auth.checkPassword', {
password: {
_: 'inputCheckPasswordSRP',
srp_id,
A,
M1,
},
});
});
}
})
.then(result => {
console.log('[+] successfully authenticated');
// start listener since the user has logged in now
startListener()
});
})
I create chatbot by Bot Framework and use LINE API Developers on node.js
Problem on my work was continueDialog not continue waterfallDialog next step.
and the stack didn't change when it's done with continueDialog
before continueDialog
stack1 [ { id: 'xxxDialog',
state: { options: {}, values: [Object], stepIndex: 0 } } ]
after continueDialog
stack2 [ { id: 'xxxDialog',
state: { options: {}, values: [Object], stepIndex: 0 } } ]
on index.js
server.post('/api/line',jsonParser, async (req, res)=> {
const conversationReference = {
type: "message",
text: "Hello world" ,
channelData: { clientActivityID: "id-xxxx" },
channelId: 'api/line/id-xxxx',
recipient:
{ id: lineID`,
name: 'line',
role: 'botLine' },
serviceUrl: 'https://localhost:3978' ,
from:
{ id: lineId`,
name: 'User',
role: 'user' },
conversation: { id: lineId },
};
const context = await adapter.createContext(conversationReference);
await bot.onTurn(context);
});
on bot.js
class Bot extends ActivityHandler {
/**
*
* #param {ConversationState} conversationState
* #param {UserState} userState
* #param {Dialog} dialog
*/
constructor(conversationState, userState) {
super();
this.conversationState = conversationState;
this.userState = userState;
this.dialogStateAccessor = conversationState.createProperty('dialogStateAccessor');
this.dialogAccessor= conversationState.createProperty('testAccessor');
this.dialog = new DialogSet(this.dialogStateAccessor);
this.dialog.add(new WaterfallDialog('testDialog', [
this.step1.bind(this),
this.step2.bind(this)
]));
}
async step1(stepContext){
linesent("step 1") ;
return {status : DialogTurnStatus.waiting} ;
}
async step2(stepContext){
linesent("step 2") ;
return await stepContext.endDialog();
}
async onTurn(turnContext) {
const reservation = await this.dialogAccessor.get(turnContext, null);
// Generate a dialog context for our dialog set.
const dc = await this.dialog.createContext(turnContext);
if (!dc.activeDialog){
// If there is no active dialog, check whether we have a reservation yet.
if (!reservation) {
// If not, start the dialog.
await dc.beginDialog(`testDialog`);
}
}
else {
//Continue the dialog.
const dialogTurnResult = await dc.continueDialog();
}
return await this.conversationState.saveChanges(turnContext, false);
}
but it did not show any error.
Any help would be appreciated.
found the continueDialog method be
async continueDialog(dc) {
// Don't do anything for non-message activities
if (dc.context.activity.type !== botbuilder_core_1.ActivityTypes.Message) {
return dialog_1.Dialog.EndOfTurn;
}
// Run next step with the message text as the result.
return await this.resumeDialog(dc, dialog_1.DialogReason.continueCalled, dc.context.activity.text);
}
the bot always do if condition.
Changed continueDialog to resumeDialog on your activeDialog id the waterfall will working on next step.