Discord.js bot random presence and status not showing nor changing when the bot starts - node.js

I've been trying to make a random bot presence/status change using Discord.js v13 that changes every 15 minutes. The problem I'm facing with my code is that the custom status and presence don't show when I first start the bot, I have to wait 15 minutes for it to show up and start changing.
Here is the code:
client.on("ready", async () => {
let servers = await client.guilds.cache.size
let servercount = await client.guilds.cache.reduce((a,b) => a+b.memberCount, 0 )
const statusArray = [
{
type: 'WATCHING',
content: `${servers} servers`,
status: 'online'
},
{
type: 'PLAYING',
content: `with my ${servercount} friends`,
status: 'online'
}
];
async function pickPresence() {
const option = Math.floor(Math.random() * statusArray.length);
try {
await client.user.setPresence({
activities: [
{
name: statusArray[option].content,
type: statusArray[option].type,
url: statusArray[option].url
},
],
status: statusArray[option].status
});
} catch (error) {
console.error(error);
}
}
setInterval(pickPresence, 1000*60*15);
});
Any ideas as to why it doesn't work instantly when I start the bot?

setInterval actually waits for the specified delay (15 minutes) before executing the code in the function for the first time. So all you need to do is simply add pickPresence() on the line before the setInterval.
pickPresence();
setInterval(pickPresence, 1000*60*15);

Related

RxJS non-blocking pooling

I'm working with Amazon Transcribe Service and in the SDK doesn't have any way to get when the transcription job has finished.
So we need to pool that information. Nowdays we have the following working code...
const jobid = nanoid();
await amazonTrascribeClient
.startTranscriptionJob({
IdentifyMultipleLanguages: true,
TranscriptionJobName: jobId,
Media: {
MediaFileUri: "s3://file-location",
},
Subtitles: {
OutputStartIndex: 1,
Formats: ["vtt", "srt"],
},
OutputBucketName: `file-location`,
OutputKey: `transcriptions/${jobId}/`,
})
.promise();
// HELP HERE:
const callIntervalFunc = () => {
const callInverval = setInterval(async () => {
const { TranscriptionJob } = await amazonTrascribeClient
.getTranscriptionJob({ TranscriptionJobName: jobId })
.promise();
if (
["COMPLETED", "FAILED"].includes(TranscriptionJob.TranscriptionJobStatus)
) {
clearInterval(callInverval);
// Persist in database etc...
}
}, 2000);
};
callIntervalFunc();
But as you can see it's extremally expensive and don't work in the concurrency mode since it's lock the thread. The objective is pool the information without block the event loop, some people said to use fire and forget, but I have no idea where I should start.

Manual approval task in step function - invoke through a script

