PageRenderTime 67ms CodeModel.GetById 2ms app.highlight 56ms RepoModel.GetById 1ms app.codeStats 1ms

/facebook/classes/micro.class.php

http://github.com/newscloud/open-social-media-toolkit
PHP | 1015 lines | 829 code | 77 blank | 109 comment | 94 complexity | 94c92ce2aa6d6dbc4d7808d0fa01ca05 MD5 | raw file
   1<?php
   2/*
   3 * Micro blogging room
   4 */
   5
   6require_once (PATH_CORE . '/classes/dbRowObject.class.php');
   7class microAccountRow extends dbRowObject
   8{
   9	function isDup($sid=0) {
  10  		$chkDup=$this->db->queryC("SELECT id FROM MicroAccounts WHERE sid=$sid;");
  11		return $chkDup;		
  12	}	
  13}
  14
  15class microAccountsTable
  16{
  17	
  18	///////////////////////////////////////////////////////////////////////////////////////////////////////
  19	// standard table fields
  20	var $db;	
  21	static $tablename="MicroAccounts";
  22	static $idname = "id";
  23	static $idtype = "INT(11) unsigned NOT NULL auto_increment";
  24	static $dbRowObjectClass = "microAccountRow";
  25	static $fields = array(		
  26		"sid" 		=> "BIGINT(20) unsigned default 0", // service id e.g. twitter id
  27		"shortName" 		=> "VARCHAR(150) default ''",
  28		"friendlyName" 		=> "VARCHAR(150) default ''",
  29		"tag" 		=> "VARCHAR(150) default ''",
  30		"profile_image_url" 		=> "VARCHAR(255) default ''",
  31		"service" => "ENUM ('twitter') default 'twitter'",
  32		"userid" => "BIGINT(20) unsigned default 0",
  33		"isTokenValid" => "TINYINT(1) default 0",
  34		"token"=>"VARCHAR(60) default ''",
  35		"tokenSecret" =>"VARCHAR(60) default ''",
  36		"lastSync"=>"TIMESTAMP DEFAULT 0"
  37	);
  38
  39	static $keydefinitions = array(); 
  40	///////////////////////////////////////////////////////////////////////////////////////////////////////
  41	// standard table functions
  42	function __construct(&$db=NULL) 
  43	{
  44		if (is_null($db)) 
  45		{ 
  46			require_once('db.class.php');
  47			$this->db=new cloudDatabase();
  48		} else
  49			$this->db=$db;		
  50	}	
  51	// although many functions will be duplicated between table subclasses, having a parent class gets too messy	
  52	function getRowObject()
  53	{	
  54		$classname = self::$dbRowObjectClass; 
  55		return new $classname($this->db, self::$tablename, array_keys(self::$fields), self::$idname);
  56	}		
  57	
  58	//  table creation routine, same for all *Table classes 		
  59	static function createTable($manageObj)
  60	{			
  61		$manageObj->addTable(self::$tablename,self::$idname,self::$idtype,"MyISAM");
  62		foreach (array_keys(self::$fields) as $key)
  63		{
  64			$manageObj->updateAddColumn(self::$tablename,$key,self::$fields[$key]);
  65		}
  66		foreach (self::$keydefinitions as $keydef)
  67		{
  68			$manageObj->updateAddKey(self::$tablename,$keydef[0], $keydef[1], $keydef[2], $keydef[3]);
  69		}
  70		
  71	}
  72	
  73///////////////////////////////////////////////////////////////////////////////////////////////////////	
  74}
  75
  76class microPostRow extends dbRowObject
  77{
  78	
  79}
  80
  81class microPostsTable
  82{
  83	
  84	///////////////////////////////////////////////////////////////////////////////////////////////////////
  85	// standard table fields
  86	var $db;	
  87	static $tablename="MicroPosts";
  88	static $idname = "id";
  89	static $idtype = "INT(11) unsigned NOT NULL auto_increment";
  90	static $dbRowObjectClass = "microPostRow";
  91	static $fields = array(
  92		"statusid" => "BIGINT(20) unsigned default 0",
  93		"sid" => "BIGINT(20) unsigned default 0",
  94		"msg" 		=> "TEXT default NULL",
  95		"numLikes" 		=> "INT(4) default 0",
  96		"isFavorite" 		=> "TINYINT(1) default 0",
  97		"dt" 				=> "DATETIME"
  98	);
  99
 100	static $keydefinitions = array(); 
 101	///////////////////////////////////////////////////////////////////////////////////////////////////////
 102	// standard table functions
 103	function __construct(&$db=NULL) 
 104	{
 105		if (is_null($db)) 
 106		{ 
 107			require_once('db.class.php');
 108			$this->db=new cloudDatabase();
 109		} else
 110			$this->db=$db;		
 111	}	
 112	// although many functions will be duplicated between table subclasses, having a parent class gets too messy	
 113	function getRowObject()
 114	{	
 115		$classname = self::$dbRowObjectClass; 
 116		return new $classname($this->db, self::$tablename, array_keys(self::$fields), self::$idname);
 117	}		
 118	
 119	//  table creation routine, same for all *Table classes 		
 120	static function createTable($manageObj)
 121	{			
 122		$manageObj->addTable(self::$tablename,self::$idname,self::$idtype,"MyISAM");
 123		foreach (array_keys(self::$fields) as $key)
 124		{
 125			$manageObj->updateAddColumn(self::$tablename,$key,self::$fields[$key]);
 126		}
 127		foreach (self::$keydefinitions as $keydef)
 128		{
 129			$manageObj->updateAddKey(self::$tablename,$keydef[0], $keydef[1], $keydef[2], $keydef[3]);
 130		}
 131		
 132	}
 133	
 134	function isDup($statusid=0) {
 135  		$chkDup=$this->db->queryC("SELECT ".self::$idname." FROM ".self::$tablename." WHERE statusid=$statusid;");
 136		return $chkDup;		
 137	}
 138	///////////////////////////////////////////////////////////////////////////////////////////////////////	
 139}
 140
 141class microAccessRow extends dbRowObject
 142{
 143	// says which microaccts can view which microposts
 144	function isDup($statusid=0,$sid=0) {
 145  		$chkDup=$this->db->queryC("SELECT id FROM MicroAccess WHERE sid=$sid AND statusid=$statusid;");
 146		return $chkDup;		
 147	}	
 148}
 149
 150class microAccessTable
 151{
 152	
 153	///////////////////////////////////////////////////////////////////////////////////////////////////////
 154	// standard table fields
 155	var $db;	
 156	static $tablename="MicroAccess";
 157	static $idname = "id";
 158	static $idtype = "INT(11) unsigned NOT NULL auto_increment";
 159	static $dbRowObjectClass = "microAccessRow";
 160	static $fields = array(
 161		"statusid" => "BIGINT(20) unsigned default 0",
 162		"sid" => "BIGINT(20) unsigned default 0",
 163	);
 164
 165	static $keydefinitions = array(); 
 166	///////////////////////////////////////////////////////////////////////////////////////////////////////
 167	// standard table functions
 168	function __construct(&$db=NULL) 
 169	{
 170		if (is_null($db)) 
 171		{ 
 172			require_once('db.class.php');
 173			$this->db=new cloudDatabase();
 174		} else
 175			$this->db=$db;		
 176	}	
 177	// although many functions will be duplicated between table subclasses, having a parent class gets too messy	
 178	function getRowObject()
 179	{	
 180		$classname = self::$dbRowObjectClass; 
 181		return new $classname($this->db, self::$tablename, array_keys(self::$fields), self::$idname);
 182	}		
 183	
 184	//  table creation routine, same for all *Table classes 		
 185	static function createTable($manageObj)
 186	{			
 187		$manageObj->addTable(self::$tablename,self::$idname,self::$idtype,"MyISAM");
 188		foreach (array_keys(self::$fields) as $key)
 189		{
 190			$manageObj->updateAddColumn(self::$tablename,$key,self::$fields[$key]);
 191		}
 192		foreach (self::$keydefinitions as $keydef)
 193		{
 194			$manageObj->updateAddKey(self::$tablename,$keydef[0], $keydef[1], $keydef[2], $keydef[3]);
 195		}
 196		
 197	}
 198	
 199}
 200
 201
 202class microLinksRow extends dbRowObject
 203{
 204	function isDup($shortUrl='') {
 205  		$chkDup=$this->db->queryC("SELECT shortUrl FROM MicroLinks WHERE shortUrl='$shortUrl';");
 206		return $chkDup;		
 207	}	
 208}
 209
 210class microLinksTable
 211{	
 212	// standard table fields
 213	var $db;	
 214	static $tablename="MicroLinks";
 215	static $idname = "id";
 216	static $idtype = "INT(11) unsigned NOT NULL auto_increment";
 217	static $dbRowObjectClass = "microLinksRow";
 218	static $fields = array(		
 219		"shortUrl" 		=> "VARCHAR(255) default ''",
 220		"shortService" => "ENUM ('bit.ly','tr.im','is.gd','ow.ly','none','na') default 'na'",
 221		"longUrl" 		=> "VARCHAR(150) default ''",
 222		"title" 		=> "VARCHAR(255) default ''",
 223		"thumb" 		=> "VARCHAR(255) default ''",
 224		"caption" 		=> "TEXT default NULL",
 225		"media_type"	=> "ENUM ('news','video','image','na') default 'na'",
 226		"numTweets" => "INT(4) default 0",
 227		"isProcessed" => "TINYINT(1) default 0",
 228		"checkedTweetMeme" => "TINYINT(1) default 0",
 229		"checkedShortService" => "TINYINT(1) default 0",
 230		"checkedLongUrl" => "TINYINT(1) default 0",		
 231	);
 232
 233	static $keydefinitions = array(); 
 234	///////////////////////////////////////////////////////////////////////////////////////////////////////
 235	// standard table functions
 236	function __construct(&$db=NULL) 
 237	{
 238		if (is_null($db)) 
 239		{ 
 240			require_once('db.class.php');
 241			$this->db=new cloudDatabase();
 242		} else
 243			$this->db=$db;		
 244	}	
 245	// although many functions will be duplicated between table subclasses, having a parent class gets too messy	
 246	function getRowObject()
 247	{	
 248		$classname = self::$dbRowObjectClass; 
 249		return new $classname($this->db, self::$tablename, array_keys(self::$fields), self::$idname);
 250	}		
 251	
 252	//  table creation routine, same for all *Table classes 		
 253	static function createTable($manageObj)
 254	{			
 255		$manageObj->addTable(self::$tablename,self::$idname,self::$idtype,"MyISAM");
 256		foreach (array_keys(self::$fields) as $key)
 257		{
 258			$manageObj->updateAddColumn(self::$tablename,$key,self::$fields[$key]);
 259		}
 260		foreach (self::$keydefinitions as $keydef)
 261		{
 262			$manageObj->updateAddKey(self::$tablename,$keydef[0], $keydef[1], $keydef[2], $keydef[3]);
 263		}
 264		
 265	}
 266}
 267
 268class microLinkMentionsRow extends dbRowObject
 269{
 270	function isDup($statusid=0,$linkid=0) {
 271  		$chkDup=$this->db->queryC("SELECT id FROM MicroLinkMentions WHERE statusid=$statusid AND linkid=$linkid;");
 272		return $chkDup;		
 273	}		
 274}
 275
 276class microLinkMentionsTable
 277{	
 278	// standard table fields
 279	var $db;	
 280	static $tablename="MicroLinkMentions";
 281	static $idname = "id";
 282	static $idtype = "INT(11) unsigned NOT NULL auto_increment";
 283	static $dbRowObjectClass = "microLinkMentionsRow";
 284	static $fields = array(		
 285		"t"=>"TIMESTAMP DEFAULT CURRENT_TIMESTAMP",		
 286		"statusid" 		=> "BIGINT(20) unsigned default 0", // service id e.g. twitter id
 287		"linkid" 		=> "INT(11) unsigned default 0"
 288	);
 289
 290	static $keydefinitions = array(); 
 291	///////////////////////////////////////////////////////////////////////////////////////////////////////
 292	// standard table functions
 293	function __construct(&$db=NULL) 
 294	{
 295		if (is_null($db)) 
 296		{ 
 297			require_once('db.class.php');
 298			$this->db=new cloudDatabase();
 299		} else
 300			$this->db=$db;		
 301	}	
 302	// although many functions will be duplicated between table subclasses, having a parent class gets too messy	
 303	function getRowObject()
 304	{	
 305		$classname = self::$dbRowObjectClass; 
 306		return new $classname($this->db, self::$tablename, array_keys(self::$fields), self::$idname);
 307	}		
 308	
 309	//  table creation routine, same for all *Table classes 		
 310	static function createTable($manageObj)
 311	{			
 312		$manageObj->addTable(self::$tablename,self::$idname,self::$idtype,"MyISAM");
 313		foreach (array_keys(self::$fields) as $key)
 314		{
 315			$manageObj->updateAddColumn(self::$tablename,$key,self::$fields[$key]);
 316		}
 317		foreach (self::$keydefinitions as $keydef)
 318		{
 319			$manageObj->updateAddKey(self::$tablename,$keydef[0], $keydef[1], $keydef[2], $keydef[3]);
 320		}
 321		
 322	}
 323}
 324
 325class micro
 326{
 327	var $initialized;
 328	var $db;	
 329	var $session;
 330	var $app;
 331	var $utilObj;
 332	var $templateObj;
 333		
 334	function __construct(&$db=NULL,&$templateObj=NULL,&$session=NULL) 
 335	{
 336		$this->initialized=false;
 337		if (is_null($db)) 
 338		{ 
 339			require_once(PATH_CORE.'/classes/db.class.php');
 340			$this->db=new cloudDatabase();
 341		} else
 342			$this->db=$db;		
 343		if (!is_null($templateObj)) $this->templateObj=$templateObj;
 344		if (!is_null($session)) $this->session=$session;
 345		$this->initObjs();
 346	}
 347	
 348	function setAppLink(&$app) {
 349		$this->app=$app;
 350	}
 351	
 352	function initObjs() {
 353		if ($this->initialized)
 354			return true;
 355		require_once(PATH_CORE.'/classes/utilities.class.php');
 356		$this->utilObj=new utilities($this->db);
 357		if (is_null($this->templateObj)) 
 358		{ 
 359			require_once(PATH_CORE.'/classes/template.class.php');
 360			$this->templateObj=new template($this->db);
 361		} 
 362		$this->templateObj->registerTemplates(MODULE_ACTIVE, 'micro');
 363		$this->initialized = true;
 364	} 
 365	
 366	function resolveLinks() {
 367		// resolve next set of links
 368		// check tweet meme
 369		$this->db->log('check tweet meme');
 370		$q=$this->db->queryC("SELECT shortUrl,id FROM MicroLinks WHERE checkedTweetMeme=0 ORDER BY id DESC LIMIT 10;");
 371		$this->checkLinksTweetMeme($q);
 372		// check short services
 373		$this->db->log('check short services');
 374		$q=$this->db->queryC("SELECT shortUrl,id FROM MicroLinks WHERE checkedTweetMeme=1 AND checkedShortService=0 AND (title='' OR longUrl='') ORDER BY RAND() LIMIT 5;");
 375		$this->checkLinksShortService($q);
 376		// check full site urls 
 377		$q=$this->db->queryC("SELECT shortUrl,longUrl,id FROM MicroLinks WHERE checkedTweetMeme=1 AND checkedShortService=1 AND checkedLongUrl=0 AND title='' AND media_type<>'image' ORDER BY RAND() LIMIT 5;");		
 378		$this->checkLinksFull($q);
 379	}
 380	
 381	function resolveLinksByUser($userid=0) {
 382		if (!is_numeric($userid)) return false;
 383		$this->db->log('resolveLinksByUser: '.$userid);
 384		// count up how many items without titles
 385		// resolve set of links for a single user
 386		// look up account by userid
 387		$q=$this->db->queryC("SELECT sid FROM MicroAccounts WHERE isTokenValid=1 AND userid=$userid;");
 388		if (!$q) return false; // no valid account
 389		$d=$this->db->readQ($q);
 390		$serviceid=$d->sid;
 391		$q=$this->db->queryC("SELECT count(MicroLinks.id) as cnt FROM MicroLinks LEFT JOIN MicroLinkMentions ON MicroLinks.id=MicroLinkMentions.linkid WHERE title='' AND statusid IN (SELECT statusid FROM MicroAccess WHERE sid=$serviceid) AND media_type<>'image' ;");
 392		$d=$this->db->readQ($q);
 393		$this->db->log('TweetLink Status: Userid - '.$userid.' Missing titles: '.$d->cnt);
 394		// find all link mentions and links with that sid
 395		$q=$this->db->queryC("SELECT * FROM MicroLinks LEFT JOIN MicroLinkMentions ON MicroLinks.id=MicroLinkMentions.linkid WHERE checkedTweetMeme=0 AND statusid IN (SELECT statusid FROM MicroAccess WHERE sid=$serviceid) AND media_type<>'image' GROUP BY MicroLinks.id ORDER BY MicroLinks.id DESC LIMIT 25;");
 396		// check tweet meme
 397		$this->checkLinksTweetMeme($q);
 398		// check other services
 399		$q=$this->db->queryC("SELECT * FROM MicroLinks LEFT JOIN MicroLinkMentions ON MicroLinks.id=MicroLinkMentions.linkid WHERE checkedTweetMeme=1 AND checkedShortService=0 AND (title='' OR longUrl='') AND statusid IN (SELECT statusid FROM MicroAccess WHERE sid=$serviceid) AND media_type<>'image' GROUP BY MicroLinks.id ORDER BY MicroLinks.id DESC  LIMIT 25;");
 400		$this->checkLinksShortService($q);
 401		// check full site urls 
 402		$q=$this->db->queryC("SELECT shortUrl,longUrl,id FROM MicroLinks WHERE checkedTweetMeme=1 AND checkedShortService=1 AND checkedLongUrl=0 AND title='' AND media_type<>'image' ORDER BY MicroLinks.id DESC LIMIT 25;");
 403		$this->checkLinksFull($q);
 404	}
 405	
 406	function isExtAllowed($url='') {
 407		$bad=array('mp3','mp4','mov','png','gif','jpg','txt','exe','js','pdf','mpg','mpeg','ico');
 408		$ext = substr($url, strrpos($url, '.') + 1);
 409		if (in_array($ext,$bad)) 
 410			return false;
 411		else
 412			return true; // ok
 413	}
 414	
 415	function checkLinksTweetMeme($q=NULL) { 
 416		if (!$q) return false;
 417		$node_count = $this->db->cnt;
 418		$urlIdList = array();
 419		$shortUrlList = array();
 420		$curl_arr = array();
 421		$master = curl_multi_init();
 422		$i=0;
 423		while ($d=$this->db->readQ($q)) {	
 424			if (!$this->isExtAllowed($d->shortUrl)) {
 425				$this->db->update("UPDATE MicroLinks SET checkedTweetMeme=1,checkedLongUrl=1,checkedShortService=1 WHERE id=".$d->id);
 426				continue;			
 427			}
 428			$url ='http://api.tweetmeme.com/url_info.json?url='.$d->shortUrl;
 429			$curl_arr[$i] = curl_init($url);
 430			$urlIdList[$i]=$d->id;
 431			$shortUrlList[$i]=$d->shortUrl;
 432			curl_setopt($curl_arr[$i], CURLOPT_RETURNTRANSFER, true);
 433			curl_multi_add_handle($master, $curl_arr[$i]);			
 434			$i+=1;
 435		}
 436		do {
 437		    curl_multi_exec($master,$running);
 438		} while($running > 0);
 439		$mlTable = new microLinksTable($this->db);
 440		$ml = $mlTable->getRowObject();		
 441		$this->db->log('nodecount'.$node_count);
 442		$this->db->log('idlist');
 443		$this->db->log($urlIdList);
 444		
 445		for($i = 0; $i < $node_count; $i++)
 446		{
 447			$results = curl_multi_getcontent  ( $curl_arr[$i]  );
 448			// json decode each
 449			$l=json_decode($results);
 450			// print_r($l);
 451			// check $l->status for failure
 452			if (!is_numeric($urlIdList[$i])) continue;
 453			if ($ml->load($urlIdList[$i])!==false) {
 454				if (isset($l->story->media_type))
 455					$ml->media_type=$l->story->media_type;
 456				if (isset($l->story->url_count))
 457					$ml->numTweets=$l->story->url_count;
 458				if (isset($l->story->url))
 459					$ml->longUrl=$l->story->url;
 460				if (isset($l->story->title))
 461					$ml->title=$l->story->title;
 462				if (isset($l->story->excerpt))
 463					$ml->caption=str_ireplace ( $shortUrlList[$i] , '', $l->story->excerpt);
 464				if (isset($l->story->thumbnail))
 465					$ml->thumb=$l->story->thumbnail;
 466				$ml->checkedTweetMeme=1;				
 467				$ml->update();			
 468			}
 469		}
 470	}
 471	
 472	function checkLinksShortService($q=NULL) { 
 473		global $init;
 474		if (!$q) return false;
 475		$mlTable = new microLinksTable($this->db);
 476		$ml = $mlTable->getRowObject();		
 477		while ($d=$this->db->readQ($q)) {			
 478			// identify service
 479			$service=false;
 480			$parts=parse_url($d->shortUrl);
 481			if (stristr($parts['host'],'bit.ly')!==false) {
 482				$apiUrl='http://api.bit.ly/expand?version=2.0.1&shortUrl='.$d->shortUrl.'&login='.$init['bitlyuser'].'&apiKey='.$init['bitly'];				
 483				$resp=$this->fetchUrlByCurl($apiUrl);
 484				$hash=trim($parts['path'],'/');
 485				$l=json_decode($resp);
 486				if (!$l->errorCode) {
 487					if ($ml->load($d->id)!==false) {
 488						$arrL=(array)$l->results; // cast obj to array for reference by value
 489						$ml->longUrl=$arrL[$hash]->longUrl;
 490						$ml->caption=str_ireplace ( $d->shortUrl , '', $ml->caption);
 491						$ml->checkedShortService=1;				
 492						$ml->update();			
 493					}
 494				}
 495			} else 	if (stristr($parts['host'],'tr.im')!==false) {
 496					$hash=trim($parts['path'],'/');
 497					$apiUrl='http://http://api.tr.im/api/trim_destination.json?trimpath='.$hash;				
 498					$resp=$this->fetchUrlByCurl($apiUrl);
 499					$l=json_decode($resp);
 500					$this->db->log('tr.im'.$apiUrl);
 501					//if (!$l->errorCode) {
 502						
 503						/*
 504						if ($ml->load($d->id)!==false) {
 505							$arrL=(array)$l->results; // cast obj to array for reference by value
 506							$ml->longUrl=$arrL[$hash]->longUrl;
 507							$ml->caption=str_ireplace ( $d->shortUrl , '', $ml->caption);
 508							$ml->checkedShortService=1;				
 509							$ml->update();			
 510						}
 511						*/
 512					//}
 513				}
 514			 
 515		}
 516	}
 517	
 518	function checkLinksFull($q=NULL) {
 519		// look up longUrl for title
 520		if (!$q) return false;
 521		$this->db->log('in checkLinksFull');
 522		require_once(PATH_CORE.'/classes/remotefile.class.php');
 523		$mlTable = new microLinksTable($this->db);
 524		$ml = $mlTable->getRowObject();
 525		while ($d=$this->db->readQ($q)) {
 526			if ($d->longUrl=='')
 527				$url=$d->shortUrl;
 528			else
 529				$url=$d->longUrl;
 530			$this->db->log('curl '.$url);
 531			$resp=$this->fetchUrlByCurl($url);
 532			if ($resp) {
 533				$this->db->log('length '.strlen($resp));
 534				preg_match_all("/<title[^>]*>([^<]+)<\/title>/i", $resp, $matches);
 535				if ($matches[1][0]) {
 536					$title= $matches[1][0];
 537				} else {
 538				        $title = "";
 539				}			
 540				$this->db->log('title '.$title);
 541				if (preg_match('/<meta name="description"[^>]*content="([^"]+)"/i', $resp, $match))
 542					$caption= $match[1];
 543				else {
 544					$caption='';
 545				} 
 546				unset($match);
 547				unset($matches);				
 548				$this->db->log('title'.$title);
 549			} else {
 550				$this->db->log('curlfailed');
 551			}
 552			//$this->db->log('caption'.$caption);
 553			if ($ml->load($d->id)!==false) {
 554				if ($ml->longUrl=='') $ml->longUrl=$url;
 555				if ($ml->title=='') $ml->title=$title;
 556				if ($ml->caption=='') $ml->caption=$caption;
 557				$ml->checkedLongUrl=1;
 558				$ml->update();			
 559			} 
 560		}
 561	}
 562
 563	function fetchUrlByCurl($url='') {
 564		if (!$this->isExtAllowed($url)) return false;
 565	      $useragent = 'NewsCloud (curl) ' . phpversion();
 566	      $ch = curl_init($url);
 567	      curl_setopt($ch,CURLOPT_FOLLOWLOCATION ,true );
 568	      curl_setopt($ch,CURLOPT_MAXREDIRS , 5);
 569	      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 570	      curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
 571	      curl_setopt($ch, CURLOPT_TIMEOUT, 30);
 572	      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 573	      curl_setopt($ch, CURLOPT_USERAGENT, $useragent);	
 574	      curl_setopt($ch, CURLOPT_AUTOREFERER, true);	
 575	      $result = curl_exec($ch);		
 576	      curl_close($ch);
 577		return $result;
 578	}
 579
 580	function syncUserAccount($userid=0) {
 581		if (!is_numeric($userid)) return false;
 582		// fetch micro account for one user
 583		$q=$this->db->queryC("SELECT *, (SELECT max(statusid) FROM MicroPosts WHERE MicroPosts.sid=MicroAccounts.sid) as lastStatus FROM MicroAccounts WHERE isTokenValid=1 AND userid=$userid;");
 584		if ($q!==false) {
 585			$this->db->log('syncAccountsByQuery: '.$userid);
 586			$q2=$this->db->query("select count(MicroAccess.sid) as cnt FROM MicroAccess,MicroAccounts WHERE MicroAccess.sid=MicroAccounts.sid AND userid=$userid;");
 587			$d2=$this->db->readQ($q2);	
 588			if ($d2->cnt==0) 
 589				$firstTime=true;		
 590			else
 591				$firstTime=false;
 592			$this->syncAccountsByQuery($q,$firstTime); 
 593		}
 594	}
 595
 596	function syncAccounts() {
 597		// fetch all micro accounts
 598		$q=$this->db->query("SELECT *, (SELECT max(statusid) FROM MicroPosts WHERE MicroPosts.sid=MicroAccounts.sid) as lastStatus FROM MicroAccounts WHERE isTokenValid=1 ORDER BY lastSync ASC LIMIT 3;");
 599		$this->syncAccountsByQuery($q);
 600	}
 601	
 602	function syncAccountsByQuery($q=NULL,$firstTime=false) {		
 603		global $init;
 604		require_once(PATH_CORE.'/utilities/twitterOAuth.php');				
 605		require_once PATH_CORE.'/utilities/twitter.php';
 606		$twObj=new Twitter($init['twitterUsr'],$init['twitterPwd'],$this->db);
 607		$twObj->setOAuth(true);
 608		while ($d=$this->db->readQ($q)) {
 609			/*
 610						$resp=$tObj->getRateLimitStatus();
 611						if (isset($resp['error'])) {
 612							continue;
 613						}
 614						*/
 615		    $to = new TwitterOAuth($init['consumerKey'], $init['consumerSecret'],$d->token, $d->tokenSecret);
 616			if (!$firstTime)
 617				$args=$twObj->getFriendsTimeline($d->lastStatus); // to do - put back  
 618			else
 619				$args=$twObj->getFriendsTimeline(NULL,NULL,100); // first time, get larger # of updates
 620		    /* Run request on twitter API as user. */
 621		    $resp = $to->OAuthRequest('https://twitter.com/'.$args['url'], $args['params'], $args['method']);
 622			$xml = @simplexml_load_string($resp);			
 623			if($xml!== false) {
 624				$this->db->update("MicroAccounts","lastSync=NOW()","sid=$d->sid");				
 625				// add or update user tokens
 626				$maTable = new microAccountsTable($this->db);
 627				$ma = $maTable->getRowObject();
 628				$mpTable = new microPostsTable($this->db);
 629				$mp = $mpTable->getRowObject();
 630				$mlTable = new microLinksTable($this->db);
 631				$ml = $mlTable->getRowObject();
 632				$accessTable = new microAccessTable($this->db);
 633				$access = $accessTable->getRowObject();
 634				$mentionsTable = new microLinkMentionsTable($this->db);
 635				$mention = $mentionsTable->getRowObject();
 636				foreach ($xml as $item) {
 637					$s=$twObj->statusXMLToArray($item, true);
 638					$mp->statusid=$s['id'];
 639					$mp->msg=$s['text'];
 640					$mp->isFavorite=$s['isFavorite'];
 641					$mp->sid=$s['user']['id'];
 642					$mp->dt=date('Y-m-d H:i:s',$s['created_at']);
 643					if ($mpTable->isDup($mp->statusid)===false) {
 644						$mp->insert();	
 645					}
 646					if ($access->isDup($mp->statusid,$d->sid)===false) {
 647						$access->statusid=$mp->statusid;
 648						$access->sid=$d->sid;	// the microaccount serviceid		
 649						$access->insert();
 650					}
 651					// update microaccount row for user
 652					if (!$ma->isDup($s['user']['id'])) {
 653						$ma->sid=$s['user']['id'];
 654						$ma->shortName=$s['user']['screen_name'];
 655						$ma->friendlyName=$s['user']['name'];
 656						$ma->profile_image_url=$s['user']['profile_image_url'];
 657						$ma->isTokenValid=0;
 658						$ma->insert();
 659					} else {
 660						$ma->loadWhere("sid=".$s['user']['id']);
 661						$ma->profile_image_url=$s['user']['profile_image_url'];
 662						$ma->update();
 663					}
 664					// scan for links					
 665					preg_match_all("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i",$s['text'],$links);
 666					foreach ($links[0] as $url) {
 667						if (!$this->isExtAllowed($url)) continue;
 668						if (!$ml->isDup($url)) {
 669							$ml->shortUrl=$url;
 670							if (!stristr($url,'twitpic.com') && !stristr($url,'flickr.com') && !stristr($url,'tweetphoto.com')) {
 671								$ml->numTweets=1;
 672								$ml->insert();
 673								$idExist=$mention->isDup($mp->statusid,$ml->id);
 674								if (!$idExist) {
 675									$mention->linkid=$ml->id;
 676									$mention->statusid=$mp->statusid;
 677									$mention->t=date('Y-m-d H:i:s',$s['created_at']);
 678									$mention->insert();
 679								} else {
 680									$mention->load($idExist);
 681									$mention->statusid=$mp->statusid;
 682									$mention->update();
 683								}
 684							}
 685						}
 686					}
 687				}
 688			}
 689		}
 690	}
 691	
 692	function buildQueries($query='',$returnStr=false,$view='recent',$tagid=0,$userid=0,$keyword='',$startRow=0,$limit=25) {
 693		$where=array();
 694		if ($tagid<>'all') 
 695			$where[]="MicroAccounts.tag='$tagid'";			
 696		if (isset($_GET['all']))
 697			$limit=99999;
 698		switch ($query) {
 699			case 'listPosts':
 700				$sortStr='dt DESC';
 701				$q="SELECT MicroPosts.*,tag,MicroAccounts.sid as serviceid,shortName,profile_image_url FROM MicroPosts LEFT JOIN MicroAccounts ON MicroPosts.sid=MicroAccounts.sid ".$this->db->buildWhereStr($where)." ORDER BY $sortStr LIMIT $startRow,$limit;";
 702			break;
 703		}
 704		if ($returnStr) 
 705			return $q;
 706		else
 707			return $this->db->query($q);
 708	}
 709
 710	function fetchBrowse($isAjax=false,$tagid='all',$userid=0,$view='recent') {
 711		$cnt=99;
 712		$inside=$this->listMessages($view,$tagid,$userid,0,$cnt);
 713		if ($isAjax) {
 714			return $inside;
 715		}
 716		$code=$this->fetchBrowseFilter($tagid,$view);
 717		$code.='<div id="postList">';
 718		$code.=$inside;
 719		$code.='<!-- end postList --></div>';
 720		//$code.='<input type="hidden" id="pagingFunction" value="fetchBrowseIdeasPage">';				
 721		return $code;
 722	}
 723
 724	function fetchBrowseFilter($tagid='all',$view='recent') {
 725		// display the filter for browsing ideas
 726		$code='';
 727		$catList=explode(',',$this->db->buildIdList("SELECT DISTINCT tag as id FROM MicroAccounts ORDER BY tag ASC;"));
 728		$catStr='&nbsp;Filter by: ';
 729		$catStr.='<select id="microCat" onchange="microCatChange();return false;">';
 730		$catStr.='<option value="all">all</option>';			
 731		foreach ($catList as $item) {
 732			$catStr.='<option value="'.$item.'">'.$item.'</option>';			
 733		}
 734		$catStr.='</select>';
 735		$code.='<div id="navFilter"><!-- end navFilter --></div>';
 736		$code.='<div class="subFilter">';
 737		$code.=$catStr;
 738        $code.='</div><!--end "subfilter"-->';
 739		return $code;
 740	}
 741
 742	function homeList($tag='all') {
 743		$code=$this->listMessages('recent',$tag,0,0,3,true);
 744		return $code;
 745	}
 746	
 747	function listMessages($view='recent',$tagid='all',$userid=0,$startRow=0,$limit=5,$forHome=false) {
 748		// displays a list of ideas
 749		$q=$this->buildQueries('listPosts',true,$view,$tagid,$userid,'',$startRow,$limit);
 750		$this->templateObj->db->result=$this->templateObj->db->query($q);
 751		if ($this->db->countQ($this->templateObj->db->result)>0) {
 752			$this->templateObj->db->setTemplateCallback('timeSince', array($this->utilObj, 'time_since'), 'dt');
 753			if (!$forHome) {
 754				$this->templateObj->db->setTemplateCallback('post', array($this, 'cbPost'), 'msg');
 755				$this->templateObj->db->setTemplateCallback('cmdShare', array($this, 'cbCommandShare'), 'id');
 756				$this->templateObj->db->setTemplateCallback('cmdReply', array($this, 'cbCommandReply'), 'shortName');
 757				$this->templateObj->db->setTemplateCallback('cmdRetweet', array($this, 'cbCommandRetweet'), 'shortName');
 758				$this->templateObj->db->setTemplateCallback('cmdDM', array($this, 'cbCommandDM'), 'shortName');
 759				$temp=$this->templateObj->mergeTemplate($this->templateObj->templates['microList'],$this->templateObj->templates['microItem']);				
 760			} else {
 761				$this->templateObj->db->setTemplateCallback('post', array($this, 'cbPostFilter'), 'msg');
 762				$temp=$this->templateObj->mergeTemplate($this->templateObj->templates['microList'],$this->templateObj->templates['microItemHome']);								
 763			}
 764		} else {
 765			$temp='<br /><fb:explanation message="No tweets found">We found no tweets. Perhaps try choosing a different filter</a></fb:explanation>';					
 766		}
 767		return $temp;
 768	}
 769		
 770	function buildDisplay($id=0) {
 771		// display the one micropost
 772		$code='';
 773		$q="SELECT MicroPosts.*,tag,MicroAccounts.sid as serviceid,shortName,profile_image_url FROM MicroPosts LEFT JOIN MicroAccounts ON MicroPosts.sid=MicroAccounts.sid WHERE MicroPosts.id=$id ;";
 774		$this->templateObj->db->result=$this->templateObj->db->query($q);		
 775		if ($this->db->countQ($this->templateObj->db->result)>0) {
 776			$this->templateObj->db->setTemplateCallback('timeSince', array($this->utilObj, 'time_since'), 'dt');
 777			$this->templateObj->db->setTemplateCallback('post', array($this, 'cbPost'), 'msg');
 778			$this->templateObj->db->setTemplateCallback('cmdShare', array($this, 'cbCommandShare'), 'id');
 779			$this->templateObj->db->setTemplateCallback('cmdReply', array($this, 'cbCommandReply'), 'shortName');
 780			$this->templateObj->db->setTemplateCallback('cmdRetweet', array($this, 'cbCommandRetweet'), 'shortName');
 781			$this->templateObj->db->setTemplateCallback('cmdDM', array($this, 'cbCommandDM'), 'shortName');
 782			$code.=$this->templateObj->mergeTemplate($this->templateObj->templates['microList'],$this->templateObj->templates['microItem']);
 783			$code.='<br />';
 784		}
 785		return $code;
 786/*		// display the comments to this idea
 787		$comTemp='<div id="ideaComments" >';
 788		$comTemp.=$this->buildCommentThread($id,false,$ir->numComments);
 789		$comTemp.='</div><br />';
 790		$code.= '<div class="panel_2 clearfix"><div class="panelBar clearfix"><h2>Comments</h2><!-- end panelBar--></div><br />'.$comTemp.'<!-- end panel_2 --></div>';
 791		*/
 792	}
 793	
 794	// cron functions
 795	
 796	function resetFriends($deleteAll=false) {
 797		require_once PATH_CORE.'/utilities/twitter.php';
 798		$tObj=new Twitter(TWITTER_USER,TWITTER_PWD,$this->db);		
 799		if ($deleteAll) {
 800			$resp=$tObj->getFriendIds(TWITTER_USER);
 801			foreach ($resp as $id) {
 802				$tObj->deleteFriendship($id);
 803			}					
 804		}
 805		$mt = new microAccountsTable($this->db);
 806		$ma = $mt->getRowObject();	
 807		$q=$this->db->query("SELECT * FROM MicroAccounts WHERE sid=0;");
 808		while ($d=$this->db->readQ($q)) {
 809			$ma->load($d->id);
 810			$this->db->log('Process:'.$ma->shortName);
 811			if ($ma->sid==0) {
 812				if ($tObj->existsFriendship(TWITTER_USER,$d->shortName)) {
 813					$resp=$tObj->getFriendship(TWITTER_USER,$d->shortName);
 814					$resp=$tObj->getUser($resp['target']['id']);
 815				} else {
 816					$resp=$tObj->createFriendship($d->shortName);
 817				}
 818				if ($resp!==false) {
 819					$this->db->log($resp);
 820					$ma->sid=$resp['id'];
 821					$ma->friendlyName=$resp['name'];
 822					$ma->profile_image_url=$resp['profile_image_url'];
 823					$ma->update();					
 824				} else {
 825					$this->db->log('FALSE');
 826				}
 827			}				
 828		}
 829	}
 830	
 831	function cleanRoom() {
 832		//$this->db->delete("MicroPosts","dt<date_sub(now(),INTERVAL 7 DAY)"); // delete posts older than one week
 833	}
 834	
 835	function syncFriends() {
 836		$mt = new microAccountsTable($this->db);
 837		$ma = $mt->getRowObject();		
 838		// get list of friends
 839		require_once PATH_CORE.'/utilities/twitter.php';
 840		$tObj=new Twitter(TWITTER_USER,TWITTER_PWD,$this->db);		
 841		$friends=$tObj->getFriendIds(TWITTER_USER);
 842		foreach ($friends as $id) {
 843			// get info for anyone not in the table
 844			$resp=$tObj->getUser($id);
 845			if ($resp!==false) {
 846	//			$this->db->log($resp);
 847				// check if they exist
 848				$ma->sid=$resp['id'];
 849				$ma->friendlyName=$resp['name'];
 850				$ma->profile_image_url=$resp['profile_image_url'];
 851				$q=$this->db->queryC("SELECT * FROM MicroAccounts WHERE sid=".$ma->sid);
 852				if (!$q) {
 853					// does not exist, add them
 854					$ma->shortName=$resp['screen_name'];
 855					$ma->tag='default';
 856					$ma->service='twitter';
 857					$ma->insert();
 858				} else {
 859					$ma->update();									
 860				}
 861			} else {
 862	//			$this->db->log('FALSE');
 863			}
 864		}
 865		// delete anyone no longer listed - set status - friends vs. not friends
 866		
 867	}
 868	
 869	function updateRoom() {
 870		require_once PATH_CORE.'/utilities/twitter.php';
 871		$tObj=new Twitter(TWITTER_USER,TWITTER_PWD,$this->db);
 872		$resp=$tObj->getRateLimitStatus();
 873		if (isset($resp['error'])) {
 874			return false;
 875		}
 876		/*
 877		if ($this->db->queryC("SELECT * FROM MicroAccounts;")===false) {
 878			// no accounts yet - so remove all followers
 879			$this->resetFriends(true);
 880			return;
 881		}
 882		*/
 883		$resp=$tObj->getFriendsTimeline();
 884		$mt = new microPostsTable($this->db);
 885		$mp = $mt->getRowObject();
 886		$maTable = new microAccountsTable($this->db);
 887		$ma = $maTable->getRowObject();
 888		foreach ($resp as $item) {
 889			$mp->statusid=$item['id'];
 890			$mp->msg=$item['text'];
 891			$mp->sid=$item['user']['id'];
 892			$mp->dt=date('Y-m-d H:i:s',$item['created_at']);
 893			if ($mt->isDup($mp->statusid)===false) {
 894				$mp->insert();				
 895			} else {
 896			}
 897			// update microaccount row for user
 898			if (!$ma->isDup($item['user']['id'])) {
 899				// to do 
 900				// in facebook app, these should always exist
 901			} else {
 902				// get latest image
 903				$ma->loadWhere("sid=".$item['user']['id']);
 904				$ma->profile_image_url=$item['user']['profile_image_url'];
 905				$ma->update();
 906			}
 907			
 908		}
 909	}
 910	
 911	// helper functions
 912
 913	function buildCommentBox($isAjax=false) {
 914		$code='';
 915		require_once(PATH_CORE.'/classes/user.class.php');
 916		$userTable 	= new UserTable($this->db);
 917		$userInfoTable 	= new UserInfoTable($this->db);
 918		$user = $userTable->getRowObject();
 919		$userinfo = $userInfoTable->getRowObject();
 920		$user->loadWhere("isAdmin=1");
 921		$userinfo->load($user->userid);
 922		$code.='<fb:comments xid="'.CACHE_PREFIX.'_microComments" canpost="true" candelete="true" simple="true" numposts="3" showform="true" publish_feed="false" quiet="true" send_notification_uid="'.$userinfo->fbId.'"></fb:comments>';	// callbackurl="'.URL_CALLBACK.'?p=ajax&m=ideasRefreshComments&id='.$id.'"
 923		if (!$isAjax) {
 924 			$code='<div id="commentBox">'.$code.'</div>';
 925		}
 926		return $code;
 927	}
 928	
 929	function fetchLinkBox() {
 930 		$microLink=URL_CANVAS.'?p=tweets';
 931		$title=htmlentities($this->templateObj->templates['microShareTitle'],ENT_QUOTES);
 932		$caption=htmlentities($this->templateObj->templates['microShareCaption'],ENT_QUOTES);
 933		$tweetStr=strip_tags($this->templateObj->templates['microShareTitle']).' '.URL_HOME.'?p=tweets '.(defined('TWITTER_HASH')?TWITTER_HASH:'');
 934		$tweetThis='<a class="tweetButton" href="http://twitter.com/?status='.rawurlencode($tweetStr).'" target="twitter"><img src="'.URL_CALLBACK.'?p=cache&img=tweet_button.gif" alt="tweet this" /></a>';
 935		$shareButton='<div style="float:left;padding:0px 5px 0px 0px;display:inline;"><fb:share-button class="meta">';
 936		$shareButton.='<meta name="title" content="'.$title.'"/><meta name="description" content="'.$caption.'" /><link rel="target_url" href="'.$microLink.'"/>';
 937		$shareButton.='</fb:share-button><!-- end share button wrap --></div>';
 938 		$code = '<div  id="actionLegend"><p class="bold">Link to this page </p>'.$shareButton.' '.$tweetThis.'';
 939          $code.= '<div class="pointsTable"><table cellspacing="0"><tbody>'.
 940				'<tr><td><input class="inputLinkNoBorder" type="text" value="'.$microLink.'" onfocus="this.select();" /></td></tr>'.
 941				'</tbody></table></div><!-- end points Table --></div><!-- end idea link box -->';
 942 		return $code;	
 943 	}
 944
 945	// template callback functions
 946	
 947	function cbCommandShare($id=0) {
 948		$msg=$this->templateObj->db->row['msg'];
 949		$shortName=$this->templateObj->db->row['shortName'];
 950		$imgUrl=$this->templateObj->db->row['profile_image_url'];
 951		$temp='<fb:share-button class="meta"><meta name="medium" content="blog" /><meta name="title" content="Tweet from '.$shortName.' via '.SITE_TITLE.'" /><meta name="description" content="'.htmlentities(strip_tags($msg),ENT_QUOTES).'" /><link rel="image_src" href="'.$imgUrl.'" /><link rel="target_url" href="'.URL_CANVAS.'?p=tweets&o=view&id='.$id.'" /></fb:share-button>';
 952		return $temp;
 953	}
 954
 955	function cbCommandRetweet($shortName='') {
 956		$msg=$this->templateObj->db->row['msg'];
 957		$str='<a class="tweetButton" href="http://twitter.com/?status='.rawurlencode('RT @'.$shortName.' '.$msg).'" target="twitter">retweet</a>';		
 958		return $str;	
 959	}
 960
 961	function cbCommandReply($shortName='') {
 962		$str='<a class="tweetButton" href="http://twitter.com/?status='.rawurlencode('@'.$shortName).'" target="twitter">reply</a>';		
 963		return $str;	
 964	}
 965
 966	function cbCommandDM($shortName='') {
 967		$str='<a class="tweetButton" href="http://twitter.com/?status='.rawurlencode('D '.$shortName).'" target="twitter">message</a>';		
 968		return $str;	
 969	}
 970
 971	function cbPost($str='') {
 972		$str=preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i","<a target=\"_blank\" href=\"$1\">$1</a>",$str);
 973		return $str;	
 974	}
 975
 976	function cbPostFilter($str='') {
 977		$id=$this->templateObj->db->row['id'];
 978		$str=preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i","<a target=\"twitter\" onclick=\"switchPage('micro','view',$id); return false;\" href=\"".URL_CANVAS."?p=tweets&o=view&id=$id\">$1</a>",$str);
 979		return $str;	
 980	}
 981		
 982	function cbCommandLike($id=0) {
 983		$score=$this->templateObj->db->row['numLikes'];
 984		$temp='<span id="li_'.$id.'" class="btn_left li_'.$id.'"><a href="#" class="voteLink" onclick="return ideaRecordLike('.$id.');" title="like this idea">Like</a> '.$score.'</span>';				
 985		return $temp;
 986	}
 987	
 988	// ajax functions
 989	
 990
 991	function ajaxIdeaRecordLike($isSessionValid=false,$userid=0,$id=0) {
 992		//$this->db->log('inside ajaxidearecordlike');
 993		if ($isSessionValid) {
 994			require_once(PATH_CORE.'/classes/log.class.php');
 995			$logObj=new log($this->db);
 996			// record the like in the log
 997			$logItem=$logObj->serialize(0,$userid,'likeIdea',$id);
 998			$inLog=$logObj->update($logItem);
 999			if ($inLog) {
1000				$iTable = new ideasTable($this->db); 
1001				$ir = $iTable->getRowObject();		
1002				$ir->load($id);
1003				$ir->numLikes+=1;
1004				$ir->update();
1005				$code='<a href="#" class="voteLink" onclick="return ideaRecordLike('.$id.');" title="like this idea">Like</a> '.$ir->numLikes;
1006			} else {
1007				$code='You already liked this!';
1008			}												
1009		} else {
1010			$code='<a href="'.URL_CANVAS.'?p=ideas" requirelogin="1">Please authorize '.SITE_TITLE.' with Facebook before continuing.</a>'; 
1011		}
1012		return $code;
1013	}	
1014}
1015?>