1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-30 09:38:57 +01:00

Allow converting URLs and streams

This commit is contained in:
Daniil Gentili 2023-08-13 17:46:04 +02:00
parent df1e6b2ba8
commit a9aeaedaf4
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
7 changed files with 44 additions and 15 deletions

View File

@ -388,6 +388,7 @@ Want to add your own open-source project to this list? [Click here!](https://doc
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideChatJoinRequest.html" name="messages.hideChatJoinRequest">Dismiss or approve a chat join request related to a specific chat or channel: messages.hideChatJoinRequest</a> * <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideChatJoinRequest.html" name="messages.hideChatJoinRequest">Dismiss or approve a chat join request related to a specific chat or channel: messages.hideChatJoinRequest</a>
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideAllChatJoinRequests.html" name="messages.hideAllChatJoinRequests">Dismiss or approve all join requests related to a specific chat or channel: messages.hideAllChatJoinRequests</a> * <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideAllChatJoinRequests.html" name="messages.hideAllChatJoinRequests">Dismiss or approve all join requests related to a specific chat or channel: messages.hideAllChatJoinRequests</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoresponse-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-amp-http-server-request-request-callable-cb-null-null-int-size-null-null-string-mime-null-null-string-name-null-amp-http-server-response" name="downloadToResponse">Download file to amphp/http-server response: downloadToResponse</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoresponse-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-amp-http-server-request-request-callable-cb-null-null-int-size-null-null-string-mime-null-null-string-name-null-amp-http-server-response" name="downloadToResponse">Download file to amphp/http-server response: downloadToResponse</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoreturnedstream-mixed-messagemedia-callable-cb-null-int-offset-0-int-end-1-amp-bytestream-readablestream" name="downloadToReturnedStream">Download file to an amphp stream, returning it: downloadToReturnedStream</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtobrowser-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-null-callable-cb-null-null-int-size-null-null-string-name-null-null-string-mime-null-void" name="downloadToBrowser">Download file to browser: downloadToBrowser</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtobrowser-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-null-callable-cb-null-null-int-size-null-null-string-name-null-null-string-mime-null-void" name="downloadToBrowser">Download file to browser: downloadToBrowser</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtocallable-mixed-messagemedia-callable-filecallbackinterface-callable-callable-cb-null-bool-seekable-true-int-offset-0-int-end-1-int-part_size-null-mixed" name="downloadToCallable">Download file to callable: downloadToCallable</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtocallable-mixed-messagemedia-callable-filecallbackinterface-callable-callable-cb-null-bool-seekable-true-int-offset-0-int-end-1-int-part_size-null-mixed" name="downloadToCallable">Download file to callable: downloadToCallable</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtodir-mixed-messagemedia-string-filecallbackinterface-dir-callable-cb-null-mixed" name="downloadToDir">Download file to directory: downloadToDir</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtodir-mixed-messagemedia-string-filecallbackinterface-dir-callable-cb-null-mixed" name="downloadToDir">Download file to directory: downloadToDir</a>

View File

@ -121,3 +121,5 @@ final class MemoryArray extends ArrayIterator implements DbArray
return $this; return $this;
} }
} }
class_alias(MemoryArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\MemoryArray');

View File

@ -142,3 +142,5 @@ final class MysqlArray extends SqlArray
"); ");
} }
} }
class_alias(MysqlArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\MysqlArray');

View File

@ -109,3 +109,5 @@ final class PostgresArray extends PostgresArrayBytea
"); ");
} }
} }
class_alias(PostgresArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\PostgresArray');

View File

@ -127,3 +127,5 @@ class PostgresArrayBytea extends SqlArray
"); ");
} }
} }
class_alias(PostgresArrayBytea::class, '\\danog\\MadelineProto\\Db\\NullCache\\PostgresArrayBytea');

View File

