Fetch a message (by ID) and edit it - javascript

I'm trying to edit a message the bot sent, in a different function.
const msg = message.channel.fetchMessage(msgId);
msg.edit(embed);
Didn't work because msg.edit is not a function.
message.channel.messages.fetch({around: "352292052538753025", limit: 1})
.then(messages => {
messages.first().edit("test");
});
Didn't work because .fetch is not a function.
function update(msgId, time, channelid, prize, winnersInt, message) {
setTimeout(function(){
let gtime = time/3600000 + " hours remaining!";
if(time < 3600000) {
gtime = time/60000 + " minuets remaining!";
}
console.log(gtime + "p: " + prize);
let embed = new Discord.RichEmbed()
.setColor("#7289da")
.setTitle("Giveaway!")
.addField('Prize: ', prize)
.addField('Amount of winners: ', winnersInt)
.addField('Time: ', gtime)
const msg = message.channel.fetchMessage(msgId);
msg.edit(embed);
time - 60000;
if(time > 0) {
update(msgId, time, channel, prize, winnersInt, message);
}
}, 60000);
}
I expect the message to be edited.

Old publication but may help those currently looking for it.
For V.13 it can be used this way:
<#Channel>.messages.fetch('messageID').then(msg => msg.edit('newMessage'))
I tested it that way and it worked perfectly.

Got it working.
Used this:
message.channel.fetchMessages({around: msgId, limit: 1})
.then(msg => {
const fetchedMsg = msg.first();
fetchedMsg.edit(embed);
});

Related

Trying to create a function that would create a scheduled post based on time and date

Basically trying to build a message board app that allows users write posts. I want to be able to write posts for the future for example in 5 mins. The problem with this function is that even with setTimeout() and the time difference(seconds) its not working as intended instead its just posting as soon as send the post. I am using firebase and react in this project. messageref refers to the collection!
const sendMessage = async (e) => {
const now = new Date().getTime()
console.log(now);
const seconds = (time - now)/1000
console.log(seconds);
e.preventDefault();
if(formValue === ""){
alert("must enter a message!")
}
if(seconds === 0){
await messageRef
.add({
text: formValue,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
})
setFormValue("")
pag.current.scrollIntoView({ behavior: "smooth" })
} else if(seconds > 0){
setTimeout(async () => {
await messageRef
.add({
text: formValue,
timestamp: time,
})
setFormValue("")
pag.current.scrollIntoView({ behavior: "smooth" })
}, seconds)
}else {
alert('cant send a post in the past')
}
};
The mistake is that you're passing a value in seconds to setTimeout, while that takes a value in milliseconds. So to fix it:
setTimeout(async () => {
await messageRef
.add({
text: formValue,
timestamp: time,
})
setFormValue("")
pag.current.scrollIntoView({ behavior: "smooth" })
}, seconds*1000)
// 👆
A longer code snippet:
const time = Date.now() + 5000; // in 5 seconds
const formValue = "Hello world";
const now = new Date().getTime()
console.log(now);
const seconds = (time - now)/1000
console.log(seconds);
if(formValue === ""){
alert("must enter a message!")
}
if(seconds === 0){
console.log("Sending now");
} else if(seconds > 0){
console.log("Sending in "+seconds+"s");
setTimeout(async () => {
console.log("Sending now");
}, seconds*1000)
}else {
alert('cant send a post in the past')
}
I recommend always reproducing problems in this format, as it makes it easiest for folks to help.

How can I edit a embed message on interval?

