mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 10:59:02 +01:00
Update
This commit is contained in:
parent
ac06acf704
commit
bd8602c57d
@ -29,7 +29,7 @@ use function Amp\ByteStream\getOutputBufferStream;
|
|||||||
*/
|
*/
|
||||||
trait Templates
|
trait Templates
|
||||||
{
|
{
|
||||||
private const TEMPLATE = '<!DOCTYPE html><html><head><title>MadelineProto</title></head><body><h1>MadelineProto</h1><p>%s</p><form method="POST">%s<button type="submit"/>%s</button></form>%s</body></html>';
|
private const TEMPLATE = '<!DOCTYPE html><html><head><title>MadelineProto</title></head><body><h1>MadelineProto</h1><p>%s</p><form method="POST">%s<button type="submit"/>%s</button></form></body></html>';
|
||||||
/**
|
/**
|
||||||
* Generate page from template.
|
* Generate page from template.
|
||||||
*
|
*
|
||||||
|
52
src/Ipc/Wrapper/Cancellation.php
Normal file
52
src/Ipc/Wrapper/Cancellation.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace danog\MadelineProto\Ipc\Wrapper;
|
||||||
|
|
||||||
|
use Amp\Cancellation as AmpCancellation;
|
||||||
|
use danog\MadelineProto\FileCallbackInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Cancellation extends Obj implements AmpCancellation
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Subscribes a new handler to be invoked on a cancellation request.
|
||||||
|
*
|
||||||
|
* This handler might be invoked immediately in case the cancellation has already been requested. Any unhandled
|
||||||
|
* exceptions will be thrown into the event loop.
|
||||||
|
*
|
||||||
|
* @param \Closure(CancelledException) $callback Callback to be invoked on a cancellation request. Will receive a
|
||||||
|
* `CancelledException` as first argument that may be used to fail the operation.
|
||||||
|
*
|
||||||
|
* @return string Identifier that can be used to cancel the subscription.
|
||||||
|
*/
|
||||||
|
public function subscribe(\Closure $callback): string {
|
||||||
|
return $this->__call('unsubscribe', [$callback]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribes a previously registered handler.
|
||||||
|
*
|
||||||
|
* The handler will no longer be called as long as this method isn't invoked from a subscribed callback.
|
||||||
|
*/
|
||||||
|
public function unsubscribe(string $id): void {
|
||||||
|
return $this->__call('unsubscribe', [$id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether cancellation has been requested yet.
|
||||||
|
*/
|
||||||
|
public function isRequested(): bool {
|
||||||
|
return $this->__call('isRequested');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws the `CancelledException` if cancellation has been requested, otherwise does nothing.
|
||||||
|
*
|
||||||
|
* @throws CancelledException
|
||||||
|
*/
|
||||||
|
public function throwIfRequested(): void {
|
||||||
|
$this->__call('throwIfRequested');
|
||||||
|
}
|
||||||
|
}
|
@ -174,6 +174,9 @@ final class Lang
|
|||||||
'en' =>
|
'en' =>
|
||||||
[
|
[
|
||||||
'go' => 'Go',
|
'go' => 'Go',
|
||||||
|
'loginChoosePromptWeb' => 'Do you want to login as a user or as a bot?',
|
||||||
|
'loginOptionBot' => 'Bot',
|
||||||
|
'loginOptionUser' => 'User',
|
||||||
'apiChooseManualAutoTip' => 'Note that you can also provide the API ID/hash directly in the code using the settings: %s',
|
'apiChooseManualAutoTip' => 'Note that you can also provide the API ID/hash directly in the code using the settings: %s',
|
||||||
'apiChooseManualAutoTipWeb' => 'Note that you can also provide the API ID/hash directly in the code using the <a target="_blank" href="%s">settings</a>.',
|
'apiChooseManualAutoTipWeb' => 'Note that you can also provide the API ID/hash directly in the code using the <a target="_blank" href="%s">settings</a>.',
|
||||||
'apiChoosePrompt' => 'Your choice (m/a): ',
|
'apiChoosePrompt' => 'Your choice (m/a): ',
|
||||||
|
@ -715,9 +715,6 @@ final class MTProto implements TLCallback, LoggerGetter
|
|||||||
|
|
||||||
'updateHandlerType',
|
'updateHandlerType',
|
||||||
|
|
||||||
// Web login template
|
|
||||||
'webTemplate',
|
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
'settings',
|
'settings',
|
||||||
'config',
|
'config',
|
||||||
|
152
src/TL/Types/LoginQrCode.php
Normal file
152
src/TL/Types/LoginQrCode.php
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login QR code.
|
||||||
|
*
|
||||||
|
* This file is part of MadelineProto.
|
||||||
|
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU Affero General Public License for more details.
|
||||||
|
* You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2023 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
|
||||||
|
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\MadelineProto\TL\Types;
|
||||||
|
|
||||||
|
use Amp\Cancellation;
|
||||||
|
use Amp\CancelledException;
|
||||||
|
use Amp\CompositeCancellation;
|
||||||
|
use Amp\DeferredFuture;
|
||||||
|
use Amp\TimeoutCancellation;
|
||||||
|
use Amp\TimeoutException;
|
||||||
|
use AssertionError;
|
||||||
|
use BaconQrCode\Renderer\Image\SvgImageBackEnd;
|
||||||
|
use BaconQrCode\Renderer\ImageRenderer;
|
||||||
|
use BaconQrCode\Renderer\PlainTextRenderer;
|
||||||
|
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
|
||||||
|
use BaconQrCode\Writer;
|
||||||
|
use danog\MadelineProto\Ipc\Client;
|
||||||
|
use danog\MadelineProto\MTProto;
|
||||||
|
use JsonSerializable;
|
||||||
|
use Webmozart\Assert\Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a login QR code.
|
||||||
|
*/
|
||||||
|
final class LoginQrCode implements JsonSerializable {
|
||||||
|
|
||||||
|
private string $session;
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
public function __construct(
|
||||||
|
private MTProto|Client $API,
|
||||||
|
/** @var non-empty-string The [QR code login link](https://core.telegram.org/api/links#qr-code-login-links) */
|
||||||
|
public readonly string $link,
|
||||||
|
/** @var positive-int The expiry date of the link */
|
||||||
|
public readonly int $expiry
|
||||||
|
) {
|
||||||
|
$this->session = $API->getWrapper()->getSession()->getSessionDirectoryPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function __sleep(): array
|
||||||
|
{
|
||||||
|
return ['link', 'expiry', 'session'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
public function jsonSerialize(): mixed
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'link' => $this->link,
|
||||||
|
'expiry' => $this->expiry,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the QR code has expired and a new one should be fetched.
|
||||||
|
*/
|
||||||
|
public function isExpired(): bool {
|
||||||
|
return $this->expiry <= time();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of seconds until the QR code expires.
|
||||||
|
*
|
||||||
|
* @return non-negative-int
|
||||||
|
*/
|
||||||
|
public function expiresIn(): int {
|
||||||
|
return max(0, $this->expiry - time());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExpirationCancellation(): Cancellation {
|
||||||
|
return new TimeoutCancellation((float) $this->expiresIn(), "The QR code expired!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getLoginCancellation(): Cancellation {
|
||||||
|
$this->API ??= Client::giveInstanceBySession($this->session);
|
||||||
|
return $this->API->getQrLoginCancellation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for the user to login or for the QR code to expire.
|
||||||
|
*
|
||||||
|
* If the user logins, null is returned.
|
||||||
|
*
|
||||||
|
* If the QR code expires, the new QR code is returned.
|
||||||
|
*
|
||||||
|
* If cancellation is requested externally through $cancellation, a CancelledException is thrown.
|
||||||
|
*
|
||||||
|
* @throws CancelledException
|
||||||
|
*
|
||||||
|
* @param Cancellation|null $customCancellation Optional additional cancellation
|
||||||
|
*/
|
||||||
|
public function waitForLoginOrQrCodeExpiration(?Cancellation $customCancellation = null): ?self {
|
||||||
|
$expire = $this->getExpirationCancellation();
|
||||||
|
if ($customCancellation) {
|
||||||
|
$cancellation = new CompositeCancellation($expire, $customCancellation);
|
||||||
|
} else {
|
||||||
|
$cancellation = $expire;
|
||||||
|
}
|
||||||
|
$login = $this->getLoginCancellation();
|
||||||
|
$cancellation = new CompositeCancellation($login, $cancellation);
|
||||||
|
try {
|
||||||
|
(new DeferredFuture)->getFuture()->await($cancellation);
|
||||||
|
} catch (CancelledException) {
|
||||||
|
$customCancellation?->throwIfRequested();
|
||||||
|
return $this->API->qrLogin();
|
||||||
|
}
|
||||||
|
throw new AssertionError("Unreachable!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render and return SVG version of QR code.
|
||||||
|
*/
|
||||||
|
public function getQRSvg(): string {
|
||||||
|
$writer = new Writer(new ImageRenderer(
|
||||||
|
new RendererStyle(400),
|
||||||
|
new SvgImageBackEnd
|
||||||
|
));
|
||||||
|
return $writer->writeString($this->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render and return plain text version of QR code.
|
||||||
|
*
|
||||||
|
* @param non-negative-int $margin Text margin
|
||||||
|
*/
|
||||||
|
public function getQRText(int $margin = 2): string {
|
||||||
|
$writer = new Writer(new PlainTextRenderer($margin));
|
||||||
|
return $writer->writeString($this->link);
|
||||||
|
}
|
||||||
|
}
|
@ -54,7 +54,7 @@ trait Templates
|
|||||||
$token = \htmlentities(Lang::$current_lang['loginBotTokenWeb']);
|
$token = \htmlentities(Lang::$current_lang['loginBotTokenWeb']);
|
||||||
$form = "<input type='text' name='token' placeholder='$token' required/>";
|
$form = "<input type='text' name='token' placeholder='$token' required/>";
|
||||||
}
|
}
|
||||||
} elseif (isset($_POST['waitQrCodeOrLogin'])) {
|
} elseif (isset($_GET['waitQrCodeOrLogin'])) {
|
||||||
header('Content-type: application/json');
|
header('Content-type: application/json');
|
||||||
try {
|
try {
|
||||||
/** @var ?LoginQrCode */
|
/** @var ?LoginQrCode */
|
||||||
|
Loading…
Reference in New Issue
Block a user