IF you want to show some tweets from twitter on a DokuWiki page, use this Plugin. The syntax is easy:
[TWITTER:TYPE:USERNAME/SEARCHWORD:COUNT]
Replace the following:
And here comes some valid examples:
//The 5 latest tweets from user schwarzenegger. [TWITTER:USER:schwarzenegger:5] //All tweets from user BritneySpears [TWITTER:USER:BritneySpears] //Search for the word mj [TWITTER:SEARCH:mj] //Search for the word dokuwiki [TWITTER:SEARCH:dokuwiki]
(Not that I would insert them in my DokuWiki
)
Maybe you can use it, to show some tweets related to your company, or insert the Tweets from your employees.
I created that plugin in around 30 minutes, so it's only a first demo and I personally don't like the look. But at least it's working. I will do some improvements, when I have more free time.
Save the following code into syntax.php and copy it into folder: /lib/plugins/twitter/conf
<?php /** * Options for the Twitter plugin */ $conf['timeout'] = 60; // timeout for twitter news cache
Save the following code into syntax.php and copy it into folder: /lib/plugins/twitter/
<?php /** * Twitter Plugin * * Action plugin component, for cache validity determination; based on the Source Plugin/Action scripts * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Christopher Smith <chris@jalakai.co.uk> ; rewritten for twitter plugin: Björn Kalkbrenner <terminar@cyberphoria.org> */ if(!defined('DOKU_INC')) die(); // no Dokuwiki, no go if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'action.php'); /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class action_plugin_twitter extends DokuWiki_Action_Plugin { /** * return some info */ function getInfo(){ return array( 'author' => 'Christopher Smith', 'email' => 'chris@jalakai.co.uk', 'date' => '2006-12-22', 'name' => 'Source Plugin', 'desc' => 'Twitter plugin cache', 'url' => 'http://wiki.splitbrain.org/plugin:twitter', ); } /** * plugin should use this method to register its handlers with the dokuwiki's event controller */ function register(&$controller) { $controller->register_hook('PARSER_CACHE_USE','BEFORE', $this, '_cache_prepare'); } /** * prepare the cache object for default _useCache action */ function _cache_prepare(&$event, $param) { $cache =& $event->data; // we're only interested in wiki pages and supported render modes if (!isset($cache->page)) return; if (!isset($cache->mode) || !in_array($cache->mode,array('i','metadata'))) return; $max_age = $this->_cache_maxage($cache->page); if (is_null($max_age)) return; if ($max_age <= 0) { // expire the cache //no cache for twitter! $event->preventDefault(); $event->stopPropagation(); $event->result = false; return; } $cache->depends['age'] = !empty($cache->depends['age']) ? min($cache->depends['age'],$max_age): $max_age; } /** * determine the max allowable age of the cache * * @param string $id wiki page name * * @return int max allowable age of the cache * null means not applicable */ function _cache_maxage($id) { $hasPart = p_get_metadata($id, 'relation haspart'); if (empty($hasPart) || !is_array($hasPart)) return null; $age = 0; foreach ($hasPart as $file => $data) { if ($file == "_plugin_twitter") { //this is us, outdate the cache if older than the configured seconds return $this->getConf('timeout'); } } return $age ? time()-$age : null; } }
<?php /** * Twitter Plugin * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Christoph Lang <calbity@gmx.de> */ // based on http://wiki.splitbrain.org/plugin:tutorial // must be run within DokuWiki if (!defined('DOKU_INC')) die(); if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); require_once(DOKU_PLUGIN . 'syntax.php'); /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class syntax_plugin_twitter extends DokuWiki_Syntax_Plugin { function getInfo() { return array( 'author' => 'Christoph Lang', 'email' => 'calbity@gmx.de', 'date' => '2008-07-05', 'name' => 'Twitter Plugin', 'desc' => 'Show Tweets from Twitter', 'url' => 'http://www.google.de' ); } private function replace($data) { $sResponse = "<h1>".$data[1]."</h1>"; $data = $data[0]; if(!isset($data)){ return $sResponse."<h4>Twitter is down....</h4>"; } $sResponse .= '<table class="twitterentries" style="width:100%;">'; foreach($data as $entry){ $text=$entry->text." "; $image=$entry->user->profile_image_url; $time=$entry->created_at; $time = strtotime($time); //$time = date("Y-m-d H:i:s",$time); $time = $this->Timesince($time); $from=$entry->from_user; $name = ""; if(!empty($entry->user->name)) $name = " (".$entry->user->name.")"; if(empty($from)) $from=$entry->user->screen_name; if(isset($entry->profile_image_url)) { $image=$entry->profile_image_url; } // get links $search = array( '`((?:https?|ftp)://\S+[[:alnum:]]/?)`si', '`((?<!//)(www\.\S+[[:alnum:]]/?))`si' ); $replace = array( '<a href="$1" target="_blank">$1</a> ', '<a href="http://$1" target="_blank">$1</a>' ); $text = preg_replace($search, $replace, $text); // get hashtags if (preg_match_all('/#(.*?)\s/', $text, $arMatches)) { for($i=0; $i < count($arMatches[0]); $i++) $text = str_replace($arMatches[0][$i], '<a target="_blank" href="http://search.twitter.com/search?q=' . $arMatches[1][$i] . '">' . $arMatches[0][$i] . "</a>", $text); } // get twitterer if (preg_match_all('/@(.*?)\s/', $text, $arMatches)) { for($i=0; $i < count($arMatches[0]); $i++){ $strTwitterer = preg_replace('/\W/', '', $arMatches[0][$i]); $text = str_replace($strTwitterer, '<a target="_blank" href="http://twitter.com/' . $strTwitterer . '">' . $strTwitterer . "</a>", $text); } } $sResponse .= '<tr onmouseover="this.style.backgroundColor=\'#cccccc\';" onmouseout="this.style.backgroundColor=\'\';" style="width:100%;"><td style="width:48px;"><img width="48" src="'.$image.'" alt="'.$from.'"/></td><td>'.$text.'<br/>About '.$time.' ago from <a target="_blank" href="http://twitter.com/'.$from.'">'.$from. $name.'</a></td></tr>'; } $sResponse .= "</table>"; return $sResponse; } /* Works out the time since the entry post, takes a an argument in unix time (seconds) */ public function Timesince($original) { // array of time period chunks $chunks = array( array(60 * 60 * 24 * 365 , 'year'), array(60 * 60 * 24 * 30 , 'month'), array(60 * 60 * 24 * 7, 'week'), array(60 * 60 * 24 , 'day'), array(60 * 60 , 'hour'), array(60 , 'min'), array(1 , 'sec'), ); $today = time(); /* Current unix time */ $since = $today - $original; // $j saves performing the count function each time around the loop for ($i = 0, $j = count($chunks); $i < $j; $i++) { $seconds = $chunks[$i][0]; $name = $chunks[$i][1]; // finding the biggest chunk (if the chunk fits, break) if (($count = floor($since / $seconds)) != 0) { break; } } $print = ($count == 1) ? '1 '.$name : "$count {$name}s"; if ($i + 1 < $j) { // now getting the second item $seconds2 = $chunks[$i + 1][0]; $name2 = $chunks[$i + 1][1]; // add second item if its greater than 0 if (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0) { $print .= ($count2 == 1) ? ', 1 '.$name2 : ", $count2 {$name2}s"; } } return $print; } function connectTo($mode) { $this->Lexer->addSpecialPattern('\[TWITTER\:USER\:.*?\]', $mode, 'plugin_twitter'); $this->Lexer->addSpecialPattern('\[TWITTER\:SEARCH\:.*?\]', $mode, 'plugin_twitter'); $this->Lexer->addSpecialPattern('{{twitter>user\:.*?}}', $mode, 'plugin_twitter'); $this->Lexer->addSpecialPattern('{{twitter>search\:.*?}}', $mode, 'plugin_twitter'); } function getType() { return 'substition'; } function getSort() { return 314; } function handle($match, $state, $pos, &$handler) { $match = str_replace(array(">","{{","}}"),array(":","[","]"),$match); $match = substr($match,1,-1); $data = explode(":",$match); $number =""; $data[2] = str_replace(" ","%20",$data[2]); if(strtoupper($data[1]) == "SEARCH"){ @$json = file_get_contents("http://search.twitter.com/search.json?q=".$data[2].$number); }else{ if(isset($data[3])) $number = "?count=".$data[3]; @$json = file_get_contents("http://twitter.com/statuses/user_timeline/".$data[2].".json".$number); } $decode = json_decode ( $json ); if(isset($decode->results)) { return array($decode->results,"Results for search: ".str_replace("%20"," and ",$data[2])); } return array($decode,"Timeline from ".$data[2]); } function render($mode, &$renderer, $data) { if ($mode == 'xhtml') { // prevent caching to ensure content is always fresh $renderer->info['cache'] = false; $renderer->doc .= $this->replace($data); return true; } elseif ($mode == 'metadata'){ // for metadata renderer $renderer->meta['relation']['haspart']['_plugin_twitter'] = true; return true; } return false; } }
I would like to send dokuwiki changes (the changelog) to twitter automatically. How can I do that? citizenkeys 2010/04/17 19:29
That is not possible with this plugin. You would need another plugin to do automatic tweeting of the changelog. The plugin needs to be a action plugin and not a syntax plugin. Currently i'm not havin any plans to realize that, althought it would be really easy because Twitter has a really good API. Christoph LangAs they say 'better late than never'. I created a new plugin called autotweet that automatically posts Tweets with page changes of specific pages to Twitter using the oAuth authentication protocoll. You can specify the look and feel of the Tweet to suit your needs and also specify which pages should be regarded. I hope this is what you had in mind, maybe it's still usefull to somebody. jdt 2011/10/06 11:10
Can you (or anybody!) please write a plugin to send dokuwiki updates to twitter? Right now, my site has a plugin to automatically send sitemap updates to Google. We would like to send page updates automatically to twitter. citizenkeys 2010/04/17 19:29
I wouldn't even know what to tweet on a page update, because 140 chars not much. Personally i think a rss feed is the much better choice here. But maybe someone will do your plugin Christoph Lang
Nice plugin! But is it possible to make the syntax more *DokuWiki-like*? Such as using reder? —
Reder 2009/07/04 08:30
Ok, just updated the code. Now you can also use:
//Timeline of user
{{twitter>user:reder}}
//Search for Keyword 'PHP'
{{twitter>search:PHP}}
Hope that helps.
I build some regex into the Plugin to make links, twitterer and hashtags clickable. rifter 2009/07/08 17:56
Thank you, seems to work very fine!
Christoph Lang 2009/07/08 23:46
Updated the code a little bit, mainly the time of the tweet is now displayed Twitter-like, e.g. 5 minutes ago, or About 1 week ago. Also there was a problem with the regex (only first hastag was clickable). Now all hastags are clickable. Christoph Lang 2009/07/09 23:01
Getting a “Twitter is down” error when it isn't. — Grimp
“Twitter is down” means either Twitter is down, or the response from Twitter is invalid. Maybe you used a wrong syntax?
Give me a sample of your syntax, and I will look. Maybe it's a Bug. — C.Lang
I have the same problem “Twitter is down” … example on http://pichat-wiki.de/links#twitter — Mark Wolfgruber
In you PHP.ini the option allow_url_fopen is Off. You have to turn it On, so that the Plugin can fetch the data from Twitter.
If Option is Off file_get_contents can only open local files, and not files on another server. — C.Lang
I can't change the parameter forallow_url_fopento On
but now it is working with the following additional function code
to install put theprivate function file_get_contentse.g. top of thefunction handle
replace in the function handles: file_get_contents with $this→file_get_contents
— Mark Wolfgruber 2009/11/23 02:42
I updated the mod, now you can use allow_url_fopen with ON or OFF (I need for local Installation ON and for the Server OFF) — Mark Wolfgruber 2010/04/23 00:16
private function file_get_contents($url) { /** * Mod from Mark Wolfgruber (http://www.600infos.de) for http://www.pichat-wiki.de * * this function is needed if you have in the PHP Core allow_url_fopen Off * replace in the function handle: file_get_contents with $this->file_get_contents * * thx to Christoph Lang and http://www.php.net/manual/en/function.curl-exec.php **/ @$json=file_get_contents($url); // handle error if fopen is Off if (is_bool($json) && $json == false) { $curl = @curl_init($url); @curl_setopt($curl, CURLOPT_HEADER, FALSE); @curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); @$json = curl_exec($curl); curl_close($curl); } return $json; }
Fantastic plugin, thanks - is there a way to do negative keywords on the search? (UPDATE 7/22 - WORKED! THANKS CHRISTOPH!) — Tyler (mail at tribalcore dot com)
Just updated the plugin. Now you can combine searchwords, e.g:
//Search for PHP but NOT Zend
{{twitter>search:php -zend}}
//Search for PHP AND Zend
{{twitter>search:php zend}}
In theory other search parameters from the Twitter-Api should also work, but I didn't test it.
This requires PHP 5.2 or later, or alternatively you'll have to add a json_decode function, e.g. from http://au.php.net/manual/en/function.json-decode.php#91216 — Robert
Your plugin does not work on my server. It shows only: About 40 years, 1 month ago from. (www.pyload.org/beta)
Johann BauerIt seems your server is returning the wrong time to the plugin. 01.01.1970 is the start of the UNIX time, and that is what your server is returning (40years and 1 month ago).
Maybe you have to set the correct time on your server first. — C.LangNo, the server's time (So 7. Feb 17:49:24 CET 2010) is right (for Germany) and there aren't tweets and pictures, so that I think it's another problem
Just checked your site pyload and saw that it wasn't working. Seems your having another problem. Do you have at least PHP 5.2?
Maybe you can provide me with more detailed information, because I can't think of any reason for your problem.
You can also contact me via Email, my mail address is on top of the page (I'm German, too).
Updated the plugin with cache “management” (from source plugin).
Björn Kalkbrenner 2010/06/18 20:15
— Andreas — Just receiving the message: Timeline from experimenteandi Twitter is down….
What's wrong ?
This was already discussed a few lines above. Check your PHP Inifile for allow_url_fopen. Christoph Lang