Help Center Live Community

Support => Installation Help & Software Support => Topic started by: BrianP on May 18, 2009, 08:48:38 PM



Title: Multiple operators starting same chat
Post by: BrianP on May 18, 2009, 08:48:38 PM
I am running HCL 2. 1. 7 on a Feodra 8 machine with apache 1. 3. 41 and PHP 5. 2. 6.   I have a department setup with 2 operators read to accept chats (one with priority 0 and one with priority 1).   Using 3 machines to test, I log in to two of them for operators, and on the third machine I start a chat.

What I am seeing is this.   When the chant request comes it, it appears on the Live Help monitor for the first operator (the one with priority 0).   If I wait 30 seconds, the chat request will appear on the second operator (with priority 1).   This is what I expected.   BUT, the chat request does not clear off first operator's monitor.

If the second operator starts the chat, the chat starts.   But the first operator can still join the chat (which becomes a conference).   Worse, if the first operator declines it, it will close the chat opened by the second operator!

The same thing happens if the 30 seconds expires, so it appears on operator 2's monitor but operator 1 grabs it.   I have a 3 way chat going on, but the client sees the same name for the operator.

Make sense?  I expected as HCL moved through the available operators, it will disable the previous operator.   Or at least prevent someone else from joining and existing chat.

I have tried this on combinations of the following 3 browsers.   I have done the aardvark changed for firefox:
Firefox 3. 0. 10 on Fedora 8
IE7 on WinXP
Seamonkey 1. 1. 12 on Fedora 8

Any thoughts? This seems wrong to me. . . .

- brian


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 19, 2009, 01:27:52 AM
Thank you for such an in-depth post, it truly makes life easier!

Personally, I find it to be sensible for it to leave the chat available for priority-0 operators yet also show it for priority-1 operators, however after the chat is joined it SHOULD be removed from both screens. I have a feeling this is a bug with the core of the current release and as such there isn't really a way around it.  All I can really suggest is that you make sure your operators know to not decline a chat if someone is in it already, and if they do join a chat with someone in it already, just close the window.

Sorry about that, hopefully V3 will be out soon and that will fix this

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 19, 2009, 06:48:33 PM
Thank you for such an in-depth post, it truly makes life easier!

Personally, I find it to be sensible for it to leave the chat available for priority-0 operators yet also show it for priority-1 operators, however after the chat is joined it SHOULD be removed from both screens. I have a feeling this is a bug with the core of the current release and as such there isn't really a way around it.

The more I think about it, the more I agree with you on allowing a higher priority user to still accept the chat.

But, here is where it gets interesting.  I wonder if there is just a refresh problem.

I am testing right now.  My client (asking for help) is IE7 on WinXP.  Priority 0 operator is on Seamonkey 1. 1. 12 on Fedora 8 and Priority 1 operator is on Firefox 3. 0. 10 on Fedora 8.  So, the request comes in.  30 seconds after the request, it appears on pri1's screen.  If I accept on pri0, pri1 still shows the request (the original problem).

But, force a refresh of the screen on pri1 (F5 in firefox).  The message to accept the request is gone!  In fact, I noticed that even after the chat is complete, it never cleans up the other windows to show the chat ended.  I have even seen this with a single operator and the chat request times out.

So, is there a different set of refresh code being called when a request is pending versus when there are no requests pending?  Anyone know some php (perl, java, c++ and I would be all over it).....

