2014-06-07 08:27:48 +00:00
< ? php
/**
* Name : App . net Connector
2014-06-10 18:14:51 +00:00
* Description : app . net postings import and export
* Version : 0.2
2014-06-07 08:27:48 +00:00
* Author : Michael Vogel < https :// pirati . ca / profile / heluecht >
*/
2014-06-10 18:14:51 +00:00
/*
Some marker in the post so that reimported posts can be treated better . ( BBCode over app . net ? )
*/
define ( 'APPNET_DEFAULT_POLL_INTERVAL' , 5 ); // given in minutes
2014-06-07 08:27:48 +00:00
function appnet_install () {
2014-06-10 18:14:51 +00:00
register_hook ( 'post_local' , 'addon/appnet/appnet.php' , 'appnet_post_local' );
register_hook ( 'notifier_normal' , 'addon/appnet/appnet.php' , 'appnet_send' );
register_hook ( 'jot_networks' , 'addon/appnet/appnet.php' , 'appnet_jot_nets' );
register_hook ( 'cron' , 'addon/appnet/appnet.php' , 'appnet_cron' );
register_hook ( 'connector_settings' , 'addon/appnet/appnet.php' , 'appnet_settings' );
register_hook ( 'connector_settings_post' , 'addon/appnet/appnet.php' , 'appnet_settings_post' );
2014-06-07 08:27:48 +00:00
}
function appnet_uninstall () {
unregister_hook ( 'post_local' , 'addon/appnet/appnet.php' , 'appnet_post_local' );
unregister_hook ( 'notifier_normal' , 'addon/appnet/appnet.php' , 'appnet_send' );
unregister_hook ( 'jot_networks' , 'addon/appnet/appnet.php' , 'appnet_jot_nets' );
2014-06-10 18:14:51 +00:00
unregister_hook ( 'cron' , 'addon/appnet/appnet.php' , 'appnet_cron' );
2014-06-07 08:27:48 +00:00
unregister_hook ( 'connector_settings' , 'addon/appnet/appnet.php' , 'appnet_settings' );
unregister_hook ( 'connector_settings_post' , 'addon/appnet/appnet.php' , 'appnet_settings_post' );
}
function appnet_module () {}
function appnet_content ( & $a ) {
2014-06-10 18:14:51 +00:00
if ( ! local_user ()) {
notice ( t ( 'Permission denied.' ) . EOL );
return '' ;
}
require_once ( " mod/settings.php " );
settings_init ( $a );
if ( isset ( $a -> argv [ 1 ]))
switch ( $a -> argv [ 1 ]) {
case " connect " :
$o = appnet_connect ( $a );
break ;
default :
$o = print_r ( $a -> argv , true );
break ;
}
else
2014-06-07 08:27:48 +00:00
$o = appnet_connect ( $a );
2014-06-10 18:14:51 +00:00
return $o ;
2014-06-07 08:27:48 +00:00
}
function appnet_connect ( & $a ) {
require_once 'addon/appnet/AppDotNet.php' ;
$clientId = get_pconfig ( local_user (), 'appnet' , 'clientid' );
$clientSecret = get_pconfig ( local_user (), 'appnet' , 'clientsecret' );
$app = new AppDotNet ( $clientId , $clientSecret );
try {
$token = $app -> getAccessToken ( $a -> get_baseurl () . '/appnet/connect' );
logger ( " appnet_connect: authenticated " );
$o .= t ( " You are now authenticated to app.net. " );
set_pconfig ( local_user (), 'appnet' , 'token' , $token );
}
catch ( AppDotNetException $e ) {
$o .= t ( " <p>Error fetching token. Please try again.</p> " );
}
$o .= '<br /><a href="' . $a -> get_baseurl () . '/settings/connectors">' . t ( " return to the connector page " ) . '</a>' ;
return ( $o );
}
function appnet_jot_nets ( & $a , & $b ) {
if ( ! local_user ())
return ;
$post = get_pconfig ( local_user (), 'appnet' , 'post' );
if ( intval ( $post ) == 1 ) {
$defpost = get_pconfig ( local_user (), 'appnet' , 'post_by_default' );
$selected = (( intval ( $defpost ) == 1 ) ? ' checked="checked" ' : '' );
$b .= '<div class="profile-jot-net"><input type="checkbox" name="appnet_enable"' . $selected . ' value="1" /> '
. t ( 'Post to app.net' ) . '</div>' ;
}
}
function appnet_settings ( & $a , & $s ) {
require_once 'addon/appnet/AppDotNet.php' ;
if ( ! local_user ())
return ;
$token = get_pconfig ( local_user (), 'appnet' , 'token' );
$app_clientId = get_pconfig ( local_user (), 'appnet' , 'clientid' );
$app_clientSecret = get_pconfig ( local_user (), 'appnet' , 'clientsecret' );
/* Add our stylesheet to the page so we can make our settings look nice */
$a -> page [ 'htmlhead' ] .= '<link rel="stylesheet" type="text/css" href="' . $a -> get_baseurl () . '/addon/appnet/appnet.css' . '" media="all" />' . " \r \n " ;
$enabled = get_pconfig ( local_user (), 'appnet' , 'post' );
$checked = (( $enabled ) ? ' checked="checked" ' : '' );
$css = (( $enabled ) ? '' : '-disabled' );
$def_enabled = get_pconfig ( local_user (), 'appnet' , 'post_by_default' );
$def_checked = (( $def_enabled ) ? ' checked="checked" ' : '' );
2014-06-10 18:14:51 +00:00
$importenabled = get_pconfig ( local_user (), 'appnet' , 'import' );
$importchecked = (( $importenabled ) ? ' checked="checked" ' : '' );
$ownid = get_pconfig ( local_user (), 'appnet' , 'ownid' );
2014-06-07 08:27:48 +00:00
$s .= '<span id="settings_appnet_inflated" class="settings-block fakelink" style="display: block;" onclick="openClose(\'settings_appnet_expanded\'); openClose(\'settings_appnet_inflated\');">' ;
$s .= '<img class="connector' . $css . '" src="images/appnet.png" /><h3 class="connector">' . t ( 'App.net Export' ) . '</h3>' ;
$s .= '</span>' ;
$s .= '<div id="settings_appnet_expanded" class="settings-block" style="display: none;">' ;
$s .= '<span class="fakelink" onclick="openClose(\'settings_appnet_expanded\'); openClose(\'settings_appnet_inflated\');">' ;
$s .= '<img class="connector' . $css . '" src="images/appnet.png" /><h3 class="connector">' . t ( 'App.net Export' ) . '</h3>' ;
$s .= '</span>' ;
if ( $token != " " ) {
$app = new AppDotNet ( $app_clientId , $app_clientSecret );
$app -> setAccessToken ( $token );
try {
$userdata = $app -> getUser ();
2014-06-10 18:14:51 +00:00
if ( $ownid != $userdata [ " id " ])
set_pconfig ( local_user (), 'appnet' , 'ownid' , $userdata [ " id " ]);
2014-06-07 08:27:48 +00:00
$s .= '<div id="appnet-info" ><img id="appnet-avatar" src="' . $userdata [ " avatar_image " ][ " url " ] . '" /><p id="appnet-info-block">' . t ( 'Currently connected to: ' ) . '<a href="' . $userdata [ " canonical_url " ] . '" target="_appnet">' . $userdata [ " username " ] . '</a><br /><em>' . $userdata [ " description " ][ " text " ] . '</em></p></div>' ;
$s .= '<div id="appnet-enable-wrapper">' ;
$s .= '<label id="appnet-enable-label" for="appnet-checkbox">' . t ( 'Enable App.net Post Plugin' ) . '</label>' ;
$s .= '<input id="appnet-checkbox" type="checkbox" name="appnet" value="1" ' . $checked . '/>' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div id="appnet-bydefault-wrapper">' ;
$s .= '<label id="appnet-bydefault-label" for="appnet-bydefault">' . t ( 'Post to App.net by default' ) . '</label>' ;
$s .= '<input id="appnet-bydefault" type="checkbox" name="appnet_bydefault" value="1" ' . $def_checked . '/>' ;
$s .= '</div><div class="clear"></div>' ;
2014-06-10 18:14:51 +00:00
$s .= '<label id="appnet-import-label" for="appnet-import">' . t ( 'Import the remote timeline' ) . '</label>' ;
$s .= '<input id="appnet-import" type="checkbox" name="appnet_import" value="1" ' . $importchecked . '/>' ;
$s .= '<div class="clear"></div>' ;
2014-06-07 08:27:48 +00:00
}
2014-06-10 18:14:51 +00:00
catch ( AppDotNetException $e ) {
2014-06-07 08:27:48 +00:00
$s .= t ( " <p>Error fetching user profile. Please clear the configuration and try again.</p> " );
}
//$s .= print_r($userdata, true);
} elseif (( $app_clientId == '' ) OR ( $app_clientSecret == '' )) {
$s .= t ( " <p>You have two ways to connect to App.net.</p> " );
$s .= " <hr /> " ;
$s .= t ( '<p>First way: Register an application at <a href="https://account.app.net/developer/apps/">https://account.app.net/developer/apps/</a> and enter Client ID and Client Secret. ' );
$s .= sprintf ( t ( " Use '%s' as Redirect URI<p> " ), $a -> get_baseurl () . '/appnet/connect' );
$s .= '<div id="appnet-clientid-wrapper">' ;
$s .= '<label id="appnet-clientid-label" for="appnet-clientid">' . t ( 'Client ID' ) . '</label>' ;
$s .= '<input id="appnet-clientid" type="text" name="clientid" value="' . $app_clientId . '" />' ;
$s .= '</div><div class="clear"></div>' ;
$s .= '<div id="appnet-clientsecret-wrapper">' ;
$s .= '<label id="appnet-clientsecret-label" for="appnet-clientsecret">' . t ( 'Client Secret' ) . '</label>' ;
$s .= '<input id="appnet-clientsecret" type="text" name="clientsecret" value="' . $app_clientSecret . '" />' ;
$s .= '</div><div class="clear"></div>' ;
$s .= " <hr /> " ;
$s .= t ( '<p>Second way: fetch a token at <a href="http://dev-lite.jonathonduerig.com/">http://dev-lite.jonathonduerig.com/</a>. ' );
$s .= t ( " Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.</p> " );
$s .= '<div id="appnet-token-wrapper">' ;
$s .= '<label id="appnet-token-label" for="appnet-token">' . t ( 'Token' ) . '</label>' ;
$s .= '<input id="appnet-token" type="text" name="token" value="' . $token . '" />' ;
$s .= '</div><div class="clear"></div>' ;
} else {
$app = new AppDotNet ( $app_clientId , $app_clientSecret );
$scope = array ( 'basic' , 'stream' , 'write_post' ,
'public_messages' , 'messages' );
$url = $app -> getAuthUrl ( $a -> get_baseurl () . '/appnet/connect' , $scope );
$s .= '<div class="clear"></div>' ;
$s .= '<a href="' . $url . '">' . t ( " Sign in using App.net " ) . '</a>' ;
}
if (( $app_clientId != '' ) OR ( $app_clientSecret != '' ) OR ( $token != '' )) {
$s .= '<div id="appnet-disconnect-wrapper">' ;
$s .= '<label id="appnet-disconnect-label" for="appnet-disconnect">' . t ( 'Clear OAuth configuration' ) . '</label>' ;
$s .= '<input id="appnet-disconnect" type="checkbox" name="appnet-disconnect" value="1" />' ;
$s .= '</div><div class="clear"></div>' ;
}
/* provide a submit button */
$s .= '<div class="settings-submit-wrapper" ><input type="submit" name="appnet-submit" class="settings-submit" value="' . t ( 'Save Settings' ) . '" /></div>' ;
$s .= '</div>' ;
}
function appnet_settings_post ( & $a , & $b ) {
if ( x ( $_POST , 'appnet-submit' )) {
if ( isset ( $_POST [ 'appnet-disconnect' ])) {
del_pconfig ( local_user (), 'appnet' , 'clientsecret' );
del_pconfig ( local_user (), 'appnet' , 'clientid' );
del_pconfig ( local_user (), 'appnet' , 'token' );
2014-06-10 18:14:51 +00:00
del_pconfig ( local_user (), 'appnet' , 'post' );
del_pconfig ( local_user (), 'appnet' , 'post_by_default' );
del_pconfig ( local_user (), 'appnet' , 'import' );
2014-06-07 08:27:48 +00:00
}
if ( isset ( $_POST [ " clientsecret " ]))
set_pconfig ( local_user (), 'appnet' , 'clientsecret' , $_POST [ 'clientsecret' ]);
if ( isset ( $_POST [ " clientid " ]))
set_pconfig ( local_user (), 'appnet' , 'clientid' , $_POST [ 'clientid' ]);
if ( isset ( $_POST [ " token " ]) AND ( $_POST [ " token " ] != " " ))
set_pconfig ( local_user (), 'appnet' , 'token' , $_POST [ 'token' ]);
2014-06-10 18:14:51 +00:00
set_pconfig ( local_user (), 'appnet' , 'post' , intval ( $_POST [ 'appnet' ]));
set_pconfig ( local_user (), 'appnet' , 'post_by_default' , intval ( $_POST [ 'appnet_bydefault' ]));
set_pconfig ( local_user (), 'appnet' , 'import' , intval ( $_POST [ 'appnet_import' ]));
2014-06-07 08:27:48 +00:00
}
}
function appnet_post_local ( & $a , & $b ) {
if ( $b [ 'edit' ])
return ;
2014-06-10 18:14:51 +00:00
if (( local_user ()) && ( local_user () == $b [ 'uid' ]) && ( ! $b [ 'private' ]) && ( ! $b [ 'parent' ])) {
$appnet_post = intval ( get_pconfig ( local_user (), 'appnet' , 'post' ));
$appnet_enable = (( $appnet_post && x ( $_REQUEST , 'appnet_enable' )) ? intval ( $_REQUEST [ 'appnet_enable' ]) : 0 );
2014-06-07 08:27:48 +00:00
2014-06-10 18:14:51 +00:00
// if API is used, default to the chosen settings
if ( $_REQUEST [ 'api_source' ] && intval ( get_pconfig ( local_user (), 'appnet' , 'post_by_default' )))
$appnet_enable = 1 ;
2014-06-07 08:27:48 +00:00
2014-06-10 18:14:51 +00:00
if ( ! $appnet_enable )
return ;
2014-06-07 08:27:48 +00:00
2014-06-10 18:14:51 +00:00
if ( strlen ( $b [ 'postopts' ]))
$b [ 'postopts' ] .= ',' ;
2014-06-07 08:27:48 +00:00
2014-06-10 18:14:51 +00:00
$b [ 'postopts' ] .= 'appnet' ;
}
2014-06-07 08:27:48 +00:00
}
function appnet_send ( & $a , & $b ) {
logger ( 'appnet_send: invoked for post ' . $b [ 'id' ] . " " . $b [ 'app' ]);
2014-06-10 18:14:51 +00:00
if ( ! get_pconfig ( $b [ " uid " ], 'appnet' , 'import' )) {
if ( $b [ 'deleted' ] || $b [ 'private' ] || ( $b [ 'created' ] !== $b [ 'edited' ]))
return ;
}
if ( $b [ 'parent' ] != $b [ 'id' ]) {
logger ( " appnet_send: parameter " . print_r ( $b , true ), LOGGER_DATA );
// Looking if its a reply to an app.net post
if (( substr ( $b [ " parent-uri " ], 0 , 5 ) != " adn:: " ) AND ( substr ( $b [ " extid " ], 0 , 5 ) != " adn:: " ) AND ( substr ( $b [ " thr-parent " ], 0 , 5 ) != " adn:: " )) {
logger ( " appnet_send: no app.net post " . $b [ " parent " ]);
return ;
}
$r = q ( " SELECT * FROM item WHERE item.uri = '%s' AND item.uid = %d LIMIT 1 " ,
dbesc ( $b [ " thr-parent " ]),
intval ( $b [ " uid " ]));
2014-06-07 08:27:48 +00:00
2014-06-10 18:14:51 +00:00
if ( ! count ( $r )) {
logger ( " appnet_send: no parent found " . $b [ " thr-parent " ]);
return ;
} else {
$iscomment = true ;
$orig_post = $r [ 0 ];
}
$nicknameplain = preg_replace ( " =https?://alpha.app.net/(.*)=ism " , " $ 1 " , $orig_post [ " author-link " ]);
$nickname = " @[url= " . $orig_post [ " author-link " ] . " ] " . $nicknameplain . " [/url] " ;
$nicknameplain = " @ " . $nicknameplain ;
logger ( " appnet_send: comparing " . $nickname . " and " . $nicknameplain . " with " . $b [ " body " ], LOGGER_DEBUG );
if (( strpos ( $b [ " body " ], $nickname ) === false ) AND ( strpos ( $b [ " body " ], $nicknameplain ) === false ))
$b [ " body " ] = $nickname . " " . $b [ " body " ];
logger ( " appnet_send: parent found " . print_r ( $orig_post , true ), LOGGER_DATA );
} else {
$iscomment = false ;
if ( $b [ 'private' ] OR ! strstr ( $b [ 'postopts' ], 'appnet' ))
return ;
}
if (( $b [ 'verb' ] == ACTIVITY_POST ) AND $b [ 'deleted' ])
appnet_action ( $a , $b [ " uid " ], substr ( $orig_post [ " uri " ], 5 ), " delete " );
if ( $b [ 'verb' ] == ACTIVITY_LIKE ) {
logger ( " appnet_send: " . print_r ( $b , true ), LOGGER_DEBUG );
logger ( " appnet_send: parameter 2 " . substr ( $b [ " thr-parent " ], 5 ), LOGGER_DEBUG );
if ( $b [ 'deleted' ])
appnet_action ( $a , $b [ " uid " ], substr ( $b [ " thr-parent " ], 5 ), " unlike " );
else
appnet_action ( $a , $b [ " uid " ], substr ( $b [ " thr-parent " ], 5 ), " like " );
2014-06-07 08:27:48 +00:00
return ;
2014-06-10 18:14:51 +00:00
}
2014-06-07 08:27:48 +00:00
2014-06-10 18:14:51 +00:00
if ( $b [ 'deleted' ] || ( $b [ 'created' ] !== $b [ 'edited' ]))
2014-06-07 08:27:48 +00:00
return ;
$token = get_pconfig ( $b [ 'uid' ], 'appnet' , 'token' );
if ( $token ) {
2014-06-10 18:14:51 +00:00
// If it's a repeated message from app.net then do a native repost and exit
if ( appnet_is_repost ( $a , $b [ 'uid' ], $b [ 'body' ]))
return ;
2014-06-07 08:27:48 +00:00
require_once 'addon/appnet/AppDotNet.php' ;
2014-06-10 18:14:51 +00:00
$clientId = get_pconfig ( $b [ " uid " ], 'appnet' , 'clientid' );
$clientSecret = get_pconfig ( $b [ " uid " ], 'appnet' , 'clientsecret' );
2014-06-07 08:27:48 +00:00
$app = new AppDotNet ( $clientId , $clientSecret );
$app -> setAccessToken ( $token );
$data = array ();
require_once ( " include/plaintext.php " );
require_once ( " include/network.php " );
$post = plaintext ( $a , $b , 256 , false );
logger ( " appnet_send: converted message " . $b [ " id " ] . " result: " . print_r ( $post , true ), LOGGER_DEBUG );
if ( isset ( $post [ " image " ])) {
$img_str = fetch_url ( $post [ 'image' ], true , $redirects , 10 );
$tempfile = tempnam ( get_config ( " system " , " temppath " ), " cache " );
file_put_contents ( $tempfile , $img_str );
try {
$photoFile = $app -> createFile ( $tempfile , array ( type => " com.github.jdolitsky.appdotnetphp.photo " ));
$data [ " annotations " ][] = array (
" type " => " net.app.core.oembed " ,
" value " => array (
" +net.app.core.file " => array (
" file_id " => $photoFile [ " id " ],
" file_token " => $photoFile [ " file_token " ],
" format " => " oembed " )
)
);
}
catch ( AppDotNetException $e ) {
logger ( " appnet_send: Error creating file " );
}
unlink ( $tempfile );
}
2014-06-10 18:14:51 +00:00
// Adding a link to the original post, if it is a root post
if ( $b [ 'parent' ] == $b [ 'id' ])
$data [ " annotations " ][] = array (
" type " => " net.app.core.crosspost " ,
" value " => array ( " canonical_url " => $b [ " plink " ])
);
// Adding the original post
$data [ " annotations " ][] = array (
" type " => " com.friendica.post " ,
" value " => array (
" uri " => $b [ " uri " ],
" title " => $b [ " title " ],
" body " => substr ( $b [ " body " ], 0 , 4000 ), // To-Do: Better shortening
" tag " => $b [ " tag " ],
" author-name " => $b [ " author-name " ],
" author-link " => $b [ " author-link " ],
" author-avatar " => $b [ " author-avatar " ],
)
);
2014-06-07 08:27:48 +00:00
// To-Do
// Alle Links verkürzen
if ( isset ( $post [ " url " ]) AND ! isset ( $post [ " title " ])) {
$display_url = str_replace ( array ( " http://www. " , " https://www. " ), array ( " " , " " ), $post [ " url " ]);
$display_url = str_replace ( array ( " http:// " , " https:// " ), array ( " " , " " ), $display_url );
if ( strlen ( $display_url ) > 26 )
$display_url = substr ( $display_url , 0 , 25 ) . " … " ;
$post [ " title " ] = $display_url ;
}
if ( isset ( $post [ " url " ]) AND isset ( $post [ " title " ])) {
$post [ " title " ] = shortenmsg ( $post [ " title " ], 90 );
$post [ " text " ] = shortenmsg ( $post [ " text " ], 256 - strlen ( $post [ " title " ]));
$post [ " text " ] .= " \n [ " . $post [ " title " ] . " ]( " . $post [ " url " ] . " ) " ;
} elseif ( isset ( $post [ " url " ])) {
$post [ " url " ] = short_link ( $post [ " url " ]);
$post [ " text " ] = shortenmsg ( $post [ " text " ], 240 );
$post [ " text " ] .= " " . $post [ " url " ];
}
//print_r($post);
$data [ " entities " ][ " parse_links " ] = true ;
2014-06-10 18:14:51 +00:00
$data [ " entities " ][ " parse_markdown_links " ] = true ;
if ( $iscomment )
$data [ " reply_to " ] = substr ( $orig_post [ " uri " ], 5 );
2014-06-07 08:27:48 +00:00
try {
$ret = $app -> createPost ( $post [ " text " ], $data );
logger ( " appnet_send: send message " . $b [ " id " ] . " result: " . print_r ( $ret , true ), LOGGER_DEBUG );
2014-06-10 18:14:51 +00:00
if ( $iscomment ) {
logger ( 'appnet_send: Update extid ' . $ret [ " id " ] . " for post id " . $b [ 'id' ]);
q ( " UPDATE `item` SET `extid` = '%s' WHERE `id` = %d " ,
dbesc ( " adn:: " . $ret [ " id " ]),
intval ( $b [ 'id' ])
);
}
2014-06-07 08:27:48 +00:00
}
catch ( AppDotNetException $e ) {
logger ( " appnet_send: Error sending message " . $b [ " id " ]);
}
}
}
2014-06-10 18:14:51 +00:00
function appnet_action ( $a , $uid , $pid , $action ) {
require_once 'addon/appnet/AppDotNet.php' ;
$token = get_pconfig ( $uid , 'appnet' , 'token' );
$clientId = get_pconfig ( $uid , 'appnet' , 'clientid' );
$clientSecret = get_pconfig ( $uid , 'appnet' , 'clientsecret' );
$app = new AppDotNet ( $clientId , $clientSecret );
$app -> setAccessToken ( $token );
logger ( " appnet_action ' " . $action . " ' ID: " . $pid , LOGGER_DATA );
try {
switch ( $action ) {
case " delete " :
$result = $app -> deletePost ( $pid );
break ;
case " like " :
$result = $app -> starPost ( $pid );
break ;
case " unlike " :
$result = $app -> unstarPost ( $pid );
break ;
}
logger ( " appnet_action ' " . $action . " ' send, result: " . print_r ( $result , true ), LOGGER_DEBUG );
}
catch ( AppDotNetException $e ) {
logger ( " appnet_action: Error sending action " . $action . " pid " . $pid , LOGGER_DEBUG );
}
}
function appnet_is_repost ( $a , $uid , $body ) {
$body = trim ( $body );
// Skip if it isn't a pure repeated messages
// Does it start with a share?
if ( strpos ( $body , " [share " ) > 0 )
return ( false );
// Does it end with a share?
if ( strlen ( $body ) > ( strrpos ( $body , " [/share] " ) + 8 ))
return ( false );
$attributes = preg_replace ( " / \ [share(.*?) \ ] \ s?(.*?) \ s? \ [ \ /share \ ] \ s?/ism " , " $ 1 " , $body );
// Skip if there is no shared message in there
if ( $body == $attributes )
return ( false );
$link = " " ;
preg_match ( " /link='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$link = $matches [ 1 ];
preg_match ( '/link="(.*?)"/ism' , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$link = $matches [ 1 ];
$id = preg_replace ( " =https?://alpha.app.net/(.*)/post/(.*)=ism " , " $ 2 " , $link );
if ( $id == $link )
return ( false );
logger ( 'appnet_is_repost: Reposting id ' . $id . ' for user ' . $uid , LOGGER_DEBUG );
require_once 'addon/appnet/AppDotNet.php' ;
$token = get_pconfig ( $uid , 'appnet' , 'token' );
$clientId = get_pconfig ( $uid , 'appnet' , 'clientid' );
$clientSecret = get_pconfig ( $uid , 'appnet' , 'clientsecret' );
$app = new AppDotNet ( $clientId , $clientSecret );
$app -> setAccessToken ( $token );
try {
$result = $app -> repost ( $id );
logger ( 'appnet_is_repost: result ' . print_r ( $result , true ), LOGGER_DEBUG );
return true ;
}
catch ( AppDotNetException $e ) {
logger ( 'appnet_is_repost: error doing repost' , LOGGER_DEBUG );
return false ;
}
}
function appnet_fetchstream ( $a , $uid ) {
require_once ( " addon/appnet/AppDotNet.php " );
require_once ( 'include/items.php' );
$token = get_pconfig ( $uid , 'appnet' , 'token' );
$clientId = get_pconfig ( $uid , 'appnet' , 'clientid' );
$clientSecret = get_pconfig ( $uid , 'appnet' , 'clientsecret' );
$app = new AppDotNet ( $clientId , $clientSecret );
$app -> setAccessToken ( $token );
$r = q ( " SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1 " ,
intval ( $uid ));
if ( count ( $r ))
$me = $r [ 0 ];
else {
logger ( " appnet_fetchstream: Own contact not found for user " . $uid , LOGGER_DEBUG );
return ;
}
$user = q ( " SELECT * FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1 " ,
intval ( $uid )
);
if ( count ( $user ))
$user = $user [ 0 ];
else {
logger ( " appnet_fetchstream: Own user not found for user " . $uid , LOGGER_DEBUG );
return ;
}
$ownid = get_pconfig ( $uid , 'appnet' , 'ownid' );
// Fetch stream
$param = array ( " count " => 200 , " include_deleted " => false , " include_directed_posts " => true ,
" include_html " => false , " include_post_annotations " => true );
$lastid = get_pconfig ( $uid , 'appnet' , 'laststreamid' );
if ( $lastid <> " " )
$param [ " since_id " ] = $lastid ;
try {
$stream = $app -> getUserStream ( $param );
}
catch ( AppDotNetException $e ) {
logger ( " appnet_fetchstream: Error fetching stream for user " . $uid );
}
$stream = array_reverse ( $stream );
foreach ( $stream AS $post ) {
$postarray = appnet_createpost ( $a , $uid , $post , $me , $user , $ownid , true );
$item = item_store ( $postarray );
logger ( 'appnet_fetchstream: User ' . $uid . ' posted stream item ' . $item );
$lastid = $post [ " id " ];
if (( $item != 0 ) AND ( $postarray [ 'contact-id' ] != $me [ " id " ])) {
$r = q ( " SELECT `thread`.`iid` AS `parent` FROM `thread`
INNER JOIN `item` ON `thread` . `iid` = `item` . `parent` AND `thread` . `uid` = `item` . `uid`
WHERE `item` . `id` = % d AND `thread` . `mention` LIMIT 1 " , dbesc( $item ));
if ( count ( $r )) {
require_once ( 'include/enotify.php' );
notification ( array (
'type' => NOTIFY_COMMENT ,
'notify_flags' => $user [ 'notify-flags' ],
'language' => $user [ 'language' ],
'to_name' => $user [ 'username' ],
'to_email' => $user [ 'email' ],
'uid' => $user [ 'uid' ],
'item' => $postarray ,
'link' => $a -> get_baseurl () . '/display/' . $user [ 'nickname' ] . '/' . $item ,
'source_name' => $postarray [ 'author-name' ],
'source_link' => $postarray [ 'author-link' ],
'source_photo' => $postarray [ 'author-avatar' ],
'verb' => ACTIVITY_POST ,
'otype' => 'item' ,
'parent' => $r [ 0 ][ " parent " ],
));
}
}
}
set_pconfig ( $uid , 'appnet' , 'laststreamid' , $lastid );
// Fetch mentions
$param = array ( " count " => 200 , " include_deleted " => false , " include_directed_posts " => true ,
" include_html " => false , " include_post_annotations " => true );
$lastid = get_pconfig ( $uid , 'appnet' , 'lastmentionid' );
if ( $lastid <> " " )
$param [ " since_id " ] = $lastid ;
try {
$mentions = $app -> getUserMentions ( " me " , $param );
}
catch ( AppDotNetException $e ) {
logger ( " appnet_fetchstream: Error fetching mentions for user " . $uid );
}
$mentions = array_reverse ( $mentions );
foreach ( $mentions AS $post ) {
$postarray = appnet_createpost ( $a , $uid , $post , $me , $user , $ownid , false );
if ( isset ( $postarray [ " id " ]))
$item = $postarray [ " id " ];
elseif ( isset ( $postarray [ " body " ])) {
$item = item_store ( $postarray );
logger ( 'appnet_fetchstream: User ' . $uid . ' posted mention item ' . $item );
} else
$item = 0 ;
$lastid = $post [ " id " ];
if (( $item != 0 ) AND ( $postarray [ 'contact-id' ] != $me [ " id " ])) {
require_once ( 'include/enotify.php' );
notification ( array (
'type' => NOTIFY_TAGSELF ,
'notify_flags' => $user [ 'notify-flags' ],
'language' => $user [ 'language' ],
'to_name' => $user [ 'username' ],
'to_email' => $user [ 'email' ],
'uid' => $user [ 'uid' ],
'item' => $postarray ,
'link' => $a -> get_baseurl () . '/display/' . $user [ 'nickname' ] . '/' . $item ,
'source_name' => $postarray [ 'author-name' ],
'source_link' => $postarray [ 'author-link' ],
'source_photo' => $postarray [ 'author-avatar' ],
'verb' => ACTIVITY_TAG ,
'otype' => 'item'
));
}
}
set_pconfig ( $uid , 'appnet' , 'lastmentionid' , $lastid );
/* To - Do
$param = array ( " interaction_actions " => " star " );
$interactions = $app -> getMyInteractions ( $param );
foreach ( $interactions AS $interaction )
appnet_dolike ( $a , $uid , $interaction );
*/
}
function appnet_createpost ( $a , $uid , $post , $me , $user , $ownid , $createuser , $threadcompletion = true ) {
require_once ( 'include/items.php' );
if ( $post [ " machine_only " ])
return ;
if ( $post [ " is_deleted " ])
return ;
$postarray = array ();
$postarray [ 'gravity' ] = 0 ;
$postarray [ 'uid' ] = $uid ;
$postarray [ 'wall' ] = 0 ;
$postarray [ 'verb' ] = ACTIVITY_POST ;
$postarray [ 'network' ] = dbesc ( NETWORK_APPNET );
$postarray [ 'uri' ] = " adn:: " . $post [ " id " ];
$r = q ( " SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1 " ,
dbesc ( $postarray [ 'uri' ]),
intval ( $uid )
);
if ( count ( $r ))
return ( $r [ 0 ]);
$r = q ( " SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1 " ,
dbesc ( $postarray [ 'uri' ]),
intval ( $uid )
);
if ( count ( $r ))
return ( $r [ 0 ]);
$postarray [ 'parent-uri' ] = " adn:: " . $post [ " thread_id " ];
if ( isset ( $post [ " reply_to " ]) AND ( $post [ " reply_to " ] != " " )) {
$postarray [ 'thr-parent' ] = " adn:: " . $post [ " reply_to " ];
// Complete the thread if the parent doesn't exists
if ( $threadcompletion ) {
$r = q ( " SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1 " ,
dbesc ( $postarray [ 'thr-parent' ]),
intval ( $uid )
);
if ( ! count ( $r )) {
require_once ( " addon/appnet/AppDotNet.php " );
$token = get_pconfig ( $uid , 'appnet' , 'token' );
$clientId = get_pconfig ( $uid , 'appnet' , 'clientid' );
$clientSecret = get_pconfig ( $uid , 'appnet' , 'clientsecret' );
$app = new AppDotNet ( $clientId , $clientSecret );
$app -> setAccessToken ( $token );
$param = array ( " count " => 200 , " include_deleted " => false , " include_directed_posts " => true ,
" include_html " => false , " include_post_annotations " => true );
try {
$thread = $app -> getPostReplies ( $post [ " thread_id " ], $param );
}
catch ( AppDotNetException $e ) {
logger ( " appnet_createpost: Error fetching thread for user " . $uid );
}
$thread = array_reverse ( $thread );
foreach ( $thread AS $tpost ) {
$threadpost = appnet_createpost ( $a , $uid , $tpost , $me , $user , $ownid , $createuser , false );
$item = item_store ( $threadpost );
}
}
}
} else
$postarray [ 'thr-parent' ] = $postarray [ 'uri' ];
$postarray [ 'plink' ] = $post [ " canonical_url " ];
if (( $post [ " user " ][ " id " ] != $ownid ) OR ( $postarray [ 'thr-parent' ] == $postarray [ 'uri' ])) {
$postarray [ 'owner-name' ] = $post [ " user " ][ " name " ];
$postarray [ 'owner-link' ] = $post [ " user " ][ " canonical_url " ];
$postarray [ 'owner-avatar' ] = $post [ " user " ][ " avatar_image " ][ " url " ];
$postarray [ 'contact-id' ] = appnet_fetchcontact ( $a , $uid , $post [ " user " ], $me , $createuser );
} else {
$postarray [ 'owner-name' ] = $me [ " name " ];
$postarray [ 'owner-link' ] = $me [ " url " ];
$postarray [ 'owner-avatar' ] = $me [ " thumb " ];
$postarray [ 'contact-id' ] = $me [ " id " ];
}
$links = array ();
if ( is_array ( $post [ " repost_of " ])) {
$postarray [ 'author-name' ] = $post [ " repost_of " ][ " user " ][ " name " ];
$postarray [ 'author-link' ] = $post [ " repost_of " ][ " user " ][ " canonical_url " ];
$postarray [ 'author-avatar' ] = $post [ " repost_of " ][ " user " ][ " avatar_image " ][ " url " ];
$content = $post [ " repost_of " ];
} else {
$postarray [ 'author-name' ] = $postarray [ 'owner-name' ];
$postarray [ 'author-link' ] = $postarray [ 'owner-link' ];
$postarray [ 'author-avatar' ] = $postarray [ 'owner-avatar' ];
$content = $post ;
}
if ( is_array ( $content [ " entities " ])) {
$converted = appnet_expand_entities ( $a , $content [ " text " ], $content [ " entities " ]);
$postarray [ 'body' ] = $converted [ " body " ];
$postarray [ 'tag' ] = $converted [ " tags " ];
} else
$postarray [ 'body' ] = $content [ " text " ];
if ( is_array ( $content [ " annotations " ]))
$postarray [ 'body' ] = appnet_expand_annotations ( $a , $postarray [ 'body' ], $content [ " annotations " ]);
if ( sizeof ( $content [ " entities " ][ " links " ]))
foreach ( $content [ " entities " ][ " links " ] AS $link ) {
$url = normalise_link ( $link [ " url " ]);
$links [ $url ] = $link [ " url " ];
}
if ( sizeof ( $content [ " annotations " ]))
foreach ( $content [ " annotations " ] AS $annotation ) {
if ( $annotation [ type ] == " net.app.core.oembed " ) {
if ( isset ( $annotation [ " value " ][ " embeddable_url " ])) {
$url = normalise_link ( $annotation [ " value " ][ " embeddable_url " ]);
if ( isset ( $links [ $url ]))
unset ( $links [ $url ]);
}
} elseif ( $annotation [ type ] == " com.friendica.post " ) {
$links = array ();
if ( isset ( $annotation [ " value " ][ " embeddable_url " ]))
$postarray [ 'title' ] = $annotation [ " value " ][ " title " ];
if ( isset ( $annotation [ " value " ][ " body " ]))
$postarray [ 'body' ] = $annotation [ " value " ][ " body " ];
if ( isset ( $annotation [ " value " ][ " tag " ]))
$postarray [ 'tag' ] = $annotation [ " value " ][ " tag " ];
if ( isset ( $annotation [ " value " ][ " author-name " ]))
$postarray [ 'author-name' ] = $annotation [ " value " ][ " author-name " ];
if ( isset ( $annotation [ " value " ][ " author-link " ]))
$postarray [ 'author-link' ] = $annotation [ " value " ][ " author-link " ];
if ( isset ( $annotation [ " value " ][ " author-avatar " ]))
$postarray [ 'author-avatar' ] = $annotation [ " value " ][ " author-avatar " ];
}
}
if ( sizeof ( $links )) {
$link = array_pop ( $links );
$url = " [url= " . $link . " ] " . $link . " [/url] " ;
$removedlink = trim ( str_replace ( $url , " " , $postarray [ 'body' ]));
if (( $removedlink == " " ) OR strstr ( $postarray [ 'body' ], $removedlink ))
$postarray [ 'body' ] = $removedlink ;
$postarray [ 'body' ] .= add_page_info ( $link );
}
$postarray [ 'created' ] = datetime_convert ( 'UTC' , 'UTC' , $post [ " created_at " ]);
$postarray [ 'edited' ] = datetime_convert ( 'UTC' , 'UTC' , $post [ " created_at " ]);
$postarray [ 'app' ] = $post [ " source " ][ " name " ];
return ( $postarray );
//print_r($postarray);
//print_r($post);
}
function appnet_expand_entities ( $a , $body , $entities ) {
if ( ! function_exists ( 'substr_unicode' )) {
function substr_unicode ( $str , $s , $l = null ) {
return join ( " " , array_slice (
preg_split ( " //u " , $str , - 1 , PREG_SPLIT_NO_EMPTY ), $s , $l ));
}
}
$tags_arr = array ();
$replace = array ();
foreach ( $entities [ " mentions " ] AS $mention ) {
$url = " @[url=https://alpha.app.net/ " . rawurlencode ( $mention [ " name " ]) . " ] " . $mention [ " name " ] . " [/url] " ;
$tags_arr [ " @ " . $mention [ " name " ]] = $url ;
$replace [ $mention [ " pos " ]] = array ( " pos " => $mention [ " pos " ], " len " => $mention [ " len " ], " replace " => $url );
}
foreach ( $entities [ " hashtags " ] AS $hashtag ) {
$url = " #[url= " . $a -> get_baseurl () . " /search?tag= " . rawurlencode ( $hashtag [ " name " ]) . " ] " . $hashtag [ " name " ] . " [/url] " ;
$tags_arr [ " # " . $hashtag [ " name " ]] = $url ;
$replace [ $hashtag [ " pos " ]] = array ( " pos " => $hashtag [ " pos " ], " len " => $hashtag [ " len " ], " replace " => $url );
}
foreach ( $entities [ " links " ] AS $links ) {
$url = " [url= " . $links [ " url " ] . " ] " . $links [ " text " ] . " [/url] " ;
$replace [ $links [ " pos " ]] = array ( " pos " => $links [ " pos " ], " len " => $links [ " len " ], " replace " => $url );
}
if ( sizeof ( $replace )) {
krsort ( $replace );
foreach ( $replace AS $entity ) {
$pre = substr_unicode ( $body , 0 , $entity [ " pos " ]);
$post = substr_unicode ( $body , $entity [ " pos " ] + $entity [ " len " ]);
$body = $pre . $entity [ " replace " ] . $post ;
}
}
return ( array ( " body " => $body , " tags " => implode ( $tags_arr , " , " )));
}
function appnet_expand_annotations ( $a , $body , $annotations ) {
foreach ( $annotations AS $annotation ) {
if ( $annotation [ " value " ][ " type " ] == " photo " ) {
if (( $annotation [ " value " ][ " thumbnail_large_url " ] != " " ) AND ( $annotation [ " value " ][ " url " ] != " " ))
$body .= " \n [url= " . $annotation [ " value " ][ " url " ] . " ][img] " . $annotation [ " value " ][ " thumbnail_large_url " ] . " [/img][/url] " ;
elseif ( $annotation [ " value " ][ " url " ] != " " )
$body .= " \n [img] " . $annotation [ " value " ][ " url " ] . " [/img] " ;
}
}
return $body ;
}
function appnet_fetchcontact ( $a , $uid , $contact , $me , $create_user ) {
$r = q ( " SELECT * FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1 " ,
intval ( $uid ), dbesc ( " adn:: " . $contact [ " id " ]));
if ( ! count ( $r ) AND ! $create_user )
return ( $me );
if ( count ( $r ) AND ( $r [ 0 ][ " readonly " ] OR $r [ 0 ][ " blocked " ])) {
logger ( " appnet_fetchcontact: Contact ' " . $r [ 0 ][ " nick " ] . " ' is blocked or readonly. " , LOGGER_DEBUG );
return ( - 1 );
}
if ( ! count ( $r )) {
// create contact record
q ( " INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,
`name` , `nick` , `photo` , `network` , `rel` , `priority` ,
`writable` , `blocked` , `readonly` , `pending` )
VALUES ( % d , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , '%s' , % d , % d , % d , 0 , 0 , 0 ) " ,
intval ( $uid ),
dbesc ( datetime_convert ()),
dbesc ( $contact [ " canonical_url " ]),
dbesc ( normalise_link ( $contact [ " canonical_url " ])),
dbesc ( $contact [ " username " ] . " @app.net " ),
dbesc ( " adn:: " . $contact [ " id " ]),
dbesc ( '' ),
dbesc ( " adn:: " . $contact [ " id " ]),
dbesc ( $contact [ " name " ]),
dbesc ( $contact [ " username " ]),
dbesc ( $contact [ " avatar_image " ][ " url " ]),
dbesc ( NETWORK_APPNET ),
intval ( CONTACT_IS_FRIEND ),
intval ( 1 ),
intval ( 1 )
);
$r = q ( " SELECT * FROM `contact` WHERE `alias` = '%s' AND `uid` = %d LIMIT 1 " ,
dbesc ( " adn:: " . $contact [ " id " ]),
intval ( $uid )
);
if ( ! count ( $r ))
return ( false );
$contact_id = $r [ 0 ][ 'id' ];
$g = q ( " SELECT def_gid FROM user WHERE uid = %d LIMIT 1 " ,
intval ( $uid )
);
if ( $g && intval ( $g [ 0 ][ 'def_gid' ])) {
require_once ( 'include/group.php' );
group_add_member ( $uid , '' , $contact_id , $g [ 0 ][ 'def_gid' ]);
}
require_once ( " Photo.php " );
$photos = import_profile_photo ( $contact [ " avatar_image " ][ " url " ], $uid , $contact_id );
q ( " UPDATE `contact` SET `photo` = '%s',
`thumb` = '%s' ,
`micro` = '%s' ,
`name-date` = '%s' ,
`uri-date` = '%s' ,
`avatar-date` = '%s'
WHERE `id` = % d " ,
dbesc ( $photos [ 0 ]),
dbesc ( $photos [ 1 ]),
dbesc ( $photos [ 2 ]),
dbesc ( datetime_convert ()),
dbesc ( datetime_convert ()),
dbesc ( datetime_convert ()),
intval ( $contact_id )
);
} else {
// update profile photos once every two weeks as we have no notification of when they change.
//$update_photo = (($r[0]['avatar-date'] < datetime_convert('','','now -2 days')) ? true : false);
$update_photo = ( $r [ 0 ][ 'avatar-date' ] < datetime_convert ( '' , '' , 'now -12 hours' ));
$update_photo = true ;
// check that we have all the photos, this has been known to fail on occasion
if (( ! $r [ 0 ][ 'photo' ]) || ( ! $r [ 0 ][ 'thumb' ]) || ( ! $r [ 0 ][ 'micro' ]) || ( $update_photo )) {
logger ( " appnet_fetchcontact: Updating contact " . $contact [ " username " ], LOGGER_DEBUG );
require_once ( " Photo.php " );
$photos = import_profile_photo ( $contact [ " avatar_image " ][ " url " ], $uid , $r [ 0 ][ 'id' ]);
q ( " UPDATE `contact` SET `photo` = '%s',
`thumb` = '%s' ,
`micro` = '%s' ,
`name-date` = '%s' ,
`uri-date` = '%s' ,
`avatar-date` = '%s' ,
`url` = '%s' ,
`nurl` = '%s' ,
`addr` = '%s' ,
`name` = '%s' ,
`nick` = '%s'
WHERE `id` = % d " ,
dbesc ( $photos [ 0 ]),
dbesc ( $photos [ 1 ]),
dbesc ( $photos [ 2 ]),
dbesc ( datetime_convert ()),
dbesc ( datetime_convert ()),
dbesc ( datetime_convert ()),
dbesc ( $contact [ " canonical_url " ]),
dbesc ( normalise_link ( $contact [ " canonical_url " ])),
dbesc ( $contact [ " username " ] . " @app.net " ),
dbesc ( $contact [ " name " ]),
dbesc ( $contact [ " username " ]),
intval ( $r [ 0 ][ 'id' ])
);
}
}
return ( $r [ 0 ][ " id " ]);
}
function appnet_cron ( $a , $b ) {
$last = get_config ( 'appnet' , 'last_poll' );
$poll_interval = intval ( get_config ( 'appnet' , 'poll_interval' ));
if ( ! $poll_interval )
$poll_interval = APPNET_DEFAULT_POLL_INTERVAL ;
if ( $last ) {
$next = $last + ( $poll_interval * 60 );
if ( $next > time ()) {
logger ( 'appnet_cron: poll intervall not reached' );
return ;
}
}
logger ( 'appnet_cron: cron_start' );
$r = q ( " SELECT * FROM `pconfig` WHERE `cat` = 'appnet' AND `k` = 'import' AND `v` = '1' ORDER BY RAND() " );
if ( count ( $r )) {
foreach ( $r as $rr ) {
logger ( 'appnet_cron: importing timeline from user ' . $rr [ 'uid' ]);
appnet_fetchstream ( $a , $rr [ " uid " ]);
}
}
logger ( 'appnet_cron: cron_end' );
set_config ( 'appnet' , 'last_poll' , time ());
}