Count messages from a channel - javascript

I would like to clean all my channels and and I'm getting there.
The problem is, it's very, very long ...
message.guild.channels.cache.forEach(c => {
if (c.isText()) {
let CompteurMessage = 0;
let CompteurSuppression;
c.messages.fetch().then(messages => {
messages.forEach(msg => {
msg.delete();
});
});
c.send(`Your server is the best, ${message.author}.`);
}
});
Do you have any idea how to go much faster, for example counting the number of messages in a channel ?
EDIT :
Now, I clone the channels but they change places ...
c.clone().then((clone) => {
clone.send(`Love ${message.author}.`);
const originalPosition = c.position;
c.delete();
clone.setPosition(originalPosition);
});
Channels n°3 and 4 change their place.
Thank you

Two ways to do this.
Cloning
You can clone the TextChannel using TextChannel.clone.
This stops you having the 14 day limitation using BulkDelete.
const newChannel = await message.channel.clone();
message.channel.delete();
newChannel.send('The channel has been purged.');
BulkDelete
You can delete all the messages in the last 14 days very easily.
await message.channel.messages.fetch();
const messageCount = message.channel.messages.cache.map(x => x).length;
message.channel.bulkDelete(messageCount, true);
Note: Not the most elegant solutions since it's late at night but this should help you out.

Related

How do you get a random voice channel ID?

