Merge branch 'master' into 0.9.x

This commit is contained in:
Evan Prodromou 2010-01-22 14:18:40 -05:00
commit e666433eb4
8 changed files with 241 additions and 86 deletions

35
README
View File

@ -2,8 +2,8 @@
README
------
StatusNet 0.9.0 ("Stand") Release Candidate 2
22 Dec 2009
StatusNet 0.9.0 ("Stand") Beta 3
20 Jan 2010
This is the README file for StatusNet (formerly Laconica), the Open
Source microblogging platform. It includes installation instructions,
@ -167,6 +167,37 @@ Notable changes this version:
- Add support for "repeats" (similar to Twitter's "retweets").
- Support for repeats in Twitter API.
- Better notification of direct messages.
- New plugin to add "powered by StatusNet" to logo.
- Returnto works for private sites.
- Localisation updates, including new Persian translation.
- CAS authentication plugin
- Get rid of DB_DataObject native cache (big memory leaker)
- setconfig.php script to set configuration variables
- Blacklist plugin, to blacklist URLs and nicknames
- Users can set flag whether they want to share location
both in notice form (for one notice) and profile settings
(any notice)
- notice inboxes moved from normalized notice_inbox table to
denormalized inbox table
- Automatic compression of Memcache
- Memory caching pluginized
- Memcache, XCache, APC and Diskcache plugins
- A script to update user locations
- cache empty query results
- A sample plugin to show best plugin practices
- CacheLog plugin to debug cache accesses
- Require users to login to view attachments on private sites
- Plugin to use Mollom spam detection service
- Plugin for RSSCloud
- Add an array of default plugins
- A version action to give credit to contributors and plugin
developers
- Daemon to read IMAP mailbox instead of using a mailbox script
- Pass session information between SSL and non-SSL server
when SSL set to 'sometimes'
- Major refactoring of queue handlers to manage very
large hosting site (like status.net)
- SubscriptionThrottle plugin to prevent subscription spamming
Prerequisites
=============

View File

@ -113,4 +113,19 @@ class ApiStatusesRetweetsAction extends ApiAuthAction
break;
}
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
}

View File

@ -69,58 +69,21 @@ class ApiTimelineRetweetedByMeAction extends ApiAuthAction
{
parent::prepare($args);
$cnt = $this->int('count', self::DEFAULTCOUNT, self::MAXCOUNT, 1);
$this->serverError('Unimplemented', 503);
$page = $this->int('page', 1, (self::MAXNOTICES/$this->cnt));
$since_id = $this->int('since_id');
$max_id = $this->int('max_id');
return true;
return false;
}
/**
* Handle the request
* Return true if read only.
*
* show a timeline of the user's repeated notices
* @param array $args other arguments
*
* @param array $args $_REQUEST data (unused)
*
* @return void
* @return boolean is read only action?
*/
function handle($args)
function isReadOnly($args)
{
parent::handle($args);
$offset = ($this->page-1) * $this->cnt;
$limit = $this->cnt;
$strm = $this->auth_user->repeatedByMe($offset, $limit, $this->since_id, $this->max_id);
switch ($this->format) {
case 'xml':
$this->showXmlTimeline($strm);
break;
case 'json':
$this->showJsonTimeline($strm);
break;
case 'atom':
$profile = $this->auth_user->getProfile();
$title = sprintf(_("Repeated by %s"), $this->auth_user->nickname);
$taguribase = common_config('integration', 'taguri');
$id = "tag:$taguribase:RepeatedByMe:" . $this->auth_user->id;
$link = common_local_url('showstream',
array('nickname' => $this->auth_user->nickname));
$this->showAtomTimeline($strm, $title, $id, $link);
break;
default:
$this->clientError(_('API method not found.'), $code = 404);
break;
}
return true;
}
}

View File

@ -122,4 +122,19 @@ class ApiTimelineRetweetedToMeAction extends ApiAuthAction
break;
}
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
}

View File

@ -123,4 +123,19 @@ class ApiTimelineRetweetsOfMeAction extends ApiAuthAction
break;
}
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
}

View File

