public static function respond($in_input) { if (trim($in_input) == '') { return JxBotConverse::get_greeting(); } else { return JxBotConverse::get_response($in_input); } }
?> <div class="right" id="right-nav"> <h2>Recent Conversations</h2> <?php if (isset($_REQUEST['purge-old'])) { purge_old_logs(); } ?> <p><button type="submit" name="purge-old" value="month">Purge Old Log Entries</button></p> <?php $sessions = JxBotConverse::latest_sessions(); JxWidget::grid(array(array('id' => 0, 'visible' => false, 'key' => true), array('id' => 1, 'label' => 'Client', 'link' => '?page=chat&subpage=logs&convo=$$')), $sessions); ?> </div> <div id="centre-content"> <h2>Transcript</h2> <style type="text/css"> .log { line-height: 1.7em; } .log-cl
die('Direct script access not permitted.'); } JxWidget::tabs(array(array('Talk', '?page=chat', 'subpage', ''), array('Defaults', '?page=chat&subpage=defaults', 'subpage', 'defaults'), array('Logs', '?page=chat&subpage=logs', 'subpage', 'logs'))); $subpage = JxBotUtil::inputs('subpage'); if ($subpage['subpage'] == 'defaults') { require_once 'admin_client.php'; } else { if ($subpage['subpage'] == 'logs') { require_once 'admin_logs.php'; } else { $inputs = JxBotUtil::inputs('input'); if (trim($inputs['input']) != '') { JxBotConverse::resume_conversation('admin'); $response = JxBotConverse::get_response($inputs['input']); } else { $response = JxBotConverse::get_greeting(); } ?> <?php JxWidget::textfield(array('name' => 'input', 'label' => 'Administrator', 'max' => 150, 'autofocus' => true)); ?> <p><?php JxWidget::button('Talk'); ?> </p>
public static function get_response($in_input) { if (JxBotConverse::user_input_looks_strange($in_input)) { return 'Your last comment looks a bit strange.'; } // ** configurable? /* cap general server requests (safety); should be configurable as people have different host specs; 300 recommended for small shared host */ $cap_bot_ipm = JxBotConfig::option('sys_cap_bot_ipm', 300); if ($cap_bot_ipm > 0) { $stmt = JxBotDB::$db->prepare('SELECT COUNT(*) FROM log WHERE stamp >= DATE_SUB(NOW(), INTERVAL 1 MINUTE)'); $stmt->execute(); $last_min_total = intval($stmt->fetchAll(PDO::FETCH_NUM)[0][0]); if ($last_min_total >= $cap_bot_ipm) { return 'Sorry, I\'m too busy to chat right now. Please come back later.'; } } /* count interaction */ JxBotDB::$db->exec('UPDATE stats SET interactions = interactions + 1'); /* start timer */ $start_time = microtime(true); /* initalize tracking variables */ JxBotConverse::$match_time = 0.0; JxBotConverse::$service_time = 0.0; JxBotConverse::$iq_score = 0.0; JxBotConverse::$category_stack = array(); $fault = false; /* run the bot */ try { $output = JxBotConverse::srai($in_input); } catch (Exception $err) { $output = $err->getMessage(); $fault = true; } /* end timer */ $end_time = microtime(true); //print 'IQ '.JxBotConverse::$iq_score. '<br>'; /* log this interaction */ if (trim($output) == '') { $fault = true; } if ($fault) { JxBotConverse::$iq_score = -1; } JxBotConverse::log($in_input, $output, $end_time - $start_time, JxBotConverse::$match_time, JxBotConverse::$service_time, JxBotConverse::$iq_score); /* return the bot response */ if ($fault) { return 'I do apologise. I seem to be experiencing a positronic malfunction.'; } return $output; }
public function generate($in_context) { switch ($this->name) { case 'system': /* security implications; will not implement until reasonable controls are developed and an on/off switch */ /* security implications; will not implement until reasonable controls are developed and an on/off switch */ case 'javascript': /* server-side javascript is not implemented */ break; case 'think': $this->text_value($in_context); break; case 'template': case 'gossip': /* doesn't do anything in this AIML interpreter and is removed in AIML 2.0 */ /* doesn't do anything in this AIML interpreter and is removed in AIML 2.0 */ case 'x-learn-1': /* AIML 1 learn tag to be filtered on import and contents passed through without further action */ return $this->text_value($in_context); case 'random': $count = $this->child_element_count(); $index = mt_rand(1, $count) - 1; return $this->child_element($index)->text_value($in_context); case 'condition': $loop = false; // preparation for AIML 2 loop; will need to keep a stack & check the stack so it can be toggled // by a <loop/> element anywhere in the depth of the <li> do { $count = $this->child_element_count('li'); if ($count == 0) { $predicate = $this->child_or_attr_named($in_context, 'name'); $value = JxBotConverse::predicate($predicate); $pattern = $this->child_or_attr_named($in_context, 'value'); if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $this->text_value($in_context, array('name', 'value')); } } else { $count = $this->child_element_count(); $predicate = $this->child_or_attr_named($in_context, 'name', null); if ($predicate !== null) { $value = JxBotConverse::predicate($predicate); for ($i = 0; $i < $count; $i++) { $item = $this->child_element($i); $pattern = $item->child_or_attr_named($in_context, 'value', null); if ($pattern === null) { return $item->text_value($in_context, array('value')); } if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $item->text_value($in_context, array('value')); } } } else { for ($i = 0; $i < $count; $i++) { $item = $this->child_element($i); $predicate = $item->child_or_attr_named($in_context, 'name'); $value = JxBotConverse::predicate($predicate); $pattern = $item->child_or_attr_named($in_context, 'value', null); if ($pattern === null) { return $item->text_value($in_context, array('value', 'name')); } if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $item->text_value($in_context, array('value', 'name')); } } } } } while ($loop); break; case 'star': case 'thatstar': case 'topicstar': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return $this->get_capture($in_context, $this->name, $index); case 'srai': return JxBotConverse::srai($this->text_value($in_context)); case 'sr': /* srai star /srai */ return JxBotConverse::srai($this->get_capture($in_context, 'star', 1)); case 'bot': case 'get': $name = trim($this->child_or_attr_named($in_context, 'name')); if ($name !== '') { if ($this->name == 'get') { return JxBotConverse::predicate($name); } else { if ($name == 'size') { return JxBotNLData::pattern_count(); } else { if ($name == 'age') { return JxBotElement::compute_age(); } else { if ($name == 'birthday') { return JxBotElement::birthday(); } else { return JxBotConfig::predicate($name); } } } } } break; case 'tag': /* non-standard Tag feature */ $name = trim($this->child_or_attr_named($in_context, 'name')); return $in_context->tag_value($name); case 'id': return JxBotConverse::predicate('id'); case 'size': /* we return the number of patterns, which is equivalent to AIML standard category count; since in JxBot one category != one pattern. */ return JxBotNLData::pattern_count(); case 'vocabulary': return JxBotNLData::word_count(); case 'version': return JxBot::VERSION; case 'program': return JxBot::PROGRAM . ' ' . JxBot::VERSION; case 'set': $name = trim($this->child_or_attr_named($in_context, 'name')); if ($name != '') { $value = $this->text_value($in_context, array('name')); JxBotConverse::set_predicate($name, $value); return $value; } break; case 'date': $php_format = 'r'; /* default - AIML 1.0 - we specify date & time format */ return date($php_format); case 'uppercase': return JxBotNL::upper($this->text_value($in_context)); case 'lowercase': return JxBotNL::lower($this->text_value($in_context)); case 'formal': return JxBotNL::formal($this->text_value($in_context)); case 'sentence': return JxBotNL::sentence($this->text_value($in_context)); case 'explode': return JxBotNL::explode($this->text_value($in_context)); case 'normalize': return JxBotNL::template_normalize($this->text_value($in_context)); case 'denormalize': return JxBotNL::template_denormalize($this->text_value($in_context)); case 'gender': if (count($this->children) == 0) { return JxBotNL::remap('gender', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('gender', $this->text_value($in_context)); case 'person': if (count($this->children) == 0) { return JxBotNL::remap('person', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('person', $this->text_value($in_context)); case 'person2': if (count($this->children) == 0) { return JxBotNL::remap('person2', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('person2', $this->text_value($in_context)); case 'map': $map_name = $this->child_or_attr_named($in_context, 'name'); return JxBotNL::remap($map_name, $this->text_value($in_context, array('name'))); case 'that': $indicies = JxBotElement::indicies($this->child_or_attr_named($in_context, 'index')); $in_response = count($indicies) >= 1 ? $indicies[0] : 1; $in_sentence = count($indicies) >= 2 ? $indicies[1] : 1; $response = JxBotConverse::history_response($in_response - 1); $sentences = JxBotNL::split_sentences($response); if ($in_sentence < 1 || $in_sentence > count($sentences)) { return ''; } return $sentences[$in_sentence - 1]; case 'input': $indicies = JxBotElement::indicies($this->child_or_attr_named($in_context, 'index')); $in_request = count($indicies) >= 1 ? $indicies[0] : 1; $in_sentence = count($indicies) >= 2 ? $indicies[1] : 1; $request = JxBotConverse::history_request($in_request - 1); $sentences = JxBotNL::split_sentences($request); if ($in_sentence < 1 || $in_sentence > count($sentences)) { return ''; } return $sentences[$in_sentence - 1]; case 'request': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return JxBotConverse::history_request($index - 1); case 'response': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return JxBotConverse::history_response($index - 1); default: /* push unknown content & tags through to output */ // ! REVIEW: A better policy might be to tightly control which tags are // allowed through, or provide an appropriate system option. return $this->flatten(); } }