]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Qvitter API changes (thanks hannes2peer)
authorMikael Nordfeldth <mmn@hethane.se>
Sun, 6 Oct 2013 19:30:29 +0000 (21:30 +0200)
committerMikael Nordfeldth <mmn@hethane.se>
Sun, 6 Oct 2013 19:51:50 +0000 (21:51 +0200)
I implemented changes from quitter.se's new API that their front-end qvitter
uses, https://github.com/hannesmannerheim/qvitter/blob/master/api-changes-1.1.1/CHANGES

However I left out the URL shortening commens, since I believe whatever behaviour
they experienced that caused them to implement this was a bug (or many) and should
be fixed in their proper areas and that shortening should not be entirely left
out in API calls.

38 files changed:
actions/apiaccountregister.php [new file with mode: 0644]
actions/apiaccountupdatebackgroundcolor.php [new file with mode: 0644]
actions/apiaccountupdatelinkcolor.php [new file with mode: 0644]
actions/apiattachment.php [new file with mode: 0644]
actions/apicheckhub.php [new file with mode: 0644]
actions/apichecknickname.php [new file with mode: 0644]
actions/apiconversation.php
actions/apiexternalprofileshow.php [new file with mode: 0644]
actions/apifriendshipsexists.php
actions/apigroupadmins.php [new file with mode: 0644]
actions/apigrouplistall.php
actions/apigroupmembership.php
actions/apigroupshow.php
actions/apihelptest.php
actions/apisearchatom.php
actions/apisearchjson.php
actions/apistatusesfavs.php [new file with mode: 0644]
actions/apistatusesshow.php
actions/apistatusnetversion.php
actions/apitimelinegroup.php
actions/apitimelinelist.php
actions/apitimelinepublic.php
actions/apitimelinetag.php
actions/apitimelineuser.php
actions/apitrends.php
actions/apiuserprofileimage.php
actions/apiusershow.php
classes/Notice.php
classes/Profile.php
classes/User_group.php
lib/action.php
lib/apiaction.php
lib/apiprivateauth.php [deleted file]
lib/apiprivateauthaction.php [new file with mode: 0644]
lib/jsonsearchresultslist.php
lib/noticelistitem.php
lib/router.php
plugins/SubMirror/classes/SubMirror.php