- brian


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 19, 2009, 07:59:04 PM
I do know PHP and Javascript myself, and I would totally figure out how to fix it, but I have no time to right now :( I am actually hacking together a custom solution for my client, as many of the employees use macs, and HCL doesn't support macs right now :( One thing you might be able to do is find the layout code (it is a smarty template) and just throw in something like
Code:
<meta http-equiv="refresh" content="30" />

into the header. It is a bit of a hack, but it will force the page to refresh every 30 seconds.

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 19, 2009, 08:15:42 PM
however after the chat is joined it SHOULD be removed from both screens. I have a feeling this is a bug with the core of the current release and as such there isn't really a way around it.

At the moment my boss is way more concerned with this problem than the refresh problem.  Since a complete refresh will make the chat request go away, in theory a check could be made to prevent the second operator from starting the chat altogether.  So, I will see if I can understand enough PHP to add a check to the accept processing to prevent the connection to the chat.  I will probably also modify the template to remove the 'decline' link to prevent the chat from closing if another operator has answered it and to prevent the round robin queuing of the operators (which is aborted if anyone in the queue hits decline).

if anyone has an idea of where I should look to add my check (or any information on the database layout) that would be helpful.

- brian


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 19, 2009, 08:48:30 PM
Well, if you check in hcl/live/chat you will find a couple different files you could add it in, my guess is either display.php, index.php (which I can't load for some reason, so not sure what is in it), or main.php. You could also add a check in a couple of the classes (hcl/classes), but I have yet to figure out which ones really... Just took a quick 5-10 minute scan through the files. The check only needs to consist of something like
Code:
if ($GLOBALS['live']->operatorid($GLOBALS['live']->chatid()) != null) {
    die ('Someone is chatting already!');
}

Didn't test that, and some of the calls are probably wrong, but you can find operatorid in the chat.php class, and running that would tell you if someone had joined the chat already. I couldn't find where the chat was actually accepted in the time I took to check though, so read around a bit.

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 20, 2009, 05:44:47 PM
Holy complicated batman!

Here is what I have found so far.  When the chat request comes in, an entry into sessions is writing like this
| id  | chatid | assignid | departmentid | operatorid | nick      | alert    | timeo      | timeg      | typeo | typeg | transfer |
+-----+--------+----------+--------------+------------+-----------+----------+------------+------------+-------+-------+----------+
| 111 |     26 |       25 |            5 |          5 | win test  | received | 1242837174 | 1242837174 |     0 |     0 |          |
+-----+--------+----------+--------------+------------+-----------+----------+------------+------------+-------+-------+----------+

Once the chat is accepted, the row is updated to:
| 111 |     26 |       25 |            5 |          5 | win test  | accept | 1242837206 | 1242837205 |     0 |     0 |          |

So, I can use this to tell if the chat is already in progress!

But, I can't just change live/chat/main.php as that is called every time the pages reload and I only want to check this when the chat starts.  The same page is used by the operator and the client, so I need to make sure I am only affecting the client also.  Not to mention I need to make sure I only affect the correct operator.  wowsers....

I think the better solution would be to affect this between the click of 'accept' and the display of main.php, but I haven't tracked this down yet (which is a bit of a pain when you don't know php and barely know javascript :)

Still looking...
-brian


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 20, 2009, 07:57:19 PM
Good to see you making a bit of progress... I am assuming there would be a function in one of the classes to handle accepting a chat request, so if we can find that, dropping a call in there should be simple, or finding the page that is called by clicking the accept button. I might look into it a bit more if I have time

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 20, 2009, 08:21:09 PM
Good to see you making a bit of progress... I am assuming there would be a function in one of the classes to handle accepting a chat request, so if we can find that, dropping a call in there should be simple, or finding the page that is called by clicking the accept button. I might look into it a bit more if I have time

I believe I have found where this needs to be done.  In class/js/monitor.php is the code that is executed when the accept link is clicked.  But I don't have a clue how to do php and javascript together and am now just beating my head against the wall.  (using class/js/nomarl/monitor.php for readability):

Code:
        this.accept = function(id, chatid, type)
        {
            this.request = false;
            MonitorConnection2.add('accept_'+type, '');
            MonitorConnection2.add('id', id);
            MonitorConnection2.add('chatid', chatid);
            MonitorConnection2.add('time', Misc.epoch());
            MonitorConnection2.send('<?php echo($GLOBALS['conf']['url']); ?>/admin/monitor/response.php', 'Monitor.reset()', 'reset');
            switch (type) {
                case 'chat':
                    window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&chatid='+chatid, 'chat_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['chat_op_width']); ?>, height=<?php echo($GLOBALS['conf']['chat_op_height']); ?>');
                    break;
                case 'transfer':
                    window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&chatid='+chatid, 'transfer_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['chat_op_width']); ?>, height=<?php echo($GLOBALS['conf']['chat_op_height']); ?>');
                    break;
                case 'opchat':
                    window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&opchat&chatid='+chatid, 'operator_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['opchat_width']); ?>, height=<?php echo($GLOBALS['conf']['opchat_height']); ?>');
                    break;
            }
        }

