0

我使用聊天脚本创建了一个机器人。目标是将它作为网站的助手(用户将提出有关网站的问题,机器人将回答/可能将他重定向到网站的适当部分)。

该机器人使用二进制文件夹中提供的 .exe 响应良好,甚至在使用 WEBINTERFACE\BETTER 文件夹中的 .php 文件时也能正常响应。尝试在弹出式聊天窗口中使用它时会出现问题,所述窗口基于看到的窗口在这里(https://www.w3schools.com/howto/howto_js_popup_chat.asp)。

当我尝试运行该页面时,机器人要么无响应,要么产生以下错误:

Fatal error: Uncaught TypeError: extract(): Argument #1 ($array) must be of type array, null given in C:\xampp\htdocs\chatscript\WEBINTERFACE\htmltest\ui2.php:38 Stack trace: #0 C:\xampp\htdocs\chatscript\WEBINTERFACE\htmltest\ui2.php(38): extract(NULL) #1 {main} thrown in C:\xampp\htdocs\chatscript\WEBINTERFACE\htmltest\ui2.php on line 38

ui2.php的代码(与聊天脚本的原始ui.php文件相同):

$host = "localhost";//  <<<<<<<<<<<<<<<<< YOUR CHATSCRIPT SERVER IP ADDRESS OR HOST-NAME GOES HERE
$port = 1024;          // <<<<<<< your port number if different from 1024
$bot  = "";       // <<<<<<< desired botname, or "" for default bot
//=========================

// Please do not change anything below this line.
$null = "\x00";
$postVars = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
extract($postVars);

if (isset($send))
{
    // open client connection to TCP server
    $userip = $_SERVER['REMOTE_ADDR']; // get actual ip address of user as his id. 
    // To check for proxies you can replace the line above with the code below, but it is easily faked so it's insecure:
    // $userip = isset($_SERVER['X_FORWARDED_FOR']) ? $_SERVER['X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
     
     
    $msg = $userip.$null.$bot.$null.$message.$null;

    // fifth parameter in fsockopen is timeout in seconds
    if(!$fp=fsockopen($host,$port,$errstr,$errno,300))
    {
        trigger_error('Error opening socket',E_USER_ERROR);
    }

    // write message to socket server
    $ret = '';
    fputs($fp,$msg);
    while (!feof($fp))
    {
        $ret .= fgets($fp, 512);
    }

    // close socket connection
    fclose($fp);
    exit($ret);}  

还有我的 index2.php(聊天窗口所在的位置):

<!DOCTYPE HTML>
<html>
  <head>
    <title>
      CHATSCRIPT SERVER
    </title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style type="text/css">
      body {font-family: Arial, Helvetica, sans-serif;}
* {box-sizing: border-box;}

/* Button used to open the chat form - fixed at the bottom of the page */
.open-button {
  background-color: #555;
  color: white;
  padding: 16px 20px;
  border: none;
  cursor: pointer;
  opacity: 0.8;
  position: fixed;
  bottom: 23px;
  right: 28px;
  width: 280px;
}

/* The popup chat - hidden by default */
.chat-popup {
  display: none;
  position: fixed;
  bottom: 0;
  right: 15px;
  border: 3px solid #f1f1f1;
  z-index: 9;
}

/* Add styles to the form container */
.form-container {
  max-width: 300px;
  padding: 10px;
  background-color: white;
}

/* Full-width textarea */
.form-container textarea {
  width: 100%;
  padding: 15px;
  margin: 5px 0 22px 0;
  border: none;
  background: #f1f1f1;
  resize: none;
  min-height: 30px;
}

#responseHolder {
        min-width: 10%;
        min-height: 10%;
        width: 80%;
        height: 300px;
        overflow: auto;
        margin: 10px auto;
        background-color: #f1f1f1;
      }



/* When the textarea gets focus, do something */
.form-container textarea:focus {
  background-color: #ddd;
  outline: none;
}