diff --git a/actions/apiaccountregister.php b/actions/apiaccountregister.php
new file mode 100644 (file)
index 0000000..fec536a
--- /dev/null
@@ -0,0 +1,252 @@
+<?php
+               
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Register account
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class ApiAccountRegisterAction extends ApiAction
+{
+
+    /**
+     * Has there been an error?
+     */
+    var $error = null;
+
+    /**
+     * Have we registered?
+     */
+    var $registered = false;
+
+    /**
+     * Are we processing an invite?
+     */
+    var $invite = null;           
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+        $this->code = $this->trimmed('code');
+
+        if (empty($this->code)) {
+            common_ensure_session();
+            if (array_key_exists('invitecode', $_SESSION)) {
+                $this->code = $_SESSION['invitecode'];
+            }
+        }
+
+        if (common_config('site', 'inviteonly') && empty($this->code)) {
+            // TRANS: Client error displayed when trying to register to an invite-only site without an invitation.
+            $this->clientError(_('Sorry, only invited people can register.'),404,'json');
+            return false;
+        }
+
+        if (!empty($this->code)) {
+            $this->invite = Invitation::staticGet('code', $this->code);
+            if (empty($this->invite)) {
+            // TRANS: Client error displayed when trying to register to an invite-only site without a valid invitation.
+                   $this->clientError(_('Sorry, invalid invitation code.'),404,'json');        
+                return false;
+            }
+            // Store this in case we need it
+            common_ensure_session();
+            $_SESSION['invitecode'] = $this->code;
+        }
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+            $this->clientError(
+                _('This method requires a POST.'),
+                400, $this->format
+            );
+            return;
+
+        } else {
+       
+            $nickname = $this->trimmed('nickname');
+            $email    = $this->trimmed('email');
+            $fullname = $this->trimmed('fullname');
+            $homepage = $this->trimmed('homepage');
+            $bio      = $this->trimmed('bio');
+            $location = $this->trimmed('location');
+
+            // We don't trim these... whitespace is OK in a password!
+            $password = $this->arg('password');
+            $confirm  = $this->arg('confirm');
+
+            // invitation code, if any
+            $code = $this->trimmed('code');
+
+            if ($code) {
+                $invite = Invitation::staticGet($code);
+            }
+
+            if (common_config('site', 'inviteonly') && !($code && $invite)) {
+                // TRANS: Client error displayed when trying to register to an invite-only site without an invitation.
+                   $this->clientError(_('Sorry, only invited people can register.'),404,'json');       
+                return;
+            }
+
+            // Input scrubbing
+            try {
+                $nickname = Nickname::normalize($nickname);
+            } catch (NicknameException $e) {
+                $this->showForm($e->getMessage());
+            }
+            $email    = common_canonical_email($email);
+
+                       if ($email && !Validate::email($email, common_config('email', 'check_domain'))) {
+                // TRANS: Form validation error displayed when trying to register without a valid e-mail address.
+                   $this->clientError(_('Not a valid email address.'),404,'json');     
+            } else if ($this->nicknameExists($nickname)) {
+                // TRANS: Form validation error displayed when trying to register with an existing nickname.
+                   $this->clientError(_('Nickname already in use. Try another one.'),404,'json');      
+            } else if (!User::allowed_nickname($nickname)) {
+                // TRANS: Form validation error displayed when trying to register with an invalid nickname.
+                   $this->clientError(_('Not a valid nickname.'),404,'json');  
+            } else if ($this->emailExists($email)) {
+                // TRANS: Form validation error displayed when trying to register with an already registered e-mail address.
+                   $this->clientError(_('Email address already exists.'),404,'json');  
+            } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
+                       !Validate::uri($homepage,
+                                      array('allowed_schemes' =>
+                                            array('http', 'https')))) {
+                // TRANS: Form validation error displayed when trying to register with an invalid homepage URL.
+                   $this->clientError(_('Homepage is not a valid URL.'),404,'json');   
+                return;
+            } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
+                // TRANS: Form validation error displayed when trying to register with a too long full name.
+                   $this->clientError(_('Full name is too long (maximum 255 characters).'),404,'json');        
+                return;
+            } else if (Profile::bioTooLong($bio)) {
+                // TRANS: Form validation error on registration page when providing too long a bio text.
+                // TRANS: %d is the maximum number of characters for bio; used for plural.
+                   $this->clientError(sprintf(_m('Bio is too long (maximum %d character).',
+                                           'Bio is too long (maximum %d characters).',
+                                           Profile::maxBio()),
+                                           Profile::maxBio()),404,'json');     
+                return;
+            } else if (!is_null($location) && mb_strlen($location) > 255) {
+                // TRANS: Form validation error displayed when trying to register with a too long location.
+                   $this->clientError(_('Location is too long (maximum 255 characters).'),404,'json'); 
+                return;
+            } else if (strlen($password) < 6) {
+                // TRANS: Form validation error displayed when trying to register with too short a password.
+                   $this->clientError(_('Password must be 6 or more characters.'),404,'json'); 
+                return;
+            } else if ($password != $confirm) {
+                // TRANS: Form validation error displayed when trying to register with non-matching passwords.
+                   $this->clientError(_('Passwords do not match.'),404,'json');        
+            } else {
+                               
+                               // annoy spammers
+                               sleep(7);
+                               
+                               if ($user = User::register(array('nickname' => $nickname,
+                                                           'password' => $password,
+                                                           'email' => $email,
+                                                           'fullname' => $fullname,
+                                                           'homepage' => $homepage,
+                                                           'bio' => $bio,
+                                                           'location' => $location,
+                                                           'code' => $code))) {
+                       if (!$user) {
+                           // TRANS: Form validation error displayed when trying to register with an invalid username or password.
+                                   $this->clientError(_('Invalid username or password.'),404,'json');  
+                           return;
+                       }
+       
+                       Event::handle('EndRegistrationTry', array($this));
+       
+                               $this->initDocument('json');
+                               $this->showJsonObjects($this->twitterUserArray($user->getProfile()));
+                               $this->endDocument('json');
+       
+                   } else {
+                       // TRANS: Form validation error displayed when trying to register with an invalid username or password.
+                       $this->clientError(_('Invalid username or password.'),404,'json');      
+               }                       
+            } 
+        }
+    }
+      
+
+    /**
+     * Does the given nickname already exist?
+     *
+     * Checks a canonical nickname against the database.
+     *
+     * @param string $nickname nickname to check
+     *
+     * @return boolean true if the nickname already exists
+     */
+    function nicknameExists($nickname)
+    {
+        $user = User::staticGet('nickname', $nickname);
+        return is_object($user);
+    }
+
+    /**
+     * Does the given email address already exist?
+     *
+     * Checks a canonical email address against the database.
+     *
+     * @param string $email email address to check
+     *
+     * @return boolean true if the address already exists
+     */
+    function emailExists($email)
+    {
+        $email = common_canonical_email($email);
+        if (!$email || strlen($email) == 0) {
+            return false;
+        }
+        $user = User::staticGet('email', $email);
+        return is_object($user);
+    }
+
+}
diff --git a/actions/apiaccountupdatebackgroundcolor.php b/actions/apiaccountupdatebackgroundcolor.php
new file mode 100644 (file)
index 0000000..230ff5b
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Update a user's background color
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class ApiAccountUpdateBackgroundColorAction extends ApiAuthAction
+{
+    var $backgroundcolor = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $this->user   = $this->auth_user;
+
+        $this->backgroundcolor = $this->trimmed('backgroundcolor');
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Try to save the user's colors in her design. Create a new design
+     * if the user doesn't already have one.
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+            $this->clientError(
+                _('This method requires a POST.'),
+                400, $this->format
+            );
+            return;
+        }
+               
+               $validhex = preg_match('/^[a-f0-9]{6}$/i',$this->backgroundcolor);
+               if($validhex === false || $validhex == 0) {
+            $this->clientError(_('Not a valid hex color.'),404,'json');                        
+            return;
+                       }
+               
+               // save the new color
+               $original = clone($this->user);
+               $this->user->backgroundcolor = $this->backgroundcolor; 
+               if (!$this->user->update($original)) {
+            $this->clientError(_('Error updating user.'),404,'json');
+            return;
+               }
+
+        $profile = $this->user->getProfile();
+
+        if (empty($profile)) {
+            $this->clientError(_('User has no profile.'),'json');
+            return;
+        }
+
+        $twitter_user = $this->twitterUserArray($profile, true);
+
+        $this->initDocument('json');
+        $this->showJsonObjects($twitter_user);
+        $this->endDocument('json');
+    }
+
+
+}
diff --git a/actions/apiaccountupdatelinkcolor.php b/actions/apiaccountupdatelinkcolor.php
new file mode 100644 (file)
index 0000000..9416a32
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Update a user's link color
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class ApiAccountUpdateLinkColorAction extends ApiAuthAction
+{
+    var $linkcolor = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $this->user   = $this->auth_user;
+
+        $this->linkcolor = $this->trimmed('linkcolor');
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Try to save the user's colors in her design. Create a new design
+     * if the user doesn't already have one.
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+            $this->clientError(
+                _('This method requires a POST.'),
+                400, $this->format
+            );
+            return;
+        }
+               
+               $validhex = preg_match('/^[a-f0-9]{6}$/i',$this->linkcolor);
+               if($validhex === false || $validhex == 0) {
+            $this->clientError(_('Not a valid hex color.'),404,'json');                        
+            return;
+                       }
+               
+               // save the new color
+               $original = clone($this->user);
+               $this->user->linkcolor = $this->linkcolor; 
+               if (!$this->user->update($original)) {
+            $this->clientError(_('Error updating user.'),404,'json');
+            return;
+               }
+
+        $profile = $this->user->getProfile();
+
+        if (empty($profile)) {
+            $this->clientError(_('User has no profile.'),'json');
+            return;
+        }
+
+        $twitter_user = $this->twitterUserArray($profile, true);
+
+        $this->initDocument('json');
+        $this->showJsonObjects($twitter_user);
+        $this->endDocument('json');
+    }
+
+
+}
diff --git a/actions/apiattachment.php b/actions/apiattachment.php
new file mode 100644 (file)
index 0000000..52cb570
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a notice's attachment
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Show a notice's attachment
+ *
+ */
+class ApiAttachmentAction extends ApiAuthAction
+{
+    const MAXCOUNT = 100;
+
+    var $original = null;
+    var $cnt      = self::MAXCOUNT;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Make a new notice for the update, save it, and show it
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+        parent::handle($args);
+        $file = new File();
+        $file->selectAdd(); // clears it
+        $file->selectAdd('url');
+        $file->id = $this->trimmed('id');
+        $url = $file->fetchAll('url');
+        
+               $file_txt = '';
+               if(strstr($url[0],'.html')) {
+                       $file_txt['txt'] = file_get_contents(str_replace('://quitter.se','://127.0.0.1',$url[0]));
+                       $file_txt['body_start'] = strpos($file_txt['txt'],'<body>')+6;
+                       $file_txt['body_end'] = strpos($file_txt['txt'],'</body>');
+                       $file_txt = substr($file_txt['txt'],$file_txt['body_start'],$file_txt['body_end']-$file_txt['body_start']);
+                       }
+
+               $this->initDocument('json');
+               $this->showJsonObjects($file_txt);
+               $this->endDocument('json');
+    }
+
+    /**
+     * Return true if read only.
+     *
+     * MAY override
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean is read only action?
+     */
+
+    function isReadOnly($args)
+    {
+        return true;
+    }
+}
diff --git a/actions/apicheckhub.php b/actions/apicheckhub.php
new file mode 100644 (file)
index 0000000..d59506b
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a notice's attachment
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Check if a url have a push-hub, i.e. if it is possible to subscribe
+ *
+ */
+class ApiCheckHubAction extends ApiAuthAction
+{
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+               $this->url = urldecode($args['url']);
+               
+               if (!$this->url) {
+            $this->clientError(_('No URL.'), 403, 'json');
+            return;                    
+               }
+
+               if (!Validate::uri(
+                       $this->url, array(
+                           'allowed_schemes' =>
+                           array('http', 'https')
+                       )
+                   )) {
+            $this->clientError(_('Invalid URL.'), 403, 'json');
+            return;
+                       }
+               
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+
+               $discover = new FeedDiscovery();
+
+           try {
+                       $feeduri = $discover->discoverFromURL($this->url);
+                       if($feeduri) {
+                       $huburi = $discover->getHubLink();                              
+                               }
+           } catch (FeedSubNoFeedException $e) {
+               $this->clientError(_('No feed found'), 403, 'json');
+               return;
+           } catch (FeedSubBadResponseException $e) {
+               $this->clientError(_('No hub found'), 403, 'json');
+               return;
+           }
+               
+               $hub_status = array();
+               if ($huburi) {
+                       $hub_status = array('huburi' => $huburi);
+               }
+                       
+               $this->initDocument('json');
+               $this->showJsonObjects($hub_status);
+               $this->endDocument('json');
+    }
+
+    /**
+     * Return true if read only.
+     *
+     * MAY override
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean is read only action?
+     */
+
+    function isReadOnly($args)
+    {
+        return true;
+    }
+}
diff --git a/actions/apichecknickname.php b/actions/apichecknickname.php
new file mode 100644 (file)
index 0000000..7aa1283
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+               
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Check nickname
+ *
+ * Returns 1 if nickname is ok, 0 if not
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class ApiCheckNicknameAction extends ApiAction
+{
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+        
+        return true;
+    }
+
+    function handle($args)
+    {
+        parent::handle($args);
+       
+        $nickname = $this->trimmed('nickname');
+               
+        if ($this->nicknameExists($nickname)) {
+            $nickname_ok = 0;
+        } else if (!User::allowed_nickname($nickname)) {
+            $nickname_ok = 0;        }
+        else {
+            $nickname_ok = 1;          
+               }
+
+        $this->initDocument('json');
+        $this->showJsonObjects($nickname_ok);
+        $this->endDocument('json');
+    }
+    
+    function nicknameExists($nickname)
+    {
+        $user = User::staticGet('nickname', $nickname);
+        return is_object($user);
+    }    
+    
+}
index b3b44c77219b415f1cbe1dfa53a8fa45ffad5871..0e292303d58b2791e052f4da9d8c50eb63e096d2 100644 (file)
@@ -75,9 +75,7 @@ class ApiconversationAction extends ApiAuthAction
                                       404);
         }
 
