Twilio - can't process phone number after clicking submit - javascript

I'm following this link for the tutorial (via twilio.) and have followed all the
required steps but when I run the localhost and input a number, I get no text message, nor does the window for verification open. It just stays at the same page of "enter your phone number".
Here's my HTML code
<!DOCTYPE HTML>
<HTML>
<head>
<title>Verify SMS Demo</title>
<style>
#verify-form,
#response-text {
display: none;
}
</style>
</head>
<body>
<form id="phone-form">
<h2>Enter your phone number with country code:</h2>
<input type="tel" id="phone-number-input" placeholder="15551235555" />
<input id="phone-submit" type="submit" />
</form>
<form id="verify-form">
<h2>Enter your verification code:</h2>
<input type="number" id="otp-input" placeholder="e.g. 123456" />
<input id="verify-submit" type="submit" />
</form>
<div id="response-text"></div>
</body>
<script type="text/javascript" src = "script.js"></script>
</html>`
And here's my code for script.js:
const phoneForm = document.getElementById('phone-form');
const verifyForm = document.getElementById('verify-form');
const responseText = document.getElementById('response-text');
let phoneNumber;
phoneForm.addEventListener('submit', async e => {
e.preventDefault();
phoneNumber = document.getElementById('phone-number-input').value;
const response = await fetch('/send-notification', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({phoneNumber : phoneNumber })
}).catch(e => console.log(e));
if (response.ok) {
phoneForm.style.display = 'none';
verifyForm.style.display = 'block';
}
});
verifyForm.addEventListener('submit', async e => {
e.preventDefault();
const otp = document.getElementById('otp-input').value;
const data = {
phoneNumber: phoneNumber,
otp: top
};
const response = await fetch('/verify-otp', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
body: JSON.stringify(data)
}).catch(e => console.log(e));
const check = await response.json();
const text = response.ok ? check.status : response.statusText;
responseText.innerHTML = text;
verifyForm.style.display = 'none';
responseText.style.display = 'block';
});
EDIT Here is my index.js file:
const express = require('express');
const path = require('path');
require('dotenv').config();
const client = require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
const app = express();
const port = process.env.PORT || 3000;
app.use(express.static(__dirname + '/public'));
app.use(express.urlencoded({extended: true}));
app.use(express.json());
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '/views/index.html'));
});
app.post('/send-verification', async (req, res) => {
client.verify.services(verify)
.verifications
.create({to: `+${req.body.phoneNumber}`, channel: 'sms'})
.then(verification => console.log(verification.status))
.catch(e => {
console.log(e)
res.status(500).send(e);
});
res.sendStatus(200);
});
app.post('/verify-otp', async (req, res) => {
const check = await client.verify.services(verify)
.verificationChecks
.create({to: `+${req.body.phoneNumber}`, code: req.body.otp})
.catch(e => {
console.log(e)
res.status(500).send(e);
});
res.status(200).send(check);
});
app.listen(port);
console.log('Server started at http://localhost:' + port);

Your front-end is making a request to /send-notification but your application end point is at /send-verification.
Update your front-end code to:
const response = await fetch('/send-verification', {
and you should be good to go.
Edit
Now, in the server you are getting the error:
sh-3.2$ node index.js Server started at localhost:3000
/Users/username/Downloads/keep_out-3/verify-sms-express/index.js:17
client.verify.services(verify)
^ ReferenceError: verify is not defined
You have the line:
const check = await client.verify.services(verify)
In the blog post this is:
client.verify.services(process.env.VERIFY_SERVICE_SID);
So, you have replaced the verify service sid with a non-existant verify variable. Go back and make sure you have VERIFY_SERVICE_SID set in your .env file and then change the code back to the original, and then you should be good to go!

Related

Why am I getting this error on live deployment but not on localhost? SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON

My app is working in the localhost but recieving the following error on the live deployemnt.
SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON
So I'm assuming it's got to do with the fetch request on handleSubmit. The site is deployed to firebase. Do I need to setup some type of api domain that can handle these requests.
Error is being produced by line 31, on the catch.
Upon entering a term to translate, below the submit button the translation should occur. Which it does when I'm using http://localhost:3000 on my pc. I changed that to the domain, though not sure what else needs to be done.
Newbie to all of this.
APP.JS
import React, { useState } from 'react';
import './App.css';
function App() {
const [message, setMessage] = useState('');
const [response, setResponse] = useState('');
const [language, setLanguage] = useState('');
// const cheerio = require('cheerio');
const handleChange = (e) => {
setMessage(e.target.value);
}
const handleLanguageChange = (e) => {
setLanguage(e.target.value);
}
const handleSubmit = (e) => {
e.preventDefault();
fetch('https://translatebrain.com/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ message })
})
.then(res => res.json())
.then(data => setResponse(data.message))
.catch(err => console.log(err));
}
return (
<div className="App">
<h1>TranslateBrain</h1>
<form onSubmit={handleSubmit}>
<h2>Type text below</h2>
<textarea value={message} onChange={handleChange} />
<h2>Tranlate to</h2>
<select value={language} onChange={handleLanguageChange}>
<option value="English">English</option>
<option value="French">French</option>
<option value="German">German</option>
<option value="Spanish">Spanish</option>
<option value="Italian">Italian</option>
</select>
<h2>Click submit</h2>
<button type="submit">Submit</button>
</form>
<p>{response}</p>
</div>
);
}
export default App;
INDEX.JS
const OpenAI = require('openai')
const { Configuration, OpenAIApi } = OpenAI;
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const port = 3001;
const configuration = new Configuration({
organization: "REDACTED",
apiKey: "REDACTED",
});
const openai = new OpenAIApi(configuration);
app.use(bodyParser.json());
app.use(cors());
app.post('/', async (req, res) => {
const { message , language } = req.body;
const response = await openai.createCompletion({
model: "text-davinci-003",
prompt: "Translate this into" + language + ":" + message,
max_tokens: 100,
temperature: 0,
});
console.log(response.data)
if(response.data.choices[0].text){
res.send({message: response.data.choices[0].text})
}
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
}
);
Spent hours trying to read how to overcome this issue, but it's quite a lot to take in as a newbie. Managed to create a private key in firebase, but not sure how to link it all up.
try this, when you have:
headers: {
'Content-Type': 'application/json'
},
add this:
headers: {
'Content-Type': 'application/json'
'Accept':'application/json'
},
this is gona "force" to recieve data as json.
If not works, try to console.log all the response and post it again.
maybe there's another error 500 ?404? .. etc we neet to know

give role to OAuth2 authorised accounts on Discord

I am creating OAuth2 for my application by which the people who are redirected to the server by clickking it will get the verified role. Can somebody please help me on how i can add it in my script. Right now I am using the script given below:
const express = require('express');
const { port } = require('./config.json');
const app = express();
app.get('/', (request, response) => {
console.log(`The access code is: ${request.query.code}`)
;
return response.sendFile('index.html', { root: '.' });
});
app.listen(port, () => console.log(`App listening at http://localhost:${port}`));
and from the index file they get redirected to the server here's the index.html script:
<script>
window.location.href = "https://discord.gg/DhsYQ3u4jj";
</script>
<div id="info">Congrats! You have been successfully connected to Discord.</div>
<a id="login" style="display: none;" href="https://discord.gg/jkBJarBY">Click here to Join Akudo's official Discord!</a>
<script>
window.onload = () => {
const fragment = new URLSearchParams(window.location.hash.slice(1));
const [accessToken, tokenType] = [fragment.get('access_token'), fragment.get('token_type')];
if (!accessToken) {
return (document.getElementById('login').style.display = 'block');
}
fetch('https://discord.com/api/users/#me', {
headers: {
authorization: `${tokenType} ${accessToken}`,
},
})
.then(result => result.json())
.then(response => {
const { username, discriminator } = response;
document.getElementById('info').innerText += ` ${username}#${discriminator}`;
})
.catch(console.error);
};
</script>

