Fun with Digg's API

Digg's api was released about a week ago a while ago, and since that time, various flash projects have surfaced, probably due to that pesky contest. But I don't have any flash experience, so PHP, here we come.

We're going to make various tag clouds, a Reddit clone, Reddit/Better RSS feed, and a live diggs app.

Update – 05/09/07 – 3 PM – Stupid host seems to be having database issues. Great. I wish I could afford a dedicated, or I guess VPS, so I don't have to put with this crap.

Update – 05/09/07 – 6 PM – It seems that it was a combination of their db sucking and the fact they got rid of some essential pear packages. WTF?

Update – 05/12/07 – 11 AM – Yup. They cut off my MySQL abilities. I can't connect to any of my databases on xrho.com. This site is fine however. I guess inserting 100+ entries a minute might have annoyed them?

Update – 05/17/07 – 7 PM – The MySQL abilities are still cut off. Fucking netfirms. Also, it seems in one of my updates, it cut off the bottom, which also happened to include the download links. You can download a ZIP or Gzip of the files. Since I'm having problems with that, feel free to download them and run them on your own site. Let me know if you do so I can add the link.

Demos of most of the scripts are available here, and more specifically:

Due to the length of this post, I'm splitting it. I hate making people click through, but it's long enough to constitute it.

Part A: The Setup

First, we need the Pear package, from http://bugs.joestump.net/code/Services_Digg/Services_Digg-0.0.2.tgz. You can install it using the Pear install command, but I just copied the folder into my directory.

We're going to be using MySQL database, so create a new database and here is the table structure I used:

-- 
-- Table structure for table `diggslive`
-- 
 
