Help/collaboration with modification to show AJAX alerts for new posts

Started by cisops, November 20, 2009, 08:31:23 PM

Previous topic - Next topic

cisops

Hello, I wanted to see if anyone would be interested in helping or collaborating on a modification which I have completed a fair amount of the work on.

Edit: The code provided in the post has been tested and is in a working state as-is but required manual integration with SMF.

The purpose of the modification is to use AJAX to poll the smf_messages table and retrieve records for any posts that have been made since the last page load.  Then, using jQuery and a growl-like plug-in, I notify the forum visitor of the new posts.  I'd like to mention that I am a rookie when it comes to writing PHP, never done it before, but I have done a lot of other coding.  So, there may be room for optimizations. 

I don't believe that such a mod currently exists for SMF.  I would like it to be called Post-Pops unless a code contributor and I agree on another name.

What I need help with is 1) adding the necessary code to give members control over whether the new post alerts are enabled or disabled and 2) assist in doing what needs to be done to package the mod for distribution.

Open Source Code Used in Mod

http://jquery.com/
jQuery (jquery-1.3.2.min.js)

http://code.google.com/p/achtung-ui/
Achtung, a growl-like plug-in for jQuery (ui.achtung-min.js)

http://www.schillmania.com/projects/soundmanager2/
SoundManager2, which is optional for a "pop" alert sound (soundmanager2-nodebug-jsmin.js)

Custom-written Javascript

(ajaxnewpost.js)


// used for AJAX call
var xmlhttp;

// the maximum ID_MSG from smf_messages at any
// given time after page load, updated with subsequent AJAX calls
var maxidmsg = '';

// store the text retrieve from the XML
// response and is used for parsing data returned
var msg = '';

// var for SoundManager
var mySound;

//initiate SoundManager2 which is used to 'pop' sound effect
soundManager.debugMode = false;
soundManager.url = '/swf/';

var s = setInterval("showNewPosts()", 15000); // poll every X milliseconds
soundManager.onload = function() {
   mySound = soundManager.createSound({
    id: 'aSound',
    url: 'short_pop_sound.mp3'
  });
}

// first make initial AJAX call
showNewPosts();

// function to retrieve data from external php file, checkforposts.php
function showNewPosts() {
xmlhttp=GetXmlHttpObject();
if (xmlhttp==null) {
  //alert ("Browser does not support HTTP Request");
  return;
  }
var url="checkforposts.php";
url=url+"?q=" + maxidmsg; // pass parameter with the most recent ID_MSG we know exists
url=url+"&sid="+Math.random();

xmlhttp.onreadystatechange=stateChanged;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);

}

// we have a response
function stateChanged() {
if (xmlhttp.readyState==4) {
// if this is the first poll, we should get the highest message ID to start with
if (maxidmsg == '') {
maxidmsg = xmlhttp.responseText;
maxidmsg = replace(maxidmsg,' ','');
}
// subsequent polls will return any new posts found
else {
msg = xmlhttp.responseText;
var mySplitResult = msg.split("|");
var i = 0;
// parse the string returned
while (i < mySplitResult.length-1) {
$.achtung({message: mySplitResult[i], timeout:0});
i++;
maxidmsg = mySplitResult[i];
i++;
}
if (i != 0) {
// if we found new posts, play popup alert sound
mySound.play();
}
}
}
}

function GetXmlHttpObject() {
if (window.XMLHttpRequest) {
  // code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject) {
  // code for IE6, IE5
  return new ActiveXObject("Microsoft.XMLHTTP");
  }
return null;
}


Here is the PHP code which is used by the AJAX call to query the smf_messages table and return any new post records

PHP Code

(checkforposts.php)


<?php

// get parameter telling us the most recent ID_MSG found
if (isset($_GET["q"])) $q=$_GET["q"]; else $q '';

$con mysql_connect('localhost''xxx''xxx'); // replace with your server's database connection parameters
if (!$con)
  {
  die(
'Could not connect: ' mysql_error());
  }

mysql_select_db("smf"$con);

