Index: bot_commands/bot_commands.admin.inc
===================================================================
RCS file: bot_commands/bot_commands.admin.inc
diff -N bot_commands/bot_commands.admin.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bot_commands/bot_commands.admin.inc	21 Dec 2009 10:59:34 -0000
@@ -0,0 +1,74 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Admin settings for Bot Commands.
+ */
+
+/**
+ * Configures bot commands.
+ */
+function bot_commands_settings() {
+  // Get a list of all available commands.
+  $bot_commands = module_invoke_all('bot_commands');
+  $form['#tree'] = TRUE;
+  foreach ($bot_commands as $command => $info) {
+    $names = bot_commands_get_names($command);
+  	$form['bot_commands'][$command]['name'] = array(
+  	  '#type' => 'item',
+  	  '#value' => $command,
+  	);
+  	$form['bot_commands'][$command]['nicks'] = array(
+  	  '#type' => 'textfield',
+  	  '#default_value' => implode(', ', $names),
+  	);
+  }
+  $form['buttons']['submit'] = array(
+    '#type' => 'submit', 
+    '#value' => t('Save configuration'),
+  );
+  return $form;
+}
+
+/**
+ * Submit handler for bot_commands_settings().
+ */
+function bot_commands_settings_submit($form, $form_state) {
+  $commands = $form_state['values']['bot_commands'];
+  foreach ($commands as $name => $value) {
+    $command = array('command' => $name);
+    $nicks = explode(',', $value['nicks']);
+    // Trim names.
+    $nicks = array_map('trim', $nicks);
+    $command['nicks'] = serialize($nicks);
+  	if ($id = db_result(db_query("SELECT id FROM {bot_commands} WHERE command = '%s'", $name))) {
+  	  $command['id'] = $id;
+  	  drupal_write_record('bot_commands', $command, 'id');
+  	}
+  	else {
+  	  drupal_write_record('bot_commands', $command);
+  	}
+  }
+  drupal_set_message(t('The settings has been saved.'));
+}
+
+/**
+ * Theme function for settings page.
+ */
+function theme_bot_commands_settings($form) {
+  $header = array(t('Bot command'), t('IRC nick names'));
+  $rows = array();
+  foreach ($form['bot_commands'] as $command => $value) {
+    if (isset($form['bot_commands'][$command]['name'])) {
+    	$rows[] = array(
+    	  array('data' => drupal_render($form['bot_commands'][$command]['name']), 'class' => 'bot-command'),
+    	  array('data' => drupal_render($form['bot_commands'][$command]['nicks']), 'class' => 'bot-nicks'),
+    	);
+    }
+  }
+  $output = theme('table', $header, $rows, array('id' => 'bot-commands'));
+  $output .= drupal_render($form);
+  return $output;
+}
+
Index: bot_commands/bot_commands.info
===================================================================
RCS file: bot_commands/bot_commands.info
diff -N bot_commands/bot_commands.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bot_commands/bot_commands.info	21 Dec 2009 10:59:34 -0000
@@ -0,0 +1,6 @@
+; $Id: bot_log.info,v 1.1.2.1.2.1 2008/04/26 01:32:31 morbus Exp $
+name = Bot Commands
+package = Bot
+dependencies[] = bot
+description = "Enables customizable bot commands for IRC users with proper permissions."
+core = 6.x
Index: bot_commands/bot_commands.install
===================================================================
RCS file: bot_commands/bot_commands.install
diff -N bot_commands/bot_commands.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bot_commands/bot_commands.install	21 Dec 2009 10:59:35 -0000
@@ -0,0 +1,57 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Table schema for Bot Commands.
+ */
+
+/**
+ * Implementation of hook_schema().
+ */
+function bot_commands_schema() {
+  $schema['bot_commands'] = array(
+    'description' => t('The single table necessary for bot commands.'),
+    'fields' => array(
+      'id' => array(
+        'description' => t('A unique ID for the bot command.'),
+        'not null'    => TRUE,
+        'size'        => 'big',
+        'type'        => 'serial',
+        'unsigned'    => TRUE,
+      ),
+      'command' => array(
+        'default'     => '',
+        'description' => t('The bot command.'),
+        'not null'    => TRUE,
+        'type'        => 'varchar',
+        'length'      => 255,
+      ),
+      'nicks' => array(
+        'default'     => '',
+        'description' => t('Serialized array of IRC user names that are allowed to run this command.'),
+        'not null'    => TRUE,
+        'type'        => 'text',
+        'size'        => 'big',
+      ),
+    ),
+    'primary key' => array('id'),
+    'key' => array('command'),
+  );
+
+  return $schema;
+}
+
+/**
+ * Implementation of hook_install().
+ */
+function bot_commands_install() {
+  drupal_install_schema('bot_commands');
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function bot_commands_uninstall() {
+  drupal_uninstall_schema('bot_commands');
+}
Index: bot_commands/bot_commands.module
===================================================================
RCS file: bot_commands/bot_commands.module
diff -N bot_commands/bot_commands.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bot_commands/bot_commands.module	21 Dec 2009 10:59:35 -0000
@@ -0,0 +1,167 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Enables customizable bot commands for IRC users with proper permissions.
+ */
+
+/**
+ * Implementation of hook_help().
+ */
+function bot_commands_help($path, $arg) {
+  switch ($path) {
+    case 'irc:features':
+      return array(t('Commands'));
+    case 'irc:features#commands':
+      return t('Users with proper permissions are able to execute bot commands by sending a message to the bot. E.g. "Botname: log stop"');
+    case 'admin/settings/bot/commands':
+      return '<p>' . t('Configure bot commands and access to them with these settings.') . '</p><p>' . t('For each registered command you can enter a comma separated list of IRC nick names that are allowed to run the command. If you leave the field blank, no user will be allowed; if you enter a "*" every user will be allowed to run the command.') . '</p>';
+  }
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function bot_commands_menu() {
+  $items['admin/settings/bot/commands'] = array(
+    'access arguments' => array('administer bot'),
+    'description' => 'Configure bot commands and access to them with these settings.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('bot_commands_settings'),
+    'file' => 'bot_commands.admin.inc',
+    'title' => 'Bot Commands',
+  );
+  return $items;
+}
+
+/**
+ * Listen for conversation directed at, or about, the bot.
+ *
+ * @param $data
+ *   The regular $data object prepared by the IRC library.
+ * @param $from_query
+ *   Boolean; whether this was a queried request.
+ */
+function bot_commands_irc_msg_channel($data, $from_query = FALSE) {
+  $substitutions = array('!who' => $data->nick, '!channel' => $data->channel);
+  $to = $from_query ? $data->nick : $data->channel;
+  $addressed = bot_name_regexp();
+
+  $commands = module_invoke_all('bot_commands');
+  $command_regexp = implode('|', array_keys($commands));
+  // We've been asked to run a command.
+  if (preg_match("/^($addressed)($command_regexp)/i", $data->message, $matches)) {
+    $command_name = $matches[3];
+    // Check permissions.
+    $allowed_users = bot_commands_get_names($command_name);
+    if (!(!is_array($allowed_users) && '*' != $allowed_users) && !in_array($data->nick, $allowed_users)) {
+    	bot_message($to, t('Sorry, but you are not allowed to run "!command".', array('!command' => $command_name)));
+    }
+    else {
+      // Get command info.
+      $info = bot_commands_get_command($command_name);
+      if (function_exists($info['callback'])) {
+        // Invoke the command.
+        call_user_func($info['callback'], $data, $from_query);
+      }
+      else {
+        bot_message($to, t("Sorry, but I couldn't run \"command\" because of technical problems.", array('!command' => $command_name)));
+      }
+    }
+  }
+}
+
+/**
+ * All responses are available via a query.
+ */
+function bot_commands_irc_msg_query($data) {
+  bot_commands_irc_msg_channel($data, TRUE);
+}
+
+/**
+ * Get a single command by its name.
+ *
+ * @param $command
+ *   Name of command to load.
+ * @return 
+ *   Array with detailed information about the command.
+ */
+function bot_commands_get_command($command) {
+  $commands = module_invoke_all('bot_commands');
+  if (isset($commands[$command])) {
+  	return $commands[$command];
+  }
+  return FALSE;
+}
+
+/**
+ * Get a list of IRC nick names that are allowed to run the command.
+ *
+ * @param $command
+ *   Name of command.
+ * @return 
+ *   Array with IRC nick names.
+ */
+function bot_commands_get_names($command) {
+  $result = db_result(db_query("SELECT nicks FROM {bot_commands} WHERE command = '%s'", $command));
+  $names = array();
+  if ($result) {
+    $names = unserialize($result);
+  }
+  return $names;
+}
+
+/**
+ * Callback function for command "bot: info".
+ * Print out some information about this bot.
+ */
+function bot_commands_botinfo($data, $from_query = FALSE) {
+  $to = $from_query ? $data->nick : $data->channel;
+  $my_name = variable_get('bot_nickname', 'bot_module');
+  $message = t("Hello, !nick. I'm !botname, the bot of this channel.", array('!nick' => $data->nick, '!botname' => $my_name));
+  // Send the message.
+  bot_message($to, $message);
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function bot_commands_theme() {
+  return array(
+    'bot_commands_settings' => array(
+      'arguments' => array(
+        'form' => NULL,
+      ),
+      'file' => 'bot_commands.admin.inc',
+    ),
+  );
+}
+
+/**
+ * Implementation of hook_bot_commands
+ * @return 
+ *   Array with information about defined bot commands.
+ *   Example:
+ *   \verbatim
+ *   array(
+ *     'log start' => array(
+ *       'description' => t('Starts logging messages in the current channel.'),
+ *       'callback' => 'bot_log_add_channel',
+ *     ),
+ *     'log stop' => array(
+ *       'description' => t('Stops logging messages in the current channel.'),
+ *       'callback' => 'bot_log_remove_channel',
+ *     ),
+ *   );
+ *   \endverbatim
+ */
+function bot_commands_bot_commands() {
+  return array(
+    'info' => array(
+      'description' => t('Print information about the bot.'),
+      'callback' => 'bot_commands_botinfo',
+    ),
+  );
+}
+