CREATE TABLE `diggslive` (
  `digging_id` int(10) unsigned NOT NULL auto_increment,
  `story_id` int(10) unsigned NOT NULL,
  `id` int(10) unsigned NOT NULL,
  `username` varchar(250) collate latin1_general_ci NOT NULL,
  `time` int(10) NOT NULL,
  `status` varchar(45) collate latin1_general_ci NOT NULL,
  PRIMARY KEY  (`digging_id`),
  UNIQUE KEY `id` (`id`),
  KEY `username` (`username`),
  KEY `story_id` (`story_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=137897 ;
 
-- --------------------------------------------------------
 
-- 
-- Table structure for table `diggstories`
-- 
 
CREATE TABLE `diggstories` (
  `digg_id` int(10) unsigned NOT NULL auto_increment,
  `title` text character set latin1 collate latin1_general_ci NOT NULL,
  `description` text character set latin1 collate latin1_general_ci NOT NULL,
  `diggs` int(5) NOT NULL,
  `comments` int(4) NOT NULL,
  `id` int(10) unsigned NOT NULL,
  `link` varchar(1000) character set latin1 collate latin1_general_ci NOT NULL,
  `submitted` int(10) NOT NULL,
  `promoted` int(10) NOT NULL,
  `href` varchar(1000) character set latin1 collate latin1_general_ci NOT NULL,
  `status` varchar(45) character set latin1 collate latin1_general_ci NOT NULL,
  `user_id` int(10) unsigned NOT NULL,
  `username` varchar(250) character set latin1 collate latin1_general_ci NOT NULL,
  `icon` text character set latin1 collate latin1_general_ci NOT NULL,
  `registered` int(10) NOT NULL,
  `profileviews` int(10) unsigned NOT NULL,
  `topic_long` varchar(100) character set latin1 collate latin1_general_ci NOT NULL,
  `topic_short` varchar(100) character set latin1 collate latin1_general_ci NOT NULL,
  `container_long` varchar(100) character set latin1 collate latin1_general_ci NOT NULL,
  `container_short` varchar(100) character set latin1 collate latin1_general_ci NOT NULL,
  `host` varchar(250) collate utf8_bin default NULL,
  PRIMARY KEY  (`digg_id`),
  UNIQUE KEY `href` (`href`),
  FULLTEXT KEY `title` (`title`),
  FULLTEXT KEY `description` (`description`),
  FULLTEXT KEY `title_2` (`title`,`description`),
  FULLTEXT KEY `link` (`link`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=3818 ;
 
-- --------------------------------------------------------
 
-- 
-- Table structure for table `diggusers`
-- 
 
CREATE TABLE `diggusers` (
  `user_id` int(10) unsigned NOT NULL auto_increment,
  `username` varchar(250) collate latin1_general_ci NOT NULL,
  `icon` text collate latin1_general_ci,
  `registered` int(10) NOT NULL,
  `profileviews` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`user_id`),
  UNIQUE KEY `username` (`username`),
  KEY `username_2` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=2550 ;

There are 3 tables. Table diggstories will store the all the info about the the popular stories that is given to us through the api. There are 3 FULLTEXT indecies to enable a better search as shown later.

Now for the config file. Edit as necessary for your setup:
config.php:

<?php
 
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "";
$dbname = "digg";
 
// Connect to DB, now!
// Regular connection
@mysql_connect($dbhost,$dbuser,$dbpass) or die("MySQL Connection error");
// Persistent conenction
// @mysql_pconnect($dbhost,$dbuser,$dbpass) or deadlyerror("MySQL Connection error (persistent) ");
@mysql_select_db($dbname) or die("Unable to select database");
 
?>

Here are some functions that we'll use later.
functions.php:

<?php
 
function sqlquote($value) {
    if(get_magic_quotes_gpc()) {
          $value = stripslashes($value);
    }
    //check if this function exists
    if( function_exists("mysql_real_escape_string") ) {
          $value = mysql_real_escape_string($value);
    }
    //for PHP version < 4.3.0 use addslashes
    else {
          $value = addslashes($value);
    }
    return $value;
}
 
function dehtml($content) {
	$content = preg_replace("/&(?!(amp|[#0-9]+|lt|gt|quot|copy|nbsp);)/ix","&amp;",$content);
	$content = str_replace(array("&#160;","&#173;","&#8205;","&#8204;","&#8237;","&#8238;"),"",$content);
	//$content = preg_replace('/&(?![a-z0-9]+;)/i', '&amp;', $content); 
	return str_replace(array("<",">","'","""),array("&lt;","&gt;","&#39;","&quot;"),$content);
}
 
function timeparse($time) {
	$since = time() - $time;
	if($since < 60) {
		return ($since == 1) ? "$since second ago" : "$since seconds ago";
	}
	elseif($since < 3600) {
		$since = floor($since/60);
		return ($since == 1) ? "$since minute ago" : "$since minutes ago";
	}
	elseif($since < 86400) {
		$since = floor($since/3600);
		return ($since == 1) ? "$since hour ago" : "$since hours ago";
	}
	else {
		$since = floor($since/86400);
		return ($since == 1) ? "$since day ago" : "$since days ago";
	}
}
 
 
function toshort($text) {
	return strtolower(str_replace(" ","_",$text));
}
 
 
function host($url) {
	$exploded = explode("/",$url);
	return str_replace("www.","",$exploded[2]);
}
 
?>

Part B: Getting data

Getting the stories

First off, let's populate our database with stories. This will take as many stories as possible and inserts them into out `diggstories` table. We are also going to insert our user info that it finds.

insert.php:

<?php
 
 
ini_set('user_agent', 'Trendds/1.0');
ini_set('max_execution_time', 3600);
 
require 'config.php';
 
include 'functions.php';
require_once 'Services/Digg.php';
Services_Digg::$appKey = 'http://www.ja.meswilson.com/blog/Services_Digg_Proxy.php';
Services_Digg::$uri = 'http://services.digg.com';
$count = 3525;
$offset = 0;
while($offset<$count) {
	$params = array('count' => 100,'offset' => $offset);
	$request = Services_Digg::factory('Stories')->popular($params);
	foreach ($request->stories as $story) {
 
		$userinfo = mysql_query("SELECT `user_id`, `profileviews` FROM `diggusers` WHERE `username` = '".sqlquote($story->user->name)."' LIMIT 1");
		if(mysql_numrows($userinfo) != 1) {
			mysql_query("INSERT INTO `diggusers`
				( `user_id` , `username`, `icon`, `registered`, `profileviews` )
				VALUES ( 
					NULL, 
					'".sqlquote($story->user->name)."', 
					'".sqlquote($story->user->icon)."', 
					'".sqlquote($story->user->registered)."',
					'".sqlquote($story->user->profileviews)."'
				) ") or die("Inserting user: ".mysql_error());
			$user_id = mysql_insert_id();
		}
		else {
			$user_id = mysql_result($userinfo,0,"user_id");
		}
		mysql_query("INSERT INTO `diggstories` ( 
		`digg_id`, `title`, `description`, `diggs`, `comments`, `id`, `link`, `submitted`, `promoted`, `href`, `status`, 
			`user_id` , `username`, `icon`, `registered`, `profileviews`, `topic_long`, `topic_short`, `container_long`, `container_short`, `host`
		)
		VALUES (
			NULL, 
			'".sqlquote($story->title)."', 
			'".sqlquote($story->description)."', 
			'".sqlquote($story->diggs)."',
			'".sqlquote($story->comments)."',
			'".sqlquote($story->id)."',
			'".sqlquote($story->link)."', 
			'".sqlquote($story->submit_date)."',
			'".sqlquote($story->promote_date)."',
			'".sqlquote($story->href)."',
			'".sqlquote($story->status)."',
			'".sqlquote($user_id)."',
			'".sqlquote($story->user->name)."',
			'".sqlquote($story->user->icon)."',
			'".sqlquote($story->user->registered)."',
			'".sqlquote($story->user->profileviews)."',
			'".sqlquote($story->topic->name)."',
			'".sqlquote($story->topic->short_name)."',
			'".sqlquote($story->container->name)."',
			'".sqlquote($story->container->short_name)."',
			'".sqlquote(host($story->link))."'
		) ") or mysql_query("UPDATE `diggstories` 
			SET `diggs` = '".sqlquote($story->diggs)."', `comments` = '".sqlquote($story->comments)."'
			WHERE `id` = '".sqlquote($story->id)."' 
			LIMIT 1
			") or die(mysql_error());
	}
	echo "<br />".$offset;
	$offset += 100;
	$count = $request->total;
}
 
 
?>

The first lines,
ini_set('user_agent', 'Trendds/1.0');
ini_set('max_execution_time', 3600);

set the User-Agent and increases the max execution time, since getting over 3000 stories takes some time, and setting a user agent is required.

Services_Digg::$appKey = 'http://www.ja.meswilson.com/blog/Services_Digg_Proxy.php';
Services_Digg::$uri = 'http://services.digg.com';

set the api key and uri, as shown in the Pear tests.

Next, we start requesting and inserting the info. This runs through a while and for each loop inserting each story.

After running that, you should now have about a 3000 entry `diggstories` table along with a couple thousand entry `diggusers` table.

In order to keep these updated, we can run update.php every so often. I did 5 minutes, but that seems to be a bit overkill.

update.php:

<?php
 
 
ini_set('user_agent', 'Trendds/1.0');
ini_set('max_execution_time', 3600);
 
require 'config.php';
 
include 'functions.php';
require_once 'Services/Digg.php';
Services_Digg::$appKey = 'http://www.ja.meswilson.com/blog/Services_Digg_Proxy.php';
Services_Digg::$uri = 'http://services.digg.com';
 
 
$params = array('count' => 100);
$request = Services_Digg::factory('Stories')->popular($params);
//print_r($request);
//exit;
foreach ($request->stories as $story) {
 
	$userinfo = mysql_query("SELECT `user_id`, `profileviews` FROM `diggusers` WHERE `username` = '".sqlquote($story->user->name)."' LIMIT 1");
	if(mysql_numrows($userinfo) != 1) {
		mysql_query("INSERT INTO `diggusers`
			( `user_id` , `username`, `icon`, `registered`, `profileviews` )
			VALUES ( 
				NULL, 
				'".sqlquote($story->user->name)."', 
				'".sqlquote($story->user->icon)."', 
				'".sqlquote($story->user->registered)."',
				'".sqlquote($story->user->profileviews)."'
			) ") or die("Inserting user: ".mysql_error());
		$user_id = mysql_insert_id();
	}
	else {
		$user_id = mysql_result($userinfo,0,"user_id");
	}
	mysql_query("INSERT INTO `diggstories` ( 
	`digg_id`, `title`, `description`, `diggs`, `comments`, `id`, `link`, `submitted`, `promoted`, `href`, `status`, 
		`user_id` , `username`, `icon`, `registered`, `profileviews`, `topic_long`, `topic_short`, `container_long`, `container_short`, `host`
	)
	VALUES (
		NULL, 
		'".sqlquote($story->title)."', 
		'".sqlquote($story->description)."', 
		'".sqlquote($story->diggs)."',
		'".sqlquote($story->comments)."',
		'".sqlquote($story->id)."',
		'".sqlquote($story->link)."', 
		'".sqlquote($story->submit_date)."',
		'".sqlquote($story->promote_date)."',
		'".sqlquote($story->href)."',
		'".sqlquote($story->status)."',
		'".sqlquote($user_id)."',
		'".sqlquote($story->user->name)."',
		'".sqlquote($story->user->icon)."',
		'".sqlquote($story->user->registered)."',
		'".sqlquote($story->user->profileviews)."',
		'".sqlquote($story->topic->name)."',
		'".sqlquote($story->topic->short_name)."',
		'".sqlquote($story->container->name)."',
		'".sqlquote($story->container->short_name)."',
		'".sqlquote(host($story->link))."'
	) ") or mysql_query("UPDATE `diggstories` 
		SET `diggs` = '".sqlquote($story->diggs)."', `comments` = '".sqlquote($story->comments)."'
		WHERE `id` = '".sqlquote($story->id)."' 
		LIMIT 1
		") or die(mysql_error());
}
 
 
 
 
?>

In order to not refresh or have a cron job (though if you plan on using this more, a cron job would be good), you can just run crondigg.py, or crondigg.pyw if you don't want to see a window, to keep the database updated. You will need to edit value for url to point to the location of your update.php.

crondigg.py

#! /usr/bin/env python
 
url = 'http://localhost/digg/update.php'
wait = 300
 
import urllib,time
 
while 1:
	try:
		print 'Requesting %s \r' % url,
		urllib.urlopen(url).read()
		print " " * (len(url)+12),'\r',
		count = 0
		while count < wait:
			print 'Waiting %d seconds \r' % (wait-count),
			count+=1
			time.sleep(1)
	except KeyboardInterrupt:
		import sys
		sys.exit(2)

Note: This python script was written on Windows, where it works fine. On linux however, it's a different story. It still works, just the output doesn't.

Gettings diggs

Next, we're going to get individual diggs. We're not going to go back in time and get as many diggs as possible. The database will get really big pretty quickly, so don't worry about it.

updatediggs.php:

<?php
 
 
ini_set('user_agent', 'Trendds/1.0');
ini_set('max_execution_time', 3600);
 
 
require 'config.php';
 
include 'functions.php';
require_once 'Services/Digg.php';
Services_Digg::$appKey = 'http://www.ja.meswilson.com/blog/Services_Digg_Proxy.php';
Services_Digg::$uri = 'http://services.digg.com';
 
 
$api = Services_Digg::factory('Stories');
 
// To keep track of the current timestamp. This could just be mysql_result(mysql_query("SELECT `time` FROM `diggslive` ORDER BY `time` DESC LIMIT 1"),0,"time")  but a txt file is easier.
//$mindate = file_get_contents('lastdiggs.txt')-1;
$mindate = mysql_result(mysql_query("SELECT `time` FROM `diggslive` ORDER BY `time` DESC LIMIT 1"),0,"time")-1 ;
//$mindate = time() - 3600;
 
$offset = 0;
$total = 1;
$runs = 0;
 
// Get as many diggs as possible since the last update
while ($offset < $total) {
	$params = array('count' => 100,'min_date' => $mindate,'offset'=>$offset);
	$diggs = $api->diggs($params);
	// Go through each digg
	//print_r($diggs);
	foreach ($diggs->diggs as $digg) {
		// This is pretty annoying. It's true if the insert failed. It might not be the most sensible thing, but it's about 2 in the morning, and I like it
		$inserted = false;
		// Insert the digg
		mysql_query("INSERT INTO `diggslive` 
			(`digging_id`, `story_id`, `id`, `username`, `time`, `status`)
			VALUES (
				NULL,
				'".sqlquote($digg->story)."',
				'".sqlquote($digg->id)."',
				'".sqlquote($digg->user)."',
				'".sqlquote($digg->date)."',
				'".sqlquote($digg->status)."'
			)") or setcheck(true);
		if(!$inserted) {
			// Increase the digg count of the story, since it just got dugg
			mysql_query("UPDATE `diggstories` SET `diggs` = `diggs`+1 WHERE `id` = '".sqlquote($digg->id)."' LIMIT 1") or die(mysql_error());
		}
	}
	// If this is the first run, update the timestamp. We could use time(), but it might be slightly off. If we take the timestamp of a later run, it'll be later than what we got back.
	if($runs == 0 AND $diggs->timestamp != "") {
		$timestamp = $diggs->timestamp;
		$runs = 1;
	}
	$total = $diggs->total;
	print $offset."<br />";
	$offset += 100;
}
 
 
// If the timestamp isn't foobared, update the file. If there are network problems or something, this can be wrong. I don't think I've still truely fixed that, but whatever.
if(isset($timestamp) AND $timestamp != "" AND is_numeric($timestamp) AND $timestamp > 1000000) {
	$file = fopen('lastdiggs.txt','w');
	fwrite($file,$timestamp);
	fclose($file);
}
 
 
// This will change the variable to say if it inserted successfully or not, because doing ... or $inserted = true;   doesn't work. -_-
function setcheck($bool) {
	global $inserted;
	$inserted = $bool;
}
 
 
?>

Before you can use this, you need to insert some digg or something into `diggslive` with `time` set to the current timestamp. After another digg gets inserted, you can get rid of this entry.

This just gets the diggs of all the stories since the last digg we got. The timestamp is one less than the time of the last digg. This is to make sure we got the diggs that occureed at the same second as the previous one.

This also edits a file called lastdigg.txt, which is just an alternative to the sql query.

As I said earlier, the table gets big. Mine was at around 330k entries before I started running deletes. Let's get rid of any diggs older than a day. We don't really need them.

removediggs.p:

<?php
 
require 'config.php';
 
$query = "DELETE FROM `diggslive` WHERE `time` < ".(time() - 24*60*60)."";
mysql_query($query)or die(mysql_error());
mysql_query("OPTIMIZE TABLE `diggslive` ") or die(mysql_error());
 
?>

To keep this updated, you can run crondiggs.py. This requests your updatediggs.php file every 30 seconds.

crondiggs.py

#! /usr/bin/env python
 
url = 'http://localhost/digg/updatediggs.php'
url2 = 'http://localhost/digg/removediggs.php'
wait = 30
 
import urllib,time
 
while 1:
	try:
		print 'Requesting %s \r' % url,
		urllib.urlopen(url).read()
		if int(time.time()) % 10 == 0:
			print 'Requesting %s \r' % url2,
			urllib.urlopen(url2).read()
		print " " * (len(url)+12),'\r',
		count = 0
		while count < wait:
			print 'Waiting %d seconds \r' % (wait-count),
			count+=1
			time.sleep(1)
	except KeyboardInterrupt:
		import sys
		sys.exit(2)

Part Gamma: Tag Clouds

Now it's time to use all this new fangled data we're collecting, and what's more Web 2.0 than tag clouds? And since we're lazy, we're going to use this tag cloud script.

First cloud set, the container cloud set. The containers are the main topics, like Technology, Science, Sports, etc.

concloud.png

concloud.php:

<?php
 
// most from: http://prism-perfect.net/archive/php-tag-cloud-tutorial/
 
// connect to database at some point
 
// In the SQL below, change these three things:
// thing is the column name that you are making a tag cloud for
// id is the primary key
// my_table is the name of the database table
 
require 'config.php';
 
$query = "SELECT container_long AS tag, COUNT(digg_id) AS quantity, container_short
  FROM diggstories
  GROUP BY container_long
  ORDER BY container_long ASC";
 
$result = mysql_query($query);
 
// here we loop through the results and put them into a simple array:
// $tag['thing1'] = 12;
// $tag['thing2'] = 25;
// etc. so we can use all the nifty array functions
// to calculate the font-size of each tag
while ($row = mysql_fetch_array($result)) {
	$shortname[$row['tag']] = $row['container_short'];
    $tags[$row['tag']] = $row['quantity'];
}
 
// change these font sizes if you will
$max_size = 250; // max font size in %
$min_size = 100; // min font size in %
 
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
 
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
    $spread = 1;
}
 
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
 
// loop through our tag array
foreach ($tags as $key => $value) {
 
    // calculate CSS font-size
    // find the $value in excess of $min_qty
    // multiply by the font-size increment ($size)
    // and add the $min_size set above
    $size = $min_size + (($value - $min_qty) * $step);
    // uncomment if you want sizes in whole %:
    // $size = ceil($size);
 
    // you'll need to put the link destination in place of the #
    // (assuming your tag links to some sort of details page)
    echo '<a href="'.$shortname[$key].'" style="font-size: '.$size.'%"';
    // perhaps adjust this title attribute for the things that are tagged
    echo ' title="'.$value.' things tagged with '.$key.'"';
    echo '>'.$key.'</a> ';
    // notice the space at the end of the link
}
 
 
 
?>

That's pretty boring though. Maybe regular categories, like Apple, Linux/Unix, Playable Web Games, etc, will be more interesting.

catcloud.png

catcloud.php

<?php
 
// most from: http://prism-perfect.net/archive/php-tag-cloud-tutorial/
 
// connect to database at some point
 
// In the SQL below, change these three things:
// thing is the column name that you are making a tag cloud for
// id is the primary key
// my_table is the name of the database table
 
require 'config.php';
require 'functions.php';
 
$query = "SELECT topic_long AS tag, COUNT(digg_id) AS quantity, topic_short
  FROM diggstories
  GROUP BY topic_long
  ORDER BY topic_long ASC";
 
$result = mysql_query($query);
 
// here we loop through the results and put them into a simple array:
// $tag['thing1'] = 12;
// $tag['thing2'] = 25;
// etc. so we can use all the nifty array functions
// to calculate the font-size of each tag
while ($row = mysql_fetch_array($result)) {
	$shortname[$row['tag']] = $row['topic_short'];
    $tags[$row['tag']] = $row['quantity'];
}
 
// change these font sizes if you will
$max_size = 250; // max font size in %
$min_size = 100; // min font size in %
 
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
 
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
    $spread = 1;
}
 
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
 
// loop through our tag array
foreach ($tags as $key => $value) {
 
    // calculate CSS font-size
    // find the $value in excess of $min_qty
    // multiply by the font-size increment ($size)
    // and add the $min_size set above
    $size = $min_size + (($value - $min_qty) * $step);
    // uncomment if you want sizes in whole %:
    // $size = ceil($size);
 
    // you'll need to put the link destination in place of the #
    // (assuming your tag links to some sort of details page)
    echo '<a href="http://digg.com/'.$shortname[$key].'" style="font-size: '.$size.'%"';
    // perhaps adjust this title attribute for the things that are tagged
    echo ' title="'.$value.' things tagged with '.$key.'"';
    echo '>'.$key.'</a> ';
    // notice the space at the end of the link
}
 
 
 
?>

A little better. How about a user cloud based on submissions?

usercloud.png

usercloud.php:

<?php
 
// most from: http://prism-perfect.net/archive/php-tag-cloud-tutorial/
 
// connect to database at some point
 
// In the SQL below, change these three things:
// thing is the column name that you are making a tag cloud for
// id is the primary key
// my_table is the name of the database table
 
require 'config.php';
 
$query = "SELECT username AS tag, COUNT(digg_id) AS quantity
  FROM diggstories
  GROUP BY username
  ORDER BY username ASC";
 
$result = mysql_query($query);
 
// here we loop through the results and put them into a simple array:
// $tag['thing1'] = 12;
// $tag['thing2'] = 25;
// etc. so we can use all the nifty array functions
// to calculate the font-size of each tag
while ($row = mysql_fetch_array($result)) {
	//$shortname[$row['tag']] = $row['container_short'];
    $tags[$row['tag']] = $row['quantity'];
}
 
// change these font sizes if you will
$max_size = 250; // max font size in %
$min_size = 100; // min font size in %
 
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
 
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
    $spread = 1;
}
 
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
 
// loop through our tag array
foreach ($tags as $key => $value) {
 
    // calculate CSS font-size
    // find the $value in excess of $min_qty
    // multiply by the font-size increment ($size)
    // and add the $min_size set above
    $size = $min_size + (($value - $min_qty) * $step);
    // uncomment if you want sizes in whole %:
    // $size = ceil($size);
 
    // you'll need to put the link destination in place of the #
    // (assuming your tag links to some sort of details page)
    echo '<a href="http://digg.com/users/'.urlencode($key).'" style="font-size: '.$size.'%"';
    // perhaps adjust this title attribute for the things that are tagged
    echo ' title="'.$value.' things tagged with '.$key.'"';
    echo '>'.$key.'</a> ';
    // notice the space at the end of the link
}
 
 
 
?>

Pretty big, but let's try bigger. A user cloud based on number of diggs.

diggusercloud.png

diggusercloud.php:

<?php
 
// most from: http://prism-perfect.net/archive/php-tag-cloud-tutorial/
 
// connect to database at some point
 
// In the SQL below, change these three things:
// thing is the column name that you are making a tag cloud for
// id is the primary key
// my_table is the name of the database table
 
require 'config.php';
 
$query = "SELECT username AS tag, COUNT(digging_id) AS quantity
  FROM diggslive
  GROUP BY username
  ORDER BY username ASC";
 
$result = mysql_query($query);
 
// here we loop through the results and put them into a simple array:
// $tag['thing1'] = 12;
// $tag['thing2'] = 25;
// etc. so we can use all the nifty array functions
// to calculate the font-size of each tag
while ($row = mysql_fetch_array($result)) {
	$href[$row['tag']] = $row['href'];
    $tags[$row['tag']] = $row['quantity'];
}
 
// change these font sizes if you will
$max_size = 250; // max font size in %
$min_size = 100; // min font size in %
 
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
 
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
    $spread = 1;
}
 
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
 
// loop through our tag array
foreach ($tags as $key => $value) {
 
    // calculate CSS font-size
    // find the $value in excess of $min_qty
    // multiply by the font-size increment ($size)
    // and add the $min_size set above
    $size = $min_size + (($value - $min_qty) * $step);
    // uncomment if you want sizes in whole %:
    // $size = ceil($size);
 
    // you'll need to put the link destination in place of the #
    // (assuming your tag links to some sort of details page)
    echo '<a href="http://digg.com/users/'.$key.'" style="font-size: '.$size.'%"';
    // perhaps adjust this title attribute for the things that are tagged
    echo ' title="'.$value.' things tagged with '.$key.'"';
    echo '>'.$key.'</a> ';
    // notice the space at the end of the link
}
 
 
 
?>

Great. How about a story cloud based on the number of diggs?

diggcloud.png

diggcloud.php:

<?php
 
// most from: http://prism-perfect.net/archive/php-tag-cloud-tutorial/
 
// connect to database at some point
 
// In the SQL below, change these three things:
// thing is the column name that you are making a tag cloud for
// id is the primary key
// my_table is the name of the database table
 
require 'config.php';
 
$query = "SELECT title AS tag, COUNT(digg_id) AS quantity, href
  FROM diggstories
  GROUP BY diggs
  ORDER BY diggs ASC";
 
$result = mysql_query($query);
 
// here we loop through the results and put them into a simple array:
// $tag['thing1'] = 12;
// $tag['thing2'] = 25;
// etc. so we can use all the nifty array functions
// to calculate the font-size of each tag
while ($row = mysql_fetch_array($result)) {
	$href[$row['tag']] = $row['href'];
    $tags[$row['tag']] = $row['quantity'];
}
 
// change these font sizes if you will
$max_size = 250; // max font size in %
$min_size = 100; // min font size in %
 
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
 
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
    $spread = 1;
}
 
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
 
// loop through our tag array
foreach ($tags as $key => $value) {
 
    // calculate CSS font-size
    // find the $value in excess of $min_qty
    // multiply by the font-size increment ($size)
    // and add the $min_size set above
    $size = $min_size + (($value - $min_qty) * $step);
    // uncomment if you want sizes in whole %:
    // $size = ceil($size);
 
    // you'll need to put the link destination in place of the #
    // (assuming your tag links to some sort of details page)
    echo '<a href="'.$href[$key].'" style="font-size: '.$size.'%"';
    // perhaps adjust this title attribute for the things that are tagged
    echo ' title="'.$value.' things tagged with '.$key.'"';
    echo '>'.$key.'</a> ';
    // notice the space at the end of the link
}
 
 
 
?>

But wait, that doesn't look right. That's because we can't use basically the same SQL query as before. It's grouping the stories by the amount of diggs, so that if there are 3 stories with 750 diggs, and only 1 story with 751 diggs, the 3 stories will be larger. Since the weight of the story is already set as an entry, we don't need to group it, so we can just use this SQL query:

SELECT title AS tag, diggs, href
  FROM diggstories
  ORDER BY title ASC

realdiggcloud.png

<?php
 
// most from: http://prism-perfect.net/archive/php-tag-cloud-tutorial/
 
// connect to database at some point
 
// In the SQL below, change these three things:
// thing is the column name that you are making a tag cloud for
// id is the primary key
// my_table is the name of the database table
 
require 'config.php';
 
$query = "SELECT title AS tag, diggs, href
  FROM diggstories
  ORDER BY title ASC";
 
$result = mysql_query($query);
 
// here we loop through the results and put them into a simple array:
// $tag['thing1'] = 12;
// $tag['thing2'] = 25;
// etc. so we can use all the nifty array functions
// to calculate the font-size of each tag
while ($row = mysql_fetch_array($result)) {
	$href[$row['tag']] = $row['href'];
    $tags[$row['tag']] = $row['diggs'];
}
 
// change these font sizes if you will
$max_size = 250; // max font size in %
$min_size = 100; // min font size in %
 
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
 
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
    $spread = 1;
}
 
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
 
// loop through our tag array
foreach ($tags as $key => $value) {
 
    // calculate CSS font-size
    // find the $value in excess of $min_qty
    // multiply by the font-size increment ($size)
    // and add the $min_size set above
    $size = $min_size + (($value - $min_qty) * $step);
    // uncomment if you want sizes in whole %:
    // $size = ceil($size);
 
    // you'll need to put the link destination in place of the #
    // (assuming your tag links to some sort of details page)
    echo '<a href="'.$href[$key].'" style="font-size: '.$size.'%"';
    // perhaps adjust this title attribute for the things that are tagged
    echo ' title="'.$value.' things tagged with '.$key.'"';
    echo '>'.$key.'</a> ';
    // notice the space at the end of the link
}
 
 
 
?>

If you noticed in insert.php and update.php, we had an entry called 'host'. This is equal to whatever the hostname of the link. Let's make a host cloud based on the amount of stories.

hostcloud.png

hostcloud.php:

<?php
 
// most from: http://prism-perfect.net/archive/php-tag-cloud-tutorial/
 
// connect to database at some point
 
// In the SQL below, change these three things:
// thing is the column name that you are making a tag cloud for
// id is the primary key
// my_table is the name of the database table
 
require 'config.php';
 
$query = "SELECT host AS tag, COUNT(digg_id) AS quantity
  FROM diggstories
  GROUP BY host
  ORDER BY host ASC";
 
$result = mysql_query($query);
 
// here we loop through the results and put them into a simple array:
// $tag['thing1'] = 12;
// $tag['thing2'] = 25;
// etc. so we can use all the nifty array functions
// to calculate the font-size of each tag
while ($row = mysql_fetch_array($result)) {
	$href[$row['tag']] = $row['href'];
    $tags[$row['tag']] = $row['quantity'];
}
 
// change these font sizes if you will
$max_size = 250; // max font size in %
$min_size = 100; // min font size in %
 
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
 
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
    $spread = 1;
}
 
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
 
// loop through our tag array
foreach ($tags as $key => $value) {
 
    // calculate CSS font-size
    // find the $value in excess of $min_qty
    // multiply by the font-size increment ($size)
    // and add the $min_size set above
    $size = $min_size + (($value - $min_qty) * $step);
    // uncomment if you want sizes in whole %:
    // $size = ceil($size);
 
    // you'll need to put the link destination in place of the #
    // (assuming your tag links to some sort of details page)
    echo '<a href="search.php?links='.urlencode($key).'" style="font-size: '.$size.'%"';
    // perhaps adjust this title attribute for the things that are tagged
    echo ' title="'.$value.' things tagged with '.$key.'"';
    echo '>'.$key.'</a> ';
    // notice the space at the end of the link
}
 
 
 
?>

Where to go: Tag clouds are fun. You can easily set it to only show a certain time period, like the past day or week, or you could use both the diggstories and diggslive tables to see what people are digging. You could also combine it with the search that we'll talk about next.

Part Dogma – Improved Search

As I said earlier, the `diggstories` table has 4 FULLTEXT indecies, so let's use those to create a better search. It's not necessarily all that better than the current one, and won't search upcoming stories, but to some, it might be better.

This will allow you to search using multiple queries, like let's say you want to find all of the stories dealing nintendo from arstechnica.com. This search can easily handle that.

It uses MySQL FULLTEXT search to handle it. This has the basic format of WHERE MATCH(`columns`) AGAINST ('query') and will return the results based on the relevance.

Better Search

search1.png

search2.png

search.php:

<?php
 
if(!isset($_GET['q']) AND !isset($_GET['title']) AND !isset($_GET['desc']) AND !isset($_GET['links'])) {
	?>
<form action="search.php" method="get">
Search title and desc: <input type="text" name="q" /><br /><br />
<b>OR</b>
<br /><br />
Search in title: <input type="text" name="title" /><br />
Search in desc: <input type="text" name="desc" /><br />
Search in links: <input type="text" name="links" /><br /><br />
 
<br />
<input type="submit" value="Search" />
 
</form>
	<?php
}
else {
	require 'config.php';
	require 'functions.php';
	if(isset($_GET['q']) AND $_GET['q'] != "") {
		$where = " MATCH (`title`, `description`) AGAINST ('".sqlquote($_GET['q'])."') ";
	}
	else {
		if(isset($_GET['title']) AND $_GET['title'] != "") {
			$where = " MATCH (`title`) AGAINST ('".sqlquote($_GET['title'])."') ";
		}
		if(isset($_GET['desc']) AND $_GET['desc'] != "") {
			$where .= ( ($where == "") ? "" : "AND")." MATCH (`description`) AGAINST ('".sqlquote($_GET['desc'])."') ";
		}
		if(isset($_GET['links']) AND $_GET['links'] != "") {
			$where .= ( ($where == "") ? "" : "AND")." MATCH (`link`) AGAINST ('".sqlquote($_GET['links'])."') ";
		}
	}
 
	$result = mysql_query("SELECT `title`, `description`, `diggs`, `comments`, `link`, `href` 
		FROM `diggstories` 
		WHERE $where") or die(mysql_error());
 
	$num = mysql_numrows($result);
 
	if($num == 0) {
		echo "No results found";
		exit;
	}
 
	echo "<table align="center">
	<thead><tr><th>Story</th><th>Diggs</th><th>Comments</th></tr></thead>";
 
	for($i=0;$i<$num;$i++) {
		echo "<tr><td><a href="".dehtml(mysql_result($result,$i,"link"))."" title="".dehtml(mysql_result($result,$i,"description"))."">".dehtml(mysql_result($result,$i,"title"))."</a> [<a href="".dehtml(mysql_result($result,$i,"href"))."">More</a>]</td>
		<td>".mysql_result($result,$i,"diggs")."</td>
		<td>".mysql_result($result,$i,"comments")."</td>
		</tr>";
	}
	echo "</table>";
 
	echo "<span style="float:right;">$num results</span>";
 
}

Where to go: There are a lot of things that can be done to improve this. Maybe add a fetaure to only return stories with over a certain amount of diggs or comments, or that were submitted between certain dates

Part Alien – Reggit/Dreddit – Reddit clone

Homepage

Everyone loves the clean, sexy layout of reddit, so let's take Digg's data and throw it into a reddit layout.

Pretty easy to make. Just copy their page layout and CSS, and throw the digg story information in there. I removed the header and footer from it, since none will really work, and we don't have some badass logo. It's just sorted by promoted time, and not popularity, though it could probably be modded to take account that.

reddit-digg ss

Reddit Clone

reddit.php

<?php
 
 
require 'config.php';
require 'functions.php';
 
 
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
<title>digg + reddit = reggit... or dreddit</title>
<script src="http://reddit.com/static/psrs.js" language="javascript" type="text/javascript"></script>
<script src="http://reddit.com/static/reddit.js" language="javascript" type='text/javascript'></script>
<link rel='stylesheet' href='http://reddit.com/static/styles.css' type='text/css' />
<link rel='shortcut icon' href='http://reddit.com/favicon.ico' type="image/x-icon" />
<script language='javascript'>
    var a = new Image();
    a.src ="http://static.reddit.com/aupmod.png";
    var b = new Image();
    b.src = "http://static.reddit.com/adownmod.png";
 
</script>
 
</head>
<body>
 
<?php
 
$offset = (isset($_GET['offset']) AND is_numeric($_GET['offset'])) ? $_GET['offset'] : 0;
 
$result = mysql_query("SELECT `title`, `diggs`, `comments`, `link`, `href`, `host`, `id`, `username`, `submitted`
	FROM `diggstories`
 
	ORDER BY `promoted` DESC
	LIMIT $offset, 25") or die(mysql_error());
 
$num = mysql_numrows($result);
?>
<div id='main'>
        <table id="siteTable">
<?php
for($i=0;$i<$num;$i++) {
	echo "<tr id="story".mysql_result($result,$i,"id")."">";
	echo ($i % 2 == 0) ? "<td colspan="1" class="evenRow spacing top"></td>
    <td colspan="4" class="evenRow spacing top"></td>
    </tr>
<tr class="evenRow">" : "<td colspan="1" class="oddRow spacing top"></td>
    <td colspan="4" class="oddRow spacing top"></td>
    </tr>
<tr class="oddRow">";
	echo "<td valign="top" class="numbercol" rowspan="3">".($i+$offset+1).".</td>";
	echo  "<td valign="top" rowspan="3">
        <div id="up".mysql_result($result,$i,"id")."" class="arrow up" onclick="javascript:mod(".mysql_result($result,$i,"id").", 1, '')"> </div>
        <div id="down".mysql_result($result,$i,"id")."" class="arrow down" onclick="javascript:mod(".mysql_result($result,$i,"id").", 0, '')"/>
    </td>";
 
	echo " <td colspan="3" id="titlerow".mysql_result($result,$i,"id")."">
        <a id="title".mysql_result($result,$i,"id")."" class="title" href="".dehtml(mysql_result($result,$i,"link")).""                                   >          ".dehtml(mysql_result($result,$i,"title"))."</a>
 
        <span class="little"> (".dehtml(mysql_result($result,$i,"host")).")</span> 
    </td>
</tr>";
 
	echo ($i % 2 == 0) ? "<tr class="evenRow">" : "<tr class="oddRow">";
 
	echo "<td valign="top" class="wide little" colspan="3">
 
<span id="score".mysql_result($result,$i,"id")."">".mysql_result($result,$i,"diggs")." diggs</span>
posted ".( floor( (time() - mysql_result($result,$i,"submitted")) / 3600) )."   hours ago by <a href="http://digg.com/user/".mysql_result($result,$i,"username")."">".mysql_result($result,$i,"username")." </a>
    <a href="".mysql_result($result,$i,"href")."" class="bylink"          >         ".mysql_result($result,$i,"comments")." comments     </a>
 
</td>
</tr>";
	echo "<tr ><td colspan="3" class="".( ($i % 2 == 0) ? "evenRow" : "oddRow" )." spacing"></td></tr>";
}
?>
    </table>
        <p class="menu"> view more:
 
 
         <a href="reddit.php?offset=<?php echo $offset+25; ?>">next »</a>
        </p>
 
</div>
 
</body></html>

Where to go: Subreddits, like technology.redditclone to only show the stories from the container 'Technology', or apple.redditclone or apple.technology.redditclone to only show stories from the topic 'Apple'. Sort by popularity or "hotness", like reddit's homepage. Maybe something like ORDER BY `diggs` / (".time()." - `promoted`), but better.

RSS

Another great part of reddit is their RSS feed. No fluff, no mess, just links, so let's rid that off too. This is also really easy to make. If you've ever had to make an RSS feed from a DB, you'll have no trouble.

The RSS feed consists of a title that links directly to the article, with the content having links [link] which goes to the article, [more] which goes to the Digg page, and a [dugg] links which goes to the Duggmirror link.

reddit digg rss

Reddit / Better RSS Feed

redditrss.php:

<?php
 
require 'config.php';
 
require 'functions.php';
 
 
$stories = mysql_query("SELECT `title`, `href`, `link`,`promoted` FROM `diggstories` ORDER BY `promoted` DESC LIMIT 0, 40");
 
rss_start();
 
$count = mysql_numrows($stories);
echo $count;
for($i=0;$i<$count;$i++) {
	rss_row(mysql_result($stories,$i,"title"), mysql_result($stories,$i,"href"), mysql_result($stories,$i,"link"),mysql_result($stories,$i,"promoted"));
}
 
rss_stop();
 
function rss_start() {
	header("Content-Type: text/xml");
	echo "<?xml version="1.0"?>";
	?>
	<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel>
        <title>reggit/dreddit: what's new on digg</title>
        <link>http://digg.com/</link>
        <description>The latest stories, voted on by users like you.</description>
	<?php
}
 
function rss_stop() {
	?>
	</channel></rss>
	<?php
}
 
function rss_row($title,$href,$link,$time) {
	echo "\n\t<item>\n\t\t<title>".dehtml($title)."</title>\n\t\t<link>".dehtml($link)."</link>\n\t\t<dc:date>".gmdate("T",$time)."</dc:date>\n\t\t
	\t<description><![CDATA[<a href="".dehtml($link)."">[link]</a> <a href="$href">[more]</a> <a href="".str_replace("digg.com","duggmirror.com",$href)."">[dugg]</a>]]></description>
	</item>";
}

Where to go: The RSS feed can further be customized to enable the ability to have the RSS feed of only certain categories, or of only stories containing certain phrases.

Part Fun – Live Diggs – A real application

After screwing with pointless tag clouds and a neat, although not important, reddit clone, we can now build an actual application.

This app will allow you to enter a title of a stories and watch as people digg it. It will display the username and time dugg, and refresh all ajaxily, cause it's got to web 2.0, right?

First, you enter the title of the story, which then will try to find it's story id first by searching our database, then, if that fails, using the Digg API story search.

Once it has the story id, it now displays at most the last 30 diggs, and refreshing every 30 seconds to add new diggs. The diggs are retrieved from our database, though using the digg api to select the new diggs could be done just as well, but we have a table full of diggs, and we're going to use it, dammit! Plus, I think it's a little nicer on digg, since if you have a fair amount of users, instead of that lot of people requesting or your server on their behalf requesting diggs every 30 seconds, there is just a consistent 1 request every 30 seconds.

Anyways, the javascript in this is just hacked together using prototype.js, meaning there are probably better ways to do this, but whatever. This works….for the most part. Sometimes there might be repeat here and there, but nothing devastating.

livediggs.png

livediggs1.png

Here it is:

Live Diggs

livediggs.php:

<?php
 
 
 
 
 
require 'config.php';
 
require 'functions.php';
 
require_once 'Services/Digg.php';
 
 
 
 
 
 
 
 
 
 
if(isset($_GET['title']) AND $_GET['title'] != "") {
 
	$result = mysql_query("SELECT `id` FROM `diggstories` WHERE `title` = '".sqlquote($_GET['title'])."' LIMIT 1");
	if(mysql_numrows($result) == 1) {
 
		if($_GET['mode'] == "ajax") {
 
			echo "storyid=".mysql_result($result,0,"id");
 
			exit;
 
		}
 
		else {
 
			header("Location: livediggs.php?storyid=".mysql_result($result,0,"id"));
 
			exit;
 
		}
 
	}
	// This doesn't work?
	$api = Services_Digg::factory('Stories');
 
	$story = $api->getStoryByTitle(preg_replace("/[^a-z0-9]/ix","_",$_GET['title']));
 
	//print_r($story);
	if(isset($story->id) AND $story->id != "" AND is_numeric($story->id)) {
 
		if($_GET['mode'] == "ajax") {
 
			echo "storyid=".$story->id;
 
			exit;
 
		}
 
		else {
 
			header("Location: livediggs.php?storyid=".$story->id);
 
			exit;
 
		}
 
	}
 
	echo "storynotfound";
 
 
}
 
elseif(isset($_GET['storyid']) AND $_GET['storyid'] != "" AND is_numeric($_GET['storyid'])) {
 
	if($_GET['mode'] == "ajax") {
 
		if(isset($_GET['time']) AND is_numeric($_GET['time'])) {
			if($_GET['time'] == 0) {
				echo "&&&timestamp=".time()."&&&";
				exit;
			}
			$where = " AND `digging_id` > '".(sqlquote($_GET['time']))."' ";
 
			$query = "SELECT * FROM `diggslive` WHERE `story_id` = '".sqlquote($_GET['storyid'])."' $where ORDER BY `time` DESC";
			//echo $query;
			$result = mysql_query($query);
 
			$num = mysql_numrows($result);
 
			for($i=0;$i<$num;$i++) {
				//echo "digger=".mysql_result($result,$i,"user")."&time=".timeparse(mysql_result($result,$i,"time"))."\n";
				echo "<tr class="digg"><td><a href="http://digg.com/users/".mysql_result($result,$i,"username")."">".mysql_result($result,$i,"username")."</a></td><td class="time" id="".mysql_result($result,$i,"time")."">".timeparse(mysql_result($result,$i,"time"))."</td></tr>";
			}
 
			echo "&&&timestamp=".( ($num == 0) ? $_GET['time'] : mysql_result($result,$num-1,"digging_id"))."&&&";
			exit;
		}
		else {
			$result = mysql_query("SELECT * FROM `diggslive` WHERE `story_id` = '".sqlquote($_GET['storyid'])."' ORDER BY `time` DESC LIMIT 0, 30");
 
			$num = mysql_numrows($result);
 
			if($num < 1) {
 
				echo "No diggs :(";
 
				std_stop();
 
			}
 
			echo "<table id="diggs" align="center">";
 
			for($i=0;$i<$num;$i++) {
 
				echo "<tr class="digg"><td><a href="http://digg.com/users/".mysql_result($result,$i,"username")."">".mysql_result($result,$i,"username")."</a></td><td class="time" id="".mysql_result($result,$i,"time")."">".timeparse(mysql_result($result,$i,"time"))."</td></tr>";
 
 
 
			}
 
			echo "</table>";
			echo "<script type="text/javascript"> time = ".mysql_result($result,0,"digging_id")."; </script>";
		}
 
	}
 
	else {
 
		std_start();
		$result = mysql_query("SELECT * FROM `diggslive` WHERE `story_id` = '".sqlquote($_GET['storyid'])."'  ORDER BY `time` LIMIT 0, 30");
		$num = mysql_numrows($result);
		if($num < 1) {
			echo "No diggs :(";
			std_stop();
		}
		echo "<table id="diggs" align="center">";
		for($i=0;$i<$num;$i++) {
			echo "<tr class="digg"><td><a href="http://digg.com/user/".mysql_result($result,$i,"username")."">".mysql_result($result,$i,"username")."</a></td><td>".timeparse(mysql_result($result,$i,"time"))."</td></tr>";
 
		}
		//$lastdiggid = mysql_result($result,$num-1,"digging_id");
		//echo $lastdiggid."!!@#!@#";
		echo "</table>";
		std_stop();
	}
 
}
 
else {
 
	std_start();
	form();
	std_stop();
 
 
 
}
 
 
 
 
 
 
 
 
 
function std_start() {
 
	?>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html>
 
<head>
 
<title>Live Diggs</title>
 
<script type="text/javascript" src="js/prototype.js"></script>
 
<!--<script type="text/javascript" src="js/scriptaculous.js"></script>-->
 
<script type="text/javascript">
var time = <?php echo time();// global $lastdiggid; echo $lastdiggid; ?>;
var resp = "";
function submitform(title) {
	$('loading').show();
	var uri = "livediggs.php";
	var params = "title="+escape(title)+"&mode=ajax";
 
	var ajax = new Ajax.Request(
		uri,
		{method:'get', parameters: params, onFailure: loadpage, onComplete: getdiggs}
	);
	return false;
}
 
function getdiggs(info) {
	resp = info.responseText;
	if(resp == "storynotfound") {
		$('error').show();
		$('loading').hide();
		return false;
	}
 
	var uri = "livediggs.php";
	var params = resp+"&mode=ajax";
	var ajax = new Ajax.Request(
		uri,
		{method:'get', parameters: params, onFailure: loadpage, onComplete:firstdone }
	);
	//update(resp);
}
 
function firstdone(info) {
	response = info.responseText;
	response.evalScripts();
	$('content').innerHTML = response;
 
	update(resp);
}
 
function update(story) {
	updater(story);
	setTimeout('update("'+story+'")',30000);
}
 
function updater(story) {
	var uri = 'livediggs.php';
	var params = "time="+time+"&mode=ajax&"+story;
	var ajax = new Ajax.Request(
		uri,
		{ method:'get',parameters: params, onFailure:loadpage, onComplete:updatepage}
	);
	return true;
}
 
function updatepage(resp) {
 
	var diggs = resp.responseText;
	var pos = diggs.indexOf("&&&timestamp=");
	var timestamp = diggs.substring(pos+13,pos+23);
	diggs = diggs.substr(0,pos);
	time = timestamp;
	$('diggs').innerHTML = diggs+$('diggs').innerHTML;
	updatetimes();
	removeold();
	return true;
}
 
function updatetimes() {
	var times = $$('td.time');
	for(var i=0;i<times.length;i++) {
		times[i].innerHTML = timeparse(times[i].id);
	}
}
 
function removeold() {
	var olds = $$('tr.digg');
	for(var i=30;i<olds.length;i++) {
		olds[i].remove(olds[i]);
	}
}
 
function timeparse(thetime) {
	var curtime = new Date();
	curtime = Math.floor(curtime.getTime()/1000);
	var since = curtime - thetime;
	if(since < 60) {
		return (since == 1) ? since+" second ago" : since+" seconds ago";
	}
	else if(since < 3600) {
		since = Math.floor(since/60);
		return (since == 1) ? since+" minute ago" : since+" minutes ago";
	}
	else if(since < 86400) {
		since = Math.floor(since/3600);
		return (since == 1) ? since+" hour ago" : since+" hours ago";
	}
	else {
		since = Math.floor(since/86400);
		return (since == 1) ? since+" day ago" : since+" days ago";
	}
}
 
function loadpage() {
	$('error').innerHTML = "Some crazy AJAX error probably";
	$('error').show();
}
 
</script>
</head>
 
<body>
 
	<?php
 
}
 
 
 
function std_stop() {
 
	echo "</body></html>";
 
	exit;
 
}
 
function form() {
	echo "<div id="content">
<div style="text-align:center; font-size: 150%;">This will allow you to watch people digg your story, live!<br /> 	
<span id="error" style="display: none; color:red;" > Story not found<br /></span>
<form action="livediggs.php" onsubmit="return submitform(this.title.value)" id="titleform">
<input type="hidden" name="nothing" value="" /><!-- This is a stupid hack, because for some reason the first input form couldn't have a starting value attribute. -->
<input type="text" name="title" value="Enter your story title" style="font-size: 125%; width:75%; text-align: center; "  onfocus="if(this.value == 'Enter your story title') { this.value = ''; } " />
<br /><input type="submit" value="Watch Diggs"  style="font-size: 125%; text-align: center;" /> <span id="loading" style="display:none;"><img style="display:inline" src="ajax-loader.gif" alt="loading..." /></span>
</form>
</div>
</div>
";
 
}

Conclusion

:

If you want to download all of these scripts, you can do so here:
Download – ZIP
Download – Gzip

They're licensed under GPL. If you have any questions, suggestions, or comments, just leave a comment or contact me.

7 Comments

  1. Joe Stump says:

    Just a little note that Services_Digg was accepted into the PEAR repository so you'll be able to install it via the normal PEAR procedures Real Soon Now[tm].

  2. James Wilson says:

    Yay! It's now live on pear.php.net

    http://pear.php.net/package/Services_Digg

    You can install it via this command:
    pear install channel://pear.php.net/Services_Digg-0.1.0

    You can't install it via just pear install Services_Digg, since it wants a stable version, but it's only in alpha, or at least that was the case for me.

    Congrats on getting it accepted.

  3. Bronwen Reid says:

    Hey, I'm just getting to grips with the Digg API and this is a really great walk-around and demo. Thank you

  4. raf says:

    great stuff man thank you for all the efford wish there was a clean and simple digg like clone

  5. rafi says:

    yes I know skeet but i was looking for something more simple , without any copyright credit and all.

  6. grazianno says:

    hi, thanks for this code,
    when i do the update.php i got a blank page. how can i fix this? thanks

Leave a Reply