How to make discord bot react to it's own reply? - discord.js

I was trying to make my bot to react an emoji to it's own reply.
so I tried
const message = interaction.reply({
ephemeral: true,
content: reply,
fetchReply: true,
})
message.react('👍🏽')
But message has type 'Promise<APIMessage | Message>', and method react doesn't exist on type 'APIMessage'.
Tried the exact same code on discord.js guide, still the same error.
Is there any way to solve this?
Thanks!
Full code:
Property 'react' does not exist on type 'APIMessage | Message<boolean>'.
Property 'react' does not exist on type 'APIMessage'.
Here's my code:
import { Message } from 'discord.js'
import { ICommand } from 'wokcommands'
export default {
category: 'Testing',
description: 'Replies with pong', // Required for slash commands
slash: true, // Create both a slash and legacy command
testOnly: false, // Only register a slash command for the testing guilds
// if interaction.reply didn't await would cause error
callback: async ({ interaction, message }) => {
const reply = 'pong'
// interaction is provided for slash commands
const replyMessage = await interaction.reply({
content: reply,
fetchReply: true,
})
replyMessage.react('👍🏽')
},
} as ICommand

You cannot react to an ephemeral interaction reply.

So after researching for hours, I found that my actual question is how to narrow down variable type to the type that has the method 'react'.
In this case it's message.
So changing the code to this works.
const replyMessage = await interaction.reply({
content: reply,
fetchReply: true,
})
if (replyMessage instanceof Message) {
replyMessage.react('👋🏼')
}
This article has pretty detailed information about type guard. FYI
https://rangle.io/blog/how-to-use-typescript-type-guards/

Related

Error when trying to add timestamps to comment section for social media web app using firebase

