<?php
// $Id: bot.module,v 1.9.2.9 2007/06/29 02:38:43 morbus Exp $

/**
 * @file
 * Enables a network and plugin framework for IRC bots.
 */

/**
 * Implementation of hook_help().
 */
function bot_help($path, $arg) {
  switch ($path) {
    case 'bot':
      return '<p>'. t('Listed here are the bot\'s enabled features and settings. Information about the bot\'s features is also available by asking it directly for "help", and then for more detail with "help &lt;feature&gt;" (such as "help Drupal URLs"). This would best be done in a private message, so as not to disrupt regular channel activity.') .'</p>';
    case 'admin/settings/bot':
      return '<p>'. t('Configure your bot framework with these settings.') .'</p>';
  }
}

/**
 * Implementation of hook_perm().
 */
function bot_perm() {
  return array('administer bot');
}

/**
 * Implementation of hook_menu().
 */
function bot_menu($may_cache) {
  $items['bot'] = array(
    'access arguments'  => array('access content'),
    'description'       => "View the bot's enabled features and settings.",
    'page callback'     => 'bot_overview',
    'title'             => 'Bot',
  );
  $items['admin/settings/bot'] = array(
    'access arguments'  => array('administer bot'),
    'description'       => 'Configure your bot framework with these settings.',
    'file'              => 'bot.admin.inc',
    'page callback'     => 'drupal_get_form',
    'page arguments'    => array('bot_settings'),
    'title'             => 'Bot',
  );

  return $items;
}

/**
 * Run an IRC-only crontab every five minutes.
 *
 * Here, we clear out some of the Drupal caches that are normally
 * flushed via page loads (which we never have via IRC operations).
 */
function bot_irc_bot_cron() {
  // recreates the variable cache.
  variable_set('bot_cache_cleared', time());
  $GLOBALS['conf'] = variable_init();
}

/**
 * Framework related messages and features.
 *
 * @param $data
 *   The regular $data object prepared by the IRC library.
 * @param $from_query
 *   Boolean; whether this was a queried request.
 */
function bot_irc_msg_channel($data, $from_query = FALSE) {
  $bot_name = variable_get('bot_nickname', 'bot_module');
  $addressed = "\s*${bot_name}[\:,-]\s*"; // bot mentioned?
  $to = $from_query ? $data->nick : $data->channel;

  // our IRC help interface which piggybacks off of Drupal's hook_help().
  if (preg_match("/^($addressed)help\s*([^\?]*)\s*\??/i", $data->message, $help_matches)) {
    if (!$help_matches[2]) { // no specific help was asked for so give 'em a list.
      $irc_features = module_invoke_all('help', 'irc:features');
      asort($irc_features); // alphabetical listing of features.
      bot_message($to, t('Detailed information is available by asking for "help <feature>" where <feature> is one of: !features.', array('!features' => implode(', ', $irc_features))));
    }
    else { // a specific type of help was required, so load up just that bit of text.
      $feature_name = 'irc:features#'. preg_replace('/[^\w\d]/', '_', drupal_strtolower(trim($help_matches[2])));
      $feature_help = module_invoke_all('help', $feature_name);
      bot_message($to, array_shift($feature_help));
    }
  }
}

/**
 * All responses are available via a query.
 */
function bot_irc_msg_query($data) {
  bot_irc_msg_channel($data, TRUE);
}

/**
 * Send an action to a channel or user.
 *
 * @param $to
 *   A channel or user.
 * @param $action
 *   The action to perform.
 */
function bot_action($to, $action) {
  global $irc; // from bot_start.php.
  $irc->message(SMARTIRC_TYPE_ACTION, $to, $action);

  // allow modules to react to bot responses. do NOT use
  // bot_action() in your implementation as you'll cause
  // an infinite loop! and that'd look really really retarded.
  module_invoke_all('irc_bot_reply_action', $to, $action);
}

/**
 * Send a message to a channel or user.
 *
 * @param $to
 *   A channel or user.
 * @param $message
 *   The message string to send.
 */
function bot_message($to, $message) {
  global $irc; // from bot_start.php.
  $type = strpos($to, '#') == 0 ? 'CHANNEL' : 'QUERY';
  $irc->message(constant('SMARTIRC_TYPE_'. $type), $to, $message);

  // allow modules to react to bot responses. do NOT use
  // bot_message() in your implementation as you'll cause
  // an infinite loop! and that'd look really really retarded.
  module_invoke_all('irc_bot_reply_message', $to, $message);
}

/**
 * Displays a quick page listing all the enabled features of the bot.
 *
 * This is a wrapper around the IRC help features, and spits those helps
 * verbatim (meaning URLs won't be linked, etc.). @todo Someday, urlfilter.
 */
function bot_overview() {
  $output = '<p>'. t('The bot connects to server %server as nick %name.', array('%server' => variable_get('bot_server', 'irc.freenode.net'), '%name' => variable_get('bot_nickname', 'bot_module'))) .'</p>';
  $output .= '<ul id="bot_features">'; // witness this incredibly long line above this equally long, but mirthfully useless, comment! ha ha!

  $irc_features = module_invoke_all('help', 'irc:features');
  asort($irc_features); // alphabetical listing of features.
  foreach ($irc_features as $irc_feature) {
    $feature_help = module_invoke_all('help', 'irc:features#'. preg_replace('/[^\w\d]/', '_', drupal_strtolower(trim($irc_feature))));
    $output .= '<li><strong>'. check_plain($irc_feature) .':</strong> '. check_plain(array_shift($feature_help)) .'</li>';
  }

  $output .= '</ul>';
  return $output;
}