@ -19,8 +19,6 @@
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Memcached_DataObject extends DB_DataObject
{
/**

View File

@ -31,66 +31,152 @@ if (!defined('STATUSNET')) {
exit(1);
}
define('DEFAULT_HUB','http://pubsubhubbub.appspot.com');
define('DEFAULT_HUB', 'http://pubsubhubbub.appspot.com');
require_once(INSTALLDIR.'/plugins/PubSubHubBub/publisher.php');
require_once INSTALLDIR.'/plugins/PubSubHubBub/publisher.php';
/**
* Plugin to provide publisher side of PubSubHubBub (PuSH)
* relationship.
*
* PuSH is a real-time or near-real-time protocol for Atom
* and RSS feeds. More information here:
*
* http://code.google.com/p/pubsubhubbub/
*
* To enable, add the following line to your config.php:
*
* addPlugin('PubSubHubBub');
*
* This will use the Google default hub. If you'd like to use
* another, try:
*
* addPlugin('PubSubHubBub',
* array('hub' => 'http://yourhub.example.net/'));
*
* @category Plugin
* @package StatusNet
* @author Craig Andrews <candrews@integralblue.com>
* @copyright 2009 Craig Andrews http://candrews.integralblue.com
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/
*/
class PubSubHubBubPlugin extends Plugin
{
private $hub;
/**
* URL of the hub to advertise and publish to.
*/
public $hub = DEFAULT_HUB;
/**
* Default constructor.
*/
function __construct()
{
parent::__construct();
}
function onInitializePlugin(){
$this->hub = common_config('PubSubHubBub', 'hub');
if(empty($this->hub)){
$this->hub = DEFAULT_HUB;
}
/**
* Hooks the StartApiAtom event
*
* Adds the necessary bits to advertise PubSubHubBub
* for the Atom feed.
*
* @param Action $action The API action being shown.
*
* @return boolean hook value
*/
function onStartApiAtom($action)
{
$action->element('link', array('rel' => 'hub', 'href' => $this->hub), null);
return true;
}
function onStartApiAtom($action){
$action->element('link',array('rel'=>'hub','href'=>$this->hub),null);
/**
* Hooks the StartApiRss event
*
* Adds the necessary bits to advertise PubSubHubBub
* for the RSS 2.0 feeds.
*
* @param Action $action The API action being shown.
*
* @return boolean hook value
*/
function onStartApiRss($action)
{
$action->element('atom:link', array('rel' => 'hub',
'href' => $this->hub),
null);
return true;
}
function onStartApiRss($action){
$action->element('atom:link',array('rel'=>'hub','href'=>$this->hub),null);
}
/**
* Hook for a queued notice.
*
* When a notice has been queued, will ping the
* PuSH hub for each Atom and RSS feed in which
* the notice appears.
*
* @param Notice $notice The notice that's been queued
*
* @return boolean hook value
*/
function onHandleQueuedNotice($notice){
function onHandleQueuedNotice($notice)
{
$publisher = new Publisher($this->hub);
$feeds = array();
//public timeline feeds
$feeds[]=common_local_url('ApiTimelinePublic',array('format' => 'rss'));
$feeds[]=common_local_url('ApiTimelinePublic',array('format' => 'atom'));
$feeds[] = common_local_url('ApiTimelinePublic', array('format' => 'rss'));
$feeds[] = common_local_url('ApiTimelinePublic', array('format' => 'atom'));
//author's own feeds
$user = User::staticGet('id',$notice->profile_id);
$feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'rss'));
$feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'atom'));
$user = User::staticGet('id', $notice->profile_id);
$feeds[] = common_local_url('ApiTimelineUser',
array('id' => $user->nickname,
'format' => 'rss'));
$feeds[] = common_local_url('ApiTimelineUser',
array('id' => $user->nickname,
'format' => 'atom'));
//tag feeds
$tag = new Notice_tag();
$tag->notice_id = $notice->id;
if ($tag->find()) {
while ($tag->fetch()) {
$feeds[]=common_local_url('ApiTimelineTag',array('tag'=>$tag->tag, 'format'=>'rss'));
$feeds[]=common_local_url('ApiTimelineTag',array('tag'=>$tag->tag, 'format'=>'atom'));
$feeds[] = common_local_url('ApiTimelineTag',
array('tag' => $tag->tag,
'format' => 'rss'));
$feeds[] = common_local_url('ApiTimelineTag',
array('tag' => $tag->tag,
'format' => 'atom'));
}
}
//group feeds
$group_inbox = new Group_inbox();
$group_inbox->notice_id = $notice->id;
if ($group_inbox->find()) {
while ($group_inbox->fetch()) {
$group = User_group::staticGet('id',$group_inbox->group_id);
$feeds[]=common_local_url('ApiTimelineGroup',array('id' => $group->nickname,'format'=>'rss'));
$feeds[]=common_local_url('ApiTimelineGroup',array('id' => $group->nickname,'format'=>'atom'));
$group = User_group::staticGet('id', $group_inbox->group_id);
$feeds[] = common_local_url('ApiTimelineGroup',
array('id' => $group->nickname,
'format' => 'rss'));
$feeds[] = common_local_url('ApiTimelineGroup',
array('id' => $group->nickname,
'format' => 'atom'));
}
}
@ -103,32 +189,63 @@ class PubSubHubBubPlugin extends Plugin
if (empty($user)) {
continue;
}
$feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'rss'));
$feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'atom'));
$feeds[] = common_local_url('ApiTimelineFriends',
array('id' => $user->nickname,
'format' => 'rss'));
$feeds[] = common_local_url('ApiTimelineFriends',
array('id' => $user->nickname,
'format' => 'atom'));
}
$replies = $notice->getReplies();
//feed of user replied to
if($notice->reply_to){
$user = User::staticGet('id',$notice->reply_to);
$feeds[]=common_local_url('ApiTimelineMentions',array('id' => $user->nickname,'format'=>'rss'));
$feeds[]=common_local_url('ApiTimelineMentions',array('id' => $user->nickname,'format'=>'atom'));
}
foreach(array_unique($feeds) as $feed){
if(! $publisher->publish_update($feed)){
common_log_line(LOG_WARNING,$feed.' was not published to hub at '.$this->hub.':'.$publisher->last_response());
foreach ($replies as $recipient) {
$user = User::staticGet('id', $recipient);
if (!empty($user)) {
$feeds[] = common_local_url('ApiTimelineMentions',
array('id' => $user->nickname,
'format' => 'rss'));
$feeds[] = common_local_url('ApiTimelineMentions',
array('id' => $user->nickname,
'format' => 'atom'));
}
}
foreach (array_unique($feeds) as $feed) {
if (!$publisher->publish_update($feed)) {
common_log_line(LOG_WARNING,
$feed.' was not published to hub at '.
$this->hub.':'.$publisher->last_response());
}
}
return true;
}
/**
* Provide version information
*
* Adds this plugin's version data to the global
* version array, for e.g. displaying on the version page.
*
* @param array &$versions array of array of versions
*
* @return boolean hook value
*/
function onPluginVersion(&$versions)
{
$versions[] = array('name' => 'PubSubHubBub',
'version' => STATUSNET_VERSION,
'author' => 'Craig Andrews',
'homepage' => 'http://status.net/wiki/Plugin:PubSubHubBub',
'homepage' =>
'http://status.net/wiki/Plugin:PubSubHubBub',
'rawdescription' =>
_m('The PubSubHubBub plugin pushes RSS/Atom updates to a <a href="http://pubsubhubbub.googlecode.com/">PubSubHubBub</a> hub.'));
_m('The PubSubHubBub plugin pushes RSS/Atom updates '.
'to a <a href = "'.
'http://pubsubhubbub.googlecode.com/'.
'">PubSubHubBub</a> hub.'));
return true;
}

View File

@ -148,6 +148,7 @@ class XMPPDaemon extends Daemon
function handle_message(&$pl)
{
$this->log(LOG_DEBUG, "Received message: " . str_replace("\n", " ", var_export($pl, true)));
$from = jabber_normalize_jid($pl['from']);
if ($pl['type'] != 'chat') {