Remove reactions for a specific member from a specific message - discord.js

I want to remove member's reactions from specific messages when they leave the server for any reason. The below code is set up to work when someone sends a message, but that is just for testing, I will change that part later.
I first thought the code was deleting all the reactions found that its not removing all users, its removing the bots reactions, since they were the author of the post.
bot.channels.cache.get('786073099685593088').messages.fetch('842501905292066857').then((message) => {
const userId = message.author.id
const userReactions = message.reactions.cache.filter(reaction => reaction.users.cache.has(userId));
try {
for (const reaction of userReactions.values()) {
reaction.users.remove(userId)
}
} catch (error) {
console.log(error)
}
})
This one does nothing at all, but I tried to make the constant be outside so it wouldn't look at who authored the message the reactions are being removed from but rather who the author of the post that triggered the action (will later be changed to the member who left)
const author = message.author.id
bot.channels.cache.get('786073099685593088').messages.fetch('852625430950838302').then((message) => {
const userReactions = message.reactions.cache.filter(reaction => reaction.users.cache.has(author));
try {
for (const reaction of userReactions.values()) {
reaction.users.remove(author)
}
} catch (error) {
console.log(error)
}
})

Try Doing The Following And It May Fix Your Issue. This Will Remove The User(s) reactions.
reaction.users.remove(user.id)

Fixed my own issue with less code
bot.channels.cache.get('channelID').messages.fetch('messageID').then((message) => {
message.reactions.cache.filter(reaction => reaction.users.remove(member.user.id));
})

Related

Cannot get channels moving event in Discord audit log