/* Set a style for the submit/send button */
.form-container .btn {
  background-color: #4CAF50;
  color: white;
  padding: 16px 20px;
  border: none;
  cursor: pointer;
  width: 100%;
  margin-bottom:10px;
  opacity: 0.8;
}

/* Add a red background color to the cancel button */
.form-container .cancel {
  background-color: red;
}

/* Add some hover effects to buttons */
.form-container .btn:hover, .open-button:hover {
  opacity: 1;
}

    </style>
  </head>
  <body>
  
 
   <button class="open-button" onclick="openForm()">Chat</button>
   <!--<div class="chat-popup" id="myForm" action="#">-->
   <input type="hidden" id="txtUser" name="user" size="20" value="You" />
   <div class="chat-popup" id="myForm2" action="#">
   <div id="responseHolder"></div>
    <form id="myForm" class="form-container" action="#">
      <label for="message"><b>Message</b></label>
      <textarea type="text" placeholder="Type message.." name="message"  id="txtMessage" required></textarea>
      <button type="submit" class="btn" name="send">Send</button>
      <button type="button" class="btn cancel" onclick="closeForm()">Close</button>
    </form>
   </div>





<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript">
var botName = 'Testy McTesty';      // change this to your bot name

// declare timer variables
var alarm = null;
var callback = null;
var loopback = null;

$(function(){
    $('#myForm').submit(function(e){
    // this function overrides the form's submit() method, allowing us to use AJAX calls to communicate with the ChatScript server
    e.preventDefault();  // Prevent the default submit() method
    var name = $('#txtUser').val();
    if (name == '') {
        alert('Please provide your name.');
        document.getElementById('txtUser').focus();
    }
    var chatLog = $('#responseHolder').html();
    var youSaid = '<strong>' + name + ':</strong> ' + $('#txtMessage').val() + "<br>\n";
    update(youSaid);
    var data = $(this).serialize();
    sendMessage(data);
    $('#txtMessage').val('').focus();
    });

    // any user typing cancels loopback or callback for this round 
    $('#txtMessage').keypress(function(){
          window.clearInterval(loopback);
          window.clearTimeout(callback);
        });
});


function sendMessage(data){ //Sends inputs to the ChatScript server, and returns the response-  data - a JSON string of input information
$.ajax({
    url: 'ui2.php',
    dataType: 'text',
    data: data,
    type: 'post',
    success: function(response){
        processResponse(parseCommands(response));
    },
    error: function(xhr, status, error){
        alert('oops? Status = ' + status + ', error message = ' + error + "\nResponse = " + xhr.responseText);
    }
  });
}