-        $profile = Profile::current();
-
-        $stream = new ConversationNoticeStream($convId, $profile);
+        $stream = new ConversationNoticeStream($convId, $this->scoped);
 
         $notice = $stream->getNotices(($this->page-1) * $this->count,
                                       $this->count,
diff --git a/actions/apiexternalprofileshow.php b/actions/apiexternalprofileshow.php
new file mode 100644 (file)
index 0000000..2acc97f
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show an external user's profile information
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Ouputs information for a user, specified by ID or screen name.
+ * The user's most recent status will be returned inline.
+ */
+class ApiExternalProfileShowAction extends ApiPrivateAuthAction
+{
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $profileurl = urldecode($this->arg('profileurl'));        
+
+        $this->profile = Profile::staticGet('profileurl', $profileurl);        
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Check the format and show the user info
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if (empty($this->profile)) {
+            // TRANS: Client error displayed when requesting profile information for a non-existing profile.
+            $this->clientError(_('Profile not found.'), 404, 'json');
+            return;
+        }
+
+        $twitter_user = $this->twitterUserArray($this->profile, true);
+
+        $this->initDocument('json');
+        $this->showJsonObjects($twitter_user);
+        $this->endDocument('json');
+    }
+
+    /**
+     * Return true if read only.
+     *
+     * MAY override
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean is read only action?
+     */
+    function isReadOnly($args)
+    {
+        return true;
+    }
+}
index 43b1daf4fc62bd10975c5d002a052cdd870d9d0e..1f76e00b1a7ab7c2a641f372b8ea9486c55e8fb3 100644 (file)
@@ -33,8 +33,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Tests for the existence of friendship between two users. Will return true if
  * user_a follows user_b, otherwise will return false.
