Before anything, we use this module to parse the form body. We also want to use the form data to call an API endpoint, and for that we need the Fetch module. There are various versions of Fetch, and for the simplest one, we'll use a slightly backdated version.
npm install --save body-parser
npm install --save node-fetch@2
npm install --save node-fetch@2
In the bdChange() function, add this line after displaying "Please wait...". It submits the form.
assets/js/functions.js
function bdChange() {
var errorContainer = document.getElementById("errorContainer");
var txtBd = document.getElementById("txtBd");
var formFortune = document.getElementById("formFortune");
var fortuneContainer = document.getElementById("fortuneContainer");
var d = new Date();
var bd = new Date(txtBd.value);
if (bd.getTime() > d.getTime()) {
errorContainer.innerHTML = "Error! You can't possibly be born in the future.";
} else {
errorContainer.innerHTML = "";
fortuneContainer.innerHTML = "Please wait..."
formFortune.submit();
}
}
var errorContainer = document.getElementById("errorContainer");
var txtBd = document.getElementById("txtBd");
var formFortune = document.getElementById("formFortune");
var fortuneContainer = document.getElementById("fortuneContainer");
var d = new Date();
var bd = new Date(txtBd.value);
if (bd.getTime() > d.getTime()) {
errorContainer.innerHTML = "Error! You can't possibly be born in the future.";
} else {
errorContainer.innerHTML = "";
fortuneContainer.innerHTML = "Please wait..."
formFortune.submit();
}
}
Now, in app.js, we'll work on the route fortune. We first want to include the Fetch module.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
});
let fetch = require("node-fetch");
});
Declare headers an an object. We are preparing to send data via an OpenAI API endpoint. For that, the object needs to have the properties Authorization, OpenAI-Organization and Content-Type.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
var headers = {
"Authorization": ,
"OpenAI-Oganization": ,
"Content-Type":
};
});
let fetch = require("node-fetch");
var headers = {
"Authorization": ,
"OpenAI-Oganization": ,
"Content-Type":
};
});
Content-Type is JSON. The other two are strings based on your OpenAI account. As for what api is, it's a file we will create right now.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
});
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
});
Having the details in this file helps protect your details. This information should be private.
api.js
module.exports = {
org: "org-xxx",
key: "sk-xxx"
}
org: "org-xxx",
key: "sk-xxx"
}
Add this line. That will import the details of api.js so that any information is obtainable by referencing the object api.
app.js
var api = require("./api.js");
var express = require("express");
var express = require("express");
Continuing on with the fortune route, we declare messages as an empty array. Then we declare obj as n object and push obj into messages.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
}
messages.push(obj);
});
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
}
messages.push(obj);
});
obj should have the role property, value set to "user". The content property is the prompt string that will be sent to OpenAI. In it, we will use the birth date passed from the form.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
"role": "user",
"content" : "It is currently 2025. My birth date is " + req.body.txtBd + ". Using exactly 5 paragraphs give me my Chinese Zodiac and element I also want a personality profile for myself. Lastly, provide a fortune for love, money and health."
}
messages.push(obj);
});
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
"role": "user",
"content" : "It is currently 2025. My birth date is " + req.body.txtBd + ". Using exactly 5 paragraphs give me my Chinese Zodiac and element I also want a personality profile for myself. Lastly, provide a fortune for love, money and health."
}
messages.push(obj);
});
In order to use the body object, however, we need to summon the power of the module body-parser.
app.js
app.set("view engine", "handlebars");
app.set("port", process.env.PORT || 3000);
app.use(require("body-parser")());
app.use(express.static("assets"));
app.set("port", process.env.PORT || 3000);
app.use(require("body-parser")());
app.use(express.static("assets"));
Back to the fortune route, we declare body as an object with model, messages and max_tokens as properties. messages will be the array messages that we just worked on, model will be whatever ChatGPT model you want to use, and max_tokens will be a matter of how much resources you want to dedicate to this call.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
"role": "user",
"content" : "It is currently 2025. My birth date is " + req.body.txtBd + ". Using exactly 5 paragraphs give me my Chinese Zodiac and element I also want a personality profile for myself. Lastly, provide a fortune for love, money and health."
};
messages.push(obj);
var body = {
"model": "gpt-3.5-turbo",
"messages" : messages,
"max_tokens" : 2500
}
});
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
"role": "user",
"content" : "It is currently 2025. My birth date is " + req.body.txtBd + ". Using exactly 5 paragraphs give me my Chinese Zodiac and element I also want a personality profile for myself. Lastly, provide a fortune for love, money and health."
};
messages.push(obj);
var body = {
"model": "gpt-3.5-turbo",
"messages" : messages,
"max_tokens" : 2500
}
});
We will then use fetch. Pass in as a first argument, the URL endpoint.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
"role": "user",
"content" : "It is currently 2025. My birth date is " + req.body.txtBd + ". Using exactly 5 paragraphs give me my Chinese Zodiac and element I also want a personality profile for myself. Lastly, provide a fortune for love, money and health."
};
messages.push(obj);
var body = {
"model": "gpt-3.5-turbo",
"messages" : messages,
"max_tokens" : 2500
}
fetch("https://api.openai.com/v1/chat/completions")
});
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var messages = [];
var obj = {
"role": "user",
"content" : "It is currently 2025. My birth date is " + req.body.txtBd + ". Using exactly 5 paragraphs give me my Chinese Zodiac and element I also want a personality profile for myself. Lastly, provide a fortune for love, money and health."
};
messages.push(obj);
var body = {
"model": "gpt-3.5-turbo",
"messages" : messages,
"max_tokens" : 2500
}
fetch("https://api.openai.com/v1/chat/completions")
});
For the second argument, we need an object with the properties method, headers and body. method is "POST". headers is the object headers which we defined earlier, and body will be a JSON string representation of the body object.
app.js
app.post("/fortune", (req, res)=> {
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var body = {
"model": "gpt-3.5-turbo",
"messages" : messages,
"max_tokens" : 2500
}
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
});
let fetch = require("node-fetch");
var headers = {
"Authorization": "Bearer " + api.key,
"OpenAI-Oganization": api.org,
"Content-Type": "application/json"
};
var body = {
"model": "gpt-3.5-turbo",
"messages" : messages,
"max_tokens" : 2500
}
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
});
Once the data has been obtained, we use the then() method to handle it. We'll use the text() method to send the text representation of the data stream response further down the line.
app.js
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
We then chain another then() method call to handle the data, and a catch() method to handle errors.
app.js
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
})
.catch(err => {
});
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
})
.catch(err => {
});
If there's an error, we render the form view but with err in the error property.
app.js
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
Handling data, we first declare json_data and assign to it the JSON representation of the string data.
app.js
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
We will derive the content by getting the first element of the choices array of json_data, then accessing the message and content properties.
app.js
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
var html_content = json_data.choices[0].message.content;
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
var html_content = json_data.choices[0].message.content;
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
We'll format this properly in HTML by using the replaceAll() method to replace all line breaks with HTML breaks.
app.js
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
var html_content = json_data.choices[0].message.content.replaceAll("\n\n", "<br /><br />");
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
var html_content = json_data.choices[0].message.content.replaceAll("\n\n", "<br /><br />");
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
And finally, render the form view with html_content as the value of the fortune property.
app.js
fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
var html_content = json_data.choices[0].message.content.replaceAll("\n\n", "<br /><br />");
res.render("form", { error: "", fortune: html_content });
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then(response => response.text())
.then(data => {
var json_data = JSON.parse(data);
var html_content = json_data.choices[0].message.content.replaceAll("\n\n", "<br /><br />");
res.render("form", { error: "", fortune: html_content });
})
.catch(err => {
res.render("form", { error: err, fortune: "" });
});
Oops, the break tags do appear, but as text!
Add an extra pair of curly brackets for the fortune placeholder, to indicate that this should be formatted.
views/form.handlebars
<h1>Welcome to the Wood Snake Fortune Teller!</h1>
<form action="/fortune" id="formFortune" method="POST">
<label for="txtBd">Birth Date</label>
<br />
<input type="date" name="txtBd" id="txtBd" value="2025-01-01" onChange="bdChange();" />
</form>
<div class="error" id="errorContainer">{{ error }}</div>
<br />
<div class="fortune" id="fortuneContainer"> {{{ fortune }}}</div>
<form action="/fortune" id="formFortune" method="POST">
<label for="txtBd">Birth Date</label>
<br />
<input type="date" name="txtBd" id="txtBd" value="2025-01-01" onChange="bdChange();" />
</form>
<div class="error" id="errorContainer">{{ error }}</div>
<br />
<div class="fortune" id="fortuneContainer"> {{{ fortune }}}</div>
Fixed!
This was a simple exercise in API calls using NodeJS. Hope you enjoyed, pretty sure I did!
Blessssssed fortunessssssss,
T___T