Skip to content

Commit fab5c48

Browse files
committed
Add Support Chat
1 parent 51c1b66 commit fab5c48

File tree

8 files changed

+309
-61
lines changed

8 files changed

+309
-61
lines changed

.eslintignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
*.min.js
1+
*.min.js
2+
temp

index.js

Lines changed: 103 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* eslint-disable max-len */
2+
const fs = require("fs");
23
const _ = require("lodash");
34
const convert = require("convert-units");
45
const extractValues = require("extract-values");
@@ -8,34 +9,41 @@ const { upperCaseFirst } = require("upper-case-first");
89
const { capitalCase } = require("change-case");
910

1011
const cors = require("cors");
12+
const path = require("path");
1113
const axios = require("axios");
1214
const morgan = require("morgan");
1315
const dotenv = require("dotenv");
1416
const express = require("express");
1517
const compression = require("compression");
18+
const serveStatic = require("serve-static");
1619

20+
const pkg = require("./package.json");
1721
const mainChat = require("./intents/Main_Chat.json");
22+
const supportChat = require("./intents/support.json");
23+
const wikipediaChat = require("./intents/wikipedia.json");
1824
const welcomeChat = require("./intents/Default_Welcome.json");
1925
const fallbackChat = require("./intents/Default_Fallback.json");
2026
const unitConverterChat = require("./intents/unit_converter.json");
21-
const wikipediaChat = require("./intents/wikipedia.json");
2227

2328
dotenv.config();
2429

30+
const standardRating = 0.6;
31+
const developerName = pkg.author.name;
32+
const developerEmail = pkg.author.email;
33+
const bugReportUrl = pkg.bugs.url;
34+
2535
const app = express();
2636
const port = process.env.PORT || 3000;
2737

28-
const allQustions = [];
38+
let allQustions = [];
2939

30-
for (let i = 0; i < mainChat.length; i++) {
31-
for (let j = 0; j < mainChat[i].questions.length; j++) {
32-
allQustions.push(mainChat[i].questions[j]);
33-
}
34-
}
40+
allQustions = _.concat(allQustions, wikipediaChat);
41+
allQustions = _.concat(allQustions, unitConverterChat);
42+
allQustions = _.concat(allQustions, _.flattenDeep(_.map(supportChat, "questions")));
43+
allQustions = _.concat(allQustions, _.flattenDeep(_.map(mainChat, "questions")));
3544

36-
for (let i = 0; i < unitConverterChat.length; i++) {
37-
allQustions.push(unitConverterChat[i].replace("{amount}", 10).replace("{unitFrom}", "cm").replace("{unitTo}", "mm"));
38-
}
45+
allQustions = _.uniq(allQustions);
46+
allQustions = _.compact(allQustions);
3947

