git.gnu.io has moved to IP address 209.51.188.249 -- please double check where you are logging in.

Commit 0caf0612 authored by mmn's avatar mmn

Make Twitter Media upload API v1.1 reach us

Now we just have to accept the 'media' or 'media_data' (base64 encoded)
POST arguments instead of $_FILES uploads.
parent 6e49281a
......@@ -57,6 +57,11 @@ class ApiMediaUploadAction extends ApiAuthAction
{
parent::handle();
// fallback to xml for older clients etc
if (empty($this->format)) {
$this->format = 'xml';
}
// Workaround for PHP returning empty $_POST and $_FILES when POST
// length > post_max_size in php.ini
......@@ -69,7 +74,7 @@ class ApiMediaUploadAction extends ApiAuthAction
$msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
intval($_SERVER['CONTENT_LENGTH']));
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
throw new ClientException(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
}
// we could catch "NoUploadedMediaException" as "no media uploaded", but here we _always_ want an upload
......@@ -77,6 +82,9 @@ class ApiMediaUploadAction extends ApiAuthAction
// Thumbnails will be generated/cached on demand when accessed (such as with /attachment/:id/thumbnail)
if (!in_array($this->format, ['json', 'xml'])) {
throw new ClientException('This API call does not support the format '._ve($this->format));
}
$this->showResponse($upload);
}
......@@ -88,19 +96,61 @@ class ApiMediaUploadAction extends ApiAuthAction
*
* @return void
*/
function showResponse(MediaFile $upload)
protected function showResponse(MediaFile $upload)
{
$this->initDocument($this->format);
switch ($this->format) {
case 'json':
return $this->showResponseJson($upload);
case 'xml':
return $this->showResponseXml($upload);
default:
throw new ClientException('This API call does not support the format '._ve($this->format));
}
$this->endDocument($this->format);
}
protected function showResponseJson(MediaFile $upload)
{
$enc = $upload->fileRecord->getEnclosure();
// note that we use media_id instead of mediaid which XML users might've gotten used to (nowadays we service media_id in both!)
$output = [
'media_id' => $upload->fileRecord->id,
'media_id_string' => (string)$upload->fileRecord->id,
'media_url' => $upload->shortUrl(),
'size' => $upload->fileRecord->size,
];
if (common_get_mime_media($enc->mimetype) === 'image') {
$output['image'] = [
'w' => $enc->width,
'h' => $enc->height,
'image_type' => $enc->mimetype,
];
}
print json_encode($output);
}
protected function showResponseXml(MediaFile $upload)
{
$this->initDocument();
$this->elementStart('rsp', array('stat' => 'ok', 'xmlns:atom'=>Activity::ATOM));
$this->element('mediaid', null, $upload->fileRecord->id);
$this->element('mediaurl', null, $upload->shortUrl());
$this->element('media_url', null, $upload->shortUrl());
$this->element('size', null, $upload->fileRecord->size);
$enclosure = $upload->fileRecord->getEnclosure();
$this->element('atom:link', array('rel' => 'enclosure',
'href' => $enclosure->url,
'type' => $enclosure->mimetype));
// Twitter specific metadata expected in response since Twitter's Media upload API v1.1 (even though Twitter doesn't use XML)
$this->element('media_id', null, $upload->fileRecord->id);
$this->element('media_id_string', null, (string)$upload->fileRecord->id);
if (common_get_mime_media($enclosure->mimetype) === 'image') {
$this->element('image', ['w'=>$enclosure->width, 'h'=>$enclosure->height, 'image_type'=>$enclosure->mimetype]);
}
$this->elementEnd('rsp');
$this->endDocument();
}
/**
......@@ -110,15 +160,24 @@ class ApiMediaUploadAction extends ApiAuthAction
*/
function clientError($msg, $code=400, $format=null)
{
$this->initDocument();
$this->elementStart('rsp', array('stat' => 'fail'));
$this->initDocument($this->format);
switch ($this->format) {
case 'json':
$error = ['errors' => array()];
$error['errors'][] = ['message'=>$msg, 'code'=>131];
print json_encode($error);
break;
case 'xml':
$this->elementStart('rsp', array('stat' => 'fail'));
// @todo add in error code
$errAttr = array('msg' => $msg);
// @todo add in error code
$errAttr = array('msg' => $msg);
$this->element('err', $errAttr, null);
$this->elementEnd('rsp');
$this->endDocument();
$this->element('err', $errAttr, null);
$this->elementEnd('rsp');
break;
}
$this->endDocument($this->format);
exit;
}
}
......@@ -369,8 +369,10 @@ class File extends Managed_DataObject
}
$enclosure = (object) array();
foreach (array('title', 'url', 'date', 'modified', 'size', 'mimetype') as $key) {
$enclosure->$key = $this->$key;
foreach (array('title', 'url', 'date', 'modified', 'size', 'mimetype', 'width', 'height') as $key) {
if ($this->$key !== '') {
$enclosure->$key = $this->$key;
}
}
$needMoreMetadataMimetypes = array(null, 'application/xhtml+xml', 'text/html');
......
......@@ -764,6 +764,13 @@ class Router
'api/statuses/update_with_media.json',
array('action' => 'ApiMediaUpload')
);
// Twitter Media upload API v1.1
$m->connect(
'api/media/upload.:format',
array('action' => 'ApiMediaUpload',
'format' => '(xml|json)',
)
);
// search
$m->connect('api/search.atom', array('action' => 'ApiSearchAtom'));
......
......@@ -179,8 +179,8 @@ class OembedPlugin extends Plugin
return true;
}
foreach (array('mimetype', 'url', 'title', 'modified') as $key) {
if (!empty($oembed->{$key})) {
foreach (array('mimetype', 'url', 'title', 'modified', 'width', 'height') as $key) {
if (isset($oembed->{$key}) && !empty($oembed->{$key})) {
$enclosure->{$key} = $oembed->{$key};
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment