PHP Classes
Icontem

File: ex_announcements.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of sk89q  >  BlueTOC  >  ex_announcements.php  
File: ex_announcements.php
Role: Example script
Content type: text/plain
Description: Example PHP AIM IM list
Class: BlueTOC
AIM client using TOC instant messaging protocol
 

Contents

Class file image Download
 <?php
/*
 * This is a more complex and complete example.
 *
 * This bot is an announcement bot where users may subscribe
 * to an AIM-hosted message list. IM it to use it once it 
 * is running. The list of subscribers will be written to disk, 
 * as well as the archive of messages. Users that are offline
 * will still receive the message (up to three are stored). 
 * This is mostly proof of concept (I think) due to the rate 
 * limiting issues with AIM.
 *
 * There is currently no way to administrate the list of 
 * subscribers or the archive.
 *
 * This is not too well documented yet.
 *
 * To get it working:
 * (1) Configure username and password
 * (2) Non-Windows: Chmod the current directory writable
 * (3) Start up script
 * (4) Talk to bot
 * 
 * Only one instance of this application can be running. 
 * It has not been written to be safe to run with
 * multiple threads.
 */
 
// We must include the BlueToc libraries
require_once "bluetoc/EventHandlers/ObjectBased.php";
require_once "bluetoc/TocProtocol.php";
require_once "bluetoc/AimClient.php";

// We define our own class, extending AimClient
class AnnouncementsBot extends AimClient
{        
    var $name = '';
    var $subscribers_file = '';
    var $messages_file = '';
    var $backlog_file = '';
    var $max_subscribers = 20;
    var $max_message_length = 60;
    var $archive_size = 5;
    var $backlog_user_size = 3;
    var $backlog_cutoff_time = 1209600; // 14 days = 2 weeks
    var $admins = array();
    
    var $subscribers = array();
    var $messages = array();
    var $backlog = array();
    
    var $online = array();
    
    function AnnouncementsBot($user, $pass, $name, $subscribers_file, $messages_file, $backlog_file, $admins)
    {        
        // Debug mode is by default off
        $this->debug_mode = false;
        
        $this->aim_user = $user;
        $this->aim_pass = $pass;
        
        $this->name = $name;
        $this->subscribers_file = $subscribers_file;
        $this->messages_file = $messages_file;
        $this->backlog_file = $backlog_file;
        
        foreach($admins as $user)
        {
            $this->admins[] = $this->normalize_string($user);
        }
        
        $this->subscribers = $this->read_archive($this->subscribers_file);
        $this->messages = $this->read_archive($this->messages_file);
        $this->backlog = $this->read_archive($this->backlog_file);
        
        // Backlog cleanup
        foreach($this->backlog as $user => $bl)
        {
            foreach((array) $this->backlog[$user] as $k => $msg)
            {
                if($msg[0] < time() - $this->backlog_cutoff_time)
                {
                    unset($this->backlog[$user][$k]);
                }
            }
        }
        foreach($this->backlog as $user => $bl)
        {
            if(!$this->backlog[$user]) unset($this->backlog[$user]);
        }
        $this->write_archive($this->backlog_file, $this->backlog);
        
        echo "* The IM list '{$this->name}' is signing on...\n";
        
        $this->connect();
    }
    
    function read_archive($file)
    {
        return (array) @unserialize(@file_get_contents($file));
    }
    
    function write_archive($file, $data)
    {
        $data = serialize($data);
        
        $fp = fopen($file, "w");
        flock($fp, LOCK_EX);
        fwrite($fp, $data);
        flock($fp, LOCK_UN);
        fclose($fp);
    }
    
    function build_reply($message)
    {
        return <<<EOB
<font face=Arial><b><u>{$this->name} IM List</u></b></font><br>
$message
EOB;
    }
    
    // Handle once we've signed on
    function event_sign_on($args)
    {
        // Let's re-add all the subscribers anyway
        foreach($this->subscribers as $user)
        {
            $list .= "\nb:$user";
        }
        if($list)
        {
            $this->add_buddies("g:Subscribers$list");
        }
                
        echo "* The IM list '{$this->name}' has signed online as {$this->aim_user}\n";
        echo "* Buddies:\n{$args['config']}\n";
    }
    