diff --git a/actions/apigroupadmins.php b/actions/apigroupadmins.php
new file mode 100644 (file)
index 0000000..3ddff15
--- /dev/null
@@ -0,0 +1,191 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * List a group's admins
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Craig Andrews <candrews@integralblue.com>
+ * @author    Evan Prodromou <evan@status.net>
+ * @author    Jeffery To <jeffery.to@gmail.com>
+ * @author    Zach Copley <zach@status.net>
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @copyright 2009 StatusNet, Inc.
+ * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) {
+    exit(1);
+}
+
+/**
+ * List 20 newest admins of the group specified by name or ID.
+ *
+ * @category API
+ * @package  GNUSocial
+ * @author   Craig Andrews <candrews@integralblue.com>
+ * @author   Evan Prodromou <evan@status.net>
+ * @author   Jeffery To <jeffery.to@gmail.com>
+ * @author   Zach Copley <zach@status.net>
+ * @author   Hannes Mannerheim <h@nnesmannerhe.im> 
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://www.gnu.org/software/social/
+ */
+class ApiGroupAdminsAction extends ApiPrivateAuthAction
+{
+    var $group    = null;
+    var $profiles = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $this->group    = $this->getTargetGroup($this->arg('id'));
+        if (empty($this->group)) {
+            // TRANS: Client error displayed trying to show group membership on a non-existing group.
+            $this->clientError(_('Group not found.'), 404, $this->format);
+            return false;
+        }
+
+        $this->profiles = $this->getProfiles();
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Show the admin of the group
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+        parent::handle($args);
+
+        // XXX: RSS and Atom
+
+        switch($this->format) {
+        case 'xml':
+            $this->showTwitterXmlUsers($this->profiles);
+            break;
+        case 'json':
+            $this->showJsonUsers($this->profiles);
+            break;
+        default:
+            $this->clientError(
+                // TRANS: Client error displayed when coming across a non-supported API method.
+                _('API method not found.'),
+                404,
+                $this->format
+            );
+            break;
+        }
+    }
+
+    /**
+     * Fetch the admins of a group
+     *
+     * @return array $profiles list of profiles
+     */
+    function getProfiles()
+    {
+        $profiles = array();
+
+        $profile = $this->group->getAdmins(
+            ($this->page - 1) * $this->count,
+            $this->count,
+            $this->since_id,
+            $this->max_id
+        );
+
+        while ($profile->fetch()) {
+            $profiles[] = clone($profile);
+        }
+
+        return $profiles;
+    }
+
+    /**
+     * Is this action read only?
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean true
+     */
+    function isReadOnly($args)
+    {
+        return true;
+    }
+
+    /**
+     * When was this list of profiles last modified?
+     *
+     * @return string datestamp of the lastest profile in the group
+     */
+    function lastModified()
+    {
+        if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+            return strtotime($this->profiles[0]->created);
+        }
+
+        return null;
+    }
+
+    /**
+     * An entity tag for this list of groups
+     *
+     * Returns an Etag based on the action name, language
+     * the group id, and timestamps of the first and last
+     * user who has joined the group
+     *
+     * @return string etag
+     */
+    function etag()
+    {
+        if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+
+            $last = count($this->profiles) - 1;
+
+            return '"' . implode(
+                ':',
+                array($this->arg('action'),
+                      common_user_cache_hash($this->auth_user),
+                      common_language(),
+                      $this->group->id,
+                      strtotime($this->profiles[0]->created),
+                      strtotime($this->profiles[$last]->created))
+            )
+            . '"';
+        }
+
+        return null;
+    }
+}
index 51c3df1b2f7e128cc8ee7d2f8bfe647f16288c7a..2fb3714257f7677258a07390539d807771633888 100644 (file)
@@ -35,8 +35,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Returns of the lastest 20 groups for the site
  *
index 7ad8fb767ec5731c24a3ed8a1b0b9a3f37d518a9..ed78d9eda8a27d588618b82cd0cd7e89ac41ebf8 100644 (file)
@@ -35,8 +35,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * List 20 newest members of the group specified by name or ID.
  *
index e99777e32c5326113d11a562570c28733769cb13..15b9edb975543937c5ed178df2d8d425e26cbb9e 100644 (file)
@@ -35,8 +35,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Outputs detailed information about the group specified by ID
  *
index 1bbbe572bf62cead29f7ed591a7d36e66864c84a..a9cd7394c92817b845246931f661039f80d407f6 100644 (file)
@@ -32,8 +32,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Returns the string "ok" in the requested format with a 200 OK HTTP status code.
  *
