How can I make a reactionCollector on a remove event work?
Similar to this question, but the solution listed was not my solution.
msg.channel.send("Hello World")
.then(async function (message) {
await message.react('✅')
const filter = (reaction, user) => {
return reaction.emoji.name === '✅'
};
const collector = message.createReactionCollector(filter, {time: time, dispose: true});
collector.on('remove', (reaction, reactionCollector) => {
console.log("React removed")
});
collector.on('collect', (reaction, reactionCollector) => {
console.log("React added")
});
});
The linked question solution was to add dispose: true to the collectorOptions, this hasn't worked for me. "React removed" is never logged.
Remove is only supported in v12+. I was using v11.
Related
Please help me, I don't know what this warning is. I'm trying to render a chat room with chat messages between two users from Cloud Firestore database. This warning throws when I render the ChatRoom screen. This worked for me without warnings on android on my previous project, not here I run on iOS. React version 17.0.2, react native version 0.66.4
full warning
EventEmitter.removeListener('keyboardDidHide', ...): Method has been deprecated. Please instead use `remove()` on the subscription returned by `EventEmitter.addListener`.
code
const ChatRoom = ({ navigation, route }) => {
React.useEffect(() => {
async function fetch() {
const response = await getUserData(receiverId);
setChatImage(response.userimg);
const chat = await getChat(user.uid, userid);
if (chat) {
const unsubscribe = firestore()
.collection("Messages")
.where("chatid", "==", chat)
.onSnapshot((querySnapshot) => {
const messages = querySnapshot
.docChanges()
.filter(({ type }) => type === "added")
.map(({ doc }) => {
const message = doc.data();
return {
...message,
createdAt: message.createdAt.toDate(),
};
})
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
appendMessages(messages);
});
return () => unsubscribe();
}
}
fetch();
}, []);
const appendMessages = React.useCallback(
(messages) => {
setMessages((previousMessages) =>
GiftedChat.append(previousMessages, messages)
);
},
[messages]
);
const handleSend = async (messages) => {
// if there are no chats, create one
const chat = await getChat(user.uid, userid);
let chatid;
if (!chat) {
chatid = await createChat(user.uid, userid);
}
// add the messages
const writes = messages.map((m) =>
firestore()
.collection("Messages")
.add({
...m,
sent: true,
received: false,
senderid: user.uid,
receiverid: userid,
chatid: chat ? chat : chatid,
})
);
await Promise.all(writes);
};
return (
<View>
<GiftedChat
messages={messages}
user={{_id: user.uid}}
onSend={handleSend}
showAvatarForEveryMessage={true}
/>
</View>
);
};
export default ChatRoom;
As I don't see any manual EventListener manipulation in your code, I assume you can't do anything.
It probably comes from a library/package you're using elsewhere, in this case, something that has to do with hiding the keyboard ('keyboardDidHide' in the error...).
Note that it is only a warning and only a deprecation, meaning it still works but is not the recommended way anymore. Try to track down what library is causing this and watch for their issues in GitHub.
Other than that, there's nothing much you can do and your code will continue to work.
EDIT: Digging further with what you gave, I found the docs of the React Native's Keyboard component stating exactly what is said in the error.
Get the listener returned by addListener, and use .remove() on it.
Example code:
const myListener = Keyboard.addListener("someListener", () => {
// do things here
});
// do some more things
// once you're done, call this
myListener.remove();
I have the same issue. For now I am just disabling it with this in my App.tsx file.
LogBox.ignoreLogs(['EventEmitter.removeListener'])
I have exactly the same problem, but based on the expo-secure-store library it seems that the latest version is not yet compatible with expo sdk 45 updates, the only thing I could do is ignore the Wharing
as mentioned before #jose garcia
LogBox.ignoreLogs(['EventEmitter.removeListener'])
I am trying this JavaScript ticket code in my discord bot, but the error TypeError: Cannot read property 'guild' of undefined keeps showing up. I don't understand why. Could someone guide me in the correct direction?
module.exports = {
name: "ticket",
aliases: [],
permissions: [],
description: "Open a ticket!",
async execute(message, args, cmd, client, discord) {
const channel = await message.guild.channels.create(`ticket: ${message.author.tag}`);
channel.setParent("820276801652916270");
channel.updateOverwrite(message.guild.id, {
SEND_MESSAGE: false,
VIEW_CHANNEL: false,
});
channel.updateOverwrite(message.author, {
SEND_MESSAGE: true,
VIEW_CHANNEL: true,
});
const reactionMessage = await channel.send("Thank you for contacting support!");
try {
await reactionMessage.react("🔒");
await reactionMessage.react("⛔");
} catch (err) {
channel.send("Error sending emojis!");
throw err;
}
const collector = reactionMessage.createReactionCollector(
(reaction, user) => message.guild.members.cache.find((member) => member.id === user.id).hasPermission("ADMINISTRATOR"),
{ dispose: true }
);
collector.on("collect", (reaction, user) => {
switch (reaction.emoji.name) {
case "🔒":
channel.updateOverwrite(message.author, { SEND_MESSAGES: false });
break;
case "⛔":
channel.send("Deleting this channel in 5 seconds!");
setTimeout(() => channel.delete(), 5000);
break;
}
});
message.channel
.send(`We will be right with you! ${channel}`)
.then((msg) => {
setTimeout(() => msg.delete(), 7000);
setTimeout(() => message.delete(), 3000);
})
.catch((err) => {
throw err;
});
},
}
Using the info in your comment, your command handler was set up incorrectly. When you put execute(message.args), the code tried to pass the args property of your message argument which returns undefined.
Instead, you should use execute(message, args) to properly pass in each argument for your command.
I have a Firestore listener to grab chat messages for which I use a limit of 10. Everything works well on first load. However, when there are 10 messages and the limit is reached, the chat does not accept new messages. It is as if the limit function accepts the first 10 messages and then will not take any more when I need it to be updated with every new message. Here's the listener code:
startChat() {
document.getElementById("myForm").style.display = "block";
const ref = firebase
.firestore()
.collection("Chats")
.doc(this.state.uid)
.collection("Messages");
const query = ref.orderBy("timestamp", "asc").limit(10);
this.unsubFromMessages = query.onSnapshot(
(snapshot) => {
console.log(
snapshot.docs.map((doc) => {
return doc.data();
})
);
if (snapshot.empty) {
console.log("No matching documents.");
firebase
.firestore()
.collection("Chats")
.doc(this.state.uid)
.set({
name: this.state.displayName,
uid: this.state.uid,
email: this.state.email,
})
.then(console.log("info saved"))
.catch((error) => {
console.log("Error saving info to document: ", error);
});
}
snapshot.docChanges().forEach((change) => {
if (change.type === "removed") {
console.log(change.doc.data().content);
} else if (change.type === "added") {
this.setState((state) => {
const messages = [
...state.messages,
{ id: change.doc.id, body: change.doc.data() },
];
return {
messages,
};
});
setTimeout(this.scrollToBottom(), 2000);
}
});
},
(error) => {
console.log(error);
}
);
}
Does anyone know why this is happening and how to make the limit function accept new messages? Thanks.
orderBy("timestamp", "asc")
With this order, you will be getting back the 10 oldest messages. New messages will have a higher timestamp, and so a new 11th message will not be part of the oldest 10.
If instead you want the 10 newest messages, use descending order:
orderBy("timestamp", "dsc")
Nicholas's answer does, indeed, solve the issue. However, it does not solve the issue of messages loading in the wrong order when the chat is closed, then started and the previously entered messages are shown. One way to solve this issue is adding reverse() to docChanges() like this: snapshot.docChanges().reverse().forEach. Hope this might help someone. Happy coding, everyone. Stackoverflow rocks!
I'm making a support command: you type a command, the bot send you a message and then you reply to that message. I've used the awaitMessages function but it doesn't work.
case `support` : {
message.channel.send("What's your problem?");
let filter = m => m.author.id === message.author.id;
let msg = await message.channel.awaitMessages(filter, {maxMatches: 1});
message.channel.send("Your problem is: " + msg.first().content);
break;
}
To use .then() you need to return a Promise. This is a basic example of how you can use Promise:
const myFunction = () => {
return new Promise((resolve, reject) => {
if(taskIsSuccesFullyDone)
{
resolve(true); // Pass anything
}else{
reject('Something went wrong!');
}
});
}
myFunction().then(() => {
// Task is succesful completed.
// Do anything
})
.catch(error => console.log(error.message || error));
In your case, your code would look something like this:
function support_message() {
return new Promise((resolve, reject) => {
message.author.send(`Hello, <#${message.author.id}>, reply to this message explaining the problem you have.`)
.then(message => resolve(message))
.catch((error) => {
message.reply("I can't send you messages, be sure that you allow direct messages from unknown users to use this command.");
reject(error);
})
});
}
case `staff-support` : {
support_message().then(message => {
// We got the message object passed from the resolved Promise
// Do anything here
})
.catch((err) => {
// There was a problem!
// Do anything here.
});
break;
}
I have set up Auth0 using custom inputs with react and hooks. I am trying to protect my routes so that the user directs where they are based on our API and what information is provided back from that. In order to do that I am setting the user data inside of the setSession, but the item is coming back undefined/ has to do with auth0Client.client.userInfo not finishing before setSession function is done.
const setSession = async authResult => {
const expiresAt = JSON.stringify(
authResult.expiresIn * 1000 + new Date().getTime()
)
localStorage.setItem('access_token', authResult.accessToken)
localStorage.setItem('id_token', authResult.idToken)
localStorage.setItem('expires_at', expiresAt)
localStorage.setItem('auth', true)
setAuthenticated(true);
await auth0Client.client.userInfo(authResult.accessToken, (err, user) => {
localStorage.setItem('user', JSON.stringify(user))
setUser(JSON.stringify(user));
})
}
I call setSession in handle authentication:
const handleAuthentication = () => {
console.log("auth0Client", auth0Client);
if (typeof window !== 'undefined') {
auth0Client.parseHash(async (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
await setSession(authResult);
history.replace('/');
} else if (err) {
console.log(err)
return err;
}
})
}
}
I have tried return the value and calling it this way instead:
await setSession(authResult).then(
() => history.replace('/')
)
Either way, the first time it accesses the route that I want it has a null value for user.
I have put a complete mock repo here. You can create accounts and if you create extra accounts use the same email with +modifier/ example test+1#test.com
https://github.com/Sbphillips19/ManualAuth0Flow
I'm sure it's something simple, I have just tried probably 100 different ways over and over again and can't see it.
I'd give Jim and Jfriend00 the answer, but since it's a comment and I can't here is the answer using Bluebird:
await new Bluebird(function (resolve, reject) {
auth0Client.client.userInfo(authResult.accessToken, (err, user) => {
if (err) return reject(err)
resolve(user);
})
}).then(
data =>
{
localStorage.setItem('user', JSON.stringify(data))
setUser(JSON.stringify(data));
}
)
It looks like auth0 has talks about converting all their functions to be able to use async await, but for now bluebird will do!