I am making a discord chatbot, but something I would like it to do is to join a random voice channel. I have tried the following from a different example, but you need to specify a channel ID. Which doesn’t suit my needs.
const channel = message.guild.channels.get('voiceChannelID');
I've also tried this from Check if a channel is a voice channel but it also requires a specific channel ID.
const channelObject = message.guild.channels.cache.get('channel id here'); // Gets the channel object
if (channelObject.type === 'voice') return; // Checks if the channel type is voice
It would be greatly appreciated if you could answer with some code that would find a random voice channel.
You can fetch all channels, filter them by their type and use Collection#random() to pick a random one from the returned collection:
let channels = await message.guild.channels.fetch();
let voiceChannels = channels.filter(ch => ch.type === 'GUILD_VOICE');
let randomVoiceChannel = voiceChannels.random();
Please note that in discord.js v13, VoiceChannel#type is GUILD_VOICE instead of voice. For more info see this answer.
Update: If you're using discord.js v12, you can use the following:
let channels = message.guild.channels.cache;
let voiceChannels = channels.filter((ch) => ch.type === 'voice');
let randomVoiceChannel = voiceChannels.random();
... and it's probably time to upgrade :)
I've had to grab all of the channels and filter out the voice channels before, so I just grabbed that code and flipped it around and added some random to it.
What I did:
let channels = Array.from(message.guild.channels.cache.keys());
const c = channels.filter(v => message.guild.channels.resolve(v).isVoice() == true);
const index = Math.floor(Math.random() * c.length);
const randomVoiceChannel = c[index];
The first line grabs all of the channels in the server.
The 2nd line removes the non-voice channels.
And finally the last 2 lines generate a random index from the array and outputs a value.
const randomVoiceChannel = Array.from(message.guild.channels.cache.keys()).filter(v => message.guild.channels.resolve(v).isVoice() == true)
[Math.floor(Math.random() * Array.from(message.guild.channels.cache.keys()).filter(v => message.guild.channels.resolve(v).isVoice() == true).length)];
nifty 1-liner (please don't use this its incredibly unreadable I just thought it was funny)

firestore Check if id exists against an array of ids

I developing a simple chat applicaiton for my website using firebase firestore. where every chat session has an id
provided i have an array of ids
chat_sessions = ["q93XhadA9QQLu6X8yfZB", "YXEYISEI8b2iixCcP3VO", "GXrSZbtrmN5NcrtvjFYp"]
I want to get all document whose id is equal to any of the id's in the chat_sessions object using the code below.
return this.afs
.collection('chats', ref => ref.where('uid','in_array',chat_sessions)).snapshotChanges...
but I am not getting any results.
I come from a PHP/MYSQL background
the PHP equivalent of what i am trying to achieve will be sth like this in PHP
if(in_array(uid,chat_sessions)){
get(doc/uid)
}
can anyone help with the right query where we check for document id against a list of ids in an array? Thank You!
Thank you #frank van Puffelen. You were almost right. I should have used in instead of in_array
ref.where(firebase.firestore.FieldPath.documentId(),'in_array',chat_sessions)
did not work. Instead I replaced in_array with in :
ref.where(firebase.firestore.FieldPath.documentId(),'in',chat_sessions)
This worked! Thank you
Your query is:
ref.where('uid','in_array',chat_sessions)
This checks a field called uid in each document against the values of the chat_sessions.
It seems that instead you want to the check the ID of each document against the array, which you can do with:
ref.where(firebase.firestore.FieldPath.documentId(),'in_array',chat_sessions)
I found something else on firestore i.e "array-contains-any" for this case.
Maybe it's updated now.
UPDATE
Hi, firebase did some update recently, so for do it I found out this method
`
const [products, setProduct] = useState([]);
const ids = ['H11LlJsh3sObwORZhA0b','om9m0lU9HYWyOJZKvEdi','1AoHyHuSFcF01zoyXyTD','6xoBlxsRXUoyzBUcWl0F',
'GJqthlmBGZaFAJqtC2jK','QNT3PxMfhNGg1RZnuqcq','RZgGoFZHyDAYaVZJWxGk','g4UO5P0EgtEqJnawwhXX','gyrZm8p0cEgJdDvTuB1g','mrscldfeYlkaSF151MpI',]
useEffect(() => {
const saveFirebaseTodos = [];
ids.forEach((element) => {
fetchMyAPI()
async function fetchMyAPI() {
const q = query(collection(db, "a"), where('__name__', '==', element));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
saveFirebaseTodos.push(({id: doc.id, ...doc.data()}));
/*console.log(doc.id, " => ", doc.data());*/
if (ids.length == saveFirebaseTodos.length) {
setProduct(saveFirebaseTodos)
}
});
}})
}, [])`
In this way, you can check how many element in arrays you want (bypassing 10 elements limit of firebase).
Hope can help anyone :D

Why does client.guilds.cache.size only say "0" in my playing status even if it's in 2 servers?

i have seen many people who had trouble with client.guilds.size but I switched to the recently suggested client.guilds.cache.size. In my playing status, it only says "WATCHING my prefix | 0 servers." same happens for trying to fetch the member count and channel count.
let activities = [ `${client.guilds.cache.size} servers`, `${client.channels.cache.size} channels`, `${client.users.cache.size} users` ], i = 0;
setInterval(() => client.user.setActivity(`${prefix}help | ${activities[i ++ % activities.length]}`, { type: "WATCHING"}),`${process.env.INTERVAL}`)
This is the script I am using to achieve that.
I already have an Eval command, that returns 2 aswell.
I can't seem to find a solution to this somehow.
I hope you can help me, if you need anything, tell me!
Your issue is that your client has not logged in before you grab the guilds collection
You need to place that code inside your ready event.
client.on('ready', () => {
let activities = [ `${client.guilds.cache.size} servers`, `${client.channels.cache.size} channels`, `${client.users.cache.size} users` ], i = 0;
setInterval(() => client.user.setActivity(`${prefix}help | ${activities[i ++ % activities.length]}`, { type: "WATCHING"}),`${process.env.INTERVAL}`)
})

Using some sort of loop to add to a string

I’m trying to make a shop command that lists the items that I have added to the shop via another command. I tried to use a for loop to add to the string, but I had no luck with that because the values were undefined For some reason. At this point, I’ve switched to forEach in an attempt to try and make this work, but instead of each value being undefined, it only lists 1 of the 2 items saved in the database.
I am using Enmap to store the shop items.
I filter the shop items using the .filter() function which returns an Enmap (map)
Expected Behavior: The command properly lists all items in the shop (in this case 2 items) and all of their values
Actual Behavior: The embed only shows 1/2 of the items.
const Discord = require('discord.js');
module.exports = {
id: 'shop',
aliases: ['buythings', 'linkcoinshop', 'edward'],
channels: 'guild',
exec: async (call) => {
try {
let filter = await call.client.shopData.filter(find => {
return find.guildID === call.message.guild.id && find.forSale === true
});
if(filter.size === 0) return call.message.channel.send(`There are no items for sale right now.`)
let embedDesc = '';
console.log(filter)
filter.forEach(found => {
embedDesc += `**__${found.itemName}__** \nDescription: ${found.itemDesc} \nCost: ${found.itemCost} \nQuantity: ${found.itemQuan} \n\n`
})
const linkCoin = call.client.emojis.get('670675326837194782');
const shopEmbed = new Discord.RichEmbed()
.setTitle(`${linkCoin} LinkCoins Shop`)
.setColor('BLURPLE')
.setDescription(embedDesc);
//.setDescription(`🔷: **__Diamond Role__** \nDescription: Gives access to diamond only perks including special giveaways and more! \nCost: 1500${linkCoin} \nQuantity: ♾️ \n\n 💠: **__Diamond + Role__** \nDescription: Access to all perks that Diamond gets you, but with extra abilities such as your own personal voice chats. \n`)
call.message.channel.send(`Click on the reactions below to purchase.`)
call.message.channel.send(shopEmbed)
} catch(error) {
call.message.channel.send(`Oops! That was an error! The issue has been reported to the adminstration team`);
console.log(error);
}
}
};
If anybody has any suggestions of a better way to do this, or just a way to make this work, please let me know. Thanks!
Always create the minimum amount of code to illustrate your problem. It makes it easier for people to help you, and 8/10 times you will solve it yourself once you extract and isolate your problem.
Sounds like: how do I turn an array of objects into a string containing a list of the object properties?
Looks like you want to do this?
filter.reduce((prev, found) => `${prev}**__${found.itemName}__** \nDescription: ${found.itemDesc} \nCost: ${found.itemCost} \nQuantity: ${found.itemQuan} \n\n`, '')
Test case:
const filter = [
{
itemCost: 5,
itemName: 'snt',
itemDesc: 'desc',
itemQuan: 8
},
{
itemCost: 3,
itemName: 'another',
itemDesc: 'desc2',
itemQuan: 10
}
]
console.log(
filter.reduce(
(prev, found) =>
`${prev}**__${found.itemName}__** \nDescription: ${found.itemDesc} \nCost: ${found.itemCost} \nQuantity: ${found.itemQuan} \n\n`,
''
)
)
Output:
➜ t test.ts
**__snt__**
Description: desc
Cost: 5
Quantity: 8
**__another__**
Description: desc2
Cost: 3
Quantity: 10
This should work with Enmap. Per the API Docs:
enmap.reduce(fn, [initialValue]) ⇒ *
Identical to Array.reduce().
Turns out, there was nothing wrong with the filter or the forEach loop.
Although .reduce() works in my testing, I will continue to use forEach.
My problem was I was setting it all as the same key, which was causing Enmap to overwrite the values, hence only showing 1 of the things I added.
Thanks for all your help!
I will leave Josh's answer as the correct one since his method would work as well.

Return most recent time in series of creationTimes

Not entirely sure how I word the question but my problem is Im doing an api call that returns a bunch of messages that have a creation time, now what I want to do is only return the latest creationTime for the messages with the same date so say If I have 30 messages on the 15/03/2018 I want to grab the latest time, and discard the rest.. and do that for each set of messages with the same date
So what Ive done so far is..
using lodash I have gotten all the messages, filtered out all the ones with a certain type, and I have ordered them by creationTime so the latest being at the top and going down.. now my question is how can I then make an array of the latest times for each date??
this._activityServiceProxy.getAllItems(start, end).subscribe(result => {
// this.messages = result;
// console.log(result);
let loginUnfiltered = _.filter(result, {'title': 'LOGIN'});
let loginFiltered = _.orderBy(loginUnfiltered, {'creationTime': 'desc'});
console.log(loginFiltered);
});
any help would be appreciated!
Thanks
Use .map(...) to get at array of only the latest creationTime:
this._activityServiceProxy.getAllItems(start, end).subscribe(result => {
// this.messages = result;
// console.log(result);
let loginUnfiltered = _.filter(result, {'title': 'LOGIN'});
let loginFiltered = _.orderBy(loginUnfiltered, {'creationTime': 'desc'});
const creationTimes = loginFiltered.map(l => l.creationTime);
console.log(creationTimes);
const latestTime = creationTimes[0];
console.log(latestTime);
});
You can use Underscore's groupBy function to achieve this:
const groups = _.groupBy(loginFiltered, (login) => {
const asDate = new Date(login.creationTime);
asDate.setHours(0, 0, 0, 0);
return asDate;
});
Object.keys(groups).forEach((key) => {
console.log(groups[key][0]);
});
You group by the creationDate property but remove the time component so all days get grouped together. You then loop through the result and just take the first entry per day.
Note that this assumes your creationTime property is a string, as it came from an API. If it's already a date, you don't need the new Date line.

Categories

Resources