var dateTime = time+' '+date;
const boosterembed = new Discord.RichEmbed()
.setTitle("Boosters")
.setColor('#ff0000')
.setDescription("Last Time updated: " + dateTime)
.setTimestamp()
setInterval(function(){guild.channels.get('740327839177375765').message.channel.fetchMessages('740327893103673466').edit(boosterembed)}, 1000)
Why is this not working? Can't add more (looks like your post is mostly code)
I'm assuming you're using Discord.js v11.
First, fetchMessages is for fetching multiple messages from a channel. You'll want to use fetchMessage instead. Second, you use edit to edit a message. Third, a channel does not have a message property, so guild.channels.get(...).message.channel will throw an error.
setInterval(
() =>
guild.channels.get('740327839177375765').fetchMessage('740327893103673466')
.then(message => message.edit(boosterembed))
// This catches all errors and logs them to stop unhandled promise rejections
.catch(console.error),
1000
)
// Or with async/await:
setInterval(
async () => {
try {
const message = await guild.channels.get('740327839177375765').fetchMessage('740327893103673466')
await message.edit(boosterembed)
} catch (error) {
console.error(error)
}
},
1000
)
This answer is adapted from cherryblossom's answer, make sure you upvote it.
function getDate() {
var today = new Date();
var date = today.getDate()+'/'+(today.getMonth()+1)+'/'+today.getFullYear();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return time + ' ' + date;
}
setInterval(
() =>
bot.channels.get('740327839177375765').fetchMessage('740327893103673466')
.then(message => message.edit(new Discord.RichEmbed(boosterembed).setDescription('Last Time updated: ' + getTime())))
// This catches all errors and logs them to stop unhandled promise rejections
.catch(console.error),
1000
)
// Or with async/await:
setInterval(
async () => {
try {
const message = await bot.channels.get('740327839177375765').fetchMessage('740327893103673466')
await message.edit(new Discord.RichEmbed(boosterembed).setDescription('Last Time updated: ' + getTime()))
} catch (error) {
console.error(error)
}
},
1000
)

quick.db leveling system - database.updateValue is not a function