After POST request redirect GET method is called but send file is not working?

When the login button is pressed I send a POST request successfully to my app.js file and just to test try to redirect it with (as instructed) used code 302.
My get request '/' is called and logged
Exist!
did we work? Why does my sendFile not work as I expected? I am relatively new to this so I may be off base on how to do this. My goal is to after submitting a POST transition the client to a new HTML file
const express = require('express');
const { json } = require('express/lib/response');
const app = express();
const fs = require('fs');
app.use(express.json());
app.get('/Register', (req, res) => {
res.sendFile(__dirname + '/Register.html');
});
app.get('/Login', (req, res) => {
res.sendFile(__dirname + '/Login.html');
});
app.get('/RegisterComplete', (req, res) => {
res.sendFile(__dirname + '/RegisterComplete.html');
});
app.get('/', (req, res) => {
console.log('did we work?')
res.sendFile(__dirname + '/Home.html');
});
app.post('/', (req, res) => {
const { username, password } = req.body;
const { authorization } = req.headers;
res.send({
username,
password,
authorization,
});
// fs.readFile('helloworld.txt', 'utf8' , (err, data) => {
// fs.writeFile('helloworld.txt', JSON.stringify(req.body) + data, function (err) {
// if (err) return console.log(err);
// });
// })
console.log(req.body + 'i am not what we need');
});
app.post('/Register', (req, res) => {
fs.readFile('Logins.Json', 'utf8' , (err, data) => {
const obj = req.body;
const testObj = JSON.stringify(obj)
const fileContent = JSON.parse(data)
const newContent = fileContent['User Info']
let test = new Boolean(false)
for (let i = 0; i < newContent.length; i++) {
if(JSON.stringify(newContent[i]) == testObj){
//console.log('Exist!')
test = true
break
}
}
//console.log(req.body);
if (test == true) {
console.log('Exist!')
}else{
newContent.push(obj);
const newData = JSON.stringify(fileContent)
fs.writeFile('Logins.Json', newData, function (err) {
console.log('Created Account!')
if (err) return console.log(err);
})
}
if (err) return console.log(err);
})
res.end()
//console.log(req.body);
});
app.post('/Login', (req, res) => {
res.redirect(302,'/');
fs.readFile('Logins.Json', 'utf8' , (err, data) => {
const obj = req.body;
const testObj = JSON.stringify(obj)
const fileContent = JSON.parse(data)
const newContent = fileContent['User Info']
let test = new Boolean(false)
for (let i = 0; i < newContent.length; i++) {
if(JSON.stringify(newContent[i]) == testObj){
//console.log('Exist!')
test = true
break
}
}
//console.log(req.body);
if (test == true) {
console.log('Exist!')
//login successful
}else{
console.log('Failed')
// login failed
}
if (err) return console.log(err);
})
});
app.listen(7777, () => {
console.log('Our express server is up on port 1000');
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>eV Login</title>
</head>
<body>
<form>
<div>
<label>Username</label>
<input type="text" id="user" />
</div>
<div>
<label>Password</label>
<input type="password" id="pass" />
</div>
<button type="submit">Login</button>
</form>
<script>
document.querySelector('button')
.addEventListener('click', (e) => {
e.preventDefault();
const username = document
.querySelector('#user').value;
const password = document
.querySelector('#pass').value;
fetch('/Login', {
method: 'POST',
headers: {
Authorization: 'Vital Gaming',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username,
password,
}),
})
.then((res) => {
return res.json();
})
.then((data) => console.log(data));
});
</script>
</body>
</html>

Why doesn't node-lame encode properly (nodeJS library)?

I've been trying to use the node-lame library to encode a file from the uploaded bitrate to 32 kbps to save space the same way I do it with sharp to compress my images.
My code first checks if the file is an audio file. If it is it then makes the encoder and it should encode it:
if (aud.test(user_file)){
const encoder = new Lame({
"output": req.file.path,
"bitrate": 32,
}).setFile(req.file.path);
await encoder
.encode()
.then(() => {})
.catch((error) => {
// Something went wrong
});
}
The problem is that it doesn't actually get encoded. I have also tried this in my .then but it doesn't help.
.then(data => {
fs.writeFileSync(req.file.path + '.mp3', data);
user_file = user_file + '.mp3';
fs.unlinkSync(req.file.path)
})
This is supposed to be a fairly simple library so I don't know what I'm doing wrong. I am trying to encode from file to file.
Also tried this:
const encoder = new Lame({
"output": user_file + '.mp3',
"bitrate": 32,
}).setFile(req.file.path);
I went ahead and wrote a demo for this. You can find the full repo here. I have verified this does work but keep in mind this is only a proof of concept.
This is what my Express server looks like:
const express = require('express');
const fs = require('fs');
const path = require('path');
const fileUpload = require('express-fileupload');
const Lame = require('node-lame').Lame;
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(fileUpload());
// File upload path
app.post('/upload', async (req, res) => {
const fileToEncode = req.files.uploadedFile;
if (!fileToEncode) {
res.status(500).end();
return;
}
const filePath = path.resolve('./uploads', fileToEncode.name);
const outputPath = path.resolve('./uploads', fileToEncode.name + '-encoded.mp3');
// Save uploaded file to disk
await fileToEncode.mv(filePath);
try {
const encoder = new Lame({
output: outputPath,
bitrate: 8,
}).setFile(filePath);
await encoder.encode();
res.download(outputPath);
} catch (encodingError) {
console.error(encodingError);
res.status(500).send(encodingError);
}
// Removed files we saved on disk
res.on('finish', async () => {
await fs.unlinkSync(filePath);
await fs.unlinkSync(outputPath);
})
});
// Home page
app.get('*', (req, res) => {
res.status(200).send(`
<!DOCTYPE html>
<html>
<body>
<p id="status"></p>
<form method="post" enctype="multipart/form-data" action="/upload" onsubmit="handleOnSubmit(event, this)">
<input name="uploadedFile" type="file" />
<button id="submit">Submit Query</button>
</form>
<script>
async function handleOnSubmit(e,form) {
const statusEl = document.getElementById("status");
statusEl.innerHTML = "Uploading ...";
e.preventDefault();
const resp = await fetch(form.action, { method:'post', body: new FormData(form) });
const blob = await resp.blob();
const href = await URL.createObjectURL(blob);
Object.assign(document.createElement('a'), {
href,
download: 'encoded.mp3',
}).click();
statusEl.innerHTML = "Done. Check your console.";
}
</script>
</body>
</html>
`);
});
process.env.PORT = process.env.PORT || 3003;
app.listen(process.env.PORT, () => {
console.log(`Server listening on port ${process.env.PORT}`);
});

Socket.io 404 Error - Client not connecting

When deploying a twitter streaming app which is working well on my local environment, to a live webserver, I'm getting a 404 error related to socket.io. I saw that there a numerous similar questions here already but did not find an answer solving the problem I'm facing.
Problem description:
Once I start server.js, it correctly logs 'Listening on Port 3000' to the console (terminal)
However, the message "Client connected..." is not triggered
In the browser console, I'm seeing the error message "GET https://exampledomain.com/socket.io/?EIO................(etc) - 404 - XHR failed loading"
I have already tried the following changes without success, amongst other things:
Changed the server.js code from const http = require('http') to const https = require('https')
Changed the port from 3000 to others to rule out a certain port # is already in use elsewhere, e.g. 8001 or 3333
The full server code (in public_html/server/server.js):
const http = require('http')
const path = require('path')
const express = require('express')
const socketIo = require('socket.io')
const needle = require('needle')
const config = require('dotenv').config()
const TWITTER_BEARER_TOKEN = 'xxxxxx'
const PORT = process.env.PORT || 3000
const app = express()
const server = http.createServer(app)
const io = socketIo(server)
console.log(path.resolve(__dirname, '../', 'public_html/client', 'index.html'))
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, '../', 'public_html/client', 'index.html'))
// /usr/www/users/antick/public_html/client/index.html
})
const rulesURL = 'https://api.twitter.com/2/tweets/search/stream/rules'
const streamURL = 'https://api.twitter.com/2/tweets/search/stream?tweet.fields=public_metrics&expansions=author_id,attachments.media_keys&media.fields=duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width&user.fields=profile_image_url'
const rules = [{ value: 'corruption' }]
// Get stream rules
async function getRules() {
const response = await needle('get', rulesURL, {
headers: {
Authorization: `Bearer ${TWITTER_BEARER_TOKEN}`
}
})
return response.body
}
// Set stream rules
async function setRules() {
const data = {
add: rules
}
const response = await needle('post', rulesURL, data, {
headers: {
'content-type': 'application/json',
Authorization: `Bearer ${TWITTER_BEARER_TOKEN}`
}
})
return response.body
}
// Delete stream rules
async function deleteRules(rules) {
if (!Array.isArray(rules.data)) {
return null
}
const ids = rules.data.map((rule) => rule.id)
const data = {
delete: {
ids: ids
}
}
const response = await needle('post', rulesURL, data, {
headers: {
'content-type': 'application/json',
Authorization: `Bearer ${TWITTER_BEARER_TOKEN}`
}
})
return response.body
}
function streamTweets(socket) {
const stream = needle.get(streamURL, {
headers: {
Authorization: `Bearer ${TWITTER_BEARER_TOKEN}`
}
})
stream.on('data', (data) => {
try {
const json = JSON.parse(data)
console.log(json)
socket.emit('tweet', json)
} catch (error) {}
})
}
io.on('connection', async () => {
console.log('Client connected...')
let currentRules
try {
// Get all stream rules
currentRules = await getRules()
// Delete all stream rules
await deleteRules(currentRules)
// Set rules based on array above (Rules)
await setRules()
} catch (error) {
console.error(error)
process.exit(1)
}
streamTweets(io)
})
server.listen(PORT, () => console.log(`Listening on Port ${PORT}`))
My client code - excerpt only (in public_html/client/index.html):
<div class="container">
<div id="tweetStream"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/socket.io.js" integrity="sha512-iZIBSs+gDyTH0ZhUem9eQ1t4DcEn2B9lHxfRMeGQhyNdSUz+rb+5A3ummX6DQTOIs1XK0gOteOg/LPtSo9VJ+w==" crossorigin="anonymous" referrerpolicy="no-referrer">
</script>
<script>
const tweetStream = document.getElementById('tweetStream')
const socket = io()
//const socket = io.connect('https://www.exampledomain.com:3000/');
const tweets = []
socket.on('connect', () => {
console.log('Connected to server...')
})
socket.on('tweet', (tweet) => {
// (code continues here)
My suspicion is that is has to do something with the paths used in these two locations:
in server/server.js:
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, '../', 'public_html/client', 'index.html'))
// resolves to: /usr/www/users/antick/public_html/client/index.html
})
in client/index.html: const socket = io() //
What else could possibly cause the error described above? I am grateful for any help. Thanks!
With help from a pro developer I was finally able to fix the problem so I would like to post the solution.
The two main points were:
Open Port # 3000 to any IPs (as it is unknown from which IP address a client would access the site)
Install pm2 in addition to node in order to constantly stream the tweets
The full resulting code looks as follows:
A) Server (index.js):
const http = require('http')
const path = require('path')
const express = require('express')
const socketIo = require('socket.io')
const needle = require('needle')
const config = require('dotenv').config()
const TOKEN = process.env.TWITTER_BEARER_TOKEN
const PORT = process.env.PORT || 3000
const app = express()
const server = http.createServer(app)
const io = socketIo(server)
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, '../', 'client', 'index.html'))
})
const rulesURL = 'https://api.twitter.com/2/tweets/search/stream/rules'
const streamURL = 'https://api.twitter.com/2/tweets/search/stream?tweet.fields=public_metrics&expansions=author_id,attachments.media_keys&media.fields=duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width&user.fields=profile_image_url'
const rules = [{ value: 'searchterm' }]
// Get stream rules
async function getRules() {
const response = await needle('get', rulesURL, {
headers: {
Authorization: `Bearer ${TOKEN}`
}
})
return response.body
}
// Set stream rules
async function setRules() {
const data = {
add: rules
}
const response = await needle('post', rulesURL, data, {
headers: {
'content-type': 'application/json',
Authorization: `Bearer ${TOKEN}`
}
})
return response.body
}
// Delete stream rules
async function deleteRules(rules) {
if(!Array.isArray(rules.data)) {
return null
}
const ids = rules.data.map((rule) => rule.id)
const data = {
delete: {
ids: ids
}
}
const response = await needle('post', rulesURL, data, {
headers: {
'content-type': 'application/json',
Authorization: `Bearer ${TOKEN}`
}
})
return response.body
}
function streamTweets (socket) {
const stream = needle.get(streamURL, {
headers: {
Authorization: `Bearer ${TOKEN}`
}
})
stream.on('data', (data) => {
try {
const json = JSON.parse(data)
console.log(json)
console.log(json.includes.media[0])
socket.emit('tweet', json)
} catch (error) {}
})
}
io.on('connection', async () => {
console.log('Client connected...')
let currentRules
try {
// Get all stream rules
currentRules = await getRules()
// Delete all stream rules
await deleteRules(currentRules)
// Set rules based on array above (Rules)
await setRules()
} catch (error) {
console.error(error)
process.exit(1)
}
streamTweets(io)
})
server.listen(PORT, () => console.log(`Listening on Port ${PORT}`))
B) Client (index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"
integrity="sha512-+4zCK9k+qNFUR5X+cKL9EIR+ZOhtIloNl9GIKS57V1MyNsYpYcUrUeQc9vNfzsWfV28IaLL3i96P9sdNyeRssA=="
crossorigin="anonymous"
/>
<title>Real-Time Tweet Stream</title>
</head>
<body>
<nav class="navbar navbar-dark bg-dark">
<div class="container">
Real-Time Tweet Stream
</div>
</nav>
<div class="container">
<div id="tweetStream"></div>
</div>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js"
integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ=="
crossorigin="anonymous"
></script>
<script>
const tweetStream = document.getElementById('tweetStream')
const socket = io('IP.IP.IP.IP:3000' , { transports : ['websocket'] } ) // webserver IP address
const tweets = []
socket.on('connect', () => {
console.log('Connected to server...')
})
socket.on('tweet', (tweet) => {
// console.log(tweet)
const tweetData = {
id: tweet.data.id,
text: tweet.data.text,
username: `#${tweet.includes.users[0].username}`,
}
const tweetEl = document.createElement('div')
tweetEl.className = 'card my-4'
tweetEl.innerHTML = `
<div class="card-body">
<h5 class="card-title">${tweetData.text}</h5>
<h6 class="card-subtitle mb-2 text-muted">${tweetData.username}</h6>
<a class="btn btn-primary mt-3" href="https://twitter.com/${tweetData.username}/status/${tweetData.id}">
<i class="fab fa-twitter"></i> Go To Tweet
</a>
</div>
`
tweetStream.appendChild(tweetEl)
})
</script>
</body>
</html>

Categories

Resources