// not the first request, so return any new message records
if ($q != '') {
$sql="SELECT b.Name, p.subject, m.realName, from_unixtime(p.posterTime, '%M %d, %Y, %h:%i %p') as posterTime, p.ID_MSG FROM ";
$sql.="smf_messages p join smf_members m on p.ID_MEMBER = m.ID_MEMBER join smf_boards b on b.ID_BOARD = p.ID_BOARD ";
$sql.="WHERE id_msg > " $q " ";
$sql.="ORDER BY p.id_msg";
  
$result mysql_query($sql);
while($row mysql_fetch_array($result))
  {
  echo '<b>' $row['subject'] . '</b><br/>by ' $row['realName'] . '<br/>at ' $row['posterTime'] . '|' $row['ID_MSG'] . '|'//. ' in ' . $row['Name']  
  }
  
} else { 
// first check, so just return the top ID_MSG so we know where to start looking for new ones
$sql="SELECT ID_MSG FROM smf_messages ORDER BY ID_MSG DESC LIMIT 1";
$result mysql_query($sql);

while($row mysql_fetch_array($result))
  {
  echo $row['ID_MSG'];
  }  
}

mysql_close($con);
?>




What needs to be done on the SMF code side?  Well, just some edits to the [head] tag in the index.template.php as follows:

SMF Code Modifications

(index.template.php)


        <link rel="stylesheet" type="text/css" href="ui.achtung-min.css" />
<script language="Javascript" type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script language="Javascript" type="text/javascript" src="ui.achtung-min.js"></script>
<script language="Javascript" type="text/javascript" src="soundmanager2-nodebug-jsmin.js"></script>
<script language="Javascript" type="text/javascript" src="ajaxnewpost.js"></script>


I think that's everything.  Granted, I don't have it provided in an easy download.  But, hopefully someone can use what I've written to improve and add the necessary functionality to complete the mod.  I would ask that I am given credit for my contributions in the code.

Tested on IE8 and Firefox 3.5 on Windows 7.  SMF v.1.1.9.

Copyright 2009, Shane Holland.

Hope someone is able to contribute to get this to a distributable state and that other members find it useful.

Arantor

Um, there's already a mod that does pretty much all of this already, called ENotify.

cisops

Thanks, Arantor.  Looks like that mod was released since I had last looked to see if something like this existed already.  However, it appears to only be available for SMF v2.0.  But it does indeed look very similar.  Can v.2.0 mods be used with v.1.1.9?

Arantor

No, they can't. But a fair amount of the code will likely be similar.

cisops

Suppose I should check out the mod-of-the-month sticky next time before introducing some potential mod code  :-[  Anyway, if anyone is interested in an alternative to eNotify or wants to assist with creating something that's inherently compatible with older versions of SMF, feel free to have at it.

I have taken over a forum that been running on SMF for a number of years.  To be honest, I don't have the time to migrate to SMF2 and would prefer to wait until it's post-RC release.

Arantor

It's always worth searching the entire mod site, rather than just the Mod of the Month, just in case.

Might be worth asking the ENotify author if he's interested working on a 1.1 compatible version with you.

darrenbeige

I know this is slightly redundant, but it would be much easier to require('SSI.php') in your PHP code, and use the SMF db_query (for 1.1.x series) functions. This removes the need for the mysql_connect() and mysql_select().

cisops

Darren, this is precisely why I posted it here.  I am no PHP programmer and had never written the first line of PHP before a couple of days ago.  My hope was that someone who knew more about PHP, or more specifically SMF and the mod system, would help with this.  Sounds like I could have referenced an include (SSI.php) that contains some predefined database connectivity functions.  Excuse my ignorance when it comes to things PHP/SMF.  I'm an ASP.net guy  :o

Arantor, my comment about checking the Mod of the Month thread was somewhat tongue-in-check since the thread was so conspicuous and I missed it.  Back when I took over this forum several months ago, I checked the mod site to see if such a mod existed.  Obviously before eNotify was posted in October... 

Anyway, I still hope someone can take over where I left off and turn this into a full fledged mod.  What I have, while it does work, is kind of half-baked as far as being a certified SMF mod with full integration.  I just don't know enough about what I'm doing at this point.

Thanks to everyone who has viewed and responded so far.

Arantor

I'm just thinking it would likely be easier trying to modify the existing mod and backport it; the author of the mod would be best placed for that - they've already done most of the work and pulling it back to 1.1 probably isn't that much work though it's been a while since I looked at that mod's code.

You could even ask him in the mod's own thread as to whether he'd be interested in doing that.

darrenbeige

I agree with Arantor. It seems like you'd only need a few changes to the database calls in the ENotify mod after all to make it work with 1.1.x

onepiece

And what's $_GET['q']? An invitation for the hack? :P

You need to sanitize it (make sure it is really what you expect) before using in a query. Since it should be an integer, use variable casting to cast it to integer type.

Arantor

All you'd need is:
$_GET['q'] = (int) $_GET['q'];

Remember, SMF does do some sanitising of $_REQUEST[] (including GET and POST) but not sure it'd cover this.

Advertisement: