11/* eslint-disable max-len */
2+ const fs = require ( "fs" ) ;
23const _ = require ( "lodash" ) ;
34const convert = require ( "convert-units" ) ;
45const extractValues = require ( "extract-values" ) ;
@@ -8,34 +9,41 @@ const { upperCaseFirst } = require("upper-case-first");
89const { capitalCase } = require ( "change-case" ) ;
910
1011const cors = require ( "cors" ) ;
12+ const path = require ( "path" ) ;
1113const axios = require ( "axios" ) ;
1214const morgan = require ( "morgan" ) ;
1315const dotenv = require ( "dotenv" ) ;
1416const express = require ( "express" ) ;
1517const compression = require ( "compression" ) ;
18+ const serveStatic = require ( "serve-static" ) ;
1619
20+ const pkg = require ( "./package.json" ) ;
1721const mainChat = require ( "./intents/Main_Chat.json" ) ;
22+ const supportChat = require ( "./intents/support.json" ) ;
23+ const wikipediaChat = require ( "./intents/wikipedia.json" ) ;
1824const welcomeChat = require ( "./intents/Default_Welcome.json" ) ;
1925const fallbackChat = require ( "./intents/Default_Fallback.json" ) ;
2026const unitConverterChat = require ( "./intents/unit_converter.json" ) ;
21- const wikipediaChat = require ( "./intents/wikipedia.json" ) ;
2227
2328dotenv . 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+
2535const app = express ( ) ;
2636const 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
4048const 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 ( / ^ ( c a n | a r e | m a y | h o w | w h a t | w h e n | w h o | d o | w h e r e | y o u r | f r o m | i s | w i l l | w h y ) / 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 = / ( c o n v e r t | c h a n g e | i n ) .{ 1 , 2 } ( \d { 1 , 8 } ) / gmi;
8896 const regExforWikipedia = / ( s e a r c h f o r | t e l l m e a b o u t | w h a t i s | w h o i s ) (? ! .y o u ) ( .{ 1 , 30 } ) / gmi;
97+ const regExforSupport = / ( i n v e n t e d | p r o g r a m m e r | t e a c h e r | c r e a t e | m a k e r | w h o m a d e | c r e a t o r | d e v e l o p e r | b u g | e m a i l | r e p o r t | p r o b l e m s ) / 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 ( / ( E T I M E D O U T | E N O T F O U N D ) / 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 ( / (?: m y n a m e i s | I ' m | I a m ) ( .{ 1 , 30 } ) / gmi. test ( humanInput ) ) {
170+ const humanName = / (?: m y n a m e i s | I ' m | I a m ) ( .{ 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 ( / ( \[ N A M E \] ) / g, developerName )
202+ . replace ( / ( \[ E M A I L \] ) / g, developerEmail )
203+ . replace ( / ( \[ B U G _ U R L \] ) / 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+
177237app . use ( cors ( ) ) ;
178238app . use ( compression ( ) ) ;
179239app . set ( "json spaces" , 4 ) ;
180- app . use ( "/api/* " , morgan ( "tiny" ) ) ;
240+ app . use ( "/api/" , morgan ( "tiny" ) ) ;
181241app . get ( "/api/question" , sendAnswer ) ;
182242app . get ( "/api/welcome" , sendWelcomeMessage ) ;
183243app . get ( "/api/allQuestions" , sendAllQuestions ) ;
244+ app . use ( serveStatic ( path . join ( __dirname , "public" ) ) ) ;
245+ app . get ( "*" , notFound ) ;
246+ app . get ( "" ) ;
184247
185248app . listen ( port , ( ) => console . log ( `app listening on port ${ port } !` ) ) ;
0 commit comments