I'm trying to log the Discord event when someone is moving any channel.
The channelUpdate event works almost like a charm and returning 2 events (two, because of when you moving one channel the rawPosition property is changing in the target's channel and in the channel you swiped the place). Except strange cases when you moved one channel and getting tone of events as if you moved all the server channels at ones. Weird thing, yep.
The problem is the "channelUpdate" event returns only oldChannel and newChannel but not the executor data (who and when).
I've tried to use guild.fetchAuditLogs({ type: 14, limit: 1 }) but looks like it's not returning changing position events. One gets the feeling Discord's log engine is not logging this event OR I'm looking in wrong place. Also tried type 11 and even NULL with no luck on finding rawPosition prop changing.
Please, help me to find the way how to log WHO is changing the channels position or tell me it's not possible at the time.
Some code here:
const Discord = require('discord.js');
const client = new Discord.Client({ shards: 'auto'});
const { prefix, token, witaitoken , guildID, DBUser, DBPass } = require('./config.json');
client.on('ready', async () => {
console.log(`Logged in as ${client.user.tag}!`);
client.user.setActivity(`Star Citizen`, { type: 'PLAYING' });
});
client.on('channelUpdate', (oldChannel, newChannel) => {
if (oldChannel.rawPosition !== newChannel.rawPosition) {
oldChannel.guild.fetchAuditLogs({ limit: 10 })
.then( (audit) => {
const log = audit.entries;
if (!log) return;
fs = require('fs');
fs.appendFile('audit.txt', JSON.stringify(log), function (err) {
if (err) return console.log(err);
});
})
}
});
client.login(token);
client.on("error", (e) => console.error(e));
client.on("warn", (e) => console.warn(e));
client.on("debug", (e) => console.info(e));

Facebook Pixel fbq('track') isn't working in production

I'm injecting the pixel script in the <Head /> and trying to use the fbq("track") function in a contact form's onSubmit handler. A dumbed down version of the handler:
const handleSubmit = async e => {
e.preventDefault();
try {
// send form data to server, if successful, proceed...
window.fbq("track", "Contact");
} catch (error) {
// handle error
}
};
In development, everything looks as expected: the Facebook Pixel Helper shows that the "Contact" event was successfully tracked.
However, in production, that event doesn't get tracked. The Pixel Helper registers a "Button Click Automatically Detected," but the explicit "Contact" event is not tracked. Edit: The title of my question may be a bit of a misnomer as the fbq("track", "PageView") call in the <Head /> is working normally.
No errors, it simply doesn't seem like it's firing.
Any ideas as to what I'm doing wrong would be much appreciated 🙏🏼
Solved.
Perhaps a bit more code context was needed for the issue. I still don't exactly know why this fix worked, but in case anybody stumbles across this in the future, here's what did it for me...
Additional context, the form data was posted to the server via fetch() and window.fbq("track") was chained into a .then() callback like so:
const handleSubmit = async e => {
e.preventDefault();
try {
await fetch("/contact", {options})
.then(res => res.json())
.then(json => {
if (json.success) {
// handle success
window.fbq("track", "Contact");
}
});
} catch (error) {
// handle error
}
};
The solution was simply to move the fbq() out of the callback:
const handleSubmit = async e => {
e.preventDefault();
try {
await fetch("/contact", {options})
.then(res => res.json())
.then(json => {
if (json.success) {
// handle success
}
});
} catch (error) {
// handle error
return;
}
window.fbq("track", "Contact");
};

Is there a way to react to every message ever sent with discord.js

I wanna use an bot to react to every single message in an channel using discord.js f.e. i got an emoji contest channel and i wanna ad an ✅ and an ✖ reaction on every post in there
ofc, all the unnecesary messages are cleaned up so that there are like 50 messages
Fetch the messages already sent in a channel with TextChannel.fetchMessages().
Iterate through the Collection.
Add reactions with Message.react().
When a new message is sent in the channel, you should also add the reactions.
const emojiChannelID = 'ChannelIDHere';
client.on('ready', async () => {
try {
const channel = client.channels.get(emojiChannelID);
if (!channel) return console.error('Invalid ID or missing channel.');
const messages = await channel.fetchMessages({ limit: 100 });
for (const [id, message] of messages) {
await message.react('✅');
await message.react('✖');
}
} catch(err) {
console.error(err);
}
});
client.on('message', async message => {
if (message.channel.id === emojiChannelID) {
try {
await message.react('✅');
await message.react('✖');
} catch(err) {
console.error(err);
}
}
});
In this code, you'll notice I'm using a for...of loop rather than Map.forEach(). The reasoning behind this is that the latter will simply call the methods and move on. This would cause any rejected promises not to be caught. I've also used async/await style rather than then() chains which could easily get messy.
According to https://discord.js.org/#/docs/main/stable/class/TextChannel
you can use fetchMessages
to get all messages from a specific channel, which then returns a collection of Message
Then you can use .react function to apply your reactions to this collection of message by iterating over it and calling .react on each.
Edit:
channelToFetch.fetchMessages()
.then(messages => {
messages.tap(message => {
message.react(`CHARACTER CODE OR EMOJI CODE`).then(() => {
// Do what ever or use async/await syntax if you don't care
about Promise handling
})
})
})

Firebase Redux update not triggering render

My react app isn't re-rendering when updating my data. I think its related to updating the state with an array, but I can't quite figure out exactly what is causing the issue.
Here is my action
export const fetchChannels = uid => dispatch => {
db.ref(`chat/userchats/${uid}`).on("value", snapshot => {
if (snapshot.exists()) {
let userchats = snapshot.val()
let channels = []
Object.values(userchats).map(function(chat, i) {
db.ref(`chat/chats/${chat}`).on("value", snap => {
let chatData = snap.val()
channels.push(chatData)
})
})
dispatch({
type: "FETCH_CHANNELS",
payload: channels
})
}
})
}
And my reducer
case 'FETCH_CHANNELS':
return {
...state,
channels:action.payload
}
Since channels is set to an empty array, I'm guessing that redux is not recognizing this as a change of state? But can't quite get the right fix.
Edit
I console.logged snapshot.exists() prior to the if statement, and that came back as True.
I also logged channels prior to the dispatch and this seems to be where there is an issue. channels does not return the updated values, but rather the previous values when updated.
Here is the code I am using to add the channel item to userchats. The action I am looking for is that a user creates a channel, which creates a channel with the member uid's and chat information. That information is then pushed to the userchats directory and is pushed in to those users channels.
export const createChannel = (name,members,purpose) => dispatch =>{
db.ref(`chat/chats/`).push({name,members,purpose})
.then(result=>{
let key = result.getKey()
members.map(function(member,i){
db.ref(`chat/userchats/${member}`).push(key)
.then(result=>{})
.catch(error=> {
console.log(error)
})
})
})
.catch(error => {
console.log(error);
})
}
When I console.log at the end of the createChannel(), and console.log prior to the channels dispatch, in fetchChannel(). When I create the channel, it shows that fetchChannels updates first, and createChannel() second, even though createChannel() is called first, and fetchChannel() is simply listening for an update.
Here is the element I am attempting to rerender when props is updated
{Object.keys(this.props.channels).map(function(item,i){
return(
<Channel channel={this.props.channels[item].name} key={i} notification={''} selected={this.state.selected} item={item} onClick={()=>this.selectChannel(item)}/>
)
},this)}
Thanks for the responses Josh.
I was able to solve my issue. I had to switch the order of database entries. Because the chats push was triggering the userchats update before it was able to create the channels entry. Creating a key and using that to create userchats entries first solved the update issue.
export const createChannel = (name,members,purpose) => dispatch =>{
let newKey = db.ref().push().getKey()
members.map(function(member,i){
db.ref(`chat/userchats/${member}`).push(newKey)
.then(result=>{})
.catch(error=> {
console.log(error)
})
})
db.ref(`chat/chats/${newKey}`).set({name,members,purpose})
}

AsyncStorage complains of array and object incompatibility during mergeItem

I'm trying to figure out why AsyncStorage in a React Native app refuses to do a mergeItem with my data. My function looks like this:
const arrToObj = (array) =>
array.reduce((obj, item) => {
obj[Object.keys(item)[0]] = Object.values(item)[0]
return obj
}, {})
export const addThingToThing = async (title, thing) => {
try {
let subThings = []
let things = {}
await AsyncStorage.getItem(THINGS_STORAGE_KEY)
.then((things) => {
let subThings = []
Object.values(JSON.parse(decks))
.map((thing) => {
if (Object.keys(thing)[0] === title) {
subThings = [...Object.values(thing)[0].subThings, subThing]
}
})
return { decks, subThings }
})
.then(({ decks, subThings }) => {
const obj = {
...arrToObj(JSON.parse(things)),
[title]: {
subThings
}
}
console.log(JSON.stringify(obj))
AsyncStorage.mergeItem(THINGS_STORAGE_KEY,
JSON.stringify(obj))
})
} catch (error) {
console.log(`Error adding thing to thing: ${error.message}`)
}
}
When I do the thing that executes this I get:
13:35:52: {"test":{"subThings":[{"one":"a","two":"a"}]},"test2":{"title":"test2","questions":[]}}
13:35:55: [Unhandled promise rejection: Error: Value [{"test":{"title":"test","subThings":[]}},{"test2":{"title":"test2","subThings":[]}}] of type org.json.JSONArray cannot be converted to JSONObject]
Which is confusing, because when the data is printed out it's an object with {...}, but AsyncStorage shows an array with [...]. Is there something I'm missing? This seems pretty dumb to me and I can't seem to figure out how to get RN to play nice.
PS. IMO the structure of the data is gross, but it's what I'm working with. I didn't decide on it, and I can't change it.
I recall working with AsyncStorage, and it is fundamentally different than localStorage because it returns Promises.
Your code looks fine which makes this super confusing, but I am suddenly suspecting that the problem may be due to a missing await keyword.
try:
.then(async ({ decks, subThings }) => {
const obj = {
...arrToObj(JSON.parse(things)),
[title]: {
subThings
}
}
console.log(JSON.stringify(obj))
// We are adding await here
await AsyncStorage.mergeItem(THINGS_STORAGE_KEY, JSON.stringify(obj))
})
It may be a classic "not waiting for the Promise to resolve" before moving on, async problem. Don't delete this question if so. It will be helpful for others including probably myself in the future.
Here's what I think is happening:
JavaScript throws AsyncStorage.mergeItem() into the function queue
There is no await for this function that returns a Promise
The interpreter does not wait for it to resolve and immediately moves to the next line of code
There is no next line of code, so it returns from the then() block 0.1ms later (keep in mind it is implicitly doing return undefined which inside an async function is the same as resolve(undefined), with the point being that it is trying to resolve the entire chain back up to await AsyncStorage.getItem(THINGS_STORAGE_KEY)
obj gets garbage collected 0.1ms after that
AsyncStorage.mergeItem() observes a falsy value where it was expecting obj, but I don't actually know for certain. It may not be doing step 5 or 6 and instead detecting that mergeItem is still pending when it tries to resolve the getItem chain, either way:
AsyncStorage then gives a confusing error message
What I ended up using to handle the promises correctly is:
export const addThingToThing = async (title, thing) => {
try {
AsyncStorage.getItem(THINGS_STORAGE_KEY, (err, things) => {
let subThings = []
Object.values(JSON.parse(decks))
.map((thing) => {
if (Object.keys(thing)[0] === title) {
subThings = [...Object.values(thing)[0].subThings, subThing]
}
})
const obj = {
[title]: {
title,
subThings
}
}
console.log(JSON.stringify(obj))
AsyncStorage.mergeItem(THINGS_STORAGE_KEY,
JSON.stringify(obj))
})
} catch (error) {
console.log(`Error adding thing to thing: ${error.message}`)
}
}
I saw some other similar examples online that used .done() that looked identical to what I'd done other than that call. That may have been something to try as well, but this worked for me.

Resources