I'm trying to make a leveling system with a discord bot using quick.db. I've been working with this for a while and couldn't figure it out so I figured I'd go here. My current code is:
(app.js)
//Message Leveling
database.updateValue(message.author.id + message.guild.id, 1).then(i => {
let messages;
if (i.value = 25) messages = 25; // Level 1
else if (i.value == 50) messages = 50; // Level 2
else if (i.value == 75) messages = 75; //Level 3
if (!isNaN(messages)) { // If messages iss STILL empty, run this
database.updateValue(`userLevel_${message.author.id + message.guild.id}`, 1).then(o => {
message.channel.send(`You sent ${messages} messages, LEVEL UP HOME BOY! level ${o.value}`)
})
}
})
(messages.js)
const db = require('quick.db');
var database = require('quick.db')
exports.run = (bot, message, args, func) => {
database.fetchObject(message.author.id + message.guild.id).then(i => {
database.fetchObject(`userLevel_${message.author.id + message.guild.id}`).then(o => {
message.channel.send('Messages sent: `' + (i.value + 1) + '`\nLevel: `' + o.value +'`');
})
})
}
Now, the error I get happens in app.js but I figured the code from messages.js might be helpful. The error is:
[help] database.updateValue(message.author.id + message.guild.id, 1).then(i => {
[help] ^
[help]
[help] TypeError: database.updateValue is not a function
Being new to this I still don't quite understand what a TypeError is or how to fix it, despite looking it up on google (I know, I'm a real researcher). So I was hoping someone could give me a hand. I also couldn't find an example of this error, so I'm pretty lost.
As always, thanks for taking the time to read my question, if I got any terminology wrong feel free to ask me about what I mean, or you can just call me stupid.
<3
database.updateValue isn't a function, instead you would want to use database.addlike:
database.add(`level_${message.guild.id}_${message.author.id}`, 1).then(i => {
let messages;
if (i.value = 25) messages = 25; // Level 1
else if (i.value == 50) messages = 50; // Level 2
else if (i.value == 75) messages = 75; //Level 3
if (!isNaN(messages)) { // If messages iss STILL empty, run this
database.add(`level_${message.guild.id}_${message.author.id}`, 1).then(o => {
message.channel.send(`You sent ${messages} messages, LEVEL UP HOME BOY! level ${o.value}`)
})
}
})
For fetching databases, fetchObject isn't a function, use fetch or get
const db = require('quick.db');
var database = require('quick.db')
exports.run = (bot, message, args, func) => {
db.fetch(level_${message.guild.id}_${message.author.id}).then(i => {
db.fetch(level_${message.guild.id}_${message.author.id}).then(o => {
message.channel.send('Messages sent: `' + (i.value + 1) + '`\nLevel: `' + o.value +'`');
})
})
}
If you've defined quick.db as db then instead of calling database, call db otherwise it just wouldn't work.
Thanks,
Chills

How to create a google search command in a discord bot?

I am extremely new to Javascript and Discord.js, meaning that I copy most of my code online and try to understand them. I tried this google search command. However, my bot does not send anything. The only thing it sends is "Need Input" when I type .google. When I do input a search, it does not complete the task. It does not give me an error in my command prompt. Have I done something wrong? Do you have a completely different code? PS. My code is from https://github.com/OblivionSan/discord-googlebot/blob/master/commands/general/google.js
I have installed npm i google, but it sends me a lot of errors when I do.
const google = require('google');
const Discord = require(`discord.js`);
exports.run = (client, message) => {
if (!suffix) {
message.channel.send({
embed: {
color: 0xff2727,
description: `:warning: **${message.author.username}**, You didn't give me anything to search. {.google \`input\`}`,
}
});
}
google.resultsPerPage = 5;
google(suffix, function (err, res) {
if (err) message.channel.send({
embed: {
color: 0xff2727,
description: `:warning: **${message.author.username}**, ${err}`,
footer: {
text: 'API Lantancy is ' + `${Date.now() - message.createdTimestamp}` + ' ms',
}
}
});
for (var i = 0; i < res.links.length; ++i) {
var link = res.links[i];
if (!link.href) {
res.next;
} else {
let embed = new Discord.RichEmbed()
.setColor(`#ffffff`)
.setAuthor(`Result for "${suffix}"`, `https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/2000px-Google_%22G%22_Logo.svg.png`)
.setDescription(`**Link**: [${link.title}](${link.href})\n**Description**:\n${link.description}`)
.setTimestamp()
.setFooter('API Lantancy is ' + `${Date.now() - message.createdTimestamp}` + ' ms', message.author.displayAvatarURL);
return message.channel.send({
embed: embed
});
} return message.react("👌");
}
});
};
I expect a google search but get basically nothing. I get left on read :/
That module is not working as of now, as far as I can tell. I'm using the GoogleIt module for my bot, and here's the code that I'm using for a sample:
const googleIt = require('google-it')
const Discord = require(`discord.js`);
exports.run = (bot, message, args) => {
const embed = new Discord.RichEmbed()
.setTitle("Google Search Results")
.setColor(3426654)
.setTimestamp()
googleIt({'query': args.join(' ')}).then(results => {
results.forEach(function(item, index) {
embed.addField((index + 1) + ": " + item.title, "<" + item.link + ">");
});
message.channel.send(embed);
}).catch(e => {
// any possible errors that might have occurred (like no Internet connection)
});
};
module.exports.help = {
name: 'google',
aliases: []
}
Check what I have below and see if that works. I usually use an object for the embed. You can generate / see one here => https://leovoel.github.io/embed-visualizer/ when you click the generate button and select discord.js
// this config option doesn't really need to be in your method / function
google.resultsPerPage = 5;
client.on('message', (message) => {
// Using !search as a suffix in a regex
if (/!search/.test(message.content))) {
// remove the suffix
const search = message.content.replace('!search ', '');
google('node.js best practices', (err, res) => {
if (err) console.error(err)
for (var i = 0; i < res.links.length; ++i) {
var link = res.links[i];
// At this point, you should see your data and just have to format your embed
console.log(link.title + ' - ' + link.href)
console.log(link.description + "\n")
}
}
}
});

Firebase function execution and subscription to list that is being updated by a firebase function

I think a firebase function updating a list that I have in the firebase database is being captured by a subscription that is subscribed to that list. From what the list output looks like on my phone (in the app)...and from what my console output looks like (the way it repeats) it seems like it is capturing the whole list and displaying it each time one is added. So (I looked this up)...I believe this equation represents what is happening:
(N(N + 1))/2
It is how you get the sum of all of the numbers from 1 to N. Doing the math in my case (N = 30 or so), I get around 465 entries...so you can see it is loading a ton, when I only want it to load the first 10.
To show what is happening with the output here is a pastebin https://pastebin.com/B7yitqvD.
In the output pay attention to the array that is above/before length - 1 load. You can see that it is rapidly returning an array with one more entry every time and adding it to the list. I did an extremely rough count of how many items are in my list too, and I got 440...so that roughly matches the 465 number.
The chain of events starts in a page that isn't the page with the list with this function - which initiates the sorting on the firebase functions side:
let a = this.http.get('https://us-central1-mane-4152c.cloudfunctions.net/sortDistance?text='+resp.coords.latitude+':'+resp.coords.longitude+':'+this.username);
this.subscription6 = a.subscribe(res => {
console.log(res + "response from firesbase functions");
loading.dismiss();
}, err => {
console.log(JSON.stringify(err))
loading.dismiss();
})
Here is the function on the page with the list that I think is capturing the entire sort for some reason. The subscription is being repeated as the firebase function sorts, I believe.
loadDistances() {
//return new Promise((resolve, reject) => {
let cacheKey = "distances"
let arr = [];
let mapped;
console.log("IN LOADDISTANCES #$$$$$$$$$$$$$$$$$$$$$");
console.log("IN geo get position #$$$$$$$5354554354$$$$$$$");
this.distancelist = this.af.list('distances/' + this.username, { query: {
orderByChild: 'distance',
limitToFirst: 10
}});
this.subscription6 = this.distancelist.subscribe(items => {
let x = 0;
console.log(JSON.stringify(items) + " length - 1 load");
items.forEach(item => {
let storageRef = firebase.storage().ref().child('/settings/' + item.username + '/profilepicture.png');
storageRef.getDownloadURL().then(url => {
console.log(url + "in download url !!!!!!!!!!!!!!!!!!!!!!!!");
item.picURL = url;
}).catch((e) => {
console.log("in caught url !!!!!!!$$$$$$$!!");
item.picURL = 'assets/blankprof.png';
});
this.distances.push(item);
if(x == items.length - 1) {
this.startAtKey4 = items[x].distance;
}
x++;
})
//this.subscription6.unsubscribe();
})
}
The subscription in loadDistances function works fine as long as I don't update the list from the other page - another indicator that it might be capturing the whole sort and listing it repeatedly as it sorts.
I have tried as as I could think of to unsubscribe from the list after I update...so then I could just load the list of 10 the next time the page with the list enters, instead of right after the update (over and over again). I know that firebase functions is in beta. Could this be a bug on their side? Here is my firebase functions code:
exports.sortDistance = functions.https.onRequest((req, res) => {
// Grab the text parameter.
var array = req.query.text.split(':');
// Push the new message into the Realtime Database using the Firebase Admin SDK.
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("profiles/stylists");
var promises = [];
// Attach an asynchronous callback to read the data at our posts reference
ref.on("value", function(snapshot) {
//console.log(snapshot.val());
var snap = snapshot.val();
for(const user in snap) {
promises.push(new Promise(function(resolve, reject) {
var snapadd = snap[user].address;
console.log(snapadd + " snap user address (((((((())))))))");
if(snapadd != null || typeof snapadd != undefined) {
googleMapsClient.geocode({
address: snapadd
}).asPromise()
.then(response => {
console.log(response.json.results[0].geometry.location.lat);
console.log(" +++ " + response.json.results[0].geometry.location.lat + ' ' + response.json.results[0].geometry.location.lng + ' ' + array[0] + ' ' + array[1]);
var distanceBetween = distance(response.json.results[0].geometry.location.lat, response.json.results[0].geometry.location.lng, array[0], array[1]);
console.log(distanceBetween + " distance between spots");
var refList = db.ref("distances/"+array[2]);
console.log(snap[user].username + " snap username");
refList.push({
username: snap[user].username,
distance: Math.round(distanceBetween * 100) / 100
})
resolve();
})
.catch(err => { console.log(err); resolve();})
}
else {
resolve();
}
}).catch(err => console.log('error from catch ' + err)));
//console.log(typeof user + 'type of');
}
var p = Promise.all(promises);
console.log(JSON.stringify(p) + " promises logged");
res.status(200).end();
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
});
What is weird is, when I check the firebase functions logs, all of this appears to only run once...but I still think the subscription could be capturing the whole sorting process in some weird way while rapidly returning it. To be as clear as possible with what I think is going on - I think each stage of the sort is being captured in an (N(N + 1))/2...starting at 1 and going to roughly 30...and the sum of the sorting ends up being the length of my list (with 1-10 items repeated over and over again).
I updated to angularfire2 5.0 and angular 5.0...which took a little while, but ended up solving the problem:
this.distanceList = this.af.list('/distances/' + this.username,
ref => ref.orderByChild("distance").limitToFirst(50)).valueChanges();
In my HTML I used an async pipe, which solved the sorting problem:
...
<ion-item *ngFor="let z of (distanceList|async)" no-padding>
...

Categories