2011-02-08 14:17:41 +00:00
< ? php
/* StatusNet Plugin for Friendika
*
* Author : Tobias Diekershoff
* tobias . diekershoff @ gmx . net
*
* License : 3 - clause BSD license ( same as Friendika )
*
* Configuration :
* To activate the plugin itself add it to the $a -> config [ 'system' ][ 'addon' ]
* setting . After this , your user can configure their Twitter account settings
* from " Settings -> Plugin Settings " .
*
* Requirements : PHP5 , curl [ Slinky library ]
*
* Documentation : http :// diekershoff . homeunix . net / redmine / wiki / friendikaplugin / StatusNet_Plugin
*/
/* __TODO__
*
* - what about multimedia content ?
* so far we just strip HTML tags from the message
*/
/***
* We have to alter the TwitterOAuth class a little bit to work with any StatusNet
* installation abroad . Basically it ' s only make the API path variable and be happy .
*
* Thank you guys for the Twitter compatible API !
*/
2011-02-22 04:19:33 +00:00
require_once ( 'library/twitteroauth.php' );
2011-02-08 14:17:41 +00:00
class StatusNetOAuth extends TwitterOAuth {
function get_maxlength () {
$config = $this -> get ( $this -> host . 'statusnet/config.json' );
return $config -> site -> textlimit ;
}
function accessTokenURL () { return $this -> host . 'oauth/access_token' ; }
function authenticateURL () { return $this -> host . 'oauth/authenticate' ; }
function authorizeURL () { return $this -> host . 'oauth/authorize' ; }
function requestTokenURL () { return $this -> host . 'oauth/request_token' ; }
function __construct ( $apipath , $consumer_key , $consumer_secret , $oauth_token = NULL , $oauth_token_secret = NULL ) {
parent :: __construct ( $consumer_key , $consumer_secret , $oauth_token , $oauth_token_secret );
$this -> host = $apipath ;
}
}
function statusnet_install () {
// we need some hooks, for the configuration and for sending tweets
register_hook ( 'plugin_settings' , 'addon/statusnet/statusnet.php' , 'statusnet_settings' );
register_hook ( 'plugin_settings_post' , 'addon/statusnet/statusnet.php' , 'statusnet_settings_post' );
register_hook ( 'post_local_end' , 'addon/statusnet/statusnet.php' , 'statusnet_post_hook' );
2011-02-24 03:09:49 +00:00
register_hook ( 'jot_networks' , 'addon/statusnet/statusnet.php' , 'statusnet_jot_nets' );
2011-02-08 14:17:41 +00:00
logger ( " installed statusnet " );
}
function statusnet_uninstall () {
unregister_hook ( 'plugin_settings' , 'addon/statusnet/statusnet.php' , 'statusnet_settings' );
unregister_hook ( 'plugin_settings_post' , 'addon/statusnet/statusnet.php' , 'statusnet_settings_post' );
unregister_hook ( 'post_local_end' , 'addon/statusnet/statusnet.php' , 'statusnet_post_hook' );
2011-02-24 03:09:49 +00:00
unregister_hook ( 'jot_networks' , 'addon/statusnet/statusnet.php' , 'statusnet_jot_nets' );
2011-02-08 14:17:41 +00:00
}
2011-02-24 02:24:29 +00:00
function statusnet_jot_nets ( & $a , & $b ) {
if ( ! local_user ())
return ;
$statusnet_post = get_pconfig ( local_user (), 'statusnet' , 'post' );
if ( intval ( $statusnet_post ) == 1 ) {
$statusnet_defpost = get_pconfig ( local_user (), 'statusnet' , 'post_by_default' );
2011-03-09 22:39:18 +00:00
$selected = (( intval ( $statusnet_defpost ) == 1 ) ? ' checked="checked" ' : '' );
2011-02-24 02:24:29 +00:00
$b .= '<div class="profile-jot-net"><input type="checkbox" name="statusnet_enable"' . $selected . 'value="1" /> '
. t ( 'Post to StatusNet' ) . '</div>' ;
}
}
2011-02-08 14:17:41 +00:00
function statusnet_settings_post ( $a , $post ) {
if ( ! local_user ())
return ;
if ( isset ( $_POST [ 'statusnet-disconnect' ])) {
/***
* if the statusnet - disconnect checkbox is set , clear the statusnet configuration
* TODO can we revoke the access tokens at Twitter and do we need to do so ?
*/
del_pconfig ( local_user (), 'statusnet' , 'consumerkey' );
del_pconfig ( local_user (), 'statusnet' , 'consumersecret' );
del_pconfig ( local_user (), 'statusnet' , 'post' );
del_pconfig ( local_user (), 'statusnet' , 'oauthtoken' );
del_pconfig ( local_user (), 'statusnet' , 'oauthsecret' );
del_pconfig ( local_user (), 'statusnet' , 'baseapi' );
} else {
if ( isset ( $_POST [ 'statusnet-consumersecret' ])) {
2011-05-17 05:20:26 +00:00
// check if we can reach the API of the StatusNet server
// we'll check the API Version for that, if we don't get one we'll try to fix the path but will
// resign
$apibase = $_POST [ 'statusnet-baseapi' ];
$f = fopen ( $apibase . 'statusnet/version.xml' , 'r' );
$c = stream_get_contents ( $f );
fclose ( $f );
if ( strlen ( $c ) > 0 ) {
// ok the API path is correct, let's save the settings
set_pconfig ( local_user (), 'statusnet' , 'consumerkey' , $_POST [ 'statusnet-consumerkey' ]);
set_pconfig ( local_user (), 'statusnet' , 'consumersecret' , $_POST [ 'statusnet-consumersecret' ]);
set_pconfig ( local_user (), 'statusnet' , 'baseapi' , $apibase );
} else {
// the API path is not correct, maybe missing trailing / ?
$apibase = $apibase . '/' ;
$f = fopen ( $apibase . 'statusnet/version.xml' , 'r' );
$c = stream_get_contents ( $f );
fclose ( $f );
if ( strlen ( $c ) > 0 ) {
// ok the API path is now correct, let's save the settings
set_pconfig ( local_user (), 'statusnet' , 'consumerkey' , $_POST [ 'statusnet-consumerkey' ]);
set_pconfig ( local_user (), 'statusnet' , 'consumersecret' , $_POST [ 'statusnet-consumersecret' ]);
set_pconfig ( local_user (), 'statusnet' , 'baseapi' , $apibase );
} else {
// still not the correct API base, let's do noting
notice ( t ( 'We could not contact the StatusNet API with the Path you entered.' ) . EOL );
}
}
2011-02-08 14:17:41 +00:00
header ( 'Location: ' . $a -> get_baseurl () . '/settings/addon' );
} else {
if ( isset ( $_POST [ 'statusnet-pin' ])) {
// if the user supplied us with a PIN from Twitter, let the magic of OAuth happen
logger ( 'got a StatusNet security code' );
$api = get_pconfig ( local_user (), 'statusnet' , 'baseapi' );
$ckey = get_pconfig ( local_user (), 'statusnet' , 'consumerkey' );
$csecret = get_pconfig ( local_user (), 'statusnet' , 'consumersecret' );
// the token and secret for which the PIN was generated were hidden in the settings
// form as token and token2, we need a new connection to Twitter using these token
// and secret to request a Access Token with the PIN
$connection = new StatusNetOAuth ( $api , $ckey , $csecret , $_POST [ 'statusnet-token' ], $_POST [ 'statusnet-token2' ]);
$token = $connection -> getAccessToken ( $_POST [ 'statusnet-pin' ] );
// ok, now that we have the Access Token, save them in the user config
set_pconfig ( local_user (), 'statusnet' , 'oauthtoken' , $token [ 'oauth_token' ]);
set_pconfig ( local_user (), 'statusnet' , 'oauthsecret' , $token [ 'oauth_token_secret' ]);
set_pconfig ( local_user (), 'statusnet' , 'post' , 1 );
// reload the Addon Settings page, if we don't do it see Bug #42
header ( 'Location: ' . $a -> get_baseurl () . '/settings/addon' );
} else {
// if no PIN is supplied in the POST variables, the user has changed the setting
// to post a tweet for every new __public__ posting to the wall
set_pconfig ( local_user (), 'statusnet' , 'post' , intval ( $_POST [ 'statusnet-enable' ]));
}}}
}
function statusnet_settings ( & $a , & $s ) {
if ( ! local_user ())
return ;
$a -> page [ 'htmlhead' ] .= '<link rel="stylesheet" type="text/css" href="' . $a -> get_baseurl () . '/addon/statusnet/statusnet.css' . '" media="all" />' . " \r \n " ;
/***
* 1 ) Check that we have a base api url and a consumer key & secret
* 2 ) If no OAuthtoken & stuff is present , generate button to get some
2011-05-17 05:20:26 +00:00
* allow the user to cancel the connection process at this step
2011-02-08 14:17:41 +00:00
* 3 ) Checkbox for " Send public notices (respect size limitation)
*/
$api = get_pconfig ( local_user (), 'statusnet' , 'baseapi' );
$ckey = get_pconfig ( local_user (), 'statusnet' , 'consumerkey' );
$csecret = get_pconfig ( local_user (), 'statusnet' , 'consumersecret' );
$otoken = get_pconfig ( local_user (), 'statusnet' , 'oauthtoken' );
$osecret = get_pconfig ( local_user (), 'statusnet' , 'oauthsecret' );
$enabled = get_pconfig ( local_user (), 'statusnet' , 'post' );
$checked = (( $enabled ) ? ' checked="checked" ' : '' );
2011-02-24 02:24:29 +00:00
$s .= '<div class="settings-block">' ;
$s .= '<h3>' . t ( 'StatusNet Posting Settings' ) . '</h3>' ;
2011-02-08 14:17:41 +00:00
if ( ( ! $ckey ) && ( ! $csecret ) ) {
/***
* no consumer keys
*/
2011-02-09 08:40:56 +00:00
$s .= '<p>' . t ( 'No consumer key pair for StatusNet found. Register your Friendika Account as an desktop client on your StatusNet account, copy the consumer key pair here and enter the API base root.<br />Before you register your own OAuth key pair ask the administrator if there is already a key pair for this Friendika installation at your favorited StatusNet installation.' ) . '</p>' ;
2011-02-08 14:17:41 +00:00
$s .= '<div id="statusnet-consumer-wrapper">' ;
2011-02-09 08:40:56 +00:00
$s .= '<label id="statusnet-consumerkey-label" for="statusnet-consumerkey">' . t ( 'OAuth Consumer Key' ) . '</label>' ;
2011-02-25 01:13:03 +00:00
$s .= '<input id="statusnet-consumerkey" type="text" name="statusnet-consumerkey" size="35" />' ;
$s .= '<div class="clear"></div>' ;
2011-02-09 08:40:56 +00:00
$s .= '<label id="statusnet-consumersecret-label" for="statusnet-consumersecret">' . t ( 'OAuth Consumer Secret' ) . '</label>' ;
2011-02-25 01:13:03 +00:00
$s .= '<input id="statusnet-consumersecret" type="text" name="statusnet-consumersecret" size="35" />' ;
$s .= '<div class="clear"></div>' ;
2011-02-15 21:33:33 +00:00
$s .= '<label id="statusnet-baseapi-label" for="statusnet-baseapi">' . t ( " Base API Path \x28 remember the trailing / \x29 " ) . '</label>' ;
2011-02-25 01:13:03 +00:00
$s .= '<input id="statusnet-baseapi" type="text" name="statusnet-baseapi" size="35" />' ;
$s .= '<div class="clear"></div></div>' ;
2011-02-08 14:17:41 +00:00
$s .= '<div class="settings-submit-wrapper" ><input type="submit" name="submit" class="settings-submit" value="' . t ( 'Submit' ) . '" /></div>' ;
} else {
/***
* ok we have a consumer key pair now look into the OAuth stuff
*/
if ( ( ! $otoken ) && ( ! $osecret ) ) {
/***
* the user has not yet connected the account to statusnet
* get a temporary OAuth key / secret pair and display a button with
* which the user can request a PIN to connect the account to a
* account at statusnet
*/
$connection = new StatusNetOAuth ( $api , $ckey , $csecret );
$request_token = $connection -> getRequestToken ( 'oob' );
$token = $request_token [ 'oauth_token' ];
/***
* make some nice form
*/
2011-02-09 08:40:56 +00:00
$s .= '<p>' . t ( 'To connect to your StatusNet account click the button below to get a security code from StatusNet which you have to copy into the input box below and submit the form. Only your <strong>public</strong> posts will be posted to StatusNet.' ) . '</p>' ;
$s .= '<a href="' . $connection -> getAuthorizeURL ( $token , False ) . '" target="_statusnet"><img src="addon/statusnet/signinwithstatusnet.png" alt="' . t ( 'Log in with StatusNet' ) . '"></a>' ;
2011-02-08 14:17:41 +00:00
$s .= '<div id="statusnet-pin-wrapper">' ;
2011-02-09 08:40:56 +00:00
$s .= '<label id="statusnet-pin-label" for="statusnet-pin">' . t ( 'Copy the security code from StatusNet here' ) . '</label>' ;
2011-02-08 14:17:41 +00:00
$s .= '<input id="statusnet-pin" type="text" name="statusnet-pin" />' ;
$s .= '<input id="statusnet-token" type="hidden" name="statusnet-token" value="' . $token . '" />' ;
$s .= '<input id="statusnet-token2" type="hidden" name="statusnet-token2" value="' . $request_token [ 'oauth_token_secret' ] . '" />' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div class="settings-submit-wrapper" ><input type="submit" name="submit" class="settings-submit" value="' . t ( 'Submit' ) . '" /></div>' ;
2011-05-17 05:20:26 +00:00
$s .= '<h4>' . t ( 'Cancel Connection Process' ) . '</h4>' ;
$s .= '<div id="statusnet-cancel-wrapper">' ;
$s .= '<p>' . t ( 'Current StatusNet API is' ) . ': ' . $api . '</p>' ;
$s .= '<label id="statusnet-cancel-label" for="statusnet-cancel">' . t ( 'Cancel StatusNet Connection' ) . '</label>' ;
$s .= '<input id="statusnet-cancel" type="checkbox" name="statusnet-disconnect" value="1" />' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div class="settings-submit-wrapper" ><input type="submit" name="submit" class="settings-submit" value="' . t ( 'Submit' ) . '" /></div>' ;
2011-02-08 14:17:41 +00:00
} else {
/***
* we have an OAuth key / secret pair for the user
* so let ' s give a chance to disable the postings to statusnet
*/
$connection = new StatusNetOAuth ( $api , $ckey , $csecret , $otoken , $osecret );
$details = $connection -> get ( 'account/verify_credentials' );
2011-02-09 08:40:56 +00:00
$s .= '<div id="statusnet-info" ><img id="statusnet-avatar" src="' . $details -> profile_image_url . '" /><p id="statusnet-info-block">' . t ( 'Currently connected to: ' ) . '<a href="' . $details -> statusnet_profile_url . '" target="_statusnet">' . $details -> screen_name . '</a><br /><em>' . $details -> description . '</em></p></div>' ;
$s .= '<p>' . t ( 'If enabled all your <strong>public</strong> postings will be posted to the associated StatusNet account as well.' ) . '</p>' ;
2011-02-08 14:17:41 +00:00
$s .= '<div id="statusnet-enable-wrapper">' ;
2011-02-09 08:40:56 +00:00
$s .= '<label id="statusnet-enable-label" for="statusnet-checkbox">' . t ( 'Send public postings to StatusNet' ) . '</label>' ;
2011-02-08 14:17:41 +00:00
$s .= '<input id="statusnet-checkbox" type="checkbox" name="statusnet-enable" value="1" ' . $checked . '/>' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div id="statusnet-disconnect-wrapper">' ;
2011-02-09 08:40:56 +00:00
$s .= '<label id="statusnet-disconnect-label" for="statusnet-disconnect">' . t ( 'Clear OAuth configuration' ) . '</label>' ;
2011-02-08 14:17:41 +00:00
$s .= '<input id="statusnet-disconnect" type="checkbox" name="statusnet-disconnect" value="1" />' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div class="settings-submit-wrapper" ><input type="submit" name="submit" class="settings-submit" value="' . t ( 'Submit' ) . '" /></div>' ;
}
}
2011-02-24 02:24:29 +00:00
$s .= '</div><div class="clear"></div></div>' ;
2011-02-08 14:17:41 +00:00
}
function statusnet_post_hook ( & $a , & $b ) {
/**
* Post to statusnet
*/
logger ( 'StatusNet post invoked' );
2011-02-09 08:40:56 +00:00
if (( local_user ()) && ( local_user () == $b [ 'uid' ]) && ( ! $b [ 'private' ]) && ( ! $b [ 'parent' ]) ) {
2011-02-08 14:17:41 +00:00
load_pconfig ( local_user (), 'statusnet' );
$api = get_pconfig ( local_user (), 'statusnet' , 'baseapi' );
$ckey = get_pconfig ( local_user (), 'statusnet' , 'consumerkey' );
$csecret = get_pconfig ( local_user (), 'statusnet' , 'consumersecret' );
$otoken = get_pconfig ( local_user (), 'statusnet' , 'oauthtoken' );
$osecret = get_pconfig ( local_user (), 'statusnet' , 'oauthsecret' );
if ( $ckey && $csecret && $otoken && $osecret ) {
$statusnet_post = get_pconfig ( local_user (), 'statusnet' , 'post' );
2011-02-24 02:24:29 +00:00
$statusnet_enable = (( $statusnet_post && x ( $_POST , 'statusnet_enable' )) ? intval ( $_POST [ 'statusnet_enable' ]) : 0 );
2011-02-08 14:17:41 +00:00
2011-02-24 02:24:29 +00:00
if ( $statusnet_enable && $statusnet_post ) {
2011-02-08 14:17:41 +00:00
require_once ( 'include/bbcode.php' );
$dent = new StatusNetOAuth ( $api , $ckey , $csecret , $otoken , $osecret );
$max_char = $dent -> get_maxlength (); // max. length for a dent
$msg = strip_tags ( bbcode ( $b [ 'body' ]));
if ( strlen ( $msg ) > $max_char ) {
$shortlink = " " ;
2011-02-22 04:19:33 +00:00
require_once ( 'library/slinky.php' );
2011-02-08 14:17:41 +00:00
// post url = base url + /display/ + owner + post id
// we construct this from the Owner link and replace
// profile by display - this will cause an error when
// /profile/ is in the owner url twice but I don't
// think this will be very common...
$posturl = str_replace ( '/profile/' , '/display/' , $b [ 'owner-link' ]) . '/' . $b [ 'id' ];
$slinky = new Slinky ( $posturl );
// setup a cascade of shortening services
// try to get a short link from these services
// in the order ur1.ca, trim, id.gd, tinyurl
$slinky -> set_cascade ( array ( new Slinky_UR1ca (), new Slinky_Trim (), new Slinky_IsGd (), new Slinky_TinyURL () ) );
$shortlink = $slinky -> short ();
// the new message will be shortened such that "... $shortlink"
// will fit into the character limit
$msg = substr ( $msg , 0 , $max_char - strlen ( $shortlink ) - 4 );
$msg .= '... ' . $shortlink ;
}
// and now tweet it :-)
2011-02-10 11:51:42 +00:00
if ( strlen ( $msg ))
$dent -> post ( 'statuses/update' , array ( 'status' => $msg ));
2011-02-08 14:17:41 +00:00
}
}
2011-02-24 02:24:29 +00:00
}
2011-02-08 14:17:41 +00:00
}