]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - lib/apiaction.php
Misses this file to merge. I like the comments.
[quix0rs-gnu-social.git] / lib / apiaction.php
index 14e21ae4fdc15f8ad8980862bc473a57d8e16fd8..0eea08bed63f147a4c05b1edaec6fbfc68793cd2 100644 (file)
@@ -54,7 +54,7 @@
 
     @subsection usermethods_sec User Methods
 
-    @subsection directmessagemethods_sec Direct Message Methods
+    @subsection directmessagemethods_sec Direct Message Methods (now a plugin)
 
     @subsection friendshipmethods_sec Friendship Methods
 
@@ -119,15 +119,17 @@ class ApiAction extends Action
     const READ_ONLY  = 1;
     const READ_WRITE = 2;
 
-    var $format    = null;
     var $user      = null;
     var $auth_user = null;
     var $page      = null;
     var $count     = null;
+    var $offset    = null;
+    var $limit     = null;
     var $max_id    = null;
     var $since_id  = null;
     var $source    = null;
     var $callback  = null;
+    var $format    = null;
 
     var $access    = self::READ_ONLY;  // read (default) or read-write
 
@@ -140,9 +142,9 @@ class ApiAction extends Action
      *
      * @return boolean false if user doesn't exist
      */
-    function prepare($args)
+    protected function prepare(array $args=array())
     {
-        StatusNet::setApi(true); // reduce exception reports to aid in debugging
+        GNUsocial::setApi(true); // reduce exception reports to aid in debugging
         parent::prepare($args);
 
         $this->format   = $this->arg('format');
@@ -152,8 +154,12 @@ class ApiAction extends Action
         $this->max_id   = (int)$this->arg('max_id', 0);
         $this->since_id = (int)$this->arg('since_id', 0);
 
+        // These two are not used everywhere, mainly just AtompubAction extensions
+        $this->offset   = ($this->page-1) * $this->count;
+        $this->limit    = $this->count + 1;
+
         if ($this->arg('since')) {
-            header('X-StatusNet-Warning: since parameter is disabled; use since_id');
+            header('X-GNUsocial-Warning: since parameter is disabled; use since_id');
         }
 
         $this->source = $this->trimmed('source');
@@ -172,10 +178,10 @@ class ApiAction extends Action
      *
      * @return void
      */
-    function handle($args)
+    protected function handle()
     {
         header('Access-Control-Allow-Origin: *');
-        parent::handle($args);
+        parent::handle();
     }
 
     /**
@@ -202,7 +208,11 @@ class ApiAction extends Action
     {
         $twitter_user = array();
 
-        $user = $profile->getUser();
+        try {
+            $user = $profile->getUser();
+        } catch (NoSuchUserException $e) {
+            $user = null;
+        }
 
         $twitter_user['id'] = intval($profile->id);
         $twitter_user['name'] = $profile->getBestName();
@@ -210,9 +220,25 @@ class ApiAction extends Action
         $twitter_user['location'] = ($profile->location) ? $profile->location : null;
         $twitter_user['description'] = ($profile->bio) ? $profile->bio : null;
 
-        $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
-        $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() :
-            Avatar::defaultImage(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);
+        $twitter_user['profile_image_url_https'] = $twitter_user['profile_image_url'];
+
+        // 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->getGroupCount();
+        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;
@@ -224,8 +250,6 @@ class ApiAction extends Action
 
         $twitter_user['created_at'] = $this->dateTwitter($profile->created);
 
-        $twitter_user['favourites_count'] = $profile->faveCount(); // British spelling!
-
         $timezone = 'UTC';
 
         if (!empty($user) && $user->timezone) {
@@ -240,28 +264,26 @@ class ApiAction extends Action
         $twitter_user['statuses_count'] = $profile->noticeCount();
 
         // Is the requesting user following this user?
+        // These values might actually also mean "unknown". Ambiguity issues?
         $twitter_user['following'] = false;
         $twitter_user['statusnet_blocking'] = false;
         $twitter_user['notifications'] = false;
 
-        if (isset($this->auth_user)) {
-
-            $twitter_user['following'] = $this->auth_user->isSubscribed($profile);
-            $twitter_user['statusnet_blocking']  = $this->auth_user->hasBlocked($profile);
-
-            // Notifications on?
-            $sub = Subscription::pkeyGet(array('subscriber' =>
-                                               $this->auth_user->id,
-                                               'subscribed' => $profile->id));
-
-            if ($sub) {
+        if ($this->scoped instanceof Profile) {
+            try {
+                $sub = Subscription::getSubscription($this->scoped, $profile);
+                // Notifications on?
+                $twitter_user['following'] = true;
+                $twitter_user['statusnet_blocking']  = $this->scoped->hasBlocked($profile);
                 $twitter_user['notifications'] = ($sub->jabber || $sub->sms);
+            } catch (NoResultException $e) {
+                // well, the values are already false...
             }
         }
 
         if ($get_notice) {
             $notice = $profile->getCurrentNotice();
-            if ($notice) {
+            if ($notice instanceof Notice) {
                 // don't get user!
                 $twitter_user['status'] = $this->twitterStatusArray($notice, false);
             }
@@ -271,6 +293,9 @@ class ApiAction extends Action
 
         $twitter_user['statusnet_profile_url'] = $profile->profileurl;
 
+        // The event call to handle NoticeSimpleStatusArray lets plugins add data to the output array
+        Event::handle('TwitterUserArray', array($profile, &$twitter_user, $this->scoped, array()));
+
         return $twitter_user;
     }
 
@@ -278,11 +303,12 @@ class ApiAction extends Action
     {
         $base = $this->twitterSimpleStatusArray($notice, $include_user);
 
+        // FIXME: MOVE TO SHARE PLUGIN
         if (!empty($notice->repeat_of)) {
-            $original = Notice::staticGet('id', $notice->repeat_of);
-            if (!empty($original)) {
-                $original_array = $this->twitterSimpleStatusArray($original, $include_user);
-                $base['retweeted_status'] = $original_array;
+            $original = Notice::getKV('id', $notice->repeat_of);
+            if ($original instanceof Notice) {
+                $orig_array = $this->twitterSimpleStatusArray($original, $include_user);
+                $base['retweeted_status'] = $orig_array;
             }
         }
 
@@ -297,13 +323,20 @@ 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 {
+            // We could just do $notice->reply_to but maybe the future holds a
+            // different story for parenting.
+            $parent = $notice->getParent();
+            $in_reply_to = $parent->id;
+        } catch (Exception $e) {
+            $in_reply_to = null;
+        }
+        $twitter_status['in_reply_to_status_id'] = $in_reply_to;
 
         $source = null;
 
         $ns = $notice->getSource();
-        if ($ns) {
+        if ($ns instanceof Notice_source) {
             if (!empty($ns->name) && !empty($ns->url)) {
                 $source = '<a href="'
                    . htmlspecialchars($ns->url)
@@ -315,13 +348,14 @@ class ApiAction extends Action
             }
         }
 
+        $twitter_status['uri'] = $notice->getUri();
         $twitter_status['source'] = $source;
         $twitter_status['id'] = intval($notice->id);
 
         $replier_profile = null;
 
         if ($notice->reply_to) {
-            $reply = Notice::staticGet(intval($notice->reply_to));
+            $reply = Notice::getKV(intval($notice->reply_to));
             if ($reply) {
                 $replier_profile = $reply->getProfile();
             }
@@ -341,12 +375,6 @@ class ApiAction extends Action
             $twitter_status['geo'] = null;
         }
 
-        if (isset($this->auth_user)) {
-            $twitter_status['favorited'] = $this->auth_user->hasFave($notice);
-        } else {
-            $twitter_status['favorited'] = false;
-        }
-
         // Enclosures
         $attachments = $notice->attachments();
 
@@ -355,13 +383,15 @@ class ApiAction extends Action
             $twitter_status['attachments'] = array();
 
             foreach ($attachments as $attachment) {
-                $enclosure_o=$attachment->getEnclosure();
-                if ($enclosure_o) {
+                try {
+                    $enclosure_o = $attachment->getEnclosure();
                     $enclosure = array();
                     $enclosure['url'] = $enclosure_o->url;
                     $enclosure['mimetype'] = $enclosure_o->mimetype;
                     $enclosure['size'] = $enclosure_o->size;
                     $twitter_status['attachments'][] = $enclosure;
+                } catch (ServerException $e) {
+                    // There was not enough metadata available
                 }
             }
         }
@@ -377,6 +407,10 @@ class ApiAction extends Action
         $twitter_status['statusnet_html'] = $notice->rendered;
         $twitter_status['statusnet_conversation_id'] = intval($notice->conversation);
 
+        // The event call to handle NoticeSimpleStatusArray lets plugins add data to the output array
+        Event::handle('NoticeSimpleStatusArray', array($notice, &$twitter_status, $this->scoped,
+                                                       array('include_user'=>$include_user)));
+
         return $twitter_status;
     }
 
@@ -389,14 +423,15 @@ class ApiAction extends Action
         $twitter_group['nickname'] = $group->nickname;
         $twitter_group['fullname'] = $group->fullname;
 
-        if (isset($this->auth_user)) {
-            $twitter_group['member'] = $this->auth_user->isMember($group);
+        if ($this->scoped instanceof Profile) {
+            $twitter_group['member'] = $this->scoped->isMember($group);
             $twitter_group['blocked'] = Group_block::isBlocked(
                 $group,
-                $this->auth_user->getProfile()
+                $this->scoped
             );
         }
 
+        $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;
@@ -431,7 +466,7 @@ class ApiAction extends Action
 
     function twitterListArray($list)
     {
-        $profile = Profile::staticGet('id', $list->tagger);
+        $profile = Profile::getKV('id', $list->tagger);
 
         $twitter_list = array();
         $twitter_list['id'] = $list->id;
@@ -443,8 +478,8 @@ class ApiAction extends Action
         $twitter_list['member_count'] = $list->taggedCount();
         $twitter_list['uri'] = $list->getUri();
 
-        if (isset($this->auth_user)) {
-            $twitter_list['following'] = $list->hasSubscriber($this->auth_user);
+        if ($this->scoped instanceof Profile) {
+            $twitter_list['following'] = $list->hasSubscriber($this->scoped);
         } else {
             $twitter_list['following'] = false;
         }
@@ -480,13 +515,15 @@ class ApiAction extends Action
             $enclosures = array();
 
             foreach ($attachments as $attachment) {
-                $enclosure_o=$attachment->getEnclosure();
-                if ($enclosure_o) {
+                try {
+                    $enclosure_o = $attachment->getEnclosure();
                     $enclosure = array();
                     $enclosure['url'] = $enclosure_o->url;
                     $enclosure['mimetype'] = $enclosure_o->mimetype;
                     $enclosure['size'] = $enclosure_o->size;
                     $enclosures[] = $enclosure;
+                } catch (ServerException $e) {
+                    // There was not enough metadata available
                 }
             }
 
@@ -531,33 +568,29 @@ class ApiAction extends Action
         $relationship = array();
 
         $relationship['source'] =
-            $this->relationshipDetailsArray($source, $target);
+            $this->relationshipDetailsArray($source->getProfile(), $target->getProfile());
         $relationship['target'] =
-            $this->relationshipDetailsArray($target, $source);
+            $this->relationshipDetailsArray($target->getProfile(), $source->getProfile());
 
         return array('relationship' => $relationship);
     }
 
-    function relationshipDetailsArray($source, $target)
+    function relationshipDetailsArray(Profile $source, Profile $target)
     {
         $details = array();
 
-        $details['screen_name'] = $source->nickname;
+        $details['screen_name'] = $source->getNickname();
         $details['followed_by'] = $target->isSubscribed($source);
-        $details['following'] = $source->isSubscribed($target);
-
-        $notifications = false;
-
-        if ($source->isSubscribed($target)) {
-            $sub = Subscription::pkeyGet(array('subscriber' =>
-                $source->id, 'subscribed' => $target->id));
 
-            if (!empty($sub)) {
-                $notifications = ($sub->jabber || $sub->sms);
-            }
+        try {
+            $sub = Subscription::getSubscription($source, $target);
+            $details['following'] = true;
+            $details['notifications_enabled'] = ($sub->jabber || $sub->sms);
+        } catch (NoResultException $e) {
+            $details['following'] = false;
+            $details['notifications_enabled'] = false;
         }
 
-        $details['notifications_enabled'] = $notifications;
         $details['blocking'] = $source->hasBlocked($target);
         $details['id'] = intval($source->id);
 
@@ -608,6 +641,7 @@ class ApiAction extends Action
                 $this->showGeoXML($value);
                 break;
             case 'retweeted_status':
+                // FIXME: MOVE TO SHARE PLUGIN
                 $this->showTwitterXmlStatus($value, 'retweeted_status');
                 break;
             default:
@@ -741,7 +775,7 @@ class ApiAction extends Action
     function showSingleAtomStatus($notice)
     {
         header('Content-Type: application/atom+xml; charset=utf-8');
-        print $notice->asAtomEntry(true, true, true, $this->auth_user);
+        print $notice->asAtomEntry(true, true, true, $this->scoped);
     }
 
     function show_single_json_status($notice)
@@ -926,101 +960,6 @@ class ApiAction extends Action
         $this->elementEnd('entry');
     }
 
-    function showXmlDirectMessage($dm, $namespaces=false)
-    {
-        $attrs = array();
-        if ($namespaces) {
-            $attrs['xmlns:statusnet'] = 'http://status.net/schema/api/1/';
-        }
-        $this->elementStart('direct_message', $attrs);
-        foreach($dm as $element => $value) {
-            switch ($element) {
-            case 'sender':
-            case 'recipient':
-                $this->showTwitterXmlUser($value, $element);
-                break;
-            case 'text':
-                $this->element($element, null, common_xml_safe_str($value));
-                break;
-            default:
-                $this->element($element, null, $value);
-                break;
-            }
-        }
-        $this->elementEnd('direct_message');
-    }
-
-    function directMessageArray($message)
-    {
-        $dmsg = array();
-
-        $from_profile = $message->getFrom();
-        $to_profile = $message->getTo();
-
-        $dmsg['id'] = intval($message->id);
-        $dmsg['sender_id'] = intval($from_profile->id);
-        $dmsg['text'] = trim($message->content);
-        $dmsg['recipient_id'] = intval($to_profile->id);
-        $dmsg['created_at'] = $this->dateTwitter($message->created);
-        $dmsg['sender_screen_name'] = $from_profile->nickname;
-        $dmsg['recipient_screen_name'] = $to_profile->nickname;
-        $dmsg['sender'] = $this->twitterUserArray($from_profile, false);
-        $dmsg['recipient'] = $this->twitterUserArray($to_profile, false);
-
-        return $dmsg;
-    }
-
-    function rssDirectMessageArray($message)
-    {
-        $entry = array();
-
-        $from = $message->getFrom();
-
-        $entry['title'] = sprintf('Message from %1$s to %2$s',
-            $from->nickname, $message->getTo()->nickname);
-
-        $entry['content'] = common_xml_safe_str($message->rendered);
-        $entry['link'] = common_local_url('showmessage', array('message' => $message->id));
-        $entry['published'] = common_date_iso8601($message->created);
-
-        $taguribase = TagURI::base();
-
-        $entry['id'] = "tag:$taguribase:$entry[link]";
-        $entry['updated'] = $entry['published'];
-
-        $entry['author-name'] = $from->getBestName();
-        $entry['author-uri'] = $from->homepage;
-
-        $avatar = $from->getAvatar(AVATAR_STREAM_SIZE);
-
-        $entry['avatar']      = (!empty($avatar)) ? $avatar->url : Avatar::defaultImage(AVATAR_STREAM_SIZE);
-        $entry['avatar-type'] = (!empty($avatar)) ? $avatar->mediatype : 'image/png';
-
-        // RSS item specific
-
-        $entry['description'] = $entry['content'];
-        $entry['pubDate'] = common_date_rfc2822($message->created);
-        $entry['guid'] = $entry['link'];
-
-        return $entry;
-    }
-
-    function showSingleXmlDirectMessage($message)
-    {
-        $this->initDocument('xml');
-        $dmsg = $this->directMessageArray($message);
-        $this->showXmlDirectMessage($dmsg, true);
-        $this->endDocument('xml');
-    }
-
-    function showSingleJsonDirectMessage($message)
-    {
-        $this->initDocument('json');
-        $dmsg = $this->directMessageArray($message);
-        $this->showJsonObjects($dmsg);
-        $this->endDocument('json');
-    }
-
     function showAtomGroups($group, $title, $id, $link, $subtitle=null, $selfuri=null)
     {
         $this->initDocument('atom');
@@ -1291,7 +1230,6 @@ class ApiAction extends Action
         default:
             // TRANS: Client error on an API request with an unsupported data format.
             $this->clientError(_('Not a supported data format.'));
-            break;
         }
 
         return;
@@ -1318,91 +1256,10 @@ class ApiAction extends Action
         default:
             // TRANS: Client error on an API request with an unsupported data format.
             $this->clientError(_('Not a supported data format.'));
-            break;
         }
         return;
     }
 
-    function clientError($msg, $code = 400, $format = null)
-    {
-        $action = $this->trimmed('action');
-        if ($format === null) {
-            $format = $this->format;
-        }
-
-        common_debug("User error '$code' on '$action': $msg", __FILE__);
-
-        if (!array_key_exists($code, ClientErrorAction::$status)) {
-            $code = 400;
-        }
-
-        $status_string = ClientErrorAction::$status[$code];
-
-        // Do not emit error header for JSONP
-        if (!isset($this->callback)) {
-            header('HTTP/1.1 ' . $code . ' ' . $status_string);
-        }
-
-        switch($format) {
-        case 'xml':
-            $this->initDocument('xml');
-            $this->elementStart('hash');
-            $this->element('error', null, $msg);
-            $this->element('request', null, $_SERVER['REQUEST_URI']);
-            $this->elementEnd('hash');
-            $this->endDocument('xml');
-            break;
-        case 'json':
-            $this->initDocument('json');
-            $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']);
-            print(json_encode($error_array));
-            $this->endDocument('json');
-            break;
-        case 'text':
-            header('Content-Type: text/plain; charset=utf-8');
-            print $msg;
-            break;
-        default:
-            // If user didn't request a useful format, throw a regular client error
-            throw new ClientException($msg, $code);
-        }
-    }
-
-    function serverError($msg, $code = 500, $content_type = null)
-    {
-        $action = $this->trimmed('action');
-        if ($content_type === null) {
-            $content_type = $this->format;
-        }
-
-        common_debug("Server error '$code' on '$action': $msg", __FILE__);
-
-        if (!array_key_exists($code, ServerErrorAction::$status)) {
-            $code = 400;
-        }
-
-        $status_string = ServerErrorAction::$status[$code];
-
-        // Do not emit error header for JSONP
-        if (!isset($this->callback)) {
-            header('HTTP/1.1 '.$code.' '.$status_string);
-        }
-
-        if ($content_type == 'xml') {
-            $this->initDocument('xml');
-            $this->elementStart('hash');
-            $this->element('error', null, $msg);
-            $this->element('request', null, $_SERVER['REQUEST_URI']);
-            $this->elementEnd('hash');
-            $this->endDocument('xml');
-        } else {
-            $this->initDocument('json');
-            $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']);
-            print(json_encode($error_array));
-            $this->endDocument('json');
-        }
-    }
-
     function initTwitterRss()
     {
         $this->startXML();
@@ -1453,7 +1310,6 @@ class ApiAction extends Action
         default:
             // TRANS: Client error on an API request with an unsupported data format.
             $this->clientError(_('Not a supported data format.'));
-            return;
         }
         return;
     }
@@ -1468,29 +1324,29 @@ class ApiAction extends Action
         if (empty($id)) {
             // Twitter supports these other ways of passing the user ID
             if (self::is_decimal($this->arg('id'))) {
-                return User::staticGet($this->arg('id'));
+                return User::getKV($this->arg('id'));
             } else if ($this->arg('id')) {
                 $nickname = common_canonical_nickname($this->arg('id'));
-                return User::staticGet('nickname', $nickname);
+                return User::getKV('nickname', $nickname);
             } else if ($this->arg('user_id')) {
                 // This is to ensure that a non-numeric user_id still
                 // overrides screen_name even if it doesn't get used
                 if (self::is_decimal($this->arg('user_id'))) {
-                    return User::staticGet('id', $this->arg('user_id'));
+                    return User::getKV('id', $this->arg('user_id'));
                 }
             } else if ($this->arg('screen_name')) {
                 $nickname = common_canonical_nickname($this->arg('screen_name'));
-                return User::staticGet('nickname', $nickname);
+                return User::getKV('nickname', $nickname);
             } else {
                 // Fall back to trying the currently authenticated user
-                return $this->auth_user;
+                return $this->scoped->getUser();
             }
 
         } else if (self::is_decimal($id)) {
-            return User::staticGet($id);
+            return User::getKV($id);
         } else {
             $nickname = common_canonical_nickname($id);
-            return User::staticGet('nickname', $nickname);
+            return User::getKV('nickname', $nickname);
         }
     }
 
@@ -1500,28 +1356,31 @@ class ApiAction extends Action
 
             // Twitter supports these other ways of passing the user ID
             if (self::is_decimal($this->arg('id'))) {
-                return Profile::staticGet($this->arg('id'));
+                return Profile::getKV($this->arg('id'));
             } else if ($this->arg('id')) {
                 // Screen names currently can only uniquely identify a local user.
                 $nickname = common_canonical_nickname($this->arg('id'));
-                $user = User::staticGet('nickname', $nickname);
+                $user = User::getKV('nickname', $nickname);
                 return $user ? $user->getProfile() : null;
             } else if ($this->arg('user_id')) {
                 // This is to ensure that a non-numeric user_id still
                 // overrides screen_name even if it doesn't get used
                 if (self::is_decimal($this->arg('user_id'))) {
-                    return Profile::staticGet('id', $this->arg('user_id'));
+                    return Profile::getKV('id', $this->arg('user_id'));
                 }
             } else if ($this->arg('screen_name')) {
                 $nickname = common_canonical_nickname($this->arg('screen_name'));
-                $user = User::staticGet('nickname', $nickname);
-                return $user ? $user->getProfile() : null;
+                $user = User::getKV('nickname', $nickname);
+                return $user instanceof User ? $user->getProfile() : null;
+            } else {
+                // Fall back to trying the currently authenticated user
+                return $this->scoped;
             }
         } else if (self::is_decimal($id)) {
-            return Profile::staticGet($id);
+            return Profile::getKV($id);
         } else {
             $nickname = common_canonical_nickname($id);
-            $user = User::staticGet('nickname', $nickname);
+            $user = User::getKV('nickname', $nickname);
             return $user ? $user->getProfile() : null;
         }
     }
@@ -1530,21 +1389,23 @@ class ApiAction extends Action
     {
         if (empty($id)) {
             if (self::is_decimal($this->arg('id'))) {
-                return User_group::staticGet('id', $this->arg('id'));
+                return User_group::getKV('id', $this->arg('id'));
             } else if ($this->arg('id')) {
                 return User_group::getForNickname($this->arg('id'));
             } else if ($this->arg('group_id')) {
                 // This is to ensure that a non-numeric group_id still
                 // overrides group_name even if it doesn't get used
                 if (self::is_decimal($this->arg('group_id'))) {
-                    return User_group::staticGet('id', $this->arg('group_id'));
+                    return User_group::getKV('id', $this->arg('group_id'));
                 }
             } else if ($this->arg('group_name')) {
                 return User_group::getForNickname($this->arg('group_name'));
             }
 
         } else if (self::is_decimal($id)) {
-            return User_group::staticGet('id', $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);
         }
@@ -1561,7 +1422,7 @@ class ApiAction extends Action
 
         if($id) {
             if (is_numeric($id)) {
-                $list = Profile_list::staticGet('id', $id);
+                $list = Profile_list::getKV('id', $id);
 
                 // only if the list with the id belongs to the tagger
                 if(empty($list) || $list->tagger != $tagger->id) {
@@ -1574,7 +1435,7 @@ class ApiAction extends Action
             }
 
             if (!empty($list) && $list->private) {
-                if ($this->auth_user->id == $list->tagger) {
+                if ($this->scoped->id == $list->tagger) {
                     return $list;
                 }
             } else {
@@ -1642,6 +1503,11 @@ class ApiAction extends Action
             $aargs['id'] = $id;
         }
 
+        $user = $this->arg('user');
+        if (!empty($user)) {
+            $aargs['user'] = $user;
+        }
+
         $tag = $this->arg('tag');
         if (!empty($tag)) {
             $aargs['tag'] = $tag;