@ -155,3 +155,5 @@ final class RedisArray extends DriverArray
} }
} }
} }
class_alias(RedisArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\RedisArray');

View File

@ -19,10 +19,15 @@ declare(strict_types=1);
namespace danog\MadelineProto; namespace danog\MadelineProto;
use Amp\ByteStream\ReadableStream; use Amp\ByteStream\ReadableStream;
use Amp\File\Whence; use Amp\ByteStream\WritableStream;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use AssertionError; use AssertionError;
use danog\MadelineProto\Stream\BufferedStreamInterface; use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\BufferInterface; use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\Transport\PremadeStream;
use FFI; use FFI;
use FFI\CData; use FFI\CData;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
@ -498,7 +503,7 @@ final class Ogg
public static function convert( public static function convert(
LocalFile|RemoteUrl|ReadableStream $wavIn, LocalFile|RemoteUrl|ReadableStream $wavIn,
string $oggOut LocalFile|WritableStream $oggOut
): void { ): void {
$opus = FFI::cdef(' $opus = FFI::cdef('
typedef struct OpusEncoder OpusEncoder; typedef struct OpusEncoder OpusEncoder;
@ -542,23 +547,33 @@ final class Ogg
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BANDWIDTH_REQUEST, self::OPUS_BANDWIDTH_FULLBAND)); $checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BANDWIDTH_REQUEST, self::OPUS_BANDWIDTH_FULLBAND));
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BITRATE_REQUEST, 130*1000)); $checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BITRATE_REQUEST, 130*1000));
$in = openFile($wavIn, 'r'); $in = $wavIn instanceof LocalFile
Assert::eq($in->read(length: 4), 'RIFF', "A .wav file must be provided!"); ? openFile($wavIn->file, 'r')
$totalLength = \unpack('V', $in->read(length: 4))[1]; : (
Assert::eq($in->read(length: 4), 'WAVE'); $wavIn instanceof RemoteUrl
? HttpClientBuilder::buildDefault()->request(new Request($wavIn->url))->getBody()
: $wavIn
);
$ctx = (new ConnectionContext())->addStream(PremadeStream::class, $in)->addStream(SimpleBufferedRawStream::class);
/** @var SimpleBufferedRawStream */
$in = $ctx->getStream();
Assert::eq($in->bufferRead(length: 4), 'RIFF', "A .wav file must be provided!");
$totalLength = \unpack('V', $in->bufferRead(length: 4))[1];
Assert::eq($in->bufferRead(length: 4), 'WAVE');
do { do {
$type = $in->read(length: 4); $type = $in->bufferRead(length: 4);
$length = \unpack('V', $in->read(length: 4))[1]; $length = \unpack('V', $in->bufferRead(length: 4))[1];
if ($type === 'fmt ') { if ($type === 'fmt ') {
Assert::eq($length, 16); Assert::eq($length, 16);
$contents = $in->read(length: $length + ($length % 2)); $contents = $in->bufferRead(length: $length + ($length % 2));
$header = \unpack('vaudioFormat/vchannels/VsampleRate/VbyteRate/vblockAlign/vbitsPerSample', $contents); $header = \unpack('vaudioFormat/vchannels/VsampleRate/VbyteRate/vblockAlign/vbitsPerSample', $contents);
Assert::eq($header['audioFormat'], 1); Assert::eq($header['audioFormat'], 1);
Assert::eq($header['sampleRate'], 48000); Assert::eq($header['sampleRate'], 48000);
} elseif ($type === 'data') { } elseif ($type === 'data') {
break; break;
} else { } else {
$in->seek($length, Whence::Current); $in->bufferRead($length);
} }
} while (true); } while (true);
@ -566,7 +581,9 @@ final class Ogg
$chunkSize = (int) ($sampleCount * $header['channels'] * ($header['bitsPerSample'] >> 3)); $chunkSize = (int) ($sampleCount * $header['channels'] * ($header['bitsPerSample'] >> 3));
$shift = (int) \log($header['channels'] * ($header['bitsPerSample'] >> 3), 2); $shift = (int) \log($header['channels'] * ($header['bitsPerSample'] >> 3), 2);
$out = openFile($oggOut, 'w'); $out = $oggOut instanceof LocalFile
? openFile($oggOut->file, 'w')
: $oggOut;
$writePage = function (int $header_type_flag, int $granule, int $streamId, int &$streamSeqno, string $packet) use ($out): void { $writePage = function (int $header_type_flag, int $granule, int $streamId, int &$streamSeqno, string $packet) use ($out): void {
Assert::true(\strlen($packet) < 65025); Assert::true(\strlen($packet) < 65025);
@ -638,19 +655,20 @@ final class Ogg
$granule = 0; $granule = 0;
$buf = FFI::cast(FFI::type('char*'), FFI::addr($opus->new('char[1024]'))); $buf = FFI::cast(FFI::type('char*'), FFI::addr($opus->new('char[1024]')));
while (!$in->eof()) { do {
$chunk = \str_pad($in->read(length: $chunkSize), $chunkSize, "\0"); $chunkOrig = $in->bufferRead(length: $chunkSize);
$chunk = \str_pad($chunkOrig, $chunkSize, "\0");
$granuleDiff = \strlen($chunk) >> $shift; $granuleDiff = \strlen($chunk) >> $shift;
$len = $opus->opus_encode($encoder, $chunk, $granuleDiff, $buf, 1024); $len = $opus->opus_encode($encoder, $chunk, $granuleDiff, $buf, 1024);
$checkErr($len); $checkErr($len);
$writePage( $writePage(
$in->eof() ? self::EOS : 0, \strlen($chunk) !== \strlen($chunkOrig) ? self::EOS : 0,
$granule += $granuleDiff, $granule += $granuleDiff,
$streamId, $streamId,
$seqno, $seqno,
FFI::string($buf, $len) FFI::string($buf, $len)
); );
} } while (\strlen($chunk) === \strlen($chunkOrig));
$opus->opus_encoder_destroy($encoder); $opus->opus_encoder_destroy($encoder);
unset($buf, $encoder, $opus); unset($buf, $encoder, $opus);