index 075a4df83de6421eb263797b9282a1972890f5a5..fdf95f1ce9fdcd8bc5290ba8d078ca8d82f25f52 100644 (file)
@@ -31,8 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
     exit(1);
 }
 
-require_once INSTALLDIR.'/lib/apiprivateauth.php';
-
 /**
  * Action for outputting search results in Twitter compatible Atom
  * format.
index 710ccdcccf94830efa7d8cf205ec230205fe9d02..9f1f71d35523075a9cfacf75e1500af04cae6050 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * @category  Search
- * @package   StatusNet
+ * @package   GNUSocial
  * @author    Zach Copley <zach@status.net>
  * @copyright 2008-2010 StatusNet, Inc.
+ * @copyright 2013 Free Software Foundation, Inc.
  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
+ * @link      http://www.gnu.org/software/social/
  */
 
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-require_once INSTALLDIR.'/lib/apiprivateauth.php';
-require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
+if (!defined('GNUSOCIAL')) { exit(1); }
 
 /**
  * Action handler for Twitter-compatible API search
@@ -89,12 +85,6 @@ class ApiSearchJSONAction extends ApiPrivateAuthAction
         $this->since_id = $this->trimmed('since_id');
         $this->geocode  = $this->trimmed('geocode');
 
-        if (!empty($this->auth_user)) {
-            $this->auth_profile = $this->auth_user->getProfile();
-        } else {
-            $this->auth_profile = null;
-        }
-
         return true;
     }
 
@@ -123,15 +113,15 @@ class ApiSearchJSONAction extends ApiPrivateAuthAction
         // TODO: Support search operators like from: and to:, boolean, etc.
 
         if (preg_match('/^#([\pL\pN_\-\.]{1,64})$/ue', $q)) {
-            $stream = new TagNoticeStream(substr($q, 1), $this->auth_profile);
+            $stream = new TagNoticeStream(substr($q, 1), $this->scoped);
         } else if ($this->isAnURL($q)) {
             $canon = File_redirection::_canonUrl($q);
             $file = File::getKV('url', $canon);
             if (!empty($file)) {
-                $stream = new FileNoticeStream($file, $this->auth_profile);
+                $stream = new FileNoticeStream($file, $this->scoped);
             }
         } else {
-            $stream = new SearchNoticeStream($q, $this->auth_profile);
+            $stream = new SearchNoticeStream($q, $this->scoped);
         }
 
         if (empty($stream)) {
diff --git a/actions/apistatusesfavs.php b/actions/apistatusesfavs.php
new file mode 100644 (file)
index 0000000..626ea37
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show up to 100 favs of a notice
+ *
+ * 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  API
+ * @package   GNUSocial
+ * @author    Hannes Mannerheim <h@nnesmannerhe.im>
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://www.gnu.org/software/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Show up to 100 favs of a notice
+ *
+ */
+class ApiStatusesFavsAction extends ApiAuthAction
+{
+    const MAXCOUNT = 100;
+
+    var $original = null;
+    var $cnt      = self::MAXCOUNT;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     */
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $id = $this->trimmed('id');
+
+        $this->original = Notice::staticGet('id', $id);
+
+        if (empty($this->original)) {
+            // TRANS: Client error displayed trying to display redents of a non-exiting notice.
+            $this->clientError(_('No such notice.'),
+                               400, $this->format);
+            return false;
+        }
+
+        $cnt = $this->trimmed('count');
+
+        if (empty($cnt) || !is_integer($cnt)) {
+            $cnt = 100;
+        } else {
+            $this->cnt = min((int)$cnt, self::MAXCOUNT);
+        }
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Get favs and return them as json object
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+    function handle($args)
+    {
+        parent::handle($args);
+       
+        $fave = new Fave();
+        $fave->selectAdd(); 
+        $fave->selectAdd('user_id');
+        $fave->notice_id = $this->original->id;
+        $fave->orderBy('modified');
+        if (!is_null($this->cnt)) {
+            $fave->limit(0, $this->cnt);
+        }
+
+               $ids = $fave->fetchAll('user_id');
+               
+               // get nickname and profile image
+               $ids_with_profile_data = array();
+               $i=0;
+               foreach($ids as $id) {
+                       $profile = Profile::staticGet('id', $id);
+                       $ids_with_profile_data[$i]['user_id'] = $id;
+                       $ids_with_profile_data[$i]['nickname'] = $profile->nickname;
+                       $ids_with_profile_data[$i]['fullname'] = $profile->fullname;                    
+                       $ids_with_profile_data[$i]['profileurl'] = $profile->profileurl;                                                
+                       $profile = new Profile();
+                       $profile->id = $id;
+                       $avatarurl = $profile->avatarUrl(24);
+                       $ids_with_profile_data[$i]['avatarurl'] = $avatarurl;                                                           
+                       $i++;
+               }
+               
+               $this->initDocument('json');
+               $this->showJsonObjects($ids_with_profile_data);
+               $this->endDocument('json');
+    }
+
+    /**
+     * Return true if read only.
+     *
+     * MAY override
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean is read only action?
+     */
+
+    function isReadOnly($args)
+    {
+        return true;
+    }
+}
index 9ab3c46e4cadf60f43b44f2ca2db4405b687275b..67d04a505ce76981bffdd91ec6ebc93d208c8536 100644 (file)
@@ -38,8 +38,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Returns the notice specified by id as a Twitter-style status and inline user
  *
index 3a7b150cab4e033d6088d2c2c912bdfae48916c0..b40f42aa161edb8f74c38c60fa470a955ee0dcdd 100644 (file)
@@ -32,8 +32,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Returns a version number for this version of StatusNet, which
  * should make things a bit easier for upgrades.
index 5a0ea60c7eb9cb6d8ee8bcde13c53222eb3c18e3..c238f3a989f005205bb63a86ebe4c87fa3cc986f 100644 (file)
@@ -35,8 +35,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Returns the most recent notices (default 20) posted to the group specified by ID
  *