I have a step function with an activity task that should wait for an input from a script that I will run from my terminal. If the script is invoked, the task that is waiting should get succeeded
Could someone provide examples on how to achieve this?
Any helpful documentations or referenced code links are appreciated.
Would I need an activity worker to invoke this?
Can a script running in my terminal invoke the lambda and mark it as succeeded?
node report-choice-step-success.js --stepfunction-arn <SFN-EXEC> --step-name ManualTask
Script report-choice-step-success.js
const main = () => {
let sfnClient;
const rolename = `StepFunctionExecuter-LOCAL`;
return getcreds({ accountId: '123456789012', region: 'us-east-1', rolename })
.then(params => {
sfnClient = new AWS.StepFunctions(params)
})
.then(() => startmystepfunction(sfnClient));
};
const startmystepfunction = (sfnClient) => {
const stateMachineArn = `arn:aws:states:us-east-1:123456789012:stateMachine:MYSTEPFUNCTION`;
const name = `Manual step`;
const executionParams = { name, stateMachineArn };
return sfnClient.startExecution(executionParams).promise()
.then(response => {
if (response && response.executionArn) {
print(`Started SFN execution for arn: ${response.executionArn}`);)
};
How should I modify the task so that it waits for a manual input so that it gets succeeded?
{
"Comment": "My state machine",
"StartAt": "Manual step",
"States": {
"ManualStep": {
"Type": "Task",
"Resource": "arn:aws:states:::activity:manualtask",
"End": true
}
}
}
I could get the Activity ARN from the executionARN using the getExecutionHistory method and filtered the scheduled activities.
Then I used that particular activityARN to getActivityTask and then used the sendTaskSuccess method to transition the step to succeeded.
sfnClient.getActivityTask(params).promise()
.then(data => {
var params = {
output: data.input.toString(),
taskToken: data.taskToken.toString()
};
sfnClient.sendTaskSuccess(params).promise()
}).catch(err => {
console.error(err);
console.error(err.stack);
});

only accept number discord.js

What I would like to eliminate in this code is that the program only reacts to numbers, not other characters, then it says "Not an appropriate value"
Can anyone help me with this?
e.g:
User: -clearr
Bot: How many messages do you want to delete?
User: asd
Bot: asd message successfully deleted!
This code:
module.exports = {
name: 'clearr',
description: "Clear messages!",
async execute(client, message, args) {
if(!args[0]) {
let filter = m => m.author.id === '365113443898097666'
message.channel.send(`How many messages do you want to delete?`).then(() => {
message.channel.awaitMessages(filter, {
max: 1,
time: 10000,
errors: ['time']
})
.then(message => {
message = message.first()
message.channel.bulkDelete(message);
message.channel.send (`\`${message} message\` successfully deleted!`)
.then(message => {
message.delete({ timeout: 5000 })
})
.catch(console.error);
})
})
}
}
}
Thank you very much in advance for your replies!
You have to use Number.isNaN(+var):
if(Number.isNaN(+args[0])) return message.reply('Please, specify how many messages do you want to delete!')

my api needs time to process a request, how can I use React + SWR to continue checking on the status?

I have an endpoint in my API that initiates a process on AWS. This process takes time. It can last several seconds or minutes depending on the size of the request. As of right now, I'm rebuilding my app to use swr. However, before this new update with swr I created a recursive function that would call itself with a timeout and continuously ping the API to request the status of my AWS process, only exiting once the response had the appropriate type.
I'd like to dump that recursive function because, well ... it was kinda hacky. Though, I'm still getting familiar with swr and I'm not a NodeJS API building master so I'm curious what thoughts come to mind in regards to improving the pattern below.
Ideally, the lowest hanging fruit would be to set up swr in some way to handle the incoming response and keep ping if the response isn't type: "complete" but I'm not sure how I'd do that. It pretty much just pings once and shows me whatever status it found at that time.
any help is appreciated!
tldr;
how can I set up swr to continually ping the API until my content is finished loading?
part of my API that sends out responses based how far along the AWS process is:
if (serviceResponse !== undefined) {
// * task is not complete
const { jobStatus } = serviceResponse.serviceJob;
if (serviceJobStatus.toLowerCase() === 'in_progress') {
return res.status(200).send({ type: 'loading', message: serviceJobStatus });
}
if (serviceJobStatus.toLowerCase() === 'queued') {
return res.status(200).send({ type: 'loading', message: serviceJobStatus });
}
if (serviceJobStatus.toLowerCase() === 'failed') {
return res.status(400).send({ type: 'failed', message: serviceJobStatus });
}
// * task is complete
if (serviceJobStatus.toLowerCase() === 'completed') {
const { serviceFileUri } = serviceResponse.serviceJob?.Data;
const { data } = await axios.get(serviceUri as string);
const formattedData = serviceDataParser(data.results);
return res.status(200).send({ type: 'complete', message: formattedData });
}
} else {
return res.status(400).send({ type: 'error', message: serviceResponse });
}
}
my current useSWR hook:
const { data: rawServiceData } = useSwr(
serviceEndpoint,
url => axios.get(url).then(r => r.data),
{
onSuccess: data => {
if (data.type === 'complete') {
dispatch(
setStatus({
type: 'success',
data: data.message,
message: 'service has been successfully generated.',
display: 'support-both',
})
);
dispatch(setRawService(data.message));
}
if (data.type === 'loading') {
dispatch(
setStatus({
type: 'success',
data: data.message,
message: 'service job is in progress.',
display: 'support-both',
})
);
}
},
}
);
After some digging around, figured I'd use the refreshInterval option that comes with swr. I am changing the state of a boolean on my component.
while the request is 'loading' the boolean in state is false.
once the job is 'complete' the boolean in state is set to true.
there is a ternary within my hook that sets the refreshInterval to 0 (default:off) or 3000.
const [serviceJobComplete, setServiceJobComplete] = useState(false);
const { data: serviceData } = useSwr(
serviceEndpoint,
url => axios.get(url).then(r => r.data),
{
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
refreshInterval: serviceJobComplete ? 0 : 3000,
...
// other options
}
);
helpful resources:
https://github.com/vercel/swr/issues/182
https://swr.vercel.app/docs/options

JMS Text Message on Oracle AQ from Nodejs

I'm trying to enqueue a jms text message on oracle AQ from nodejs.
const enqueue = async () => {
try {
await oracle.createPool();
const connection = await oracle.getConnection();
const jmsMessageType = "SYS.AQ$_JMS_TEXT_MESSAGE";
const queue = await connection.getQueue(bv.REQUEST_QUEUE_NAME, {payloadType: jmsMessageType});
const theRequest = new queue.payloadTypeClass({
text_length: request.length,
text_vc: request
});
await queue.enqOne(theRequest);
await connection.commit();
} catch(e){
console.error(e);
}
}
enqueue();
I can see that the message is queued in the AQ's table in oracle, but the consumer breaks when trying to dequeue the message:
oracle.jms.AQjmsException: JMS-120: Dequeue failed
at oracle.jms.AQjmsError.throwEx(AQjmsError.java:337)
at oracle.jms.AQjmsConsumer.jdbcDequeueCommon(AQjmsConsumer.java:1995)
at oracle.jms.AQjmsConsumer.receiveFromAQ(AQjmsConsumer.java:1374)
at oracle.jms.AQjmsConsumer.receiveFromAQ(AQjmsConsumer.java:1292)
at oracle.jms.AQjmsConsumer.receiveFromAQ(AQjmsConsumer.java:1270)
at oracle.jms.AQjmsConsumer.receiveNoWait(AQjmsConsumer.java:1068)
...
Caused by: java.lang.NullPointerException
at oracle.jms.AQjmsTextMessage.readTextMessageContainer(AQjmsTextMessage.java:328)
at oracle.jms.AQjmsTextMessage.<init>(AQjmsTextMessage.java:161)
at oracle.jms.AQjmsConsumer.jdbcDequeueCommon(AQjmsConsumer.java:1751)
... 19 more
Any ideas on the correct structure of the JMSTextMessage type?
Basically just had to get the definitions of the types and user UPPER CASE for the property names. Upper case is very important - it just ignores lower case property names.
SYS.AQ$_JMS_TEXT_MESSAGE
SYS.AQ$_JMS_HEADER
SYS.AQ$_JMS_USERPROPARRAY
SYS.AQ$_JMS_USERPROPERTY
Look here if you need more:
https://docs.oracle.com/cd/B10501_01/appdev.920/a96612/t_jms3.htm
const theRequest = new queue.payloadTypeClass(
{
HEADER: {
USERID: "YOUR_USER",
PROPERTIES: [
{
NAME: "JMS_OracleDeliveryMode",
TYPE: 100,
STR_VALUE: "2",
NUM_VALUE: null,
JAVA_TYPE: 27
},
{
NAME: "JMS_OracleTimestamp",
TYPE: 200,
STR_VALUE: null,
NUM_VALUE: new Date().getTime(),
JAVA_TYPE: 24
}
]
},
TEXT_LEN: request.length,
TEXT_VC: request
}
);

Resources