function flickr_api_call($method, $args = array(), $more = array())
{
    list($url, $args) = flickr_api_call_build($method, $args, $more);
    $defaults = array('http_timeout' => 10);
    $more = array_merge($defaults, $more);
    $headers = array();
    $rsp = http_post($url, $args, $headers, $more);
    # $url = $url . "?" . http_build_query($args);
    # $rsp = http_get($url);
    if (!$rsp['ok']) {
        return $rsp;
    }
    if (isset($more['raw'])) {
        return $rsp;
    }
    $json = json_decode($rsp['body'], 'as a hash');
    if (!$json) {
        return array('ok' => 0, 'error' => 'failed to parse response');
    }
    if ($json['stat'] != 'ok') {
        return array('ok' => 0, 'error' => $json['message']);
    }
    unset($json['stat']);
    return array('ok' => 1, 'rsp' => $json);
}
function flickr_api_call($method, $args = array(), $more = array())
{
    list($url, $args) = flickr_api_call_build($method, $args, $more);
    $defaults = array('http_timeout' => 10);
    $more = array_merge($defaults, $more);
    $headers = array();
    $rsp = http_post($url, $args, $headers, $more);
    # $url = $url . "?" . http_build_query($args);
    # $rsp = http_get($url);
    return flickr_api_parse_response($rsp);
}
# nw: which would make sense as to why I didn't put it in
#   before :)
# asc: yeah
# nw: there would have to be a little trickiness to wire it
#   up so that you could only use that format if you were getting your photos
# nw: or just remove the stuff you're not authed for
# So, instead we're going to call flickr.photos.getInfo a bunch...
# Note: this assumes that $to_backups will simply be empty if the
# various feature flags around push backups are disabled.
if (count($to_backup)) {
    loadlib("http");
    loadlib("flickr_photos_import");
    loadlib("flickr_faves_import");
    $reqs = array();
    foreach ($to_backup as $args) {
        list($url, $args) = flickr_api_call_build('flickr.photos.getInfo', $args);
        $url = $url . "?" . http_build_query($args);
        $reqs[] = array('method' => 'GET', 'url' => $url);
    }
    $multi_rsp = http_multi($reqs);
    $topic_map = flickr_push_topic_map();
    $topic_id = $subscription['topic_id'];
    $topic = $topic_map[$topic_id];
    foreach ($multi_rsp as $rsp) {
        $rsp = flickr_api_parse_response($rsp);
        if (!$rsp['ok']) {
            continue;
        }
        $photo = $rsp['rsp']['photo'];
        $spr = flickr_push_utils_info2spr($photo);
        # log_info("[PUSH] {$topic} ({$user['id']}) start import...");
function _flickr_photos_import_flickr_meta_urls($photo, $more = array())
{
    $req = array();
    # basic photo info
    if ($more['auth_token']) {
        $auth_token = $more['auth_token'];
    } else {
        $flickr_user = flickr_users_get_by_user_id($photo['user_id']);
        $auth_token = $flickr_user['auth_token'];
    }
    $method = 'flickr.photos.getInfo';
    $args = array('auth_token' => $auth_token, 'photo_id' => $photo['id']);
    list($url, $args) = flickr_api_call_build($method, $args);
    $api_call = $url . "?" . http_build_query($args);
    $req['info'] = $api_call;
    # fetch comments, which is to say check to see if there
    # are any new photos worth storing
    $fetch_comments = 1;
    if ($more['min_date']) {
        $method = 'flickr.photos.comments.getList';
        $args = array('photo_id' => $photo['id'], 'min_comment_date' => $more['min_date']);
        $rsp = flickr_api_call($method, $args);
        if ($rsp['ok'] && !isset($rsp['rsp']['comments']['comment'])) {
            $fetch_comments = 0;
        }
    }
    if ($fetch_comments) {
        $method = 'flickr.photos.comments.getList';
        $args = array('photo_id' => $photo['id']);
        list($url, $args) = flickr_api_call_build($method, $args);
        $api_call = $url . "?" . http_build_query($args);
        $req['comments'] = $api_call;
    }
    return $req;
}