When trying to setup timestamps for a comment system for users on my social media web app I get the error:
"TypeError: firebase__WEBPACK_IMPORTED_MODULE_4__["default"].firestore.FieldValue.serverTimeStamp is not a function. (In 'firebase__WEBPACK_IMPORTED_MODULE_4__["default"].firestore.FieldValue.serverTimeStamp()', 'firebase__WEBPACK_IMPORTED_MODULE_4__["default"].firestore.FieldValue.serverTimeStamp' is undefined)"
This is the section of code where the errors are coming from:
const postComment = (event) => {
event.preventDefault();
db.collection("posts").doc(postId).collection("comments").add({
text: comment,
username: username.displayName,
timestamp: firebase.firestore.FieldValue.serverTimeStamp(),
});
setComment('');
}
If anyone can help I would greatly appreciate it.
screenshot:
![screenshot] (https://cdn.glitch.com/0f2dd307-0d28-4fe9-9ef9-db84277033dd%2FScreenshot%202021-07-18%20at%2011.36.14.png?v=1626604625641)
First off, there's a typo. It's serverTimestamp and not serverTimeStamp.
Also that firebase.js file (visible in screenshot) is where you initialize Firebase, then I'll say export the timestamp from there itself as in this answer.
import firebase from "firebase/app"
import "firebase/firestore"
const firestore = firebase.firestore()
const serverTimestamp = firebase.firestore.FieldValue.serverTimestamp()
export {firestore, serverTimestamp}
Now you can easily use serverTimestamp() directly in any other components.
The username seems to be a string:
db.collection("posts").doc(postId).collection("comments").add({
text: comment,
username, //username.displayName,
^^^^^^^^^^^^^^^^^^^^ remove this
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
It's "serverTimestamp()" there is no capital S.. But if that isn't the problem try importing the serverTimestamp inside your firebase.js or where ever you are initializing the firebase app
For the username field being invalid, it is because in firebase there is no username, it's displayName and it's inside the user object and not the username object
const postComment = (event) => {
event.preventDefault();
db.collection("posts").doc(postId).collection("comments").add({
text: comment,
username: user.displayName,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
setComment('');
}

stripe.redirectToCheckout parameter: price is not an accepted parameter react

I have an error I am running into on my stripe checkout in react... I have a button and when it is clicked, it is supposed to redirect to the stripe checkout page. However, I get the error
Uncaught (in promise) IntegrationError: Invalid stripe.redirectToCheckout parameter: price is not an accepted parameter.
this happens when I run this code -- this is my entire checkout.js page
import { loadStripe } from '#stripe/stripe-js';
import firebase from 'firebase';
import getStripe from './stripe';
const firestore = firebase.firestore();
export async function createCheckoutSession(){
// without uid
// return firestore.collection()
const checkoutSessionRef = await firestore.collection('profiledata').doc().collection('checkout_sessions').add(
// {price : 'price_1IGEdTKDPaWWeL1ymwWH5Ubb',
{price : '9.99',
success_url : window.location.origin,
// cancel_url: window.location.origin,
}
);
console.log("Before onSnapShot");
checkoutSessionRef.onSnapshot(async (snap) => {
const sessionid = snap.data();
console.log("Snap Data: ", snap.data());
console.log("Session ID: ", sessionid);
if (sessionid) {
console.log("Inside session ID: ", sessionid);
const stripe = loadStripe("pk_test_mystripeid")
stripe.redirectToCheckout(sessionid)
}
});
}
does anyone know why this is happening?
When creating a Checkout Session, line_items.price is a Price ID in the form of price_123, not an integer.
What is sessionid in this context? Is it a string or an object? Since you're using sessions it should be a string in the form of cs_test_123. What do your console.log's output? On what line is the error happening?
stripe.redirectToCheckout is an asynchronous method, but you're not catching any errors. Try something like this instead:
const result = await stripe.redirectToCheckout({
sessionId: session.id,
});
if (result.error) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer
// using `result.error.message`.
}
You also don't appear to be using loadStripe correctly, as it's also an asynchronous method that returns a promise: https://github.com/stripe/stripe-js#loadstripe.
There's a lot going on here and not much info (for instance, what does getStripe do?). I suggest you take some time to read the react-stripe-js docs to familiarise yourself with the library and how to use it: https://github.com/stripe/react-stripe-js

Amplify Graphql subscription: Works in query editor, not in app

I'm trying to set up a basic graphQL subscription to update a list of messages whenever one is crated, based off the recipes in Nader Dabit’s book and in this Medium post, and my subscription is just never firing in the client. What's strange is that in the query editor in Amplify’s Admin UI, the subscription fires as expected. In the app, however, it’s crickets. No errors, nothing.
As far as I can tell, the only thing unusual about my version is the typescript (and the //#ts-ignore’s that are required to account for the SDK’s lack of an Observable type).
Creating the message:
const handleMessageSubmit = async () => {
try {
const response = await API.graphql(
graphqlOperation(mutations.createMessage, {
input: {
authorID: userState.person.id,
text: message,
messageGroupID,
},
}),
);
} catch (err) {
console.log(err);
}
};
The subscription:
useEffect(() => {
const subscription = API.graphql(
graphqlOperation(subscriptions.onCreateMessage),
// #ts-ignore
).subscribe({
next: (event: any) => {
console.log('new message:', event);
},
error: (error: any) => {
console.log(error);
},
});
return () => {
console.log('unsubscribing');
// #ts-ignore
subscription.unsubscribe();
};
}, [messages]);
Turns out it was a problem with my imports.
Incorrect: import API from '#aws-amplify/api'
Correct: import { API } from '#aws-amplify'
The incorrect API worked just fine for other graphQL queries, but it was borking subscriptions.
I should also note that the failure was generating a AWSAppSyncProvider.ts:204 Uncaught (in promise) undefined error in the console, which I hadn't noticed earlier, though that didn't help much toward finding the solution.

React Extendable-Media-Recorder Unhandled Rejection (Error): There was no instance of an encoder stored with the given id

In a React project that is written in TypeScript, I use the 'extendable-media-recorder' along with the 'extendable-media-recorder-wav-encoder' (link to repo). This package is used to allow the user to record his/her voice. This works when the user records his/her voice only once but upon recording again and stopping the recording the following error is given:
Media encoder error
This error is given after the user stops the recorder the second time, so starting the recorder again does seem to work. I don't understand where this error comes from since the error and the way it occurs would indicate the error originates from stopping the recorder the second time. However, the code for stopping the recorder does catch potential errors whereas the error states that it is not caught.
The way I use the media-recorder in my code is the following:
import microphoneLogo from '../images/microphone.png'
import stopLogo from '../images/stop.png'
import { MediaRecorder, register } from 'extendable-media-recorder';
import { connect } from 'extendable-media-recorder-wav-encoder';
let mediaRecorder: any;
export default () => {
const [microphoneOn, setMicrophone] = useState<boolean>(false)
const [audioSetUp, setAudioSetUp] = useState<boolean>(false)
//Instantiate the mediaRecorder and create an encoder object.
async function setupAudioRecording() {
let port;
try {
port = await connect();
try {
await register(port);
} catch (e2) {
console.log('E2: ' + e2);
}
} catch (e1) {
console.log('E1: ' + e1);
}
const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(mediaStream, {
mimeType: 'audio/wav',
audioBitsPerSecond: 44100,
});
setAudioSetUp(true);
}
async function startRecording() {
try {
mediaRecorder.start();
} catch (e) {
console.log(e);
}
mediaRecorder.addEventListener('dataavailable', ({ data }: any) => {
put(data); //This method sends the blob data to the server to be processed
});
}
async function stopRecording() {
try {
await mediaRecorder?.stop()
} catch (e) {
console.log(e);
}
}
return (
<div className="input">
<input
className="input__microphone"
type="image"
src={microphoneOn ? stopLogo : microphoneLogo}
alt="Microphone"
onClick={handleClick}
/>
</div>
)
}
Does anyone know what causes this error and how I could fix it? Possible suggestions regarding other audio recording libraries (compatible with TypeScript) are also more than welcome.
Many thanks in advance.
I just stumbled upon this today. There was a bug in the code which is hopefully fixed in v6.1.56.
https://github.com/chrisguttandin/extendable-media-recorder/commit/8f639309b93061dd39233ee702c11515cb992d4d
It should now work as expected. Please feel free to open an issue on GitHub if you run into any further problems.

GraphQL Subscriptions with Express-GraphQL and React-Apollo

I've followed Apollo's docs for setting up GraphQL subscriptions on both the client and server, and though I'm 90% there, I can't figure out how to set up subscription channels and how to connect mutations to those channels so that whenever a mutation occurs, the server pushes the new data to the client. (For content, I'm making a Reddit clone where people post topics and others comment on it. So when you see "Topics" or "TopicList," think of those as posts.)
So far, I have set up Apollo Client for subscriptions successfully:
const wsClient = new SubscriptionClient('ws://localhost:3001/subscriptions', {
reconnect: true
});
const networkInterface = createNetworkInterface({
uri: '/graphql',
opts: {
credentials: 'same-origin'
}
});
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
networkInterface,
wsClient,
);
const client = new ApolloClient({
networkInterface: networkInterfaceWithSubscriptions,
dataIdFromObject: o => o.id
});
And I've set up my back-end for subscriptions as well. Here's my server.js file:
//===========================================================
//Subscription Managaer
//===========================================================
const pubsub = new PubSub();
const subscriptionManager = new SubscriptionManager({
schema: schema,
pubsub: pubsub
});
//=====================================
//WebSocket + Express Server
//=====================================
const server = createServer(app);
//setup listening port
server.listen(3001, ()=>{
new SubscriptionServer(
{
subscriptionManager: subscriptionManager,
onConnect: (connectionParams, webSocket) => {
console.log('Websocket connection established');
},
onSubscribe: (message, params, webSocket) => {
console.log("The client has been subscribed", message, params);
},
onUnsubsribe: (webSocket) => {
console.log("Now unsubscribed");
},
onDisconnect: (webSocket) => {
console.log('Now disconnected');
}
},
{
server: server,
path: '/subscriptions',
});
console.log('Server is hot my man!');
})
I know these are successful, because I get the "Websocket connection established" message logged in my terminal.
Next is the actual subscription - I've created a subscription schema type (just like queries and mutations):
const SubscriptionType = new GraphQLObjectType({
name: 'Subscription',
fields: () => ({
topicAdded: {
type: TopicType,
args: {repoFullName: {type: GraphQLString}}, //I don't understand what repoFullName is - I was trying to follow the Apollo docs, but they never specified that
resolve(parentValue, args){
return parentValue;
}
}
})
});
module.exports = SubscriptionType;
and incorporated it into my root schema. So when I check out GraphiQL, I see: this subscription available in the Docs side menu
My GraphiQIL UI showing the subscriptionSchema successfully
In my React component, I successfully 'subscribe' to it using Apollo's subscribeToMore method:
const TOPICS_SUBSCRIPTION = gql`
subscription OnTopicAdded($repoFullName: String){
topicAdded(repoFullName: $repoFullName){
id
}
}
`;
class TopicList extends Component {
componentDidMount() {
this.createMessageSubscription = this.props.data.subscribeToMore({
document: TOPICS_SUBSCRIPTION,
// updateQuery: (previousState, {subscriptionData}) => {
// const newTopic = subscriptionData.data.Topic.node
// const topics = previousState.findTopics.concat([newTopic])
// return {
// findTopics: topics
// }
// },
onError: (err) => console.error(err)
})
} //...
And I get my "The client has been subscribed" message logged into my terminal. But this is where I'm stuck. I've read about the SetupFunction for the SubscriptionManager, but that isn't included in Apollo's docs. And I can't find how to map a 'createTopic' mutation to this subscription so that whenever someone adds a new topic, it pops up in TopicList.
I realize this is really long, but I've been pulling my hair out tyring to figure out what's the next step. Any help would be much appreciated!! Thank you for reading!
Yes you are missing the setup function. You could take a look at this links GraphQL subscription docu or this example.
How it should work:
First you need the channel on which you publish the changed data. In your case it could look like this:
const manager = new sub.SubscriptionManager({
schema,
pubSub,
setupFunctions: {
topicAdded: (options, args) => ({ // name of your graphQL subscription
topicAddedChannel: { // name of your pubsub publish-tag
filter: (topic) => {
console.log(topic); //should always show you the new topic if there is a subscribed client
return true; // You might want to add a filter. Maybe for guest users or so
},
},
}),
},
});
And here you see the need of the args: {repoFullName: {type: GraphQLString}} argument in the subscription. If you want to filter the subscription dependent on the "repoName". Meaning that only the client with a subscription with the "repoName" as argument gets an update.
Next you need a place where you call the pubsub.publish function. In your case after the add topic mutation has passed. Could look like this:
...
const topic = new Topic(/* args */);
topic.save((error, topic) => {
if (!error) {
pubsub.publish("topicAddedChannel", topic);
}
...
});
....

Resources