mirror of
https://github.com/danog/TelegramApiServer.git
synced 2024-11-30 04:19:13 +01:00
downloadToCallable for media.
This commit is contained in:
parent
a42356592e
commit
6ef127e9a8
@ -3,7 +3,6 @@
|
||||
namespace TelegramApiServer\Controllers;
|
||||
|
||||
use Amp\ByteStream\ResourceInputStream;
|
||||
use Amp\Coroutine;
|
||||
use Amp\Http\Server\Request;
|
||||
use Amp\Http\Server\RequestHandler\CallableRequestHandler;
|
||||
use Amp\Http\Server\Response;
|
||||
@ -21,8 +20,10 @@ abstract class AbstractApiController
|
||||
public const JSON_HEADER = ['Content-Type'=>'application/json;charset=utf-8'];
|
||||
|
||||
protected Client $client;
|
||||
protected Request $request;
|
||||
protected $extensionClass;
|
||||
|
||||
|
||||
public array $page = [
|
||||
'headers' => self::JSON_HEADER,
|
||||
'success' => false,
|
||||
@ -40,8 +41,8 @@ abstract class AbstractApiController
|
||||
{
|
||||
return new CallableRequestHandler(
|
||||
static function (Request $request) use($client, $extensionClass) {
|
||||
$requestCallback = new static($client, $extensionClass);
|
||||
$response = yield from $requestCallback->process($request);
|
||||
$requestCallback = new static($client, $request, $extensionClass);
|
||||
$response = yield from $requestCallback->process();
|
||||
|
||||
return new Response(
|
||||
$requestCallback->page['code'],
|
||||
@ -52,9 +53,10 @@ abstract class AbstractApiController
|
||||
);
|
||||
}
|
||||
|
||||
public function __construct(Client $client, $extensionClass)
|
||||
public function __construct(Client $client, Request $request, $extensionClass = null)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->request = $request;
|
||||
$this->extensionClass = $extensionClass;
|
||||
}
|
||||
|
||||
@ -63,33 +65,31 @@ abstract class AbstractApiController
|
||||
* @return ResourceInputStream|string
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function process(Request $request)
|
||||
public function process()
|
||||
{
|
||||
$body = '';
|
||||
while ($chunk = yield $request->getBody()->read()) {
|
||||
$body .= $chunk;
|
||||
}
|
||||
|
||||
$this->resolvePath($request->getAttribute(Router::class));
|
||||
$this->resolveRequest($request->getUri()->getQuery(), $body, $request->getHeader('Content-Type'));
|
||||
$this->resolvePath($this->request->getAttribute(Router::class));
|
||||
yield from $this->resolveRequest($this->request);
|
||||
yield from $this->generateResponse();
|
||||
|
||||
return $this->getResponse();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Получаем параметры из GET и POST
|
||||
*
|
||||
* @param string $query
|
||||
* @param string|null $body
|
||||
* @param string|null $contentType
|
||||
* @param Request $request
|
||||
*
|
||||
* @return AbstractApiController
|
||||
*/
|
||||
private function resolveRequest(string $query, $body, $contentType)
|
||||
private function resolveRequest(Request $request)
|
||||
{
|
||||
$query = $request->getUri()->getQuery();
|
||||
$body = '';
|
||||
while ($chunk = yield $request->getBody()->read()) {
|
||||
$body .= $chunk;
|
||||
}
|
||||
$contentType = $request->getHeader('Content-Type');
|
||||
|
||||
parse_str($query, $get);
|
||||
|
||||
switch ($contentType) {
|
||||
@ -144,9 +144,9 @@ abstract class AbstractApiController
|
||||
protected function callApiCommon($madelineProto)
|
||||
{
|
||||
$pathCount = count($this->api);
|
||||
if ($pathCount === 1 && is_callable([$this->extensionClass,$this->api[0]])) {
|
||||
if ($pathCount === 1 && $this->extensionClass && is_callable([$this->extensionClass,$this->api[0]])) {
|
||||
/** @var ApiExtensions|SystemApiExtensions $madelineProtoExtensions */
|
||||
$madelineProtoExtensions = new $this->extensionClass($madelineProto);
|
||||
$madelineProtoExtensions = new $this->extensionClass($madelineProto, $this->request);
|
||||
$result = $madelineProtoExtensions->{$this->api[0]}(...$this->parameters);
|
||||
} else {
|
||||
//Проверяем нет ли в MadilineProto такого метода.
|
||||
@ -204,7 +204,7 @@ abstract class AbstractApiController
|
||||
}
|
||||
if (isset($this->page['response']['stream'])) {
|
||||
$this->page['headers'] = $this->page['response']['headers'];
|
||||
return new ResourceInputStream($this->page['response']['stream']);
|
||||
return $this->page['response']['stream'];
|
||||
}
|
||||
|
||||
$data = [
|
||||
|
@ -4,6 +4,9 @@
|
||||
namespace TelegramApiServer\MadelineProtoExtensions;
|
||||
|
||||
|
||||
use Amp\ByteStream\IteratorStream;
|
||||
use Amp\Http\Server\Request;
|
||||
use Amp\Producer;
|
||||
use Amp\Promise;
|
||||
use danog\MadelineProto\TL\Conversion\BotAPI;
|
||||
use OutOfRangeException;
|
||||
@ -16,10 +19,12 @@ class ApiExtensions
|
||||
use BotAPI;
|
||||
|
||||
private MadelineProto\Api $madelineProto;
|
||||
private Request $request;
|
||||
|
||||
public function __construct(MadelineProto\Api $madelineProto)
|
||||
public function __construct(MadelineProto\Api $madelineProto, Request $request)
|
||||
{
|
||||
$this->madelineProto = $madelineProto;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,17 +330,7 @@ class ApiExtensions
|
||||
);
|
||||
}
|
||||
|
||||
$stream = fopen('php://memory', 'rwb');
|
||||
yield $this->madelineProto->downloadToStream($info, $stream);
|
||||
rewind($stream);
|
||||
|
||||
return [
|
||||
'headers' => [
|
||||
'Content-Length' => $info['size'],
|
||||
'Content-Type' => $info['mime'],
|
||||
],
|
||||
'stream' => $stream,
|
||||
];
|
||||
return $this->downloadToResponse($info);
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -399,17 +394,7 @@ class ApiExtensions
|
||||
$info = $infoFull;
|
||||
}
|
||||
|
||||
$stream = fopen('php://memory', 'rwb');
|
||||
yield $this->madelineProto->downloadToStream($info, $stream);
|
||||
rewind($stream);
|
||||
|
||||
return [
|
||||
'headers' => [
|
||||
'Content-Length' => $info['size'],
|
||||
'Content-Type' => $info['mime'],
|
||||
],
|
||||
'stream' => $stream,
|
||||
];
|
||||
return $this->downloadToResponse($info);
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -440,4 +425,54 @@ class ApiExtensions
|
||||
);
|
||||
}
|
||||
|
||||
private function getByteRange(?string $header) {
|
||||
$matches = [
|
||||
'start' => 0,
|
||||
'end' => -1
|
||||
];
|
||||
if ($header) {
|
||||
preg_match("~bytes=(?'start'\d+)-(?'end'\d*)~", $header, $matches);
|
||||
}
|
||||
return [
|
||||
'start' => (int) $matches['start'],
|
||||
'end' => (int) $matches['end'] ?: -1
|
||||
];
|
||||
}
|
||||
|
||||
private function downloadToResponse(array $info) {
|
||||
|
||||
$range = $this->getByteRange($this->request->getHeader('Range'));
|
||||
|
||||
if ($range['end'] === -1) {
|
||||
$range['end'] = $info['size'] - 1;
|
||||
} else {
|
||||
$range['end'] = min($range['end'], $info['size'] - 1);
|
||||
}
|
||||
|
||||
$stream = new IteratorStream(new Producer(function (callable $emit) use($info, $range) {
|
||||
yield $this->madelineProto->downloadToCallable($info, static function($payload) use($emit) {
|
||||
yield $emit($payload);
|
||||
return strlen($payload);
|
||||
}, null, false, $range['start'], $range['end'] + 1);
|
||||
}));
|
||||
|
||||
$headers = [
|
||||
'Content-Type' => $info['mime'],
|
||||
// 'Accept-Ranges' => 'bytes',
|
||||
// 'Content-Transfer-Encoding'=> 'Binary',
|
||||
];
|
||||
|
||||
if ($range['start'] > 0 || $range['end'] < $info['size'] - 1) {
|
||||
$headers['Content-Length'] = ($range['end'] - $range['start'] + 1);
|
||||
$headers['Content-Range'] = "bytes {$range['start']}-{$range['end']}/{$info['size']}";
|
||||
} else {
|
||||
$headers['Content-Length'] = $info['size'];
|
||||
}
|
||||
|
||||
return [
|
||||
'headers' => $headers,
|
||||
'stream' => $stream,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user