function parseCommands(response){ // Response is data from CS server. This processes OOB commands sent from the CS server returning the remaining response w/o oob commands

    var len  = response.length;
    var i = -1;
    while (++i < len )
    {
        if (response.charAt(i) == ' ' || response.charAt(i) == '\t') continue; // starting whitespace
        if (response.charAt(i) == '[') break;   // we have an oob starter
        return response;                        // there is no oob data 
    }
    if ( i == len) return response; // no starter found
    var user = $('#txtUser').val();
     
    // walk string to find oob data and when ended return rest of string
    var start = 0;
    while (++i < len )
    {
        if (response.charAt(i) == ' ' || response.charAt(i) == ']') // separation
        {
            if (start != 0) // new oob chunk
            {
                var blob = response.slice(start,i);
                start = 0;

                var commandArr = blob.split('=');
                if (commandArr.length == 1) continue;   // failed to split left=right

                var command = commandArr[0]; // left side is command 
                var interval = (commandArr.length > 1) ? commandArr[1].trim() : -1; // right side is millisecond count
                if (interval == 0)  /* abort timeout item */
                {
                    switch (command){
                        case 'alarm':
                            window.clearTimeout(alarm);
                            alarm = null;
                            break;
                        case 'callback':
                            window.clearTimeout(callback);
                            callback = null;
                            break;
                        case 'loopback':
                            window.clearInterval(loopback);
                            loopback = null;
                            break;
                    }
                }
                else if (interval == -1) interval = -1; // do nothing
                else
                {
                    var timeoutmsg = {user: user, send: true, message: '[' + command + ' ]'}; // send naked command if timer goes off 
                    switch (command) {
                        case 'alarm':
                            alarm = setTimeout(function(){sendMessage(timeoutmsg );}, interval);
                            break;
                        case 'callback':
                            callback = setTimeout(function(){sendMessage(timeoutmsg );}, interval);
                            break;
                        case 'loopback':
                            loopback = setInterval(function(){sendMessage(timeoutmsg );}, interval);
                            break;
                    }
                }
            } // end new oob chunk
            if (response.charAt(i) == ']') return response.slice(i + 2); // return rest of string, skipping over space after ] 
        } // end if
        else if (start == 0) start = i; // begin new text blob
    } // end while
    return response;    // should never get here
 }
 
 
 
 function update(text){ // text is  HTML code to append to the 'chat log' div. This appends the input text to the response div
    var chatLog = $('#responseHolder').html();
    $('#responseHolder').html(chatLog + text);
    var rhd = $('#responseHolder');
    var h = rhd.get(0).scrollHeight;
    rhd.scrollTop(h);
}
 

function processResponse(response) { // given the final CS text, converts the parsed response from the CS server into HTML code for adding to the response holder div
    var botSaid = '<strong>' + botName + ':</strong> ' + response + "<br>\n";
    update(botSaid);
}

</script>


<script>
function openForm() {
  document.getElementById("myForm2").style.display = "block";
}

function closeForm() {
  document.getElementById("myForm2").style.display = "none";
}
</script>


</body>
</html>

和聊天脚本原始 index.php:

<!DOCTYPE HTML>
<html>
  <head>
    <title>
      CHATSCRIPT SERVER
    </title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style type="text/css">
      #responseHolder {
        min-width: 600px;
        min-height: 300px;
        width: 80%;
        height: 300px;
        overflow: auto;
        margin: 10px auto;
        background-color: pink;
      }

    </style>
  </head>
  <body>
    <div id="responseHolder"></div>
    <form id="frmChat" action="#">
    <p>
      Enter your message below:
    </p>
    <table>
      <tr>
        <td>Name:</td>
        <td>
          <input type="text" id="txtUser" name="user" size="20" value="" />
          <input type="hidden" name="send" />
        </td>
      </tr>
      <tr>
        <td>Message:</td>
        <td><input type="text" name="message" id="txtMessage" size="70" /></td>
      </tr>
      <tr>
        <td colspan="2"><input type="submit" name="send" value="Send Value" /></td>
      </tr>
    </table>
    </form>

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript">

var botName = 'Testy McTesty';      // change this to your bot name

// declare timer variables
var alarm = null;
var callback = null;
var loopback = null;

$(function(){
    $('#frmChat').submit(function(e){
    // this function overrides the form's submit() method, allowing us to use AJAX calls to communicate with the ChatScript server
    e.preventDefault();  // Prevent the default submit() method
    var name = $('#txtUser').val();
    if (name == '') {
        alert('Please provide your name.');
        document.getElementById('txtUser').focus();
    }
    var chatLog = $('#responseHolder').html();
    var youSaid = '<strong>' + name + ':</strong> ' + $('#txtMessage').val() + "<br>\n";
    update(youSaid);
    var data = $(this).serialize();
    sendMessage(data);
    $('#txtMessage').val('').focus();
    });

    // any user typing cancels loopback or callback for this round 
    $('#txtMessage').keypress(function(){
          window.clearInterval(loopback);
          window.clearTimeout(callback);
        });
});