    // Handle when we get an instant message
    function event_im($args)
    {        
        $user = $this->normalize_string($args['user']);
        
        // Remember that AIM IMs usually have HTML
        // so we must strip it so that we can
        // easily parse it
        $message = strip_tags($args['message']);
        
        echo "* Received an instant message from: {$args['user']} -> $message\n";
        
        // Subscription command
        if(strtolower($message) == "subscribe")
        {
            // Check whether the user is already subscribed or not
            if(in_array($user, $this->subscribers))
            {
                $reply = "ERROR! You are already subscribed to this list.";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
            // Limit the number of subscribers allowed
            else if(count($this->subscribers) >= $this->max_subscribers)
            {
                $reply = "ERROR! There are already too many people subscribed to this list (max: {$this->max_subscribers})";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
            // Subscribe
            else
            {
                // We need to keep track of who is online to track them
                $this->add_buddies("g:Subscribers\nb:$user");
                
                $this->subscribers[] = $user;
                $this->write_archive($this->subscribers_file, $this->subscribers);
                
                $reply = "SUCCESS! You have been subscribed. Tell me <b>unsubscribe</b> to leave this list at any time.";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
        }
        // Unsubscribe command
        else if(strtolower($message) == "unsubscribe")
        {
            // Check whether the user is subscribed or not
            if(!in_array($user, $this->subscribers))
            {
                $reply = "ERROR! You <i>aren't</i> subscribed.";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
            else
            {
                // Remove from tracking
                $this->remove_buddy($user, "Subscribers");
                
                $this->subscribers = array_diff($this->subscribers, array($user));
                $this->write_archive($this->subscribers_file, $this->subscribers);
                
                unset($this->online[$user]);
                
                $reply = "SUCCESS! We are sorry for you to leave, but you have been removed.";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
        }
        // Message archival
        else if(preg_match("#^archive( (.*))?$#is", $message, $m))
        {
            if(!$m[2])
            {
                print_r($this->messages);
                $messages = array();
                foreach($this->messages as $msg)
                {
                    // Command is archive DATETIMESTAMP
                    $messages[] = "{$msg[0]}:<br><strong>archive {$msg[2]}</strong>";
                }
                
                $reply = "Please type the bolded command to read:<br><br>" . implode("<br><br>", $messages);
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
            else
            {
                // The date timestamp is stored in array key 2
                // We need to look for that
                $i = -1;
                foreach($this->messages as $k => $msg)
                {
                    if($msg[2] == $m[2])
                    {
                        $i = $k;
                        break;
                    }
                }
                
                if($this->messages[$i])
                {
                    $msg = $this->messages[$i];
                    
                    $reply = "Date: {$msg[0]}<br>{$msg[1]}";
                    $this->send_im($args['user'], $this->build_reply($reply), false);
                }
                else
                {
                    $reply = "ERROR! The requested message does not eixst.";
                    $this->send_im($args['user'], $this->build_reply($reply), false);
                }
            }
        }
        // Posting command
        else if(preg_match("#^post( (.*))?$#is", $message, $m))
        {
            if(!in_array($user, $this->admins))
            {
                $reply = "ERROR! You <i>aren't</i> an administrator. You cannot post to this list.";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
            else if(strlen($m[2]) > $this->max_message_length)
            {
                $reply = "ERROR! Your message is too long.";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
            else if(!$m[2])
            {
                $reply = "ERROR! You must enter a message.";
                $this->send_im($args['user'], $this->build_reply($reply), false);
            }
            else
            {
                $time = time();
                $this->messages[] = array(date("r", $time), "From: {$user}<br>{$m[2]}", $time);
                while(count($this->messages) > $this->archive_size) array_shift($this->messages);
                $this->write_archive($this->messages_file, $this->messages);
                
                $reply = "SUCCESS! The message has been posted!";
                $this->send_im($args['user'], $this->build_reply($reply), false);
                
                // This loops through all the users...
                // And locks up everything =/
                $m = $this->build_reply("From: {$user}<br>{$m[2]}");
                foreach($this->subscribers as $sub)
                {
                    if($this->online[$sub])
                    {
                        $this->send_im($sub, $m, true);
                        usleep(1000000 / 2);
                    }
                    // Send when they're online!
                    else
                    {
                        $this->backlog[$sub][] = array($time, "Date: " . date("r", $time) . "<br>From: {$user}<br>{$m[2]}");
                        while(count($this->backlog[$sub]) > $this->backlog_user_size) array_shift($this->backlog[$sub]);
                    }
                }
                
                $this->write_archive($this->backlog_file, $this->backlog);
            }
        }
        // About command
        else if(strtolower($message) == "about")
        {
            $reply = "This announcement IM list is derived from the <i>ex_announcements.php</i> example from the <a href=\"http://www.therisenrealm.com/scripts/bluetoc/\">BlueTOC</a> PHP AIM connection class";
            $this->send_im($args['user'], $this->build_reply($reply), false);
        }
        else
        {
            $reply = "Welcome to this list. Repeat back the follow commands to interact with me:<br>" .
                     "<b>subscribe</b> - Subscribe to this IM list<br>" .
                     "<b>unsubscribe</b> - Unsubscribe to this IM list<br>" .
                     "<b>archive</b> - View this list's archive<br>" .
                     "<b>post</b> - Post to this list (admins only)<br>" .
                     "<b>about</b> - About this list<br>";
            $this->send_im($args['user'], $this->build_reply($reply), false);
        }
    }
    
    function event_buddy_update($args)
    {
        $user = $this->normalize_string($args['user']);
        
        echo "Online: {$user}: " . ($args['is_online'] ? "Online" : "Offline") . "\n";
        
        if($args['is_online'])
        {
            $this->online[$user] = 1;
            
            // Sends back log
            if($this->backlog[$user])
            {
                // This loops through all the messages...
                // And locks up everything =/
                foreach($this->backlog[$user] as $msg)
                {
                    if($msg[0] < time() - $this->backlog_cutoff_time) continue;
                    $this->send_im($user, $this->build_reply($msg[1]), true);
                    usleep(1000000 / 2);
                }
                
                unset($this->backlog[$user]);
                $this->write_archive($this->backlog_file, $this->backlog);
            }
        }
        else
        {
            unset($this->online[$user]);
        }
    }
    
    function event_error($args)
    {
        // These are a list of errors in English
        // Most, if not all, errors will return an error number
        // and not the error description
        $connection_errors = array(
            100 => 'Data unable to be sent',
            200 => 'Flapon',
            201 => 'Data not received from server after FLAPON packet',
            202 => 'Invalid FLAP SIGNON response from the server',
            203 => 'Invalid response from the server' );
        
        $aim_errors = array(
            0 => 'Success',
            1 => 'AOLIM Error: Unknown Error',
            2 => 'AOLIM Error: Incorrect Arguments',
            3 => 'AOLIM Error: Exceeded Max Packet Length (1024)',
            4 => 'AOLIM Error: Reading from server',
            5 => 'AOLIM Error: Sending to server',
            6 => 'AOLIM Error: Login timeout',
            901 => 'General Error: %s not currently available',
            902 => 'General Error: Warning of %s not currently available',
            903 => 'General Error: A message has been dropped, you are exceeding the 
                    server speed limit',
            950 => 'Chat Error: Chat in %s is unavailable',
            960 => 'IM and Info Error: You are sending messages too fast to %s',
            961 => 'IM and Info Error: You missed an IM from %s because it was too big',
            962 => 'IM and Info Error: You missed an IM from %s because it was sent
                    too fast',
            970 => 'Dir Error: Failure',
            971 => 'Dir Error: Too many matches',
            972 => 'Dir Error: Need more qualifiers',
            973 => 'Dir Error: Dir service temporarily unavailble',
            974 => 'Dir Error: Email lookup restricted',
            975 => 'Dir Error: Keyword ignored',
            976 => 'Dir Error: No keywords',
            977 => 'Dir Error: Language not supported',
            978 => 'Dir Error: Country not supported',
            979 => 'Dir Error: Failure unknown %s',
            980 => 'Auth Error: Incorrect nickname or password',
            981 => 'Auth Error: The service is temporarily unavailable',
            982 => 'Auth Error: Your warning level is too high to sign on',
            983 => 'Auth Error: You have been connecting and disconnecting too frequently.
                    Wait 10 minutes and try again. If you continue to try, you will need to
                    wait even longer.',
            989 => 'Auth Error: An unknown signon error has occurred %s' ); 
            
        // Let's see what kind of error we are faced with
        switch($args['type'])
        {
            // Connection error
            case ERROR_CONNECTION:
                echo "* Connection error: {$connection_errors[$args['number']]} ({$args['number']})\n";
                break;
            // AIM is giving us an error
            case ERROR_AIM:
                echo "* AIM error: {$aim_errors[$args['number']]} ({$args['number']})\n";
                break;
        }
    }
}

// Create a new instance of the bot
$client = new AnnouncementsBot('username1', 'password1',
                               $name = "Latest Updates",
                               $subscribers_file = "ex_announce_subs.txt",
                               $messages_file = "ex_announce_msgs.txt",
                               $backlog_file = "ex_announce_backlog.txt",
                               $admins = array("username2", "username3", "username4"));

// Listen to the bot infinitely
while(true)
{
    $client->listen();
    usleep(150);
}
?> 

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products