4048
const changeUnit = (amount, unitFrom, unitTo) => {
4149
try {
@@ -53,7 +61,7 @@ const sendAllQuestions = (req, res) => {
5361

5462
try {
5563
allQustions.forEach((qus) => {
56-
if (qus.length >= 10) {
64+
if (qus.length >= 15) {
5765
if (/^(can|are|may|how|what|when|who|do|where|your|from|is|will|why)/gi.test(qus)) {
5866
humanQuestions.push(`${upperCaseFirst(qus)}?`);
5967
} else {
@@ -78,25 +86,39 @@ const sendAnswer = async (req, res) => {
7886
let isFallback = false;
7987
let responseText = null;
8088
let rating = 0;
81-
let similarQuestion = null;
8289
let action = null;
8390

8491
try {
8592
const query = decodeURIComponent(req.query.q).replace(/\s+/g, " ").trim() || "Hello";
8693
const humanInput = lowerCase(query.replace(/(\?|\.|!)$/gmi, ""));
94+
8795
const regExforUnitConverter = /(convert|change|in).{1,2}(\d{1,8})/gmi;
8896
const regExforWikipedia = /(search for|tell me about|what is|who is)(?!.you) (.{1,30})/gmi;
97+
const regExforSupport = /(invented|programmer|teacher|create|maker|who made|creator|developer|bug|email|report|problems)/gmi;
8998

90-
if (regExforUnitConverter.test(humanInput)) {
91-
const similarQuestionObj = stringSimilarity.findBestMatch(humanInput, unitConverterChat).bestMatch;
92-
similarQuestion = similarQuestionObj.target;
93-
const valuesObj = extractValues(humanInput, similarQuestion, {
94-
delimiters: ["{", "}"],
95-
});
99+
let similarQuestionObj;
96100

97-
rating = 1;
101+
if (regExforUnitConverter.test(humanInput)) {
98102
action = "unit_converter";
103+
similarQuestionObj = stringSimilarity.findBestMatch(humanInput, unitConverterChat).bestMatch;
104+
} else if (regExforWikipedia.test(humanInput)) {
105+
action = "wikipedia";
106+
similarQuestionObj = stringSimilarity.findBestMatch(humanInput, wikipediaChat).bestMatch;
107+
} else if (regExforSupport.test(humanInput)) {
108+
action = "support";
109+
similarQuestionObj = stringSimilarity.findBestMatch(humanInput, _.flattenDeep((_.map(supportChat, "questions")))).bestMatch;
110+
} else {
111+
action = "main_chat";
112+
similarQuestionObj = stringSimilarity.findBestMatch(humanInput, _.flattenDeep((_.map(mainChat, "questions")))).bestMatch;
113+
}
114+
115+
const similarQuestionRating = similarQuestionObj.rating;
116+
const similarQuestion = similarQuestionObj.target;
117+
118+
if (action == "unit_converter") {
119+
const valuesObj = extractValues(humanInput, similarQuestion, { delimiters: ["{", "}"] });
99120

121+
rating = 1;
100122
try {
101123
const {
102124
amount,
@@ -109,34 +131,49 @@ const sendAnswer = async (req, res) => {
109131
responseText = "One or more units are missing.";
110132
console.log(error);
111133
}
112-
} else if (regExforWikipedia.test(humanInput)) {
113-
const similarQuestionObj = stringSimilarity.findBestMatch(humanInput, wikipediaChat).bestMatch;
114-
similarQuestion = similarQuestionObj.target;
115-
const valuesObj = extractValues(humanInput, similarQuestion, {
116-
delimiters: ["{", "}"],
117-
});
134+
} else if (action == "wikipedia") {
135+
const valuesObj = extractValues(humanInput, similarQuestion, { delimiters: ["{", "}"] });
118136

119137
let { topic } = valuesObj;
120138
topic = capitalCase(topic);
121139

122-
const wikipediaResponse = await axios(`https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=1&explaintext=1&titles=${topic}`);
123-
const wikipediaResponseData = wikipediaResponse.data;
124-
const wikipediaResponsePageNo = Object.keys(wikipediaResponseData.query.pages)[0];
125-
const wikipediaResponseText = wikipediaResponseData.query.pages[wikipediaResponsePageNo].extract;
126-
127-
if (wikipediaResponseText == undefined || wikipediaResponseText == "") {
128-
responseText = `Sorry, we can't find any article related to "${topic}".`;
129-
isFallback = true;
130-
} else {
131-
responseText = wikipediaResponseText;
140+
try {
141+
const wikipediaResponse = await axios(`https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=1&explaintext=1&titles=${topic}`);
142+
const wikipediaResponseData = wikipediaResponse.data;
143+
const wikipediaResponsePageNo = Object.keys(wikipediaResponseData.query.pages)[0];
144+
const wikipediaResponseText = wikipediaResponseData.query.pages[wikipediaResponsePageNo].extract;
145+
146+
if (wikipediaResponseText == undefined || wikipediaResponseText == "") {
147+
responseText = `Sorry, I can't find any article related to "${topic}".`;
148+
isFallback = true;
149+
} else {
150+
responseText = wikipediaResponseText;
151+
}
152+
} catch (error) {
153+
if (/(ETIMEDOUT|ENOTFOUND)/gi.test(error.message)) {
154+
responseText = `Sorry, we can't find any article related to "${topic}".`;
155+
}
132156
}
157+
} else if (action == "support") {
158+
rating = similarQuestionRating;
159+
160+
if (similarQuestionRating > standardRating) {
161+
for (let i = 0; i < supportChat.length; i++) {
162+
for (let j = 0; j < supportChat[i].questions.length; j++) {
163+
if (similarQuestion == supportChat[i].questions[j]) {
164+
responseText = _.sample(supportChat[i].answers);
165+
}
166+
}
167+
}
168+
}
169+
} else if (/(?:my name is|I'm|I am) (.{1,30})/gmi.test(humanInput)) {
170+
const humanName = /(?:my name is|I'm|I am) (.{1,30})/gmi.exec(humanInput);
171+
responseText = `Nice to meet you ${humanName[1]}.`;
172+
rating = 1;
133173
} else {
134-
const similarQuestionObj = stringSimilarity.findBestMatch(humanInput, allQustions).bestMatch;
135-
const similarQuestionRating = similarQuestionObj.rating;
136-
similarQuestion = similarQuestionObj.target;
137174
action = "main_chat";
138175

139-
if (similarQuestionRating > 0.6) {
176+
if (similarQuestionRating > standardRating) {
140177
for (let i = 0; i < mainChat.length; i++) {
141178
for (let j = 0; j < mainChat[i].questions.length; j++) {
142179
if (similarQuestion == mainChat[i].questions[j]) {
@@ -156,6 +193,16 @@ const sendAnswer = async (req, res) => {
156193
}
157194
}
158195

196+
if (responseText == null) {
197+
responseText = _.sample(fallbackChat);
198+
isFallback = true;
199+
} else if (action != "wikipedia") {
200+
responseText = responseText
201+
.replace(/(\[NAME\])/g, developerName)
202+
.replace(/(\[EMAIL\])/g, developerEmail)
203+
.replace(/(\[BUG_URL\])/g, bugReportUrl);
204+
}
205+
159206
res.json({
160207
responseText,
161208
query,
@@ -174,12 +221,28 @@ const sendAnswer = async (req, res) => {
174221
}
175222
};
176223

224+
const notFound = async (req, res) => {
225+
try {
226+
const pageNotFoundHtml = await fs.readFileSync(
227+
path.join(__dirname, "public/404.html"),
228+
"utf8",
229+
);
230+
res.status(404).send(pageNotFoundHtml);
231+
} catch (err) {
232+
res.status(404).send("Page Not Found!");
233+
console.log(err);
234+
}
235+
};
236+
177237
app.use(cors());
178238
app.use(compression());
179239
app.set("json spaces", 4);
180-
app.use("/api/*", morgan("tiny"));
240+
app.use("/api/", morgan("tiny"));
181241
app.get("/api/question", sendAnswer);
182242
app.get("/api/welcome", sendWelcomeMessage);
183243
app.get("/api/allQuestions", sendAllQuestions);
244+
app.use(serveStatic(path.join(__dirname, "public")));
245+
app.get("*", notFound);
246+
app.get("");
184247

185248
app.listen(port, () => console.log(`app listening on port ${port}!`));

intents/Default_Fallback.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
[
2-
"I didn't get that. Can you say it again?",
3-
"I missed what you said. Say it again?",
2+
"I missed what you said.",
43
"Sorry, I didn't get that.",
54
"Sorry, what was that?",
65
"What was that?",

intents/support.json

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
[
2+
{
3+
"questions": [
4+
"bring me up your developers email",
5+
"how to email your developers",
6+
"could you please give me the email address of your developers",
7+
"show me the email of your developers",
8+
"get me your developers email",
9+
"I want to contact your developers show me their email",
10+
"I need to contact your developers give me their email address",
11+
"what's your developers email",
12+
"how to email your creators",
13+
"give me the email address of your developers",
14+
"I would like to write an email to your developers",
15+
"where to get your developers email",
16+
"can I send an email to your developers",
17+
"your creators email",
18+
"I want to contact your developers by email",
19+
"your developers email"
20+
],
21+
"answers": [
22+
"My developer email is [EMAIL]."
23+
]
24+
},
25+
{
26+
"questions": [
27+
"what's the name of your programmer",
28+
"who is your teacher",
29+
"and who create you",
30+
"who made your application",
31+
"what is your makers name",
32+
"so who created you",
33+
"can you tell me who created you",
34+
"do you know your creators",
35+
"do you know your maker",
36+
"can you tell me something about your creators",
37+
"your developers",
38+
"I said who are your creators",
39+
"who did create you",
40+
"what is your developer name",
41+
"do you know who makes you",
42+
"who made you",
43+
"what is your teachers name",
44+
"what's the name of your creators",
45+
"so who made this application",
46+
"so who is your creator",
47+
"who created you",
48+
"so who made you",
49+
"who is your programmer",
50+
"what is the name of your developers",
51+
"so who create you",
52+
"what's the name of your creator",
53+
"do you know who created you",
54+
"tell me who is your creator",
55+
"who were your creators",
56+
"do you know who made you",
57+
"and who created you",
58+
"who is your developer",
59+
"I said who made you tell me"
60+
],
61+
"answers": []
62+
},
63+
{
64+
"questions": [
65+
"I need to report a bug that I've found",
66+
"report bug to developers",
67+
"send report about your problems",
68+
"I'm having problem with this app",
69+
"I need to report bug",
70+
"you have bugs everywhere",
71+
"tell your developers that you have a bug",
72+
"you have problems in understanding",
73+
"send bug report to your creators",
74+
"you are full of problems",
75+
"there are bugs",
76+
"I want to show errors to your creators",
77+
"I want to report error",
78+
"I've found bugs",
79+
"I need to report a bug that I've found in you",
80+
"send problem to developers"
81+
],
82+
"answers": [
83+
"You can report your bug here."
84+
]
85+
}
86+
]

package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,18 @@
33
"description": "A Powerful ChatBot in NodeJs",
44
"version": "0.0.1",
55
"private": false,
6-
"license": "Apache Version 2.0",
6+
"license": "MIT",
7+
"author": {
8+
"name": "Prateek Singh",
9+
"email": "bhps82@gmail.com"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "https://github.com/7orp3do/javascript-chatbot.git"
14+
},
15+
"bugs": {
16+
"url": "https://github.com/7orp3do/javascript-chatbot/issues"
17+
},
718
"scripts": {
819
"dev": "nodemon",
920
"start": "node index.js",

public/index.html

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,29 +35,33 @@
3535
<h2>JavaScript ChatBot</h2>
3636
<p class="typing">bot is typing. . .</p>
3737
</div>
38-
<div>
38+
<div onclick="toogleShowQuestions()">
3939
<div class="status"></div>
4040
</div>
4141
</header>
4242

4343
<main>
44+
</main>
4445

45-
<div class="main-background">
46-
<div>
47-
<h3>JavaScript ChatBot</h3>
48-
<p>A Simple & Powerful chatbot in JavaScript.</p>
49-
</div>
46+
<div class="main-background">
47+
<div>
48+
<h3>JavaScript ChatBot</h3>
49+
<p>A Simple & Powerful chatbot in JavaScript.</p>
5050
</div>
51-
</main>
51+
</div>
5252

53-
<section class="all-questions">
54-
<p>How are You?</p>
53+
<section class="all-questions">
5554
</section>
5655

5756
<footer>
5857
<form id="chat-form">
59-
<input type="text" class="chat-input">
60-
<button type="submit" class="chat-submit">S</button>
58+
<input type="text" class="chat-input" required>
59+
<button type="submit" class="chat-submit"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"
60+
viewBox="0 0 24 24">
61+
<path
62+
d="M24 0l-6 22-8.129-7.239 7.802-8.234-10.458 7.227-7.215-1.754 24-12zm-15 16.668v7.332l3.258-4.431-3.258-2.901z" />
63+
</svg>
64+
</button>
6165
</form>
6266
</footer>
6367

0 commit comments

Comments
 (0)