Here is where the windows are opened for the actually chat.  So, I figure is I do a query against the DB before the opening a windows, so I changed it to this:
Code:
        this.accept = function(id, chatid, type)
        {
query2 = 'SELECT * FROM `sessions` WHERE `chatid`="' + chatid + '" and `alert`="accept" and `alert`;

<?php if (!$GLOBALS['db']->query($query2)) { ?>

            this.request = false;
            MonitorConnection2.add('accept_'+type, '');
            MonitorConnection2.add('id', id);
            MonitorConnection2.add('chatid', chatid);
            MonitorConnection2.add('time', Misc.epoch());
            MonitorConnection2.send('<?php echo($GLOBALS['conf']['url']); ?>/admin/monitor/response.php', 'Monitor.reset()', 'reset');
            switch (type) {
                case 'chat':
                    window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&chatid='+chatid, 'chat_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['chat_op_width']); ?>, height=<?php echo($GLOBALS['conf']['chat_op_height']); ?>');
                    break;
                case 'transfer':
                    window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&chatid='+chatid, 'transfer_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['chat_op_width']); ?>, height=<?php echo($GLOBALS['conf']['chat_op_height']); ?>');
                    break;
                case 'opchat':
                    window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&opchat&chatid='+chatid, 'operator_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['opchat_width']); ?>, height=<?php echo($GLOBALS['conf']['opchat_height']); ?>');
                    break;
            }
        }