index c2339f9c357cdc0d104f1c244c5908b7dc3a2523..6a3f6bfcc8346c1cc5d5acda52da8908cac19d9a 100644 (file)
@@ -35,7 +35,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
 require_once INSTALLDIR . '/lib/atomlistnoticefeed.php';
 
 /**
index b82e01aafe5658494544ab7f83b89bfe9a130a3d..338cd16fa093eff36a9a0c22081146ceed0cb56b 100644 (file)
@@ -38,8 +38,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Returns the most recent notices (default 20) posted by everybody
  *
index 5bc330a26eb485929f88cfa5f45fea9eb25a24f3..b3f17d0712019c9578f92f5fd8aa6dccbfe4b0f2 100644 (file)
@@ -35,8 +35,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Returns the 20 most recent notices tagged by a given tag
  *
@@ -179,7 +177,9 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
         $notice = Notice_tag::getStream(
             $this->tag,
             ($this->page - 1) * $this->count,
-            $this->count + 1
+            $this->count + 1,
+            $this->since_id,
+            $this->max_id
         );
 
         while ($notice->fetch()) {
index 2540c036c141b112d7f496ef6166cc656a95a64c..10771fad73972f0d93f153a57690bdf70ab0c0bf 100644 (file)
@@ -229,7 +229,8 @@ class ApiTimelineUserAction extends ApiBareAuthAction
         $notice = $this->user->getNotices(($this->page-1) * $this->count,
                                           $this->count + 1,
                                           $this->since_id,
-                                          $this->max_id);
+                                          $this->max_id,
+                                          $this->scoped);
 
         while ($notice->fetch()) {
             if (count($notices) < $this->count) {
index 3e854b1096cea7dc7c384f2513940268bec55d16..a39769a34e60024fb1744d2ecc2cba109d2bf678 100644 (file)
@@ -31,8 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
     exit(1);
 }
 
-require_once INSTALLDIR.'/lib/apiprivateauth.php';
-
 /**
  *  Returns the top ten queries that are currently trending
  *
index 81b447f7e73f673e61ed67d01ff5ce21488a1040..a996fe171806c1f618d5131c7e4aafb9d5ff20ce 100644 (file)
@@ -31,8 +31,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Ouputs avatar URL for a user, specified by screen name.
  * Unlike most API endpoints, this returns an HTTP redirect rather than direct data.
index 0ea0b2e72fd93643eea57eacaadcfb1417ae30d8..e68047eb2946fcdd66bdb8f90d648afb593d1018 100644 (file)
@@ -34,8 +34,6 @@ if (!defined('STATUSNET')) {
     exit(1);
 }
 
-require_once INSTALLDIR . '/lib/apiprivateauth.php';
-
 /**
  * Ouputs information for a user, specified by ID or screen name.
  * The user's most recent status will be returned inline.
index 13b37993858301e7c3de3f7b9db5df8fd1c1a29a..4812dff91a29b5caf70fb9e2262154fcaef43889 100644 (file)
@@ -211,6 +211,11 @@ class Notice extends Managed_DataObject
         return $result;
     }
 
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
     /**
      * Extract #hashtags from this notice's content and save them to the database.
      */
@@ -417,7 +422,7 @@ class Notice extends Managed_DataObject
 
             $repeat = Notice::getKV('id', $repeat_of);
 
-            if (empty($repeat)) {
+            if (!($repeat instanceof Notice)) {
                 // TRANS: Client exception thrown in notice when trying to repeat a missing or deleted notice.
                 throw new ClientException(_('Cannot repeat; original notice is missing or deleted.'));
             }
@@ -439,7 +444,7 @@ class Notice extends Managed_DataObject
                 throw new ClientException(_('Cannot repeat a notice you cannot read.'), 403);
             }
 
-            if ($profile->hasRepeated($repeat->id)) {
+            if ($profile->hasRepeated($repeat)) {
                 // TRANS: Client error displayed when trying to repeat an already repeated notice.
                 throw new ClientException(_('You already repeated that notice.'));
             }
@@ -1710,9 +1715,9 @@ class Notice extends Managed_DataObject
         // favorite and repeated
 
         if (!empty($cur)) {
-            $noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false";
             $cp = $cur->getProfile();
-            $noticeInfoAttr['repeated'] = ($cp->hasRepeated($this->id)) ? "true" : "false";
+            $noticeInfoAttr['favorite'] = ($cp->hasFave($this)) ? "true" : "false";
+            $noticeInfoAttr['repeated'] = ($cp->hasRepeated($this)) ? "true" : "false";
         }
 
         if (!empty($this->repeat_of)) {
index c0af2635a7d0705563eba491f15874411e3d17cd..e1bba076e9e31d0d9020b8d757537395e2afd5c1 100644 (file)
@@ -211,9 +211,9 @@ class Profile extends Managed_DataObject
         return $stream->getNotices($offset, $limit, $since_id, $max_id);
     }
 
-    function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
+    function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, Profile $scoped=null)
     {
-        $stream = new ProfileNoticeStream($this);
+        $stream = new ProfileNoticeStream($this, $scoped);
 
         return $stream->getNotices($offset, $limit, $since_id, $max_id);
     }
@@ -1157,12 +1157,13 @@ class Profile extends Managed_DataObject
         return $result;
     }
 
-    function hasRepeated($notice_id)
+    // FIXME: Can't put Notice typing here due to ArrayWrapper
+    public function hasRepeated($notice)
     {
         // XXX: not really a pkey, but should work
 
         $notice = Notice::pkeyGet(array('profile_id' => $this->id,
-                                        'repeat_of' => $notice_id));
+                                        'repeat_of' => $notice->id));
 
         return !empty($notice);
     }
