forked from GNUsocial/gnu-social
Merge branch '0.9.x' into pluginize-twitter-bridge
* 0.9.x: (247 commits) Added in credits. Use site's name for basic auth realm Make apigroupcreate.php pass phpcs Took out some unnecessary intializations Implemented create group api CamelCase all function names in the API code These same params are used in most API actions; moved to base API class Missed some of the references to the old TwitterApiAction - removed Remove more redundant $formats Remove dead code Move all basic auth output and processing to base classes $format is used by every API action. Set it in the base class. Delete action/api.php and rename lib/twitterapi.php to lib/api.php New actions for blocks via API fix FBConnect so it doesn't muffle EndPrimaryNav don't write session if it's unchanged Fixed facebook connect primary nav to hide search option when site is private and user is not logged in Fixed facebook connect primary nav to obey sms/twitter/openid settings Fixed facebook connect login nav to obey openid settings Fixed facebook connect nav to obey sms/twitter disabled ...
This commit is contained in:
@@ -1,38 +1,37 @@
|
||||
$(document).ready(function(){
|
||||
$.getJSON($('address .url')[0].href+'/api/statuses/friends.json?user_id=' + current_user['id'] + '&lite=true&callback=?',
|
||||
function(friends){
|
||||
$('#notice_data-text').autocomplete(friends, {
|
||||
$('#notice_data-text').autocomplete($('address .url')[0].href+'/plugins/Autocomplete/autocomplete.json', {
|
||||
multiple: true,
|
||||
multipleSeparator: " ",
|
||||
minChars: 1,
|
||||
formatItem: function(row, i, max){
|
||||
return '@' + row.screen_name + ' (' + row.name + ')';
|
||||
row = eval("(" + row + ")");
|
||||
switch(row.type)
|
||||
{
|
||||
case 'user':
|
||||
return row.nickname + ' (' + row.fullname + ')';
|
||||
case 'group':
|
||||
return row.nickname + ' (' + row.fullname + ')';
|
||||
}
|
||||
},
|
||||
formatMatch: function(row, i, max){
|
||||
return '@' + row.screen_name;
|
||||
row = eval("(" + row + ")");
|
||||
switch(row.type)
|
||||
{
|
||||
case 'user':
|
||||
return row.nickname;
|
||||
case 'group':
|
||||
return row.nickname;
|
||||
}
|
||||
},
|
||||
formatResult: function(row){
|
||||
return '@' + row.screen_name;
|
||||
row = eval("(" + row + ")");
|
||||
switch(row.type)
|
||||
{
|
||||
case 'user':
|
||||
return '@' + row.nickname;
|
||||
case 'group':
|
||||
return '!' + row.nickname;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
$.getJSON($('address .url')[0].href+'/api/statusnet/groups/list.json?user_id=' + current_user['id'] + '&callback=?',
|
||||
function(groups){
|
||||
$('#notice_data-text').autocomplete(groups, {
|
||||
multiple: true,
|
||||
multipleSeparator: " ",
|
||||
minChars: 1,
|
||||
formatItem: function(row, i, max){
|
||||
return '!' + row.nickname + ' (' + row.fullname + ')';
|
||||
},
|
||||
formatMatch: function(row, i, max){
|
||||
return '!' + row.nickname;
|
||||
},
|
||||
formatResult: function(row){
|
||||
return '!' + row.nickname;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -31,6 +31,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once(INSTALLDIR.'/plugins/Autocomplete/autocomplete.php');
|
||||
|
||||
class AutocompletePlugin extends Plugin
|
||||
{
|
||||
function __construct()
|
||||
@@ -40,13 +42,6 @@ class AutocompletePlugin extends Plugin
|
||||
|
||||
function onEndShowScripts($action){
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
$js_string = <<<EOT
|
||||
<script type="text/javascript">
|
||||
var current_user = { id: '$current_user->id' };
|
||||
</script>
|
||||
EOT;
|
||||
$action->raw($js_string);
|
||||
$action->script('plugins/Autocomplete/jquery-autocomplete/jquery.autocomplete.pack.js');
|
||||
$action->script('plugins/Autocomplete/Autocomplete.js');
|
||||
}
|
||||
@@ -59,5 +54,12 @@ EOT;
|
||||
}
|
||||
}
|
||||
|
||||
function onRouterInitialized($m)
|
||||
{
|
||||
if (common_logged_in()) {
|
||||
$m->connect('plugins/Autocomplete/autocomplete.json', array('action'=>'autocomplete'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
136
plugins/Autocomplete/autocomplete.php
Normal file
136
plugins/Autocomplete/autocomplete.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* List users for autocompletion
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Plugin
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2008-2009 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* List users for autocompletion
|
||||
*
|
||||
* This is the form for adding a new g
|
||||
*
|
||||
* @category Plugin
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class AutocompleteAction extends Action
|
||||
{
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* Last-modified date for page
|
||||
*
|
||||
* When was the content of this page last modified? Based on notice,
|
||||
* profile, avatar.
|
||||
*
|
||||
* @return int last-modified date as unix timestamp
|
||||
*/
|
||||
function lastModified()
|
||||
{
|
||||
$max=0;
|
||||
foreach($this->users as $user){
|
||||
$max = max($max,strtotime($user->modified),strtotime($user->profile->modified));
|
||||
}
|
||||
foreach($this->groups as $group){
|
||||
$max = max($max,strtotime($group->modified));
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this page
|
||||
*
|
||||
* Shows the ETag for the page, based on the notice ID and timestamps
|
||||
* for the notice, profile, and avatar. It's weak, since we change
|
||||
* the date text "one hour ago", etc.
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
function etag()
|
||||
{
|
||||
return '"' . implode(':', array($this->arg('action'),
|
||||
crc32($this->arg('q')), //the actual string can have funny characters in we don't want showing up in the etag
|
||||
$this->arg('limit'),
|
||||
$this->lastModified())) . '"';
|
||||
}
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->groups=array();
|
||||
$this->users=array();
|
||||
$q = $this->arg('q');
|
||||
$limit = $this->arg('limit');
|
||||
if($limit > 200) $limit=200; //prevent DOS attacks
|
||||
if(substr($q,0,1)=='@'){
|
||||
//user search
|
||||
$q=substr($q,1);
|
||||
$user = new User();
|
||||
$user->limit($limit);
|
||||
$user->whereAdd('nickname like \'' . trim($user->escape($q), '\'') . '%\'');
|
||||
$user->find();
|
||||
while($user->fetch()) {
|
||||
$profile = Profile::staticGet($user->id);
|
||||
$user->profile=$profile;
|
||||
$this->users[]=$user;
|
||||
}
|
||||
}
|
||||
if(substr($q,0,1)=='!'){
|
||||
//group search
|
||||
$q=substr($q,1);
|
||||
$group = new User_group();
|
||||
$group->limit($limit);
|
||||
$group->whereAdd('nickname like \'' . trim($group->escape($q), '\'') . '%\'');
|
||||
$group->find();
|
||||
while($group->fetch()) {
|
||||
$this->groups[]=$group;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$results = array();
|
||||
foreach($this->users as $user){
|
||||
$results[]=array('nickname' => $user->nickname, 'fullname'=> $user->profile->fullname, 'type'=>'user');
|
||||
}
|
||||
foreach($this->groups as $group){
|
||||
$results[]=array('nickname' => $group->nickname, 'fullname'=> $group->fullname, 'type'=>'group');
|
||||
}
|
||||
foreach($results as $result) {
|
||||
print json_encode($result) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
Autocomplete allows users to autocomplete screen names in @ replies. When an "@" is typed into the notice text area, an autocomplete box is displayed populated with the user's friends' screen names.
|
||||
|
||||
Note: This plugin doesn't work if the site is in Private mode, i.e. when $config['site']['private'] is set to true.
|
||||
|
||||
Installation
|
||||
============
|
||||
Add "addPlugin('Autocomplete');" to the bottom of your config.php
|
||||
|
||||
@@ -78,16 +78,20 @@ class FBCLoginGroupNav extends Widget
|
||||
// action => array('prompt', 'title')
|
||||
$menu = array();
|
||||
|
||||
$menu['login'] = array(_('Login'),
|
||||
_('Login with a username and password'));
|
||||
if (!common_config('site','openidonly')) {
|
||||
$menu['login'] = array(_('Login'),
|
||||
_('Login with a username and password'));
|
||||
|
||||
if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||
$menu['register'] = array(_('Register'),
|
||||
_('Sign up for a new account'));
|
||||
if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||
$menu['register'] = array(_('Register'),
|
||||
_('Sign up for a new account'));
|
||||
}
|
||||
}
|
||||
|
||||
$menu['openidlogin'] = array(_('OpenID'),
|
||||
_('Login or register with OpenID'));
|
||||
if (common_config('openid', 'enabled')) {
|
||||
$menu['openidlogin'] = array(_('OpenID'),
|
||||
_('Login or register with OpenID'));
|
||||
}
|
||||
|
||||
$menu['FBConnectLogin'] = array(_('Facebook'),
|
||||
_('Login or register using Facebook'));
|
||||
|
||||
@@ -77,32 +77,34 @@ class FBCSettingsNav extends Widget
|
||||
$this->action->elementStart('dd');
|
||||
|
||||
# action => array('prompt', 'title')
|
||||
$menu =
|
||||
array('imsettings' =>
|
||||
array(_('IM'),
|
||||
_('Updates by instant messenger (IM)')),
|
||||
'smssettings' =>
|
||||
array(_('SMS'),
|
||||
_('Updates by SMS')),
|
||||
'twittersettings' =>
|
||||
array(_('Twitter'),
|
||||
_('Twitter integration options')),
|
||||
'FBConnectSettings' =>
|
||||
array(_('Facebook'),
|
||||
_('Facebook Connect settings')));
|
||||
$menu = array();
|
||||
if (common_config('xmpp', 'enabled')) {
|
||||
$menu['imsettings'] =
|
||||
array(_('IM'),
|
||||
_('Updates by instant messenger (IM)'));
|
||||
}
|
||||
if (common_config('sms', 'enabled')) {
|
||||
$menu['smssettings'] =
|
||||
array(_('SMS'),
|
||||
_('Updates by SMS'));
|
||||
}
|
||||
if (common_config('twitter', 'enabled')) {
|
||||
$menu['twittersettings'] =
|
||||
array(_('Twitter'),
|
||||
_('Twitter integration options'));
|
||||
}
|
||||
$menu['FBConnectSettings'] =
|
||||
array(_('Facebook'),
|
||||
_('Facebook Connect settings'));
|
||||
|
||||
$action_name = $this->action->trimmed('action');
|
||||
$this->action->elementStart('ul', array('class' => 'nav'));
|
||||
|
||||
foreach ($menu as $menuaction => $menudesc) {
|
||||
if ($menuaction == 'imsettings' &&
|
||||
!common_config('xmpp', 'enabled')) {
|
||||
continue;
|
||||
}
|
||||
$this->action->menuItem(common_local_url($menuaction),
|
||||
$menudesc[0],
|
||||
$menudesc[1],
|
||||
$action_name === $menuaction);
|
||||
$menudesc[0],
|
||||
$menudesc[1],
|
||||
$action_name === $menuaction);
|
||||
}
|
||||
|
||||
$this->action->elementEnd('ul');
|
||||
|
||||
@@ -232,6 +232,14 @@ class FBConnectPlugin extends Plugin
|
||||
{
|
||||
|
||||
$user = common_current_user();
|
||||
$connect = 'FBConnectSettings';
|
||||
if (common_config('xmpp', 'enabled')) {
|
||||
$connect = 'imsettings';
|
||||
} else if (common_config('sms', 'enabled')) {
|
||||
$connect = 'smssettings';
|
||||
} else if (common_config('twitter', 'enabled')) {
|
||||
$connect = 'twittersettings';
|
||||
}
|
||||
|
||||
if (!empty($user)) {
|
||||
|
||||
@@ -266,13 +274,8 @@ class FBConnectPlugin extends Plugin
|
||||
_('Home'), _('Personal profile and friends timeline'), false, 'nav_home');
|
||||
$action->menuItem(common_local_url('profilesettings'),
|
||||
_('Account'), _('Change your email, avatar, password, profile'), false, 'nav_account');
|
||||
if (common_config('xmpp', 'enabled')) {
|
||||
$action->menuItem(common_local_url('imsettings'),
|
||||
_('Connect'), _('Connect to IM, SMS, Twitter'), false, 'nav_connect');
|
||||
} else {
|
||||
$action->menuItem(common_local_url('smssettings'),
|
||||
_('Connect'), _('Connect to SMS, Twitter'), false, 'nav_connect');
|
||||
}
|
||||
$action->menuItem(common_local_url($connect),
|
||||
_('Connect'), _('Connect to services'), false, 'nav_connect');
|
||||
if (common_config('invite', 'enabled')) {
|
||||
$action->menuItem(common_local_url('invite'),
|
||||
_('Invite'),
|
||||
@@ -300,18 +303,30 @@ class FBConnectPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!common_config('site', 'closed')) {
|
||||
$action->menuItem(common_local_url('register'),
|
||||
_('Register'), _('Create an account'), false, 'nav_register');
|
||||
if (!common_config('site', 'openidonly')) {
|
||||
if (!common_config('site', 'closed')) {
|
||||
$action->menuItem(common_local_url('register'),
|
||||
_('Register'), _('Create an account'), false, 'nav_register');
|
||||
}
|
||||
$action->menuItem(common_local_url('login'),
|
||||
_('Login'), _('Login to the site'), false, 'nav_login');
|
||||
} else {
|
||||
$this->menuItem(common_local_url('openidlogin'),
|
||||
_('OpenID'), _('Login with OpenID'), false, 'nav_openid');
|
||||
}
|
||||
$action->menuItem(common_local_url('login'),
|
||||
_('Login'), _('Login to the site'), false, 'nav_login');
|
||||
}
|
||||
|
||||
$action->menuItem(common_local_url('doc', array('title' => 'help')),
|
||||
_('Help'), _('Help me!'), false, 'nav_help');
|
||||
$action->menuItem(common_local_url('peoplesearch'),
|
||||
_('Search'), _('Search for people or text'), false, 'nav_search');
|
||||
if ($user || !common_config('site', 'private')) {
|
||||
$action->menuItem(common_local_url('peoplesearch'),
|
||||
_('Search'), _('Search for people or text'), false, 'nav_search');
|
||||
}
|
||||
|
||||
// We are replacing the primary nav entirely; give other
|
||||
// plugins a chance to handle it here.
|
||||
|
||||
Event::handle('EndPrimaryNav', array($action));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class InfiniteScrollPlugin extends Plugin
|
||||
|
||||
function onEndShowScripts($action)
|
||||
{
|
||||
$action->script('plugins/InfiniteScroll/jquery.infinitescroll.min.js');
|
||||
$action->script('plugins/InfiniteScroll/jquery.infinitescroll.js');
|
||||
$action->script('plugins/InfiniteScroll/infinitescroll.js');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
jQuery(document).ready(function($){
|
||||
$('notices_primary').infinitescroll({
|
||||
debug: true,
|
||||
infiniteScroll : false,
|
||||
nextSelector : "li.nav_next a",
|
||||
loadingImg : $('address .url')[0].href+'plugins/InfiniteScroll/ajax-loader.gif',
|
||||
text : "<em>Loading the next set of posts...</em>",
|
||||
@@ -12,4 +13,3 @@ jQuery(document).ready(function($){
|
||||
NoticeAttachments();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -92,14 +92,14 @@
|
||||
|
||||
if (props.isDuringAjax || props.isInvalidPage || props.isDone) return;
|
||||
|
||||
if ( !isNearBottom(opts,props) ) return;
|
||||
if ( opts.infiniteScroll && !isNearBottom(opts,props) ) return;
|
||||
|
||||
// we dont want to fire the ajax multiple times
|
||||
props.isDuringAjax = true;
|
||||
|
||||
// show the loading message and hide the previous/next links
|
||||
props.loadingMsg.appendTo( opts.contentSelector ).show();
|
||||
$( opts.navSelector ).hide();
|
||||
if(opts.infiniteScroll) $( opts.navSelector ).hide();
|
||||
|
||||
// increment the URL bit. e.g. /page/3/
|
||||
props.currPage++;
|
||||
@@ -205,10 +205,19 @@
|
||||
}
|
||||
});
|
||||
|
||||
// bind scroll handler to element (if its a local scroll) or window
|
||||
$(opts.localMode ? this : window)
|
||||
.bind('scroll.infscr', function(){ infscrSetup(path,opts,props,callback); } )
|
||||
.trigger('scroll.infscr'); // trigger the event, in case it's a short page
|
||||
if(opts.infiniteScroll){
|
||||
// bind scroll handler to element (if its a local scroll) or window
|
||||
$(opts.localMode ? this : window)
|
||||
.bind('scroll.infscr', function(){ infscrSetup(path,opts,props,callback); } )
|
||||
.trigger('scroll.infscr'); // trigger the event, in case it's a short page
|
||||
}else{
|
||||
$(opts.nextSelector).click(
|
||||
function(){
|
||||
infscrSetup(path,opts,props,callback);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return this;
|
||||
@@ -222,6 +231,7 @@
|
||||
$.infinitescroll = {
|
||||
defaults : {
|
||||
debug : false,
|
||||
infiniteScroll : true,
|
||||
preload : false,
|
||||
nextSelector : "div.navigation a:first",
|
||||
loadingImg : "http://www.infinite-scroll.com/loading.gif",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// update the local timeline from a Meteor server
|
||||
//
|
||||
// Update the local timeline from a Meteor server
|
||||
// XXX: If @a is subscribed to @b, @a should get @b's notices in @a's Personal timeline.
|
||||
// Do Replies timeline.
|
||||
|
||||
var MeteorUpdater = function()
|
||||
{
|
||||
|
||||
@@ -222,4 +222,19 @@ class OpenIDPlugin extends Plugin
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function onCheckSchema() {
|
||||
$schema = Schema::get();
|
||||
$schema->ensureTable('user_openid',
|
||||
array(new ColumnDef('canonical', 'varchar',
|
||||
'255', false, 'PRI'),
|
||||
new ColumnDef('display', 'varchar',
|
||||
'255', false),
|
||||
new ColumnDef('user_id', 'integer',
|
||||
null, false, 'MUL'),
|
||||
new ColumnDef('created', 'datetime',
|
||||
null, false),
|
||||
new ColumnDef('modified', 'timestamp')));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
154
plugins/Orbited/OrbitedPlugin.php
Normal file
154
plugins/Orbited/OrbitedPlugin.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to do "real time" updates using Orbited + STOMP
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Plugin
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/plugins/Realtime/RealtimePlugin.php';
|
||||
|
||||
/**
|
||||
* Plugin to do realtime updates using Orbited + STOMP
|
||||
*
|
||||
* This plugin pushes data to a STOMP server which is then served to the
|
||||
* browser by the Orbited server.
|
||||
*
|
||||
* @category Plugin
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class OrbitedPlugin extends RealtimePlugin
|
||||
{
|
||||
public $webserver = null;
|
||||
public $webport = null;
|
||||
public $channelbase = null;
|
||||
public $stompserver = null;
|
||||
public $stompport = null;
|
||||
public $username = null;
|
||||
public $password = null;
|
||||
public $webuser = null;
|
||||
public $webpass = null;
|
||||
|
||||
protected $con = null;
|
||||
|
||||
function onStartShowHeadElements($action)
|
||||
{
|
||||
// See http://orbited.org/wiki/Deployment#Cross-SubdomainDeployment
|
||||
$action->element('script', null, ' document.domain = document.domain; ');
|
||||
}
|
||||
|
||||
function _getScripts()
|
||||
{
|
||||
$scripts = parent::_getScripts();
|
||||
|
||||
$port = (is_null($this->webport)) ? 8000 : $this->webport;
|
||||
|
||||
$server = (is_null($this->webserver)) ? common_config('site', 'server') : $this->webserver;
|
||||
|
||||
$root = 'http://'.$server.(($port == 80) ? '':':'.$port);
|
||||
|
||||
$scripts[] = $root.'/static/Orbited.js';
|
||||
$scripts[] = common_path('plugins/Orbited/orbitedextra.js');
|
||||
$scripts[] = $root.'/static/protocols/stomp/stomp.js';
|
||||
$scripts[] = common_path('plugins/Orbited/orbitedupdater.js');
|
||||
|
||||
return $scripts;
|
||||
}
|
||||
|
||||
function _updateInitialize($timeline, $user_id)
|
||||
{
|
||||
$script = parent::_updateInitialize($timeline, $user_id);
|
||||
|
||||
$server = $this->_getStompServer();
|
||||
$port = $this->_getStompPort();
|
||||
|
||||
return $script." OrbitedUpdater.init(\"$server\", $port, ".
|
||||
"\"{$timeline}\", \"{$this->webuser}\", \"{$this->webpass}\");";
|
||||
}
|
||||
|
||||
function _connect()
|
||||
{
|
||||
require_once(INSTALLDIR.'/extlib/Stomp.php');
|
||||
|
||||
$url = $this->_getStompUrl();
|
||||
|
||||
$this->con = new Stomp($url);
|
||||
|
||||
if ($this->con->connect($this->username, $this->password)) {
|
||||
$this->log(LOG_INFO, "Connected.");
|
||||
} else {
|
||||
$this->log(LOG_ERR, 'Failed to connect to queue server');
|
||||
throw new ServerException('Failed to connect to queue server');
|
||||
}
|
||||
}
|
||||
|
||||
function _publish($channel, $message)
|
||||
{
|
||||
$result = $this->con->send($channel,
|
||||
json_encode($message));
|
||||
|
||||
return $result;
|
||||
// TODO: parse and deal with result
|
||||
}
|
||||
|
||||
function _disconnect()
|
||||
{
|
||||
$this->con->disconnect();
|
||||
}
|
||||
|
||||
function _pathToChannel($path)
|
||||
{
|
||||
if (!empty($this->channelbase)) {
|
||||
array_unshift($path, $this->channelbase);
|
||||
}
|
||||
return '/' . implode('/', $path);
|
||||
}
|
||||
|
||||
function _getStompServer()
|
||||
{
|
||||
return (!is_null($this->stompserver)) ? $this->stompserver :
|
||||
(!is_null($this->webserver)) ? $this->webserver :
|
||||
common_config('site', 'server');
|
||||
}
|
||||
|
||||
function _getStompPort()
|
||||
{
|
||||
return (!is_null($this->stompport)) ? $this->stompport : 61613;
|
||||
}
|
||||
|
||||
function _getStompUrl()
|
||||
{
|
||||
$server = $this->_getStompServer();
|
||||
$port = $this->_getStompPort();
|
||||
return "tcp://$server:$port/";
|
||||
}
|
||||
}
|
||||
2
plugins/Orbited/orbitedextra.js
Normal file
2
plugins/Orbited/orbitedextra.js
Normal file
@@ -0,0 +1,2 @@
|
||||
TCPSocket = Orbited.TCPSocket;
|
||||
|
||||
24
plugins/Orbited/orbitedupdater.js
Normal file
24
plugins/Orbited/orbitedupdater.js
Normal file
@@ -0,0 +1,24 @@
|
||||
// Update the local timeline from a Orbited server
|
||||
|
||||
var OrbitedUpdater = function()
|
||||
{
|
||||
return {
|
||||
|
||||
init: function(server, port, timeline, username, password)
|
||||
{
|
||||
// set up stomp client.
|
||||
stomp = new STOMPClient();
|
||||
|
||||
stomp.onmessageframe = function(frame) {
|
||||
RealtimeUpdate.receive(JSON.parse(frame.body));
|
||||
};
|
||||
|
||||
stomp.onconnectedframe = function() {
|
||||
stomp.subscribe(timeline);
|
||||
}
|
||||
|
||||
stomp.connect(server, port, username, password);
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
@@ -38,30 +38,24 @@ if (!defined('STATUSNET')) {
|
||||
* This plugin will spoot out the correct JavaScript spell to invoke
|
||||
* Piwik Analytics on a page.
|
||||
*
|
||||
* To use this plugin please add the following three lines to your config.php
|
||||
* To use this plugin add the following to your config.php
|
||||
*
|
||||
* require_once('plugins/PiwikAnalyticsPlugin.php');
|
||||
* $pa = new PiwikAnalyticsPlugin("example.com/piwik/","id");
|
||||
* addPlugin('PiwikAnalytics', array('piwikroot' => 'example.com/piwik/',
|
||||
* 'piwikId' => 'id'));
|
||||
*
|
||||
* exchange example.com/piwik/ with the url to your piwik installation and
|
||||
* make sure you don't forget the final /
|
||||
* exchange id with the ID your statusnet installation has in your Piwik analytics
|
||||
* Replace 'example.com/piwik/' with the URL to your Piwik installation and
|
||||
* make sure you don't forget the final /.
|
||||
* Replace 'id' with the ID your statusnet installation has in your Piwik
|
||||
* analytics setup - for example '8'.
|
||||
*
|
||||
* @category Plugin
|
||||
* @package StatusNet
|
||||
* @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*
|
||||
* @see Event
|
||||
*/
|
||||
|
||||
class PiwikAnalyticsPlugin extends Plugin
|
||||
{
|
||||
/** the base of your Piwik installation */
|
||||
var $piwikroot = null;
|
||||
public $piwikroot = null;
|
||||
/** the Piwik Id of your statusnet installation */
|
||||
var $piwikId = null;
|
||||
public $piwikId = null;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
@@ -73,7 +67,7 @@ class PiwikAnalyticsPlugin extends Plugin
|
||||
function __construct($root=null, $id=null)
|
||||
{
|
||||
$this->piwikroot = $root;
|
||||
$this->piwikid = $id;
|
||||
$this->piwikId = $id;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@@ -96,7 +90,7 @@ document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/ja
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
try {
|
||||
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 4);
|
||||
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", {$this->piwikId});
|
||||
piwikTracker.trackPageView();
|
||||
piwikTracker.enableLinkTracking();
|
||||
} catch( err ) {}
|
||||
@@ -108,4 +102,4 @@ ENDOFPIWIK;
|
||||
$action->raw($piwikCode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
define('DEFAULT_HUB','http://2pubsubhubbub.appspot.com');
|
||||
define('DEFAULT_HUB','http://pubsubhubbub.appspot.com');
|
||||
|
||||
require_once(INSTALLDIR.'/plugins/PubSubHubBub/publisher.php');
|
||||
|
||||
@@ -59,7 +59,7 @@ class PubSubHubBubPlugin extends Plugin
|
||||
$action->element('atom:link',array('rel'=>'hub','href'=>$this->hub),null);
|
||||
}
|
||||
|
||||
function onEndNoticeSave($notice){
|
||||
function onHandleQueuedNotice($notice){
|
||||
$publisher = new Publisher($this->hub);
|
||||
|
||||
$feeds = array();
|
||||
|
||||
@@ -50,6 +50,11 @@ class RealtimePlugin extends Plugin
|
||||
protected $favorurl = null;
|
||||
protected $deleteurl = null;
|
||||
|
||||
/**
|
||||
* When it's time to initialize the plugin, calculate and
|
||||
* pass the URLs we need.
|
||||
*/
|
||||
|
||||
function onInitializePlugin()
|
||||
{
|
||||
$this->replyurl = common_local_url('newnotice');
|
||||
@@ -57,29 +62,26 @@ class RealtimePlugin extends Plugin
|
||||
// FIXME: need to find a better way to pass this pattern in
|
||||
$this->deleteurl = common_local_url('deletenotice',
|
||||
array('notice' => '0000000000'));
|
||||
return true;
|
||||
}
|
||||
|
||||
function onEndShowScripts($action)
|
||||
{
|
||||
$path = null;
|
||||
$timeline = $this->_getTimeline($action);
|
||||
|
||||
switch ($action->trimmed('action')) {
|
||||
case 'public':
|
||||
$path = array('public');
|
||||
break;
|
||||
case 'tag':
|
||||
$tag = $action->trimmed('tag');
|
||||
if (!empty($tag)) {
|
||||
$path = array('tag', $tag);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// If there's not a timeline on this page,
|
||||
// just return true
|
||||
|
||||
if (empty($timeline)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$timeline = $this->_pathToChannel($path);
|
||||
$base = $action->selfUrl();
|
||||
if (mb_strstr($base, '?')) {
|
||||
$url = $base . '&realtime=1';
|
||||
} else {
|
||||
$url = $base . '?realtime=1';
|
||||
}
|
||||
|
||||
$scripts = $this->_getScripts();
|
||||
|
||||
@@ -95,10 +97,22 @@ class RealtimePlugin extends Plugin
|
||||
$user_id = 0;
|
||||
}
|
||||
|
||||
if ($action->boolean('realtime')) {
|
||||
$realtimeUI = ' RealtimeUpdate.initPopupWindow();';
|
||||
}
|
||||
else {
|
||||
$iconurl = common_path('plugins/Realtime/icon_external.gif');
|
||||
$realtimeUI = ' RealtimeUpdate.addPopup("'.$url.'", "'.$timeline.'", "'. $iconurl .'");';
|
||||
}
|
||||
|
||||
$action->elementStart('script', array('type' => 'text/javascript'));
|
||||
$action->raw("$(document).ready(function() { ");
|
||||
$action->raw($this->_updateInitialize($timeline, $user_id));
|
||||
$action->raw(" });");
|
||||
|
||||
$script = ' $(document).ready(function() { '.
|
||||
$realtimeUI.
|
||||
$this->_updateInitialize($timeline, $user_id).
|
||||
'}); ';
|
||||
$action->raw($script);
|
||||
|
||||
$action->elementEnd('script');
|
||||
|
||||
return true;
|
||||
@@ -108,13 +122,23 @@ class RealtimePlugin extends Plugin
|
||||
{
|
||||
$paths = array();
|
||||
|
||||
// XXX: Add other timelines; this is just for the public one
|
||||
// Add to the author's timeline
|
||||
|
||||
$user = User::staticGet('id', $notice->profile_id);
|
||||
|
||||
if (!empty($user)) {
|
||||
$paths[] = array('showstream', $user->nickname);
|
||||
}
|
||||
|
||||
// Add to the public timeline
|
||||
|
||||
if ($notice->is_local ||
|
||||
($notice->is_local == 0 && !common_config('public', 'localonly'))) {
|
||||
$paths[] = array('public');
|
||||
}
|
||||
|
||||
// Add to the tags timeline
|
||||
|
||||
$tags = $this->getNoticeTags($notice);
|
||||
|
||||
if (!empty($tags)) {
|
||||
@@ -123,6 +147,46 @@ class RealtimePlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
// Add to inbox timelines
|
||||
// XXX: do a join
|
||||
|
||||
$inbox = new Notice_inbox();
|
||||
$inbox->notice_id = $notice->id;
|
||||
|
||||
if ($inbox->find()) {
|
||||
while ($inbox->fetch()) {
|
||||
$user = User::staticGet('id', $inbox->user_id);
|
||||
$paths[] = array('all', $user->nickname);
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the replies timeline
|
||||
|
||||
$reply = new Reply();
|
||||
$reply->notice_id = $notice->id;
|
||||
|
||||
if ($reply->find()) {
|
||||
while ($reply->fetch()) {
|
||||
$user = User::staticGet('id', $reply->profile_id);
|
||||
if (!empty($user)) {
|
||||
$paths[] = array('replies', $user->nickname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to the group timeline
|
||||
// XXX: join
|
||||
|
||||
$gi = new Group_inbox();
|
||||
$gi->notice_id = $notice->id;
|
||||
|
||||
if ($gi->find()) {
|
||||
while ($gi->fetch()) {
|
||||
$ug = User_group::staticGet('id', $gi->group_id);
|
||||
$paths[] = array('showgroup', $ug->nickname);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($paths) > 0) {
|
||||
|
||||
$json = $this->noticeAsJson($notice);
|
||||
@@ -140,18 +204,49 @@ class RealtimePlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
|
||||
function onStartShowBody($action)
|
||||
{
|
||||
$realtime = $action->boolean('realtime');
|
||||
if (!$realtime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$action->elementStart('body',
|
||||
(common_current_user()) ? array('id' => $action->trimmed('action'),
|
||||
'class' => 'user_in')
|
||||
: array('id' => $action->trimmed('action')));
|
||||
|
||||
// XXX hack to deal with JS that tries to get the
|
||||
// root url from page output
|
||||
|
||||
$action->elementStart('address');
|
||||
$action->element('a', array('class' => 'url',
|
||||
'href' => common_local_url('public')),
|
||||
'');
|
||||
$action->elementEnd('address');
|
||||
|
||||
if (common_logged_in()) {
|
||||
$action->showNoticeForm();
|
||||
}
|
||||
|
||||
$action->showContentBlock();
|
||||
$action->showScripts();
|
||||
$action->elementEnd('body');
|
||||
return false; // No default processing
|
||||
}
|
||||
|
||||
function noticeAsJson($notice)
|
||||
{
|
||||
// FIXME: this code should be abstracted to a neutral third
|
||||
// party, like Notice::asJson(). I'm not sure of the ethics
|
||||
// of refactoring from within a plugin, so I'm just abusing
|
||||
// the TwitterApiAction method. Don't do this unless you're me!
|
||||
// the ApiAction method. Don't do this unless you're me!
|
||||
|
||||
require_once(INSTALLDIR.'/lib/twitterapi.php');
|
||||
require_once(INSTALLDIR.'/lib/api.php');
|
||||
|
||||
$act = new TwitterApiAction('/dev/null');
|
||||
$act = new ApiAction('/dev/null');
|
||||
|
||||
$arr = $act->twitter_status_array($notice, true);
|
||||
$arr = $act->twitterStatusArray($notice, true);
|
||||
$arr['url'] = $notice->bestUrl();
|
||||
$arr['html'] = htmlspecialchars($notice->rendered);
|
||||
$arr['source'] = htmlspecialchars($arr['source']);
|
||||
@@ -224,4 +319,41 @@ class RealtimePlugin extends Plugin
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
function _getTimeline($action)
|
||||
{
|
||||
$path = null;
|
||||
$timeline = null;
|
||||
|
||||
$action_name = $action->trimmed('action');
|
||||
|
||||
switch ($action_name) {
|
||||
case 'public':
|
||||
$path = array('public');
|
||||
break;
|
||||
case 'tag':
|
||||
$tag = $action->trimmed('tag');
|
||||
if (!empty($tag)) {
|
||||
$path = array('tag', $tag);
|
||||
}
|
||||
break;
|
||||
case 'showstream':
|
||||
case 'all':
|
||||
case 'replies':
|
||||
case 'showgroup':
|
||||
$nickname = common_canonical_nickname($action->trimmed('nickname'));
|
||||
if (!empty($nickname)) {
|
||||
$path = array($action_name, $nickname);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($path)) {
|
||||
$timeline = $this->_pathToChannel($path);
|
||||
}
|
||||
|
||||
return $timeline;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
plugins/Realtime/icon_external.gif
Normal file
BIN
plugins/Realtime/icon_external.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 B |
@@ -1,8 +1,8 @@
|
||||
// add a notice encoded as JSON into the current timeline
|
||||
//
|
||||
// TODO: i18n
|
||||
|
||||
RealtimeUpdate = {
|
||||
|
||||
_userid: 0,
|
||||
_replyurl: '',
|
||||
_favorurl: '',
|
||||
@@ -10,27 +10,42 @@ RealtimeUpdate = {
|
||||
|
||||
init: function(userid, replyurl, favorurl, deleteurl)
|
||||
{
|
||||
RealtimeUpdate._userid = userid;
|
||||
RealtimeUpdate._replyurl = replyurl;
|
||||
RealtimeUpdate._favorurl = favorurl;
|
||||
RealtimeUpdate._deleteurl = deleteurl;
|
||||
RealtimeUpdate._userid = userid;
|
||||
RealtimeUpdate._replyurl = replyurl;
|
||||
RealtimeUpdate._favorurl = favorurl;
|
||||
RealtimeUpdate._deleteurl = deleteurl;
|
||||
|
||||
$(window).blur(function() {
|
||||
$('#notices_primary .notice').css({
|
||||
'border-top-color':$('#notices_primary .notice:last').css('border-top-color'),
|
||||
'border-top-style':'dotted'
|
||||
});
|
||||
|
||||
$('#notices_primary .notice:first').css({
|
||||
'border-top-color':'#AAAAAA',
|
||||
'border-top-style':'solid'
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
receive: function(data)
|
||||
{
|
||||
id = data.id;
|
||||
setTimeout(function() {
|
||||
id = data.id;
|
||||
|
||||
// Don't add it if it already exists
|
||||
|
||||
if ($("#notice-"+id).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var noticeItem = RealtimeUpdate.makeNoticeItem(data);
|
||||
$("#notices_primary .notices").prepend(noticeItem, true);
|
||||
$("#notices_primary .notice:first").css({display:"none"});
|
||||
$("#notices_primary .notice:first").fadeIn(1000);
|
||||
NoticeReply();
|
||||
// Don't add it if it already exists
|
||||
if ($("#notice-"+id).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var noticeItem = RealtimeUpdate.makeNoticeItem(data);
|
||||
$("#notices_primary .notices").prepend(noticeItem);
|
||||
$("#notices_primary .notice:first").css({display:"none"});
|
||||
$("#notices_primary .notice:first").fadeIn(1000);
|
||||
NoticeReply();
|
||||
}, 500);
|
||||
},
|
||||
|
||||
makeNoticeItem: function(data)
|
||||
@@ -50,30 +65,19 @@ RealtimeUpdate = {
|
||||
"<p class=\"entry-content\">"+html+"</p>"+
|
||||
"</div>"+
|
||||
"<div class=\"entry-content\">"+
|
||||
"<dl class=\"timestamp\">"+
|
||||
"<dt>Published</dt>"+
|
||||
"<dd>"+
|
||||
"<a rel=\"bookmark\" href=\""+data['url']+"\" >"+
|
||||
"<a class=\"timestamp\" rel=\"bookmark\" href=\""+data['url']+"\" >"+
|
||||
"<abbr class=\"published\" title=\""+data['created_at']+"\">a few seconds ago</abbr>"+
|
||||
"</a> "+
|
||||
"</dd>"+
|
||||
"</dl>"+
|
||||
"<dl class=\"device\">"+
|
||||
"<dt>From</dt> "+
|
||||
"<dd>"+source+"</dd>"+ // may have a link, I think
|
||||
"</dl>";
|
||||
|
||||
"<span class=\"source\">"+
|
||||
"from "+
|
||||
"<span class=\"device\">"+source+"</span>"+ // may have a link
|
||||
"</span>";
|
||||
if (data['in_reply_to_status_id']) {
|
||||
ni = ni+" <dl class=\"response\">"+
|
||||
"<dt>To</dt>"+
|
||||
"<dd>"+
|
||||
"<a href=\""+data['in_reply_to_status_url']+"\" rel=\"in-reply-to\">in reply to</a>"+
|
||||
"</dd>"+
|
||||
"</dl>";
|
||||
ni = ni+" <a class=\"response\" href=\""+data['in_reply_to_status_url']+"\">in context</a>";
|
||||
}
|
||||
|
||||
ni = ni+"</div>"+
|
||||
"<div class=\"notice-options\">";
|
||||
"<div class=\"notice-options\">";
|
||||
|
||||
if (RealtimeUpdate._userid != 0) {
|
||||
var input = $("form#form_notice fieldset input#token");
|
||||
@@ -95,12 +99,12 @@ RealtimeUpdate = {
|
||||
var ff;
|
||||
|
||||
ff = "<form id=\"favor-"+id+"\" class=\"form_favor\" method=\"post\" action=\""+RealtimeUpdate._favorurl+"\">"+
|
||||
"<fieldset>"+
|
||||
"<legend>Favor this notice</legend>"+ // XXX: i18n
|
||||
"<fieldset>"+
|
||||
"<legend>Favor this notice</legend>"+
|
||||
"<input name=\"token-"+id+"\" type=\"hidden\" id=\"token-"+id+"\" value=\""+session_key+"\"/>"+
|
||||
"<input name=\"notice\" type=\"hidden\" id=\"notice-n"+id+"\" value=\""+id+"\"/>"+
|
||||
"<input type=\"submit\" id=\"favor-submit-"+id+"\" name=\"favor-submit-"+id+"\" class=\"submit\" value=\"Favor\" title=\"Favor this notice\"/>"+
|
||||
"</fieldset>"+
|
||||
"</fieldset>"+
|
||||
"</form>";
|
||||
return ff;
|
||||
},
|
||||
@@ -108,28 +112,71 @@ RealtimeUpdate = {
|
||||
makeReplyLink: function(id, nickname)
|
||||
{
|
||||
var rl;
|
||||
rl = "<dl class=\"notice_reply\">"+
|
||||
"<dt>Reply to this notice</dt>"+
|
||||
"<dd>"+
|
||||
"<a href=\""+RealtimeUpdate._replyurl+"?replyto="+nickname+"\" title=\"Reply to this notice\">Reply <span class=\"notice_id\">"+id+"</span>"+
|
||||
"</a>"+
|
||||
"</dd>"+
|
||||
"</dl>";
|
||||
rl = "<a class=\"notice_reply\" href=\""+RealtimeUpdate._replyurl+"?replyto="+nickname+"\" title=\"Reply to this notice\">Reply <span class=\"notice_id\">"+id+"</span></a>";
|
||||
return rl;
|
||||
},
|
||||
},
|
||||
|
||||
makeDeleteLink: function(id)
|
||||
{
|
||||
var dl, delurl;
|
||||
delurl = RealtimeUpdate._deleteurl.replace("0000000000", id);
|
||||
|
||||
dl = "<dl class=\"notice_delete\">"+
|
||||
"<dt>Delete this notice</dt>"+
|
||||
"<dd>"+
|
||||
"<a href=\""+delurl+"\" title=\"Delete this notice\">Delete</a>"+
|
||||
"</dd>"+
|
||||
"</dl>";
|
||||
dl = "<a class=\"notice_delete\" href=\""+delurl+"\" title=\"Delete this notice\">Delete</a>";
|
||||
|
||||
return dl;
|
||||
},
|
||||
|
||||
addPopup: function(url, timeline, iconurl)
|
||||
{
|
||||
$('#notices_primary').css({'position':'relative'});
|
||||
$('#notices_primary').prepend('<button id="realtime_timeline" title="Pop up in a window">Pop up</button>');
|
||||
|
||||
$('#realtime_timeline').css({
|
||||
'margin':'0 0 11px 0',
|
||||
'background':'transparent url('+ iconurl + ') no-repeat 0% 30%',
|
||||
'padding':'0 0 0 20px',
|
||||
'display':'block',
|
||||
'position':'absolute',
|
||||
'top':'-20px',
|
||||
'right':'0',
|
||||
'border':'none',
|
||||
'cursor':'pointer',
|
||||
'color':$("a").css("color"),
|
||||
'font-weight':'bold',
|
||||
'font-size':'1em'
|
||||
});
|
||||
|
||||
$('#realtime_timeline').click(function() {
|
||||
window.open(url,
|
||||
timeline,
|
||||
'toolbar=no,resizable=yes,scrollbars=yes,status=yes');
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
initPopupWindow: function()
|
||||
{
|
||||
window.resizeTo(500, 550);
|
||||
$('address').hide();
|
||||
$('#content').css({'width':'93.5%'});
|
||||
|
||||
$('#form_notice').css({
|
||||
'margin':'18px 0 18px 1.795%',
|
||||
'width':'93%',
|
||||
'max-width':'451px'
|
||||
});
|
||||
|
||||
$('#form_notice label[for=notice_data-text], h1').css({'display': 'none'});
|
||||
|
||||
$('.notices li:first-child').css({'border-top-color':'transparent'});
|
||||
|
||||
$('#form_notice label[for="notice_data-attach"], #form_notice #notice_data-attach').css({'top':'0'});
|
||||
|
||||
$('#form_notice #notice_data-attach').css({
|
||||
'left':'auto',
|
||||
'right':'0'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
|
||||
define('TWITTER_SERVICE', 1); // Twitter is foreign_service ID 1
|
||||
|
||||
function update_twitter_user($twitter_id, $screen_name)
|
||||
function updateTwitter_user($twitter_id, $screen_name)
|
||||
{
|
||||
$uri = 'http://twitter.com/' . $screen_name;
|
||||
$fuser = new Foreign_user();
|
||||
@@ -115,7 +115,7 @@ function save_twitter_user($twitter_id, $screen_name)
|
||||
// Only update if Twitter screen name has changed
|
||||
|
||||
if ($fuser->nickname != $screen_name) {
|
||||
$result = update_twitter_user($twitter_id, $screen_name);
|
||||
$result = updateTwitter_user($twitter_id, $screen_name);
|
||||
|
||||
common_debug('Twitter bridge - Updated nickname (and URI) for Twitter user ' .
|
||||
"$fuser->id to $screen_name, was $fuser->nickname");
|
||||
|
||||
@@ -36,8 +36,14 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
*
|
||||
* @category Integration
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @author Adrian Lang <mail@adrianlang.de>
|
||||
* @author Brenda Wallace <shiny@cpan.org>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Dan Moore <dan@moore.cx>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author mEDI <medi@milaro.net>
|
||||
* @author Sarven Capadisli <csarven@status.net>
|
||||
* @author Zach Copley <zach@status.net> * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@ Use:
|
||||
1. Get an API key from http://recaptcha.net
|
||||
|
||||
2. In config.php add:
|
||||
include_once('plugins/recaptcha.php');
|
||||
include_once('plugins/recaptcha/recaptcha.php');
|
||||
$captcha = new recaptcha(publickey, privatekey, showErrors);
|
||||
|
||||
Changelog
|
||||
|
||||
Reference in New Issue
Block a user