TwitterBridge.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. class TwitterBridge extends BridgeAbstract {
  3. const NAME = 'Twitter Bridge';
  4. const URI = 'https://twitter.com/';
  5. const CACHE_TIMEOUT = 300; // 5min
  6. const DESCRIPTION = 'returns tweets';
  7. const MAINTAINER = 'pmaziere';
  8. const PARAMETERS = array(
  9. 'global' => array(
  10. 'nopic' => array(
  11. 'name' => 'Hide profile pictures',
  12. 'type' => 'checkbox',
  13. 'title' => 'Activate to hide profile pictures in content'
  14. )
  15. ),
  16. 'By keyword or hashtag' => array(
  17. 'q' => array(
  18. 'name' => 'Keyword or #hashtag',
  19. 'required' => true,
  20. 'exampleValue' => 'rss-bridge, #rss-bridge',
  21. 'title' => 'Insert a keyword or hashtag'
  22. )
  23. ),
  24. 'By username' => array(
  25. 'u' => array(
  26. 'name' => 'username',
  27. 'required' => true,
  28. 'exampleValue' => 'sebsauvage',
  29. 'title' => 'Insert a user name'
  30. ),
  31. 'norep' => array(
  32. 'name' => 'Without replies',
  33. 'type' => 'checkbox',
  34. 'title' => 'Only return initial tweets'
  35. )
  36. )
  37. );
  38. public function getName(){
  39. switch($this->queriedContext){
  40. case 'By keyword or hashtag':
  41. $specific = 'search ';
  42. $param = 'q';
  43. break;
  44. case 'By username':
  45. $specific = '@';
  46. $param = 'u';
  47. break;
  48. default: return parent::getName();
  49. }
  50. return 'Twitter ' . $specific . $this->getInput($param);
  51. }
  52. public function getURI(){
  53. switch($this->queriedContext){
  54. case 'By keyword or hashtag':
  55. return self::URI
  56. . 'search?q='
  57. . urlencode($this->getInput('q'))
  58. . '&f=tweets';
  59. case 'By username':
  60. return self::URI
  61. . urlencode($this->getInput('u'))
  62. . ($this->getInput('norep') ? '' : '/with_replies');
  63. default: return parent::getURI();
  64. }
  65. }
  66. public function collectData(){
  67. $html = '';
  68. $html = getSimpleHTMLDOM($this->getURI());
  69. if(!$html){
  70. switch($this->queriedContext){
  71. case 'By keyword or hashtag':
  72. returnServerError('No results for this query.');
  73. case 'By username':
  74. returnServerError('Requested username can\'t be found.');
  75. }
  76. }
  77. $hidePictures = $this->getInput('nopic');
  78. foreach($html->find('div.js-stream-tweet') as $tweet){
  79. $item = array();
  80. // extract username and sanitize
  81. $item['username'] = $tweet->getAttribute('data-screen-name');
  82. // extract fullname (pseudonym)
  83. $item['fullname'] = $tweet->getAttribute('data-name');
  84. // get author
  85. $item['author'] = $item['fullname'] . ' (@' . $item['username'] . ')';
  86. // get avatar link
  87. $item['avatar'] = $tweet->find('img', 0)->src;
  88. // get TweetID
  89. $item['id'] = $tweet->getAttribute('data-tweet-id');
  90. // get tweet link
  91. $item['uri'] = self::URI . $tweet->find('a.js-permalink', 0)->getAttribute('href');
  92. // extract tweet timestamp
  93. $item['timestamp'] = $tweet->find('span.js-short-timestamp', 0)->getAttribute('data-time');
  94. // generate the title
  95. $item['title'] = strip_tags(
  96. html_entity_decode(
  97. $tweet->find('p.js-tweet-text', 0)->innertext,
  98. ENT_QUOTES,
  99. 'UTF-8'
  100. )
  101. );
  102. // processing content links
  103. foreach($tweet->find('a') as $link){
  104. if($link->hasAttribute('data-expanded-url')){
  105. $link->href = $link->getAttribute('data-expanded-url');
  106. }
  107. $link->removeAttribute('data-expanded-url');
  108. $link->removeAttribute('data-query-source');
  109. $link->removeAttribute('rel');
  110. $link->removeAttribute('class');
  111. $link->removeAttribute('target');
  112. $link->removeAttribute('title');
  113. }
  114. // process emojis (reduce size)
  115. foreach($tweet->find('img.Emoji') as $img){
  116. $img->style .= ' height: 1em;';
  117. }
  118. // get tweet text
  119. $cleanedTweet = str_replace(
  120. 'href="/',
  121. 'href="' . self::URI,
  122. $tweet->find('p.js-tweet-text', 0)->innertext
  123. );
  124. // Add picture to content
  125. $picture_html = '';
  126. if(!$hidePictures){
  127. $picture_html = <<<EOD
  128. <a href="https://twitter.com/{$item['username']}">
  129. <img
  130. style="align: top; width:75 px; border: 1px solid black;"
  131. alt="{$item['username']}"
  132. src="{$item['avatar']}"
  133. title="{$item['fullname']}" />
  134. </a>
  135. EOD;
  136. }
  137. // add content
  138. $item['content'] = <<<EOD
  139. <div style="display: inline-block; vertical-align: top;">
  140. {$picture_html}
  141. </div>
  142. <div style="display: inline-block; vertical-align: top;">
  143. <blockquote>{$cleanedTweet}</blockquote>
  144. </div>
  145. EOD;
  146. // put out
  147. $this->items[] = $item;
  148. }
  149. }
  150. }