PageRenderTime 59ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

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