<?php } else { ?>
alert("Chat started by another user");
<?php ?>

But this fails (apache doesn't like it).  I tried building the query right in the php line
Code:
<?php if (!$GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `chatid`="' ?> chatid <?php '" and `alert`="accept"')) { ?>
But that is no better.

Anyone help me with the php/javascript part?


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 20, 2009, 09:18:06 PM
Making good progress!

Here is where the windows are opened for the actually chat.  So, I figure is I do a query against the DB before the opening a windows, so I changed it to this:

CODE IN HERE

But this fails (apache doesn't like it).  I tried building the query right in the php line
Code:
<?php if (!$GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `chatid`="' ?> chatid <?php '" and `alert`="accept"')) { ?>
But that is no better.

Okay, so what you are basically doing is combining server side code (PHP) with client side code (javascript) and the browser (and apache) can't figure out what you want it to do. You are telling it to run a query on 'SELECT * FROM `sessions` WHERE `chatid`="' and then output the string 'chatid' to the client, and then do something with '" and `alert`="accept"'.

And I was about to give you some code to fix that, but looking at it, you can't actually add that there, as PHP doesn't know what chat we are talking about. So you have to add it on the other side of that request. Meaning we have to edit /live/chat/main.php after all.

Code:
<?php
    
include_once('../../class/include.php');
    
$inc = new Includer();
    
$inc->template();
    
$inc->auth();
    
$inc->operator();
    
$inc->department();
    
$inc->chat();
    
$inc->db();
    
$inc->chat();

    if (
$GLOBALS['chat']->blocked()) {
        
$GLOBALS['template']->assign('text'$GLOBALS['lang']['blocked']);
        
$GLOBALS['template']->display('plain.tpl');
        
$inc->finished();
        exit;
    }

    if (isset(
$_GET['admin'])) {
        
$GLOBALS['template']->assign('admin''true');
    } else {
        
$GLOBALS['template']->assign('admin''false');
    }

    
$GLOBALS['chat']->session(addslashes($_GET['chatid']));
    
$GLOBALS['chat']->assign(addslashes($_GET['chatid']));

    
$GLOBALS['template']->assign('chatid'addslashes($_GET['chatid']));

    if (
$GLOBALS['auth']->operator() && isset($_GET['admin']) && !isset($_GET['opchat'])) {
        
$GLOBALS['db']->query('UPDATE `sessions` SET `typeo`="0" WHERE `chatid`="'.addslashes($_GET['chatid']).'"');
    } else {
        
$GLOBALS['db']->query('UPDATE `sessions` SET `typeg`="0" WHERE `chatid`="'.addslashes($_GET['chatid']).'"');
    }

    if (isset(
$_GET['opchat'])) {
        
$GLOBALS['template']->assign('opchat''true');
        
$GLOBALS['template']->assign('javascript''chat&opchat');
    } else {
        
$GLOBALS['template']->assign('opchat''false');
        
$GLOBALS['template']->assign('javascript''chat');
    }
    
    if (!
$GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `chatid`="'.addslashes($_GET['chatid']).'"')) {
        
$GLOBALS['template']->assign('onload'' onload="Chat.empty();"');
        
$GLOBALS['template']->assign('text'$GLOBALS['lang']['chat_empty']);
    }

    
// Display the output
    
$GLOBALS['template']->display('chat.tpl');
    
    
// do events that need to be done at the end of the file
    
$inc->finished();
?>

So what you want to do is add a check right in here:
Code:
<?php
    
if (isset($_GET['admin'])) {
        
// Add the check here!
        
$GLOBALS['template']->assign('admin''true');
    } else {
        
$GLOBALS['template']->assign('admin''false');
    }
?>

And we can do that with some code that I sent earlier...
Code:
if ($GLOBALS['chat']->operatorid($_GET['chatid']) != null) {
    die ('Someone is chatting already!');
}

Give that a shot and see what it does. It is probably pretty harsh (as it will just throw a one line error message most likely) but it should handle it

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 21, 2009, 03:02:48 PM
And we can do that with some code that I sent earlier...
Code:
if ($GLOBALS['chat']->operatorid($_GET['chatid']) != null) {
    die ('Someone is chatting already!');
}

Give that a shot and see what it does. It is probably pretty harsh (as it will just throw a one line error message most likely) but it should handle it

Nope, this doesn't work.  The first operator is getting the message the Someone is chatting already message.  The client still starts the chat, but I have no operator at the other end.  I think the problem is at this point, the database/sessions has already been updated to indicate the chat has been started (I believe by class/monitor.php::chats() but I am not sure who calls that, or the first time the page refreshes it calls this code and hits the check, I can't tell.

Bummer, I thought we were there, I will keep looking, but.....

- brian


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 21, 2009, 03:44:19 PM
Poking around some more in the database, I notice that the session gets updated when the time expires on the first operator:
Code:
mysql> select * from hcl_sessions;
+-----+--------+----------+--------------+------------+----------+----------+------------+------------+-------+-------+----------+
| id  | chatid | assignid | departmentid | operatorid | nick     | alert    | timeo      | timeg      | typeo | typeg | transfer |
+-----+--------+----------+--------------+------------+----------+----------+------------+------------+-------+-------+----------+
| 140 |     26 |       25 |            5 |          5 | win test | received | 1242915533 | 1242915533 |     0 |     0 |          |
+-----+--------+----------+--------------+------------+----------+----------+------------+------------+-------+-------+----------+
1 row in set (0.00 sec)


mysql> select * from hcl_sessions;
+-----+--------+----------+--------------+------------+----------+---------+------------+------------+-------+-------+----------+
| id  | chatid | assignid | departmentid | operatorid | nick     | alert   | timeo      | timeg      | typeo | typeg | transfer |
+-----+--------+----------+--------------+------------+----------+---------+------------+------------+-------+-------+----------+
| 140 |     26 |       24 |            5 |          6 | win test | request | 1242915564 | 1242915564 |     0 |     0 |          |
+-----+--------+----------+--------------+------------+----------+---------+------------+------------+-------+-------+----------+
1 row in set (0.00 sec)
Notice that the operator ID changed when the new operator got the request.  I know previously we stated that it would be nice if the higher operator still had access to that chat, but I am more concerned about the 2 operators in a chat.

So, since I am already aware of a bug where the monitor widow doesn't update operly (the chat request stays shown on operator 1's window when operator 2 gets it or the chat ends).  And I noticed that when a new chat request comes in, the first chat is removed and replaced by the second chat, I think that is the place to look.  Get the refresh fixed so it isn't being shown once it has moved past the operator.

So, if I can just figure out what is different between a new chat request versuse an update, I think I am there.  Of course, I really don't know where to look yet and dont' really know how to debug a php script <sigh>

- brian


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 21, 2009, 03:46:11 PM
Okay, so what you are basically doing is combining server side code (PHP) with client side code (javascript) and the browser (and apache) can't figure out what you want it to do.

BTW, I am an idiot, I should have realized this myself.

- brian


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 21, 2009, 07:50:45 PM
BTW, I am an idiot, I should have realized this myself.

Its a mistake we all make once or twice. Not an hour after I had replied to you did I have a friend with the exact same issue :P

Nope, this doesn't work.  The first operator is getting the message the Someone is chatting already message.  The client still starts the chat, but I have no operator at the other end.  I think the problem is at this point, the database/sessions has already been updated to indicate the chat has been started (I believe by class/monitor.php::chats() but I am not sure who calls that, or the first time the page refreshes it calls this code and hits the check, I can't tell.

Bummer, I thought we were there, I will keep looking, but.....

- brian

It could also be that my code was a bit wrong and it doesn't return null, but instead returns false or '' or something. But if it is already updating the db, we should definitely fix it at the root of the problem.

On a separate note, I still haven't heard back from anyone on an update on this, and I am tempted to start making my own if I don't see any progress being made, or the code being made public. Its bull that we have to fix all of these bugs while we wait yet another year for v3


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 21, 2009, 08:56:35 PM
Well, I figured out how to get debug messages in the php code, so I am making some progress.....

It could also be that my code was a bit wrong and it doesn't return null, but instead returns false or '' or something. But if it is already updating the db, we should definitely fix it at the root of the problem.

Well, I have found the code to prevent updating the database.  Now, based on the fact that the sessions table gets updated and the operator ID changed when it is round robining, I am making the assumption that once your time is passed, you can't start a chat anymore (which is not that Spenser wanted as above, but...).  So, I put in this change in class/monitor.php
Code:
        function accept_chat($id, $chatid)
        {
            if ($id == 0) {
                $this->result = $GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `chatid`="'.$chatid.'" ORDER BY `id` DESC');
                $id = $this->result[0]['id'];
            }
// see if this is still available for this operator
if ($GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `alert`="received" AND `operatorid`="'.$GLOBALS['operator']->id().'"'))
{
            $this->new_time = time() + $GLOBALS['conf']['chat_timeout'];
            $GLOBALS['db']->query('UPDATE `sessions` SET `alert`="accept", `operatorid`="'.$GLOBALS['operator']->id().'", `timeo`="'.$this->new_time.'"
, `timeg`="'.$this->new_time.'" WHERE `id`="'.$id.'" AND `chatid`="'.$chatid.'"');
            $GLOBALS['db']->query('DELETE FROM `chat` WHERE `chatid`="'.$chatid.'"');
            $GLOBALS['stats']->accept($GLOBALS['operator']->id());
            // Autosave transcript
            $GLOBALS['transcript']->create($chatid);
}
        }

But, the chat window still opens for the operator even though they shouldn't have it.  This puts it into some weird states (depending on if another operator has started the chat or not).  I need to figure out how to either stop the window from opening (really hard) or at least have that new window get the $GLOBALS['lang']['chat_empty'] message.  Which I think I need to do in the live/chat/main.php, I just don't know how yet.

Then I need to do something in the monitor to make the chat request messages go away when the timeout has happened for that operator.  I know there is a way, because the message will go away when the chat is started, I just haven't found it yet.  But I am focusing on preventing the chat first.

- brian


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 21, 2009, 09:33:19 PM
Nice work Brian, you are making awesome progress! I hadn't even seen that function when I took a quick look in all of the files. Would you mind making a diff when you are done everything? Or if you send me the code I can make a diff/patch file with your changes!

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 22, 2009, 08:56:21 PM
So, here is where I am at.  I have made a change to prevent updating the database if an operator accepts a chat that has already expired their allotted time.  This change:
Code:
class/monitor.php
423a429,431
> // Only update the database if this is still available for this operator
> if ($GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `alert`="received" AND `operatorid`="'.$GLOBALS['operator']->id().'"'))
> {
429a438
> }

Now, the operator can still open the chat however, and either it will join an existing chat (but NOT clear the client chat window, which is very important), or it will wait for the chat to be joined and the comments will be added to that chat.

However, the monitor itself doesn't clear itself to indicate the chat has expired this operator and moved to the next.  I made this change:
Code:
class/monitor.php
391a392,396
> // See there are chats waiting for other operators and tell client to refresh monitor
> if ($GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `alert`="received" AND `operatorid`!="'.$GLOBALS['operator']->id().'"'))
> {
>     $this->response .= 'request-cancelled|';
> }
which clears the monitor screen of chats that are not valid.  This does cause extra page reloads of the monitor window.

There are still problems though.  The current implementation does not clear the monitor screen of the last operator in the round robin (bad), but if that operator tries to open it, they receive the not valid chat message.  It also leaves a small window (about 5 seconds) where two operators could get the same chat (the chat has moved to the next operator, but the first operator's screen hasn't refreshed.

So, I would still like to try to figure out how to get the chat window to be empty if the chat isn't valid, which is probably in live/chat/main.php but I haven't figured out if the operator ID is remotely available there.  Still looking.

If you are interested, I also made this change to add the timezone to the chat transcript in case your installation supports multiple timezones (mine does).  I also have the changes for the firefox 3.0.6 fix, which is posted elsewhere.

I will probably post a complete list when I am done with everything, but I thought I would at least provide the changes I have made so far.

- brian



Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 26, 2009, 08:34:57 PM
Looking good Brian. I was away for the weekend, so I haven't been too into HCL for a little while, but I am gonna be getting back into it soon if all goes well. But you are definitely doing good on this! Gonna help a lot of people out

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 26, 2009, 09:11:13 PM
Well, ain't that a b!tch.  I solve the problem and I can't upload files to the forum....

Code:
The attachments upload directory is not writable. Your attachment or avatar cannot be saved.

And you can't remove an attachment from the post once you have it listed.  <sigh>  Let me recreate my entire post......

- brian


Title: FIXED: Multiple operators starting same chat
Post by: BrianP on May 26, 2009, 09:26:17 PM
Here are all the code changes I have made to my installation.  The only thing left is to have the chat request in the operator's monitor to be removed once the chat times out, but my boss doesn't care about that right now, to neither do I  ;)

Fix for preventing multiple operators from being on the same chat
Few of things to be aware of.  1) This will prevent an operator with a higher priority from accepting a chat after the system has moved it to the next operator.  2) I have only tested this with 2 operators and they do not have the same priority.  3) While there are chats waiting to be accepted, the monitor will do full refreshes, not just AJAX queries.

class/js/monitor.php: This change is needed to send the operator ID to the server when trying to open the new chat window.
Code:
52c52
< window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&chatid='+chatid, 'chat_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['chat_op_width']); ?>, height=<?php echo($GLOBALS['conf']['chat_op_height']); ?>'); break; case 'transfer':
---
> window.open('<?php echo($GLOBALS['conf']['url']); ?>/live/chat/main.php?admin&chatid='+chatid+'&operatorid='+'<?php echo($operatorid); ?>', 'chat_'+chatid, 'toolbar=no, status=no, scrollbars=no, resizable=yes, location=no, menubar=no, directories=no, width=<?php echo($GLOBALS['conf']['chat_op_width']); ?>, height=<?php echo($GLOBALS['conf']['chat_op_height']); ?>'); break; case 'transfer':

class/monitor.php: This change prevents the database from being updated if the accept button is clicked and the chat has already moved on to the next operator.
Code:
391a392,396
> // See there are chats waiting for other operators and tell client to refresh monitor
> if ($GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `alert`="received" AND `operatorid`!="'.$GLOBALS['operator']->id().'"'))
> {
>     $this->response .= 'request-cancelled|';
> }
423a429,431
> // Only update the database if this is still available for this operator
> if ($GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `alert`="received" AND `operatorid`="'.$GLOBALS['operator']->id().'"'))
> {
429a438
> }

live/chat/main.php: This change prevents the pop-up chat window from connecting to a chat that has already moved on to the next operator.
Code:
53a54,64
> if ($GLOBALS['auth']->operator() && isset($_GET['admin']) && !isset($_GET['opchat']))
> {
>   // Check to make sure this is valid for this operator
>   if (! $GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `chatid`="'.addslashes($_GET['chatid']).'" AND `operatorid`="'.addslashes($_GET['operatorid']).'"'))
>   {
>     // And it isn't
>     $GLOBALS['template']->assign('onload', ' onload="Chat.empty();"');
>     $GLOBALS['template']->assign('text', $GLOBALS['lang']['chat_empty']);
>   }
>   else
>   {
58a70,71
>   } // if (! $GLOBALS['db']->query('SELECT * FROM `sessions` WHERE `alert`="received" AND `operatorid`="'.$GLOBALS['operator']->id().'"'))
> } // if ($GLOBALS['auth']->operator() && isset($_GET['admin']) && !isset($_GET['opchat']))

And that is it.  I have done a couple of other things:
Fix put timezone in transcript
class/transcript.php
Code:
33a34
>         var $timezone;
50a52
>                     $this->timezone = date('T');
59,60c61,62
<                         $this->text = '<span class="operator"><i>('.$this->timestamp.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.rawurldecode($this->text).'</span><br />';
<                         //$this->text = '<span class="operator"><i>('.$this->timestamp.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.char_to_html($this->text).'</span><br />';
---
>                         $this->text = '<span class="operator"><i>('.$this->timestamp.' '.$this->timezone.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.rawurldecode($this->text).'</span><br />';
>                         //$this->text = '<span class="operator"><i>('.$this->timestamp.' '.$this->timezone.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.char_to_html($this->text).'</span><br />';
62c64
<                         $this->text = '<span class="guest"><i>('.$this->timestamp.')</i> <b>'.$_SESSION['hcl_'.$chatid]['guest'].':</b> '.rawurldecode($message).'</span><br />';
---
>                         $this->text = '<span class="guest"><i>('.$this->timestamp.' '.$this->timezone.')</i> <b>'.$_SESSION['hcl_'.$chatid]['guest'].':</b> '.rawurldecode($message).'</span><br />';
77a80
>                     $this->timezone = date('T');
86c89
<                         $this->text = '<span class="operator"><i>('.$this->timestamp.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.char_to_html($this->text).'</span><br />';
---
>                         $this->text = '<span class="operator"><i>('.$this->timestamp.' '.$this->timezone.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.char_to_html($this->text).'</span><br />';
88c91
<                         $this->text = '<span class="guest"><i>('.$this->timestamp.')</i> <b>'.$_SESSION['hcl_'.$chatid]['guest'].':</b> '.rawurldecode($this->result2[$key]['message']).'</span><br />';
---
>                         $this->text = '<span class="guest"><i>('.$this->timestamp.' '.$this->timezone.')</i> <b>'.$_SESSION['hcl_'.$chatid]['guest'].':</b> '.rawurldecode($this->result2[$key]['message']).'</span><br />';
159a163
>                         $this->timezone = date('T');
168c172
<                             $this->text = '<span class="operator"><i>('.$this->timestamp.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.char_to_html($this->text).'</span><br />';
---
>                             $this->text = '<span class="operator"><i>('.$this->timestamp.' '.$this->timezone.')</i> <b>'.$_SESSION['hcl_'.$chatid]['operator'].':</b> '.char_to_html($this->text).'</span><br />';
170c174
<                             $this->text = '<span class="guest"><i>('.$this->timestamp.')</i> <b>'.$_SESSION['hcl_'.$chatid]['guest'].':</b> '.rawurldecode($this->result2[$key]['message']).'</span><br />';
---
>                             $this->text = '<span class="guest"><i>('.$this->timestamp.' '.$this->timezone.')</i> <b>'.$_SESSION['hcl_'.$chatid]['guest'].':</b> '.rawurldecode($this->result2[$key]['message']).'</span><br />';

Firefox 3.0.6 fix
class/js/aardvark.php
Code:
28c28,38
< function Aardvark(object) { this.object = object; this.xmlhttp = new XMLHttpRequest(); this.mac = navigator.platform.indexOf('Mac'); this.msie = navigator.userAgent.indexOf("MSIE"); this.image = new Image(); this.fallback = false; this.url = ''; this.variables = new Array(); this.vars = new Array(); this.connect_host = ''; this.install_host = ''; this.initiated = false; this.url_built = false; this.response = ''; this.gc = 'reset'; this.validateurl = function()
---
> function Aardvark(object) { this.object = object; this.xmlhttp = new XMLHttpRequest(); this.mac = navigator.platform.indexOf('Mac'); this.msie = navigator.userAgent.indexOf("MSIE"); this.image = new Image();
> /* Start Changed the following line to fix the Firefox 3.0.6 bug
> this.fallback = false;
> */
> if (navigator.appName == 'Microsoft Internet Explorer') {
>         this.fallback = false;
> } else {
>         this.fallback = true;
> }
> /* End Changed the following line to fix the Firefox 3.0.6 bug */
> this.url = ''; this.variables = new Array(); this.vars = new Array(); this.connect_host = ''; this.install_host = ''; this.initiated = false; this.url_built = false; this.response = ''; this.gc = 'reset'; this.validateurl = function()

Firefox 3.0.7 fix (I haven't tested this http://www.helpcenterlive.com/smf/sound_issues_with_firefox_307-t928.0.html)
templates/Bliss/monitor_content.tpl (or in your own template directory)
Code:
54c54
< <embed src="{$conf.url}/templates/{$conf.template}/sounds/{$sounds[i].file}.mp3" autostart="true" hidden="true">
---
> <embed src="{$conf.url}/templates/{$conf.template}/sounds/{$sounds[i].file}.mp3" autostart="true" hidden="true" type="audio/mpeg">
class/js/chat.php
Code:
155c155
< if ((x == 'o' && admin == 'false') || (x == 'g' && admin == 'true')) { parent.window.chat_display.document.body.innerHTML = parent.window.chat_display.document.body.innerHTML + this.chat_message; this.font_apply(); if (this.sounds_flag) { if (this.mac > -1) { parent.window.chat_type.document.getElementById('typing').innerHTML = '<embed src="<?php echo($GLOBALS['conf']['url']); ?>/templates/<?php echo($GLOBALS['conf']['template']); ?>/sounds/ding.mp3" id="message_sound" loop="false" autostart="true" hidden="true"></embed>';} else { parent.window.chat_type.document.getElementById('typing').innerHTML = '<object height="0" width="0" classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95"><param name="AutoStart" value="1" /><param name="FileName" value="<?php echo($GLOBALS['conf']['url']); ?>/templates/<?php echo($GLOBALS['conf']['template']); ?>/sounds/ding.mp3" /></object>';}
---
> if ((x == 'o' && admin == 'false') || (x == 'g' && admin == 'true')) { parent.window.chat_display.document.body.innerHTML = parent.window.chat_display.document.body.innerHTML + this.chat_message; this.font_apply(); if (this.sounds_flag) { if (this.mac > -1) { parent.window.chat_type.document.getElementById('typing').innerHTML = '<embed src="<?php echo($GLOBALS['conf']['url']); ?>/templates/<?php echo($GLOBALS['conf']['template']); ?>/sounds/ding.mp3" id="message_sound" loop="false" autostart="true" hidden="true" type="audio/mpeg"></embed>';} else { parent.window.chat_type.document.getElementById('typing').innerHTML = '<object height="0" width="0" classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95"><param name="AutoStart" value="1" /><param name="FileName" value="<?php echo($GLOBALS['conf']['url']); ?>/templates/<?php echo($GLOBALS['conf']['template']); ?>/sounds/ding.mp3" /></object>';}

- brian

(of, I have to b!tch a little)
You know, a little input from a developer would have helped a lot here.  If nothing else, just to understand the database layout.  I mean, I see the post on the front page of HCL
Code:
The 'community' certainly hasn't contributed much more than questions and overhead, and some outside assistance in handling that would really be appreciated.
I was (obviously) willing to make the fixes myself.  I was just looking for some info on how everything works.  <sigh>



Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 26, 2009, 11:00:16 PM
You did good Brian. Sorry I didn't help more, but life has been a little hectic, and I ended up making my own live support script that syncs with MSN messenger since we needed something working in ALL browsers that was more convenient. But you did awesome on that and the code looks very good. What did you use to make the patch files?

And I agree, some developer input would have been nice. I knew a little bit more than you did, and that was about it. So getting someone who knows the code in here would have helped a ton!

Spenser


Title: Re: Multiple operators starting same chat
Post by: BrianP on May 27, 2009, 02:10:39 PM
But you did awesome on that and the code looks very good. What did you use to make the patch files?

I am a linux guy, so I just used diff between an original version of the file and my changed version.

In hindsight, it is also possible that the change to class/monitor.php would no longer be needed with the change to live/chat/main.php.  But I didn't test it without the change and I figured a single DB query wouldn't matter in the grand scheme of things.

- brian


Title: Re: Multiple operators starting same chat
Post by: SpenserJ on May 27, 2009, 10:17:50 PM
Okay, that is what I figured, but wanted to make sure

And no, I don't think a small query will slow much down.

Spenser