function sendMessage(data){ //Sends inputs to the ChatScript server, and returns the response-  data - a JSON string of input information
$.ajax({
    url: 'ui.php',
    dataType: 'text',
    data: data,
    type: 'post',
    success: function(response){
        processResponse(parseCommands(response));
    },
    error: function(xhr, status, error){
        alert('oops? Status = ' + status + ', error message = ' + error + "\nResponse = " + xhr.responseText);
    }
  });
}

function parseCommands(response){ // Response is data from CS server. This processes OOB commands sent from the CS server returning the remaining response w/o oob commands

    var len  = response.length;
    var i = -1;
    while (++i < len )
    {
        if (response.charAt(i) == ' ' || response.charAt(i) == '\t') continue; // starting whitespace
        if (response.charAt(i) == '[') break;   // we have an oob starter
        return response;                        // there is no oob data 
    }
    if ( i == len) return response; // no starter found
    var user = $('#txtUser').val();
     
    // walk string to find oob data and when ended return rest of string
    var start = 0;
    while (++i < len )
    {
        if (response.charAt(i) == ' ' || response.charAt(i) == ']') // separation
        {
            if (start != 0) // new oob chunk
            {
                var blob = response.slice(start,i);
                start = 0;

                var commandArr = blob.split('=');
                if (commandArr.length == 1) continue;   // failed to split left=right

                var command = commandArr[0]; // left side is command 
                var interval = (commandArr.length > 1) ? commandArr[1].trim() : -1; // right side is millisecond count
                if (interval == 0)  /* abort timeout item */
                {
                    switch (command){
                        case 'alarm':
                            window.clearTimeout(alarm);
                            alarm = null;
                            break;
                        case 'callback':
                            window.clearTimeout(callback);
                            callback = null;
                            break;
                        case 'loopback':
                            window.clearInterval(loopback);
                            loopback = null;
                            break;
                    }
                }
                else if (interval == -1) interval = -1; // do nothing
                else
                {
                    var timeoutmsg = {user: user, send: true, message: '[' + command + ' ]'}; // send naked command if timer goes off 
                    switch (command) {
                        case 'alarm':
                            alarm = setTimeout(function(){sendMessage(timeoutmsg );}, interval);
                            break;
                        case 'callback':
                            callback = setTimeout(function(){sendMessage(timeoutmsg );}, interval);
                            break;
                        case 'loopback':
                            loopback = setInterval(function(){sendMessage(timeoutmsg );}, interval);
                            break;
                    }
                }
            } // end new oob chunk
            if (response.charAt(i) == ']') return response.slice(i + 2); // return rest of string, skipping over space after ] 
        } // end if
        else if (start == 0) start = i; // begin new text blob
    } // end while
    return response;    // should never get here
 }
 
function update(text){ // text is  HTML code to append to the 'chat log' div. This appends the input text to the response div
    var chatLog = $('#responseHolder').html();
    $('#responseHolder').html(chatLog + text);
    var rhd = $('#responseHolder');
    var h = rhd.get(0).scrollHeight;
    rhd.scrollTop(h);
}

function processResponse(response) { // given the final CS text, converts the parsed response from the CS server into HTML code for adding to the response holder div
    var botSaid = '<strong>' + botName + ':</strong> ' + response + "<br>\n";
    update(botSaid);
}

</script>
</body>
</html>


是的,除了聊天窗口(它本身没有太多编辑)之外,网页是空的,因为我想让机器人在其他任何事情之前在网页中工作(我使用 XAMPP 进行连接)。

4

1 回答 1

0

如果机器人使用 BETTER ui 正确对应,则首先尝试分析发送到ui.php的 $postVars(带有 vardump)。然后按照相同的步骤在弹出窗口中使用它。

该错误告诉您,ui.php 期望从您的 index2.php 中获取一个数组,但它没有收到任何可提取的内容。

因为数据是通过AJAX发送的,可能和原来的 JS 代码和你弹出的 JS 代码有冲突。

于 2021-01-24T08:50:26.287 回答