index 50f4b7ddc7cb232e10e1c5dd60c862f71b6fc746..47ca3538e585598427ac2d573903619e75ce19c6 100644 (file)
@@ -210,7 +210,12 @@ class User_group extends Managed_DataObject
         return $members;
     }
 
-    function getMemberCount()
+    public function getAdminCount()
+    {
+        return $this->getAdmins()->N;
+    }
+
+    public function getMemberCount()
     {
         $key = sprintf("group:member_count:%d", $this->id);
 
index 36f22a3da517096cc59fc3419b7c9d5b44296330..d16edfd8049d083a7423cfa0a7485238465fbaa3 100644 (file)
@@ -62,7 +62,7 @@ class Action extends HTMLOutputter // lawsuit
     protected $menus  = true;
     protected $needLogin = false;
 
-    // The currently scoped profile
+    // The currently scoped profile (normally Profile::current; from $this->auth_user for API)
     protected $scoped = null;
 
     // Messages to the front-end user
index 781d106cf6bf4a68913b54dcd37dd82d891a66bf..0bafd8fdbba90b359b7fa8847ae0a95a083aa25c 100644 (file)
@@ -214,7 +214,23 @@ class ApiAction extends Action
         $twitter_user['location'] = ($profile->location) ? $profile->location : null;
         $twitter_user['description'] = ($profile->bio) ? $profile->bio : null;
 
-        $twitter_user['profile_image_url'] = $profile->avatarUrl(AVATAR_STREAM_SIZE);
+        // TODO: avatar url template (example.com/user/avatar?size={x}x{y})
+        $twitter_user['profile_image_url'] = Avatar::urlByProfile($profile, AVATAR_STREAM_SIZE);
+        // START introduced by qvitter API, not necessary for StatusNet API
+        $twitter_user['profile_image_url_profile_size'] = Avatar::urlByProfile($profile, AVATAR_PROFILE_SIZE);
+        try {
+            $avatar  = Avatar::getUploaded($profile);
+            $origurl = $avatar->displayUrl();
+        } catch (Exception $e) {
+            $origurl = $twitter_user['profile_image_url_profile_size'];
+        }
+        $twitter_user['profile_image_url_original'] = $origurl;
+
+        $twitter_user['groups_count'] = $profile->getGroups(0, null)->N;
+        foreach (array('linkcolor', 'backgroundcolor') as $key) {
+            $twitter_user[$key] = Profile_prefs::getConfigData($profile, 'theme', $key);
+        }
+        // END introduced by qvitter API, not necessary for StatusNet API
 
         $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null;
         $twitter_user['protected'] = (!empty($user) && $user->private_stream) ? true : false;
@@ -263,7 +279,7 @@ class ApiAction extends Action
 
         if ($get_notice) {
             $notice = $profile->getCurrentNotice();
-            if ($notice) {
+            if ($notice instanceof Notice) {
                 // don't get user!
                 $twitter_user['status'] = $this->twitterStatusArray($notice, false);
             }
@@ -299,8 +315,12 @@ class ApiAction extends Action
         $twitter_status['text'] = $notice->content;
         $twitter_status['truncated'] = false; # Not possible on StatusNet
         $twitter_status['created_at'] = $this->dateTwitter($notice->created);
-        $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ?
-            intval($notice->reply_to) : null;
+        try {
+            $in_reply_to = $notice->getParent()->id;
+        } catch (Exception $e) {
+            $in_reply_to = null;
+        }
+        $twitter_status['in_reply_to_status_id'] = $in_reply_to;
 
         $source = null;
 
@@ -317,6 +337,7 @@ class ApiAction extends Action
             }
         }
 
+        $twitter_status['uri'] = $notice->getUri();
         $twitter_status['source'] = $source;
         $twitter_status['id'] = intval($notice->id);
 
@@ -343,10 +364,12 @@ class ApiAction extends Action
             $twitter_status['geo'] = null;
         }
 
-        if (isset($this->auth_user)) {
-            $twitter_status['favorited'] = $this->auth_user->hasFave($notice);
+        if (!is_null($this->scoped)) {
+            $twitter_status['favorited'] = $this->scoped->hasFave($notice);
+            $twitter_status['repeated']  = $this->scoped->hasRepeated($notice);
         } else {
             $twitter_status['favorited'] = false;
+            $twitter_status['repeated'] = false;
         }
 
         // Enclosures
@@ -399,6 +422,7 @@ class ApiAction extends Action
             );
         }
 
+        $twitter_group['admin_count'] = $group->getAdminCount();
         $twitter_group['member_count'] = $group->getMemberCount();
         $twitter_group['original_logo'] = $group->original_logo;
         $twitter_group['homepage_logo'] = $group->homepage_logo;
@@ -1550,6 +1574,8 @@ class ApiAction extends Action
 
         } else if (self::is_decimal($id)) {
             return User_group::getKV('id', $id);
+        } else if ($this->arg('uri')) { // FIXME: move this into empty($id) check?
+            return User_group::getKV('uri', urldecode($this->arg('uri')));
         } else {
             return User_group::getForNickname($id);
         }
diff --git a/lib/apiprivateauth.php b/lib/apiprivateauth.php
deleted file mode 100644 (file)
index 12f9898..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Base class for API actions that only require auth when a site
- * is configured to be private
- *
- * 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  API
- * @package   StatusNet
- * @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>
- * @copyright 2009 StatusNet, Inc.
- * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
- * @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')) {
-    exit(1);
-}
-
-/**
- * Actions extending this class will require auth only if a site is private
- *
- * @category API
- * @package  StatusNet
- * @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/
- */
-class ApiPrivateAuthAction extends ApiAuthAction
-{
-   /**
-     * Does this API resource require authentication?
-     *
-     * @return boolean true or false
-     */
-    function requiresAuth()
-    {
-        // If the site is "private", all API methods except statusnet/config
-        // need authentication
-        if (common_config('site', 'private')) {
-            return true;
-        }
-
-        return false;
-    }
-}
diff --git a/lib/apiprivateauthaction.php b/lib/apiprivateauthaction.php
new file mode 100644 (file)
index 0000000..12f9898
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Base class for API actions that only require auth when a site
+ * is configured to be private
+ *
+ * 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  API
+ * @package   StatusNet
+ * @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>
+ * @copyright 2009 StatusNet, Inc.
+ * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
+ * @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')) {
+    exit(1);
+}
+
+/**
+ * Actions extending this class will require auth only if a site is private
+ *
+ * @category API
+ * @package  StatusNet
+ * @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/
+ */
+class ApiPrivateAuthAction extends ApiAuthAction
+{
+   /**
+     * Does this API resource require authentication?
+     *
+     * @return boolean true or false
+     */
+    function requiresAuth()
+    {
+        // If the site is "private", all API methods except statusnet/config
+        // need authentication
+        if (common_config('site', 'private')) {
+            return true;
+        }
+
+        return false;
+    }
+}
index 48540a4d587a56f76c8361ee7107efe147a9d74b..357ab9be5d0ac50ab35f4673d6c1df4286c3369b 100644 (file)
@@ -232,14 +232,7 @@ class ResultItem
         $this->id           = $this->notice->id;
         $this->from_user_id = $this->profile->id;
 
-        $user = $this->profile->getUser();
-
-        if (empty($user)) {
-            // Gonna have to do till we can detect it
-            $this->iso_language_code = common_config('site', 'language');
-        } else {
-            $this->iso_language_code = $user->language;
-        }
+        $this->iso_language_code = Profile_prefs::getConfigData($this->profile, 'site', 'language');
         
         $this->source = $this->getSourceLink($this->notice->source);
 
index 8fa5c5dcd4de2bfcd9ce8a3f160c4c42080135ea..19d6674ae35f9387590f70f0f0a0d3ae6514aed3 100644 (file)
@@ -693,7 +693,7 @@ class NoticeListItem extends Widget
                 $user->id != $this->notice->profile_id) {
                 $this->out->text(' ');
                 $profile = $user->getProfile();
-                if ($profile->hasRepeated($this->notice->id)) {
+                if ($profile->hasRepeated($this->notice)) {
                     $this->out->element('span', array('class' => 'repeated',
                                                       // TRANS: Title for repeat form status in notice list when a notice has been repeated.
                                                       'title' => _('Notice repeated.')),
index a7b59e6ab4edfc025c93988e30ae8f26953879a5..0d38d448359f9320b0b76b286a4651d905bd7957 100644 (file)
@@ -460,6 +460,41 @@ class Router
                               'id' => '[0-9]+',
                               'format' => '(xml|json)'));
 
+            // START qvitter API additions
+
+            $m->connect('api/statuses/favs/:id.json',
+                array('action' => 'ApiStatusesFavs',
+                'id' => '[0-9]+'));
+            
+            $m->connect('api/attachment/:id.json',
+                array('action' => 'ApiAttachment',
+                'id' => '[0-9]+'));
+            
+            $m->connect('api/checkhub.json',
+                array('action' => 'ApiCheckHub'));
+            
+            $m->connect('api/externalprofile/show.json',
+                array('action' => 'ApiExternalProfileShow'));
+
+            $m->connect('api/statusnet/groups/admins/:id.:format',
+                array('action' => 'ApiGroupAdmins',
+                    'id' => Nickname::INPUT_FMT,
+                    'format' => '(xml|json)'));
+            
+            $m->connect('api/account/update_link_color.json',
+                array('action' => 'ApiAccountUpdateLinkColor'));
+                
+            $m->connect('api/account/update_background_color.json',
+                array('action' => 'ApiAccountUpdateBackgroundColor'));
+
+            $m->connect('api/account/register.json',
+                array('action' => 'ApiAccountRegister'));
+            
+            $m->connect('api/check_nickname.json',
+                array('action' => 'ApiCheckNickname'));
+
+            // END qvitter API additions
+
             // users
 
             $m->connect('api/users/show/:id.:format',
@@ -773,6 +808,7 @@ class Router
             // Tags
             $m->connect('api/statusnet/tags/timeline/:tag.:format',
                         array('action' => 'ApiTimelineTag',
+                              'tag'    => self::REGEX_TAG,
                               'format' => '(xml|json|rss|atom|as)'));
 
             // media related
index 7e8d288b61331e69743eb90b571b5ca73ec637a9..0920856192f1487f1516b94d700b19c1e0f2793d 100644 (file)
@@ -148,10 +148,10 @@ class SubMirror extends Managed_DataObject
      * @param Notice $notice
      * @return mixed Notice on successful mirroring, boolean if not
      */
-    public function mirrorNotice($notice)
+    public function mirrorNotice(Notice $notice)
     {
         $profile = Profile::getKV('id', $this->subscriber);
-        if (!$profile) {
+        if (!($profile instanceof Profile)) {
             common_log(LOG_ERR, "SubMirror plugin skipping auto-repeat of notice $notice->id for missing user $profile->id");
             return false;
         }
@@ -172,9 +172,9 @@ class SubMirror extends Managed_DataObject
      * @param Notice $notice
      * @return mixed Notice on successful repeat, true if already repeated, false on failure
      */
-    protected function repeatNotice($profile, $notice)
+    protected function repeatNotice(Profile $profile, Notice $notice)
     {
-        if($profile->hasRepeated($notice->id)) {
+        if($profile->hasRepeated($notice)) {
             common_log(LOG_INFO, "SubMirror plugin skipping auto-repeat of notice $notice->id for user $profile->id; already repeated.");
             return true;
         } else {