how can i send custom sms message with twilio api via express - javascript

so im trying to make a simple function in a web that has input and button , and when i click the button twilio api send message with the body of input value life if input is hello the message sent is hello, this is the index.js file which is include the simple function that gonna send the message and i don't know if i should use POST method or get just look
let input = document.querySelector("input").value;
document.querySelector("button").addEventListener("click", whatTheHell);
let whatTheHell = () => {
fetch("/sendSms")
.then((res) => res.json())
.then((res) => console.log(res))
.catch((err) => console.log(err));
};
and this the express.js file that contain the twilio api that gonna send the sms
const express = require("express");
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const accountSid = process.env.accountSid;
const authToken = process.env.authToken ;
const app = express();
const client = require("twilio")(accountSid, authToken);
app.use(express.json());
app.use(express.static("public"));
app.get("/sendSms", (req, res) => {
client.messages
.create({
body: "message from me",
messagingServiceSid: "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
to: "NUMBER",
})
.then((message) => {
res.json({ message: message }).done();
});
});
app.listen(3000, () => {
console.log("Server Started");
});
so what i want here in body: "message from me" is to be something like this body : user.input or something like that , i tried using post method and did req.body.msg and msg is input.value but it dont accept post method .

Twilio developer evangelist here.
I would recommend making this a POST request. You need to update a few things to get your input from the front end to the server. Let's start with the front end.
Instead of getting the input's value straight away, you should wait until the button is clicked to get the value. Then, when it is clicked, you need to make a POST request with the message you want to send in the body of the request. One way to do that is to JSON stringify an object of data.
let input = document.querySelector("input");
document.querySelector("button").addEventListener("click", whatTheHell);
let whatTheHell = () => {
const message = input.value;
fetch("/sendSms", {
method: "POST",
body: JSON.stringify({ message: message }),
headers: {
'Content-Type': 'application/json'
}
})
.then((res) => res.json())
.then((res) => console.log(res))
.catch((err) => console.log(err));
};
Now, on the server side we need to update your endpoint to receive POST requests. You are already using the express JSON parsing middleware, so the message will be available as req.body.message. We can then use that in the request to Twilio.
const express = require("express");
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const accountSid = process.env.accountSid;
const authToken = process.env.authToken ;
const app = express();
const client = require("twilio")(accountSid, authToken);
app.use(express.json());
app.use(express.static("public"));
app.post("/sendSms", (req, res) => {
const message = req.body.message;
client.messages
.create({
body: message,
messagingServiceSid: "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
to: "NUMBER",
})
.then((message) => {
res.json({ message: message });
})
.catch((error) => {
console.error(error);
res.status(500).json({ error: error.message });
});
});
app.listen(3000, () => {
console.log("Server Started");
});
And that should work.

You can use a query paramater to send the message to your express server and retrieve them in your server as explained here: How to get GET (query string) variables in Express.js on Node.js?.
If you make your method a post method when sending it you also need to make your express from get to post like so: app.get() -> app.post()

Related

How to send data (a url string) in express to backend from frontend?

I am trying to build a wikipedia web scraper api and this is my code:
const app = express()
const port = 3000
const url = "https://en.wikipedia.org/wiki/Yeti_Airlines_Flight_691"
axios.get(url).then(async (res) => {
try {
if (res.status == 200) {
const result = // Doing cheerio stuff here
app.get('/', (req, res) => {
res.status(200).send(result)
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
}
} finally {
//
}
});
How can I send url dynamically to backend using express and do some stuff then send result back to frontend?
Client side:
This is a function you define in your frontend. You set a request link, which must be known here on client side and server side. Thus take something like /request. Then use axios to send a request to the server. You can pass any parameters with „dynamic“ Information as you called it. The server will receive these informations and can handle them.
const getData = () => {
// insert your server url here instead, with the /request at the end
const requestLink = `http://localhost:3001/request`;
axios
.get(requestLink, {
params: { url: "wikipedia.de/test123" },
})
.catch((error) => {
// here you can implement error handling
console.log(error);
})
.then((res) => {
// print result, received from the server
console.log(res);
});
};
Server side:
The backend is going to wait for a request to the defined link /request.
If he receives such a request, he is executing the code. The req variable contains your dynamic data, such as the wiki url.
Use res.json to send data back to your frontend.
app.get(`/request`, (req, res) => {
// do something with the request here
console.log(req.query);
// send result to the frontend
res.json({
status: "This could be an answer to the frontend.",
});
});

oauth authorization and token not functioning as expected in JS script

My application uses the Zoom API with OAuth.
The process is well put in the zoom developer docs and I followed them
I created a zoom app in the developer's account and got the clientID and clientSecret.
First we need to get the Authorization code from "https://zoom.us/oauth/authorize". With this code we can get the access token from "https://zoom.us/oauth/token". Pretty straight forward. I tried it on Postman and all the APIs work.
My JS code below doesn't work and keeps failing to do this task.
const express = require('express');
const axios = require('axios');
let token = null;
const app = express();
const clientId = 'ADqR4l7KTfMmXXXXXXXX';
const clientSecret = 'mhVytefIFS4fSqQ3XXXXXXXXXX';
const redirectURL = 'http://localhost:3000/oauth-callback'
app.get('/', (req, res) => {
res.redirect(`https://zoom.us/oauth/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectURL}`);
});
app.get('/oauth-callback', (req, res) => {
const body = {
client_id: clientId,
client_secret: clientSecret,
code: req.query.code
};
const opts = { headers: { accept: 'application/json' } };
axios.post(`https://zoom.us/oauth/token`, body, opts).
then(res => res.data['access_token']).
then(_token => {
console.log('My token:', token);
token = _token;
res.json({ ok: 1 });
}).
catch(err => res.status(500).json({ message: err.message }));
});
app.listen(3000);
console.log('App listening on port 3000');
zoom dev acct:
zoom dev account
Error message:
Error message
How can I get the access token? Please help me find my errors in the code.

Twilio throws access denied error when trying to access by using fetch method

Good Evening,
I am experimenting with using APIs and rendering that data in an EJS template.
I am trying to get a specific message from Twilio using the URL.
I downloaded node-fetch so I can use fetch with nodejs.
If I use the URL Twilio wants me to use it says access denied.
URL: https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/Messages/{Message Id};
If I put my auth token in before or after the account sid, it says that it cant find the message.
URL: 'https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/{Auth token}/Messages/{Message Id}';
I have added my nodejs code below, any help is much appreciated.
/* Imports */
var express = require('express');
var router = express.Router();
var path = require('path');
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
/* .env import */
require('dotenv').config();
/* This parses the JSON from the AJAX req */
router.use(bodyParser.json());
/* Inputing the API keys for Twilio, they are in a .env file */
var accountSid = process.env.ACCOUNT_SID; // Your Account SID from www.twilio.com/console
var authToken = process.env.AUTH_TOKEN; // Your Auth Token from www.twilio.com/console
/* Creating boilerplate Twilio */
var twilio = require('twilio');
const { data } = require('jquery');
var client = new twilio(accountSid, authToken);
/* GET home page */
router.get('/', async (req, res, next) => {
const url_api = 'https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/Messages/{Message Id}';
/* Test */
const test = 'https://httpbin.org/get'
try {
await fetch(url_api)
.then(res => res.json())
.then(data => {
const body = body;
console.log(body);
res.render('index', {
body: body
});
})
} catch (error) {
console.log(error);
}
});
/*Twilio
1. Create a message on Twilio and send the message
2. The body is JSON from the AJAX request
*/
router.post('/', (req, res, next) => {
client.messages.create({
body: `${req.body.message}`,
to: `${req.body.number}`, // Text this number
from: process.env.PHONE_NUMBER // From a valid Twilio number
})
.then((message) => console.log(message.sid));
next();
})
module.exports = router;
After hours of working with the API, I found the solution.
The try method is where the magic happens. This gets the most recent message sent to the Twilio number and allows the body of the message to be available to the EJS template
/* GET home page */
router.get('/', async (req, res, next) => {
const url_api = 'https://api.twilio.com/2010-04-01/Accounts/{Account Sid}/Messages/SM025191920c117b50102d09f0c1200ed3.json';
/*The try is where the magic happens. This gets the most recent message sent to the Twilio number and allows the body of the message to be available to the EJS template*/
try {
client.messages
.list({
from: '+17185412931',
limit: 1
})
.then(messages => messages.forEach(m =>
res.render('index', {
messagesId: m.body
})));
} catch (error) {
console.log(error);
}
});

How to test image upload (stream) with supertest and jest?

I have an image upload endpoint in my API that accepts application/octet-stream requests and handles these streams. I'd like to write test coverage for this endpoint but cannot figure out how to use supertest to stream an image.
Here's my code so far:
import request from 'supertest'
const testImage = `${__dirname}/../../../assets/test_image.jpg`
describe('Upload endpoint', () => {
test('Successfully uploads jpg image', async () =>
request(app)
.post(`${ROOT_URL}${endpoints.add_image.route}`)
.set('Authorization', `Bearer ${process.env.testUserJWT}`)
.set('content-type', 'application/octet-stream')
.pipe(fs.createReadStream(testImage))
.on('finish', (something) => {
console.log(something)
}))
})
This code produces nothing, the finish event is never called, nothing is console logged, and this test suite actually passes as nothing is expected. I cannot chain a .expect onto this request, otherwise I get this runtime error:
TypeError: (0 , _supertest2.default)(...).post(...).set(...).set(...).pipe(...).expect is not a function
How is such a thing accomplished?
This should work. To pipe data to a request you have to tell the readable stream to pipe to the request. The other way is for receiving data from the server. This also uses done instead of async as pipes do not work with async/await.
Also worth nothing is that by default the pipe will call end and then superagent will call end, resulting in an error about end being called twice. To solve this you have to tell the pipe call not to do that and then call end in the on end event of the stream.
import request from 'supertest'
const testImage = `${__dirname}/../../../assets/test_image.jpg`
describe('Upload endpoint', () => {
test('Successfully uploads jpg image', (done) => {
const req = request(app)
.post(`${ROOT_URL}${endpoints.add_image.route}`)
.set('Authorization', `Bearer ${process.env.testUserJWT}`)
.set('content-type', 'application/octet-stream')
const imgStream = fs.createReadStream(testImage);
imgStream.on('end', () => req.end(done));
imgStream.pipe(req, {end: false})
})
})
Edited to add: this has worked for me with small files. If I try testing it with a large test_image.jpg the request times out.
const testImage = `${__dirname}/../../../assets/test_image.jpg`
describe('Upload endpoint', () => {
test('Successfully uploads jpg image', async () =>
request(app)
.post(`${ROOT_URL}${endpoints.add_image.route}`)
.set('Authorization', `Bearer ${process.env.testUserJWT}`)
.attach("name",testImage,{ contentType: 'application/octet-stream' })
.expect(200)
.then(response => {
console.log("response",response);
})
);
});
I had to make assumptions about your upload method taking the body as input instead of multipart form-data. So below is an example where the raw body is passed for upload
const request = require('supertest');
const express = require('express');
const fs = require('fs')
const app = express();
var bodyParser = require('body-parser')
app.use(bodyParser.raw({type: 'application/octet-stream'}))
app.post('/user', function(req, res) {
res.status(200).json({ name: 'tobi' });
});
testImage = './package.json'
resp = request(app)
.post('/user')
resp.set('Authorization', `Bearer Test`).set('Content-Type', 'application/octet-stream')
resp.send(fs.readFileSync(testImage, 'utf-8'))
resp.expect(200)
.then(response => {
console.log("response",response);
}).catch((err) => {
console.log(err)
})
If you use multipart/form-data then below code shows an example
const request = require('supertest');
const express = require('express');
const fs = require('fs')
const app = express();
app.post('/user', function(req, res) {
// capture the encoded form data
req.on('data', (data) => {
console.log(data.toString());
});
// send a response when finished reading
// the encoded form data
req.on('end', () => {
res.status(200).json({ name: 'tobi' });
});
});
testImage = './package.json'
resp = request(app)
.post('/user')
resp.set('Authorization', `Bearer Test`)
resp.attach("file", testImage)
resp.expect(200)
.then(response => {
console.log("response",response);
}).catch((err) => {
console.log(err)
})
I think you actually want to use fs.createReadStream(testImage) to read that image into your request, since fs.createWriteStream(testImage) would be writing data into the file descriptor provided (in this case testImage). Feel free to checkout Node Streams to see how they work in more detail.
I'm not quite sure where you're getting the finish event from for supertest, but you can see how to use the .pipe() method here.
You might also want to consider using supertest multipart attachments, if that better suits your test.

How to send messages without user inputs Telegram BOT API

I made a simple bot with Node.js and the Telegram BOT API and the question is how can I send a message each certain time, for example I want to say "hello" every 5 minutes, What do I have to do ?
Here is my current code:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
const axios = require('axios')
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({
extended: true
})); // for parsing application/x-www-form-urlencoded
//This is the route the API will call
app.post('/new-message', function(req, res) {
const {message} = req.body;
//Each message contains "text" and a "chat" object, which has an "id" which is the chat id
axios.get('some_api'+message.text.toLowerCase()+ '/')
.then(resp => {
axios.post('https://api.telegram.org/bot<MYTOKEN>/sendMessage', {
chat_id: message.chat.id,
text: `*${resp.data[0].name} (#${resp.data[0].symbol})*
Price USD: ${resp.data[0].price_usd}
Percent Change 24h: ${resp.data[0].percent_change_24h}
Market Cap USD: ${resp.data[0].market_cap_usd}`,
parse_mode:'Markdown'
})
.then(response => {
// We get here if the message was successfully posted
console.log('Message posted')
res.end('ok')
})
.catch(err => {
// ...and here if it was not
console.log('Error :', err)
res.end('Error :' + err)
})
})
.catch(err => {
// ...and here if it was not
console.log('Error :', err)
res.end('Error :' + err)
})
});
// Finally, start our server
app.listen(3000, function() {
console.log('Telegram app listening on port 3000!');
});
you can do that,
you can send messages to a specific user or to a specific chat.
But first you need to get the msg.from.id or 'msg.chat.id', store it, and send notifications whenever you need.
when a user joins your bot, and he press the 'start' button you can trigger that action, on your server:
// on global scope or wherever
var fromId=null
var chatId=null
// trigers when user press 'start' button
bot.onText(/\/start/, function (msg, match) {
chatId=msg.chat.id;
fromId = msg.from.id; // store that value and use it as param on sendMessage()
var name = msg.from.first_name
bot.sendMessage(fromId, `Welcome dear ${name} have fun`);
});
Now you can create our time intervals and send to user or char
if(fromId) {
setInterval(() => {
bot.sendMessage(fromId, `message to the user`),
300,000}) // every 5 mins
}
I hope this helps.

Categories

Resources