Index: bot.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/bot/bot.module,v
retrieving revision 1.9.2.9.2.9
diff -u -r1.9.2.9.2.9 bot.module
--- bot.module	23 Jun 2008 17:30:41 -0000	1.9.2.9.2.9
+++ bot.module	24 Jun 2008 02:03:56 -0000
@@ -22,7 +22,7 @@
  * Implementation of hook_perm().
  */
 function bot_perm() {
-  return array('administer bot');
+  return array('administer bot', 'set own irc credentials');
 }
 
 /**
@@ -46,6 +46,35 @@
   return $items;
 }
 
+/*
+ * Implementation of hook_user().
+ */
+function bot_user($op, $edit, &$account, $category = NULL) {
+  if ($op == 'form' && $category == 'account') {
+   global $user;
+    $form['bot'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('IRC credentials'),
+      '#collapsible' => TRUE,
+      '#weight' => 4,
+      '#access' => ((user_access('set own irc credentials') && ($account->uid == $user->uid)) || user_access('administer bot')),
+    );
+    $form['bot']['bot_hostname'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Hostname'),
+      '#default_value' => empty($edit['bot_hostname']) ? '' : $edit['bot_hostname'],
+      '#description' => t('The hostname associated with your IRC account (Example: <em>drupal.org/user/123456/view</em>).')
+    );
+    $form['bot']['bot_autologout'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Automatically Logout'),
+      '#default_value' => isset($edit['bot_autologout']) ? $edit['bot_autologout'] : FALSE,
+      '#description' => t('When you quit, or change your nickname on IRC, automatically have the bot log you out of your session. Usage of this is strongly recommended. It is handy to not use it if you are running under a secure hostname.'),
+    );
+    return $form;
+  }
+}
+
 /**
  * Run an IRC-only crontab every five minutes.
  *
@@ -91,6 +120,39 @@
  */
 function bot_irc_msg_query($data) {
   bot_irc_msg_channel($data, TRUE);
+
+  // See if the user wants to login.
+  if (preg_match("/^login ([a-zA-Z0-9\ \[\]\{\}\\\|\^\`\-\_\*]*)/i", $data->message, $matches)) {
+    // Check if the user credentials are correct.
+    $user = user_authenticate(array('name' => $data->nick, 'pass' => $matches[1]));
+    if ($user) {
+      // Update their hostname to log them in.
+      user_save($user, array('bot_hostname' => $data->host));
+      bot_authenticate($data, TRUE);
+      bot_message($data->nick, t('Login successful.'));
+    }
+    else {
+      bot_message($data->nick, t('Login failed.'));
+    }
+  }
+  else if ($data->message == 'logout') {
+    // Log the user out only if they're authenticated.
+    $user = bot_authenticate($data, TRUE);
+    if ($user) {
+      // Remove their hostname, making their authentication invalid.
+      user_save($user, array('bot_hostname' => ''));
+      bot_authenticate($data, TRUE);
+      bot_message($data->nick, t('You have logged out.'));
+    }
+    else {
+      bot_message($data->nick, t('You are currently not logged in.'));
+    }
+  }
+  else if ($data->message == 'login') {
+    // User wants to authmatically login, or check their status.
+    $user = bot_authenticate($data, TRUE);
+    bot_message($data->nick, $user ? t('You are logged in.') : t('You are not logged in. Login with "login <password>".'));
+  }
 }
 
 /**
@@ -211,3 +273,68 @@
 
   return system_settings_form($form);
 }
+
+/**
+ * Check a given user's credentials.
+ *
+ * Looks up the IRC hostname, and compares what is provided on the website.
+ *
+ * $user = bot_authenticate($data);
+ * if (user_access('ahem', $user)) {
+ *   // Do something
+ * }
+ *
+ * @param $data
+ *   The regular $data object prepared by the IRC library.
+ * @param $reset
+ *   Whether or not we should reload the cached user data
+ * @return
+ *   The original data object, along with its associated uid.
+ *   This can be thought of as the user object.
+ */
+function bot_authenticate($data, $reset = FALSE) {
+  static $users = array();
+  // Cache the users so that we don't hit the database for every action
+  if (isset($data->nick)) {
+    // See if we need to reset the cache
+    if (!isset($users[$data->nick]) || $reset) {
+      // Load the user and see if they have the correct hostname information
+      $user = user_load(array('name' => $data->nick));
+      if (!empty($user->bot_hostname) && isset($data->host) && ($data->host == $user->bot_hostname)) {
+        // Combine the data and the user object, and cache them
+        $users[$data->nick] = (object)array_merge((array)$user, (array)$data);
+        //$users[$data->nick] = $data;
+        //$users[$data->nick]->uid = $user->uid;
+      }
+      else {
+        return $users[$data->nick] = NULL;
+      }
+    }
+  }
+  else {
+    return NULL;
+  }
+  // Return the user object if the user is still the same authenticated user
+  return ($users[$data->nick]->host == $data->host) ? $users[$data->nick] : NULL;
+}
+
+/**
+ * When a user quits, check to see if we should log them out.
+ */
+function bot_irc_msg_quit($data) {
+  $user = bot_authenticate($data);
+  if (isset($user->bot_autologout) && ($user->bot_autologout == TRUE)) {
+    // Remove their hostname, making them logout.
+    user_save($user, array('bot_hostname' => ''));
+
+    // Reset the cache
+    bot_authenticate($data, TRUE);
+  }
+}
+
+/**
+ * A nickname change is considered the same as quitting.
+ */
+function bot_irc_msg_nickchange($data) {
+  bot_irc_msg_quit($data);
+}
