Localize login

This commit is contained in:
Daniil Gentili 2020-09-26 21:57:06 +02:00
parent c9ebdd0fa8
commit 86fc8b6e6e
17 changed files with 341 additions and 261 deletions

View File

@ -23,8 +23,8 @@ use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop; use Amp\Loop;
use danog\MadelineProto\Ipc\Client; use danog\MadelineProto\Ipc\Client;
use danog\MadelineProto\Ipc\Server; use danog\MadelineProto\Ipc\Server;
use danog\MadelineProto\Settings\Ipc as SettingsIpc;
use danog\MadelineProto\Settings\Logger as SettingsLogger; use danog\MadelineProto\Settings\Logger as SettingsLogger;
use danog\MadelineProto\Settings\Serialization as SettingsSerialization;
/** /**
* Main API wrapper for MadelineProto. * Main API wrapper for MadelineProto.
@ -128,7 +128,7 @@ class API extends InternalDoc
/** /**
* Async constructor function. * Async constructor function.
* *
* @param Settings|SettingsEmpty|SettingsSerialization $settings Settings * @param Settings|SettingsEmpty|SettingsIpc $settings Settings
* *
* @return \Generator * @return \Generator
*/ */
@ -136,13 +136,15 @@ class API extends InternalDoc
{ {
Logger::constructorFromSettings($settings instanceof Settings Logger::constructorFromSettings($settings instanceof Settings
? $settings->getLogger() ? $settings->getLogger()
: new SettingsLogger); : ($settings instanceof SettingsLogger ? $settings : new SettingsLogger));
if (yield from $this->connectToMadelineProto($settings)) { if (yield from $this->connectToMadelineProto($settings)) {
return; // OK return; // OK
} }
if (!$settings instanceof Settings) { if (!$settings instanceof Settings) {
$settings = new Settings; $newSettings = new Settings;
$newSettings->merge($settings);
$settings = $newSettings;
} }
$appInfo = $settings->getAppInfo(); $appInfo = $settings->getAppInfo();
@ -184,7 +186,7 @@ class API extends InternalDoc
*/ */
protected function connectToMadelineProto(SettingsAbstract $settings, bool $forceFull = false): \Generator protected function connectToMadelineProto(SettingsAbstract $settings, bool $forceFull = false): \Generator
{ {
if ($settings instanceof SettingsSerialization) { if ($settings instanceof SettingsIpc) {
$forceFull = $forceFull || $settings->getForceFull(); $forceFull = $forceFull || $settings->getForceFull();
} elseif ($settings instanceof Settings) { } elseif ($settings instanceof Settings) {
$forceFull = $forceFull || $settings->getSerialization()->getForceFull(); $forceFull = $forceFull || $settings->getSerialization()->getForceFull();
@ -218,7 +220,7 @@ class API extends InternalDoc
unset($unserialized); unset($unserialized);
if ($settings instanceof SettingsSerialization) { if ($settings instanceof SettingsIpc) {
$settings = new SettingsEmpty; $settings = new SettingsEmpty;
} }
yield from $this->API->wakeup($settings, $this->wrapper); yield from $this->API->wakeup($settings, $this->wrapper);

View File

@ -189,7 +189,7 @@ final class APIWrapper
} }
yield from $this->session->serialize( yield from $this->session->serialize(
yield from $this->API->serializeSession($this), $this->API ? yield from $this->API->serializeSession($this) : $this,
$this->session->getSessionPath() $this->session->getSessionPath()
); );

View File

@ -19,6 +19,7 @@
namespace danog\MadelineProto\ApiWrappers; namespace danog\MadelineProto\ApiWrappers;
use danog\MadelineProto\Lang;
use danog\MadelineProto\MyTelegramOrgWrapper; use danog\MadelineProto\MyTelegramOrgWrapper;
use danog\MadelineProto\Settings; use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools; use danog\MadelineProto\Tools;
@ -41,31 +42,37 @@ trait Start
if (\defined(\MADELINE_WORKER::class)) { if (\defined(\MADELINE_WORKER::class)) {
throw new \danog\MadelineProto\Exception('Not inited!'); throw new \danog\MadelineProto\Exception('Not inited!');
} }
if ($this->getWebAPITemplate() === 'legacy') {
$this->setWebAPITemplate($settings->getTemplates()->getHtmlTemplate());
}
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
$stdout = getStdout(); $stdout = getStdout();
yield $stdout->write('You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a) $prepare = Lang::$current_lang['apiChooseManualAuto'].PHP_EOL;
Note that you can also provide the API parameters directly in the code using the settings: https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id'.PHP_EOL); $prepare .= \sprintf(Lang::$current_lang['apiChooseManualAutoTip'], 'https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id');
if (\strpos(yield Tools::readLine('Your choice (m/a): '), 'm') !== false) { $prepare .= PHP_EOL;
yield $stdout->write('1) Login to my.telegram.org yield $stdout->write($prepare);
2) Go to API development tools if (\strpos(yield Tools::readLine(Lang::$current_lang['apiChoosePrompt']), 'm') !== false) {
3) App title: your app\'s name, can be anything yield $stdout->write("1) ".Lang::$current_lang['apiManualInstructions0'].PHP_EOL);
Short name: your app\'s short name, can be anything yield $stdout->write("2) ".Lang::$current_lang['apiManualInstructions1'].PHP_EOL);
URL: your app/website\'s URL, or t.me/yourusername yield $stdout->write("3) ");
Platform: anything foreach (['App title', 'Short name', 'URL', 'Platform', 'Description'] as $k => $key) {
Description: Describe your app here yield $stdout->write($k ? " $key: " : "$key: ");
4) Click on create application'.PHP_EOL); yield $stdout->write(Lang::$current_lang["apiAppInstructionsManual$k"].PHP_EOL);
$app['api_id'] = yield Tools::readLine('5) Enter your API ID: '); }
$app['api_hash'] = yield Tools::readLine('6) Enter your API hash: '); yield $stdout->write("4) ".Lang::$current_lang['apiManualInstructions2'].PHP_EOL);
$app['api_id'] = yield Tools::readLine("5) ".Lang::$current_lang['apiManualPrompt0']);
$app['api_hash'] = yield Tools::readLine("6) ".Lang::$current_lang['apiManualPrompt1']);
return $app; return $app;
} }
$this->myTelegramOrgWrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings); $this->myTelegramOrgWrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings);
yield from $this->myTelegramOrgWrapper->login(yield Tools::readLine('Enter a phone number that is already registered on Telegram: ')); yield from $this->myTelegramOrgWrapper->login(yield Tools::readLine(Lang::$current_lang['apiAutoPrompt0']));
yield from $this->myTelegramOrgWrapper->completeLogin(yield Tools::readLine('Enter the verification code you received in telegram: ')); yield from $this->myTelegramOrgWrapper->completeLogin(yield Tools::readLine(Lang::$current_lang['apiAutoPrompt1']));
if (!(yield from $this->myTelegramOrgWrapper->hasApp())) { if (!(yield from $this->myTelegramOrgWrapper->hasApp())) {
$app_title = yield Tools::readLine('Enter the app\'s name, can be anything: '); $app_title = yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto0']);
$short_name = yield Tools::readLine('Enter the app\'s short name, can be anything: '); $short_name = yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto1']);
$url = yield Tools::readLine('Enter the app/website\'s URL, or t.me/yourusername: '); $url = yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto2']);
$description = yield Tools::readLine('Describe your app: '); $description = yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto4']);
$app = (yield from $this->myTelegramOrgWrapper->createApp(['app_title' => $app_title, 'app_shortname' => $short_name, 'app_url' => $url, 'app_platform' => 'web', 'app_desc' => $description])); $app = (yield from $this->myTelegramOrgWrapper->createApp(['app_title' => $app_title, 'app_shortname' => $short_name, 'app_url' => $url, 'app_platform' => 'web', 'app_desc' => $description]));
} else { } else {
$app = (yield from $this->myTelegramOrgWrapper->getApp()); $app = (yield from $this->myTelegramOrgWrapper->getApp());
@ -82,7 +89,7 @@ Note that you can also provide the API parameters directly in the code using the
} elseif (isset($_POST['phone_number'])) { } elseif (isset($_POST['phone_number'])) {
yield from $this->webAPIPhoneLogin($settings); yield from $this->webAPIPhoneLogin($settings);
} else { } else {
yield from $this->webAPIEcho(); yield $this->webAPIEcho();
} }
} elseif (!$this->myTelegramOrgWrapper->loggedIn()) { } elseif (!$this->myTelegramOrgWrapper->loggedIn()) {
if (isset($_POST['code'])) { if (isset($_POST['code'])) {
@ -90,7 +97,7 @@ Note that you can also provide the API parameters directly in the code using the
if (yield from $this->myTelegramOrgWrapper->hasApp()) { if (yield from $this->myTelegramOrgWrapper->hasApp()) {
return yield from $this->myTelegramOrgWrapper->getApp(); return yield from $this->myTelegramOrgWrapper->getApp();
} }
yield from $this->webAPIEcho(); yield $this->webAPIEcho();
} elseif (isset($_POST['api_id']) && isset($_POST['api_hash'])) { } elseif (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
$app['api_id'] = (int) $_POST['api_id']; $app['api_id'] = (int) $_POST['api_id'];
$app['api_hash'] = $_POST['api_hash']; $app['api_hash'] = $_POST['api_hash'];
@ -100,7 +107,7 @@ Note that you can also provide the API parameters directly in the code using the
yield from $this->webAPIPhoneLogin($settings); yield from $this->webAPIPhoneLogin($settings);
} else { } else {
$this->myTelegramOrgWrapper = null; $this->myTelegramOrgWrapper = null;
yield from $this->webAPIEcho(); yield $this->webAPIEcho();
} }
} else { } else {
if (isset($_POST['app_title'], $_POST['app_shortname'], $_POST['app_url'], $_POST['app_platform'], $_POST['app_desc'])) { if (isset($_POST['app_title'], $_POST['app_shortname'], $_POST['app_url'], $_POST['app_platform'], $_POST['app_desc'])) {
@ -108,7 +115,7 @@ Note that you can also provide the API parameters directly in the code using the
$this->gettingApiId = false; $this->gettingApiId = false;
return $app; return $app;
} }
yield from $this->webAPIEcho("You didn't provide all of the required parameters!"); yield from $this->webAPIEcho(Lang::$current_lang['apiParamsError']);
} }
return null; return null;
} }
@ -117,9 +124,9 @@ Note that you can also provide the API parameters directly in the code using the
try { try {
$this->myTelegramOrgWrapper = new MyTelegramOrgWrapper($settings); $this->myTelegramOrgWrapper = new MyTelegramOrgWrapper($settings);
yield from $this->myTelegramOrgWrapper->login($_POST['phone_number']); yield from $this->myTelegramOrgWrapper->login($_POST['phone_number']);
yield from $this->webAPIEcho(); yield $this->webAPIEcho();
} catch (\Throwable $e) { } catch (\Throwable $e) {
yield from $this->webAPIEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
private function webAPICompleteLogin(): \Generator private function webAPICompleteLogin(): \Generator
@ -127,9 +134,9 @@ Note that you can also provide the API parameters directly in the code using the
try { try {
yield from $this->myTelegramOrgWrapper->completeLogin($_POST['code']); yield from $this->myTelegramOrgWrapper->completeLogin($_POST['code']);
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
yield from $this->webAPIEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
yield from $this->webAPIEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
private function webAPICreateApp(): \Generator private function webAPICreateApp(): \Generator
@ -140,9 +147,9 @@ Note that you can also provide the API parameters directly in the code using the
$app = (yield from $this->myTelegramOrgWrapper->createApp($params)); $app = (yield from $this->myTelegramOrgWrapper->createApp($params));
return $app; return $app;
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
yield from $this->webAPIEcho('ERROR: '.$e->getMessage().' Try again.'); yield from $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
yield from $this->webAPIEcho('ERROR: '.$e->getMessage().' Try again.'); yield from $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
} }

View File

@ -19,6 +19,9 @@
namespace danog\MadelineProto\ApiWrappers; namespace danog\MadelineProto\ApiWrappers;
use Amp\Promise;
use danog\MadelineProto\Lang;
use function Amp\ByteStream\getOutputBufferStream; use function Amp\ByteStream\getOutputBufferStream;
trait Templates trait Templates
@ -28,7 +31,7 @@ trait Templates
* *
* @var string * @var string
*/ */
private $webApiTemplate = '<!DOCTYPE html><html><head><title>MadelineProto</title></head><body><h1>MadelineProto</h1><p>%s</p><form method="POST">%s<button type="submit"/>Go</button></form></body></html>'; private $webApiTemplate = 'legacy';
/** /**
* Generate page from template. * Generate page from template.
* *
@ -39,7 +42,7 @@ trait Templates
*/ */
private function webAPIEchoTemplate(string $message, string $form): string private function webAPIEchoTemplate(string $message, string $form): string
{ {
return \sprintf($this->webApiTemplate, $message, $form); return \sprintf($this->webApiTemplate, $message, $form, Lang::$current_lang['go']);
} }
/** /**
* Get web API login HTML template string. * Get web API login HTML template string.
@ -64,72 +67,86 @@ trait Templates
* *
* @param string $message Message to echo * @param string $message Message to echo
* *
* @return \Generator * @return Promise
*/ */
private function webAPIEcho(string $message = ''): \Generator private function webAPIEcho(string $message = ''): Promise
{ {
$stdout = getOutputBufferStream(); $message = \htmlentities($message);
if (!isset($this->myTelegramOrgWrapper)) { if (!isset($this->myTelegramOrgWrapper)) {
if (isset($_POST['type'])) { if (isset($_POST['type'])) {
if ($_POST['type'] === 'manual') { if ($_POST['type'] === 'manual') {
yield $stdout->write($this->webAPIEchoTemplate('Enter your API ID and API hash<br><b>'.$message.'</b><ol> $title = \htmlentities(Lang::$current_lang['apiManualWeb']);
<li>Login to my.telegram.org</li> $title .= "<br><b>$message</b>";
<li>Go to API development tools</li> $title .= "<ol>";
<li> $title .= "<li>".\htmlentities(Lang::$current_lang['apiManualInstructions0'])."</li>";
<ul> $title .= "<li>".\htmlentities(Lang::$current_lang['apiManualInstructions1'])."</li>";
<li>App title: your app&apos;s name, can be anything</li> $title .= "<li><ul>";
<li>Short name: your app&apos;s short name, only numbers and letters</li> foreach (['App title', 'Short name', 'URL', 'Platform', 'Description'] as $k => $key) {
<li>Platform: Web</li> $title .= "<li>$key: ";
<li>Description: describe your app here</li> $title .= \htmlentities(Lang::$current_lang["apiAppInstructionsManual$k"]);
</ul> $title .= "</li>";
</li> }
<li>Click on create application</li> $title .= "</li></ul>";
</ol>', '<input type="string" name="api_id" placeholder="API ID" required/><input type="string" name="api_hash" placeholder="API hash" required/>')); $title .= "<li>".\htmlentities(Lang::$current_lang['apiManualInstructions2'])."</li>";
$title .= "</ol>";
$form = '<input type="string" name="api_id" placeholder="API ID" required/>';
$form .= '<input type="string" name="api_hash" placeholder="API hash" required/>';
} else { } else {
yield $stdout->write($this->webAPIEchoTemplate('Enter a phone number that is <b>already registered</b> on telegram to get the API ID<br><b>'.$message.'</b>', '<input type="text" name="phone_number" placeholder="Phone number" required/>')); $title = Lang::$current_lang['apiAutoWeb'];
$title .= "<br><b>$message</b>";
$phone = \htmlentities(Lang::$current_lang['loginUserPhoneWeb']);
$form = "<input type='text' name='phone_number' placeholder='$phone' required/>";
} }
} else { } else {
if ($message) { if ($message) {
$message = '<br><br>'.$message; $message = '<br><br>'.$message;
} }
yield $stdout->write($this->webAPIEchoTemplate('Do you want to enter the API id and the API hash manually or automatically?<br>Note that you can also provide it directly in the code using the <a href="https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id">settings</a>.<b>'.$message.'</b>', '<select name="type"><option value="automatic">Automatically</option><option value="manual">Manually</option></select>')); $title = \htmlentities(Lang::$current_lang['apiChooseManualAutoWeb']);
$title .= "<br>";
$title .= \sprintf(Lang::$current_lang['apiChooseManualAutoTipWeb'], 'https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id');
$title .= "<b>$message</b>";
$automatically = \htmlentities(Lang::$current_lang['apiChooseAutomaticallyWeb']);
$manually = \htmlentities(Lang::$current_lang['apiChooseManuallyWeb']);
$form = "<select name='type'><option value='automatic'>$automatically</option><option value='manual'>$manually</option></select>";
} }
} else { } else {
if (!$this->myTelegramOrgWrapper->loggedIn()) { if (!$this->myTelegramOrgWrapper->loggedIn()) {
yield $stdout->write($this->webAPIEchoTemplate('Enter your code<br><b>'.$message.'</b>', '<input type="text" name="code" placeholder="Code" required/>')); $title = \htmlentities(Lang::$current_lang['loginUserCode']);
$title .= "<br><b>$message</b>";
$code = \htmlentities(Lang::$current_lang['loginUserPhoneCodeWeb']);
$form = "<input type='text' name='code' placeholder='$code' required/>";
} else { } else {
yield $stdout->write($this->webAPIEchoTemplate('Enter the API info<br><b>'.$message.'</b>', '<input type="hidden" name="creating_app" value="yes" required/> $title = \htmlentities(Lang::$current_lang['apiAppWeb']);
Enter the app name, can be anything: <br><input type="text" name="app_title" required/><br> $title .= "<br><b>$message</b>";
<br>Enter the app&apos;s short name, alphanumeric, 5-32 chars: <br><input type="text" name="app_shortname" required/><br>
<br>Enter the app/website URL, or https://t.me/yourusername: <br><input type="text" name="app_url" required/><br> $form = '<input type="hidden" name="creating_app" value="yes" required/>';
<br>Enter the app platform: <br> foreach (['app_title', 'app_shortname', 'app_url', 'app_platform', 'app_desc'] as $field) {
<label> $desc = \htmlentities(Lang::$current_lang["apiAppInstructionsAuto$field"]);
<input type="radio" name="app_platform" value="android" checked> Android if ($field == 'app_platform') {
</label> $form .= "$desc<br>";
<label> foreach ([
<input type="radio" name="app_platform" value="ios"> iOS 'android' => 'Android',
</label> 'ios' => 'iOS',
<label> 'wp' => 'Windows Phone',
<input type="radio" name="app_platform" value="wp"> Windows Phone 'bb' => 'BlackBerry',
</label> 'desktop' => 'Desktop',
<label> 'web' => 'Web',
<input type="radio" name="app_platform" value="bb"> BlackBerry 'ubp' => 'Ubuntu phone',
</label> 'other' => \htmlentities(Lang::$current_lang['apiAppInstructionsAutoTypeOther'])
<label> ] as $key => $desc) {
<input type="radio" name="app_platform" value="desktop"> Desktop $form .= "<label><input type='radio' name='app_platform' value='$key' checked> $desc</label>";
</label> }
<label> } elseif ($field === 'app_desc') {
<input type="radio" name="app_platform" value="web"> Web $form .= "$desc<br><textarea name='$field' required></textarea><br><br>";
</label> } else {
<label> $form .= "$desc<br><input type='text' name='$field' required/><br><br>";
<input type="radio" name="app_platform" value="ubp"> Ubuntu phone
</label>
<label>
<input type="radio" name="app_platform" value="other"> Other (specify in description)
</label>
<br><br>Enter the app description, can be anything: <br><textarea name="app_desc" required></textarea><br><br>
'));
} }
} }
} }
} }
return getOutputBufferStream()->write($this->webAPIEchoTemplate($title, $form));
}
}

View File

@ -200,7 +200,7 @@ class DataCenter
{ {
$this->API = $API; $this->API = $API;
$changed = []; $changed = [];
$changedSettings = $settings->haveChanged(); $changedSettings = $settings->hasChanged();
if (!$reconnectAll) { if (!$reconnectAll) {
$changed = []; $changed = [];
$test = $API->getCachedConfig()['test_mode'] ?? false ? 'test' : 'main'; $test = $API->getCachedConfig()['test_mode'] ?? false ? 'test' : 'main';

View File

@ -30,9 +30,9 @@ class DbPropertiesFactory
$config = $propertyType['config'] ?? []; $config = $propertyType['config'] ?? [];
$propertyType = \is_array($propertyType) ? $propertyType['type'] : $propertyType; $propertyType = \is_array($propertyType) ? $propertyType['type'] : $propertyType;
$propertyType = \strtolower($propertyType); $propertyType = \strtolower($propertyType);
$class = $config['enableCache'] ?? true && !$dbSettings instanceof Memory $class = !($config['enableCache'] ?? true) && !$dbSettings instanceof Memory
? __NAMESPACE__ ? __NAMESPACE__.'\\NullCache'
: __NAMESPACE__.'\\NullCache'; : __NAMESPACE__;
switch (true) { switch (true) {
case $dbSettings instanceof Memory: case $dbSettings instanceof Memory:

View File

@ -105,7 +105,7 @@ class Lang
'type_extract_error_id' => 'Non sono riuscito ad estrarre il tipo %s con ID %s', 'type_extract_error_id' => 'Non sono riuscito ad estrarre il tipo %s con ID %s',
'constructor_not_found' => 'Costruttore non trovato per tipo: ', 'constructor_not_found' => 'Costruttore non trovato per tipo: ',
'rand_bytes_too_small' => 'random_bytes è troppo corto!', 'rand_bytes_too_small' => 'random_bytes è troppo corto!',
'botapi_conversion_error' => 'NOn sono risucito a convertire %s in un oggetto bot API', 'botapi_conversion_error' => 'Non sono risucito a convertire %s in un oggetto bot API',
'non_text_conversion' => 'Non posso ancora convertire messaggi media', 'non_text_conversion' => 'Non posso ancora convertire messaggi media',
'last_byte_invalid' => 'L\'ultimo byte non è valido', 'last_byte_invalid' => 'L\'ultimo byte non è valido',
'file_type_invalid' => 'È stato fornito un tipo file errato', 'file_type_invalid' => 'È stato fornito un tipo file errato',
@ -123,42 +123,62 @@ class Lang
'apiAppInstructionsAuto4' => 'Descrivi la tua app: ', 'apiAppInstructionsAuto4' => 'Descrivi la tua app: ',
'apiAppInstructionsManual0' => 'titolo dell\'app, può essere qualsiasi cosa', 'apiAppInstructionsManual0' => 'titolo dell\'app, può essere qualsiasi cosa',
'apiAppInstructionsManual1' => 'il nome ridotto dell\'app, caratteri alfanumerici: ', 'apiAppInstructionsManual1' => 'il nome ridotto dell\'app, caratteri alfanumerici: ',
'apiAppInstructionsManual2' => '', 'apiAppInstructionsManual2' => 'L\'indirizzo del tuo sito, oppure t.me/username',
'apiAppInstructionsManual3' => '', 'apiAppInstructionsManual3' => 'Qualsiasi',
'apiAppInstructionsManual4' => '', 'apiAppInstructionsManual4' => 'Descrivi la tua app',
'apiAutoPrompt0' => '', 'apiAutoPrompt0' => 'Inserisci un numero di telefono che è già registrato su Telegram: ',
'apiAutoPrompt1' => '', 'apiAutoPrompt1' => 'Inserisci il codice di verifica che hai ricevuto su Telegram: ',
'apiChooseManualAuto' => '', 'apiChooseManualAutoTip' => 'Nota che puoi anche fornire i parametri API direttamente nelle impostazioni: %s',
'apiChooseManualAutoTip' => '', 'apiChoosePrompt' => 'La tua scelta (m/a): ',
'apiChoosePrompt' => '', 'apiError' => 'ERRORE: %s. Prova ancora.',
'apiError' => '', 'apiManualInstructions0' => 'Effettua il login su my.telegram.org',
'apiManualInstructions0' => '', 'apiManualInstructions1' => 'Vai su API development tools',
'apiManualInstructions1' => '', 'apiManualInstructions2' => 'Clicca su create application',
'apiManualInstructions2' => '', 'apiManualPrompt0' => 'Inserisci il tuo API ID: ',
'apiManualPrompt0' => '', 'apiManualPrompt1' => 'Inserisci il tuo API hash: ',
'apiManualPrompt1' => '', 'apiParamsError' => 'Non hai fornito tutti i parametri richiesti!',
'apiParamsError' => '', 'loginBot' => 'Inserisci il tuo bot token: ',
'loginBot' => '', 'loginChoosePrompt' => 'Vuoi effettuare il login come utente o come bot (u/b)? ',
'loginChoosePrompt' => '', 'loginNoCode' => 'Non hai fornito un codice di verifica!',
'loginNoCode' => '', 'loginNoName' => 'Non hai fornito un nome!',
'loginNoName' => '', 'loginNoPass' => 'Non hai fornito la password!',
'loginNoPass' => '', 'loginUser' => 'Inserisci il tuo numero di telefono: ',
'loginUser' => '', 'loginUserPass' => 'Inserisci la tua password (suggerimento %s): ',
'loginUser2FA' => '', 'loginUserPassHint' => 'Suggerimento: %s',
'loginUser2FAHint' => '', 'loginUserPassWeb' => 'Inserisci la tua password: ',
'loginUser2FAWeb' => '', 'loginUserCode' => 'Inserisci il codice di verifica: ',
'loginUserCode' => '', 'signupFirstName' => 'Inserisci il tuo nome: ',
'signupFirstName' => '', 'signupFirstNameWeb' => 'Nome',
'signupFirstNameWeb' => '', 'signupLastName' => 'Inserisci il tuo cognome: ',
'signupLastName' => '', 'signupLastNameWeb' => 'Cognome',
'signupLastNameWeb' => '', 'signupWeb' => 'Registrazione',
'signupWeb' => '', 'go' => 'Vai',
'loginChoosePromptWeb' => 'Vuoi effettuare il login come utente o come bot?',
'loginOptionBot' => 'Bot',
'loginOptionUser' => 'Utente',
'loginBotTokenWeb' => 'Token del bot',
'loginUserPhoneCodeWeb' => 'Codice di verifica',
'loginUserPhoneWeb' => 'Numero di telefono',
'apiAutoWeb' => 'Inserisci un numero di telefono <b>gi&agrave; registrato su Telegram</b> per ottenere l&apos;API ID',
'apiChooseManualAuto' => 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)',
'apiManualWeb' => 'Inserisci il tuo API ID e API hash',
'apiAppInstructionsAutoTypeOther' => 'Altro (specificare nella descrizione)',
'apiAppWeb' => 'Inserire informazioni API',
'apiChooseAutomaticallyWeb' => 'Automaticamente',
'apiChooseManualAutoTipWeb' => 'Nota che puoi anche fornire i parametri API direttamente nelle <a target="_blank" href="%s">impostazioni</a>.',
'apiChooseManualAutoWeb' => 'Vuoi configurare il tuo API ID/hash manualmente o automaticamente?',
'apiChooseManuallyWeb' => 'Manualmente',
], ],
'en' => 'en' =>
[ [
'apiChooseManualAuto' => 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)', 'go' => 'Go',
'apiChooseManualAutoTip' => 'Note that you can also provide the API parameters directly in the code using the settings: %s', 'apiChooseManualAuto' => 'Do you want to enter the API id and the API hash manually or automatically? (m/a)',
'apiChooseManualAutoWeb' => 'Do you want to enter the API id and the API hash manually or automatically?',
'apiChooseManualAutoTip' => 'Note that you can also provide them directly in the code using the settings: %s',
'apiChooseManualAutoTipWeb' => 'Note that you can also provide them directly in the code using the <a target="_blank" href="%s">settings</a>.',
'apiChoosePrompt' => 'Your choice (m/a): ', 'apiChoosePrompt' => 'Your choice (m/a): ',
'apiChooseAutomaticallyWeb' => 'Automatically',
'apiChooseManuallyWeb' => 'Manually',
'apiManualInstructions0' => 'Login to my.telegram.org', 'apiManualInstructions0' => 'Login to my.telegram.org',
'apiManualInstructions1' => 'Go to API development tools', 'apiManualInstructions1' => 'Go to API development tools',
'apiManualInstructions2' => 'Click on create application', 'apiManualInstructions2' => 'Click on create application',
@ -167,24 +187,31 @@ class Lang
'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername', 'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername',
'apiAppInstructionsManual3' => 'anything', 'apiAppInstructionsManual3' => 'anything',
'apiAppInstructionsManual4' => 'Describe your app here', 'apiAppInstructionsManual4' => 'Describe your app here',
'apiManualWeb' => 'Enter your API ID and API hash',
'apiManualPrompt0' => 'Enter your API ID: ', 'apiManualPrompt0' => 'Enter your API ID: ',
'apiManualPrompt1' => 'Enter your API hash: ', 'apiManualPrompt1' => 'Enter your API hash: ',
'apiAutoWeb' => 'Enter a phone number that is <b>already registered</b> on telegram to get the API ID',
'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ', 'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ',
'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ', 'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ',
'apiAppWeb' => 'Enter API information',
'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ', 'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ',
'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric: ', 'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric: ',
'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ', 'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ',
'apiAppInstructionsAuto3' => 'Enter the app platform: ', 'apiAppInstructionsAuto3' => 'Enter the app platform: ',
'apiAppInstructionsAuto4' => 'Describe your app: ', 'apiAppInstructionsAuto4' => 'Describe your app: ',
'apiAppInstructionsAutoTypeOther' => 'Other (specify in description)',
'apiParamsError' => 'You didn\'t provide all of the required parameters!', 'apiParamsError' => 'You didn\'t provide all of the required parameters!',
'apiError' => 'ERROR: %s. Try again.', 'apiError' => 'ERROR: %s. Try again.',
'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ', 'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ',
'loginChoosePromptWeb' => 'Do you want to login as user or bot?',
'loginOptionBot' => 'Bot',
'loginOptionUser' => 'User',
'loginBot' => 'Enter your bot token: ', 'loginBot' => 'Enter your bot token: ',
'loginUser' => 'Enter your phone number: ', 'loginUser' => 'Enter your phone number: ',
'loginUserCode' => 'Enter the phone code: ', 'loginUserCode' => 'Enter the code: ',
'loginUser2FA' => 'Enter your password (hint %s): ', 'loginUserPass' => 'Enter your password (hint %s): ',
'loginUser2FAWeb' => 'Enter your password: ', 'loginUserPassWeb' => 'Enter your password: ',
'loginUser2FAHint' => 'Hint: %s', 'loginUserPassHint' => 'Hint: %s',
'signupFirstName' => 'Enter your first name: ', 'signupFirstName' => 'Enter your first name: ',
'signupLastName' => 'Enter your last name (can be empty): ', 'signupLastName' => 'Enter your last name (can be empty): ',
'signupWeb' => 'Sign up please', 'signupWeb' => 'Sign up please',
@ -193,6 +220,9 @@ class Lang
'loginNoCode' => 'You didn\'t provide a phone code!', 'loginNoCode' => 'You didn\'t provide a phone code!',
'loginNoPass' => 'You didn\'t provide the password!', 'loginNoPass' => 'You didn\'t provide the password!',
'loginNoName' => 'You didn\'t provide the first name!', 'loginNoName' => 'You didn\'t provide the first name!',
'loginBotTokenWeb' => 'Bot token',
'loginUserPhoneWeb' => 'Phone number',
'loginUserPhoneCodeWeb' => 'Code',
'done' => 'Done!', 'done' => 'Done!',
'cdn_reupload' => 'File is not stored on CDN, requesting reupload!', 'cdn_reupload' => 'File is not stored on CDN, requesting reupload!',
'stored_on_cdn' => 'File is stored on CDN!', 'stored_on_cdn' => 'File is stored on CDN!',
@ -292,9 +322,14 @@ class Lang
// THIS WILL BE OVERWRITTEN BY $lang["en"] // THIS WILL BE OVERWRITTEN BY $lang["en"]
public static $current_lang = [ public static $current_lang = [
'apiChooseManualAuto' => 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)', 'go' => 'Go',
'apiChooseManualAutoTip' => 'Note that you can also provide the API parameters directly in the code using the settings: %s', 'apiChooseManualAuto' => 'Do you want to enter the API id and the API hash manually or automatically? (m/a)',
'apiChooseManualAutoWeb' => 'Do you want to enter the API id and the API hash manually or automatically?',
'apiChooseManualAutoTip' => 'Note that you can also provide them directly in the code using the settings: %s',
'apiChooseManualAutoTipWeb' => 'Note that you can also provide them directly in the code using the <a href="%s">settings</a>.',
'apiChoosePrompt' => 'Your choice (m/a): ', 'apiChoosePrompt' => 'Your choice (m/a): ',
'apiChooseAutomaticallyWeb' => 'Automatically',
'apiChooseManuallyWeb' => 'Manually',
'apiManualInstructions0' => 'Login to my.telegram.org', 'apiManualInstructions0' => 'Login to my.telegram.org',
'apiManualInstructions1' => 'Go to API development tools', 'apiManualInstructions1' => 'Go to API development tools',
'apiManualInstructions2' => 'Click on create application', 'apiManualInstructions2' => 'Click on create application',
@ -303,24 +338,31 @@ class Lang
'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername', 'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername',
'apiAppInstructionsManual3' => 'anything', 'apiAppInstructionsManual3' => 'anything',
'apiAppInstructionsManual4' => 'Describe your app here', 'apiAppInstructionsManual4' => 'Describe your app here',
'apiManualWeb' => 'Enter your API ID and API hash',
'apiManualPrompt0' => 'Enter your API ID: ', 'apiManualPrompt0' => 'Enter your API ID: ',
'apiManualPrompt1' => 'Enter your API hash: ', 'apiManualPrompt1' => 'Enter your API hash: ',
'apiAutoWeb' => 'Enter a phone number that is <b>already registered</b> on telegram to get the API ID',
'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ', 'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ',
'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ', 'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ',
'apiAppWeb' => 'Enter API information',
'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ', 'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ',
'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric: ', 'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric: ',
'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ', 'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ',
'apiAppInstructionsAuto3' => 'Enter the app platform: ', 'apiAppInstructionsAuto3' => 'Enter the app platform: ',
'apiAppInstructionsAuto4' => 'Describe your app: ', 'apiAppInstructionsAuto4' => 'Describe your app: ',
'apiAppInstructionsAutoTypeOther' => 'Other (specify in description)',
'apiParamsError' => 'You didn\'t provide all of the required parameters!', 'apiParamsError' => 'You didn\'t provide all of the required parameters!',
'apiError' => 'ERROR: %s. Try again.', 'apiError' => 'ERROR: %s. Try again.',
'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ', 'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ',
'loginChoosePromptWeb' => 'Do you want to login as user or bot?',
'loginOptionBot' => 'Bot',
'loginOptionUser' => 'User',
'loginBot' => 'Enter your bot token: ', 'loginBot' => 'Enter your bot token: ',
'loginUser' => 'Enter your phone number: ', 'loginUser' => 'Enter your phone number: ',
'loginUserCode' => 'Enter the phone code: ', 'loginUserCode' => 'Enter the code: ',
'loginUser2FA' => 'Enter your password (hint %s): ', 'loginUserPass' => 'Enter your password (hint %s): ',
'loginUser2FAWeb' => 'Enter your password: ', 'loginUserPassWeb' => 'Enter your password: ',
'loginUser2FAHint' => 'Hint: %s', 'loginUserPassHint' => 'Hint: %s',
'signupFirstName' => 'Enter your first name: ', 'signupFirstName' => 'Enter your first name: ',
'signupLastName' => 'Enter your last name (can be empty): ', 'signupLastName' => 'Enter your last name (can be empty): ',
'signupWeb' => 'Sign up please', 'signupWeb' => 'Sign up please',
@ -329,6 +371,9 @@ class Lang
'loginNoCode' => 'You didn\'t provide a phone code!', 'loginNoCode' => 'You didn\'t provide a phone code!',
'loginNoPass' => 'You didn\'t provide the password!', 'loginNoPass' => 'You didn\'t provide the password!',
'loginNoName' => 'You didn\'t provide the first name!', 'loginNoName' => 'You didn\'t provide the first name!',
'loginBotTokenWeb' => 'Bot token',
'loginUserPhoneWeb' => 'Phone number',
'loginUserPhoneCodeWeb' => 'Code',
'done' => 'Done!', 'done' => 'Done!',
'cdn_reupload' => 'File is not stored on CDN, requesting reupload!', 'cdn_reupload' => 'File is not stored on CDN, requesting reupload!',
'stored_on_cdn' => 'File is stored on CDN!', 'stored_on_cdn' => 'File is stored on CDN!',

View File

@ -505,6 +505,7 @@ class MTProto extends AsyncConstruct implements TLCallback
return $data; return $data;
} }
yield $this->session['data'] = \serialize($data); yield $this->session['data'] = \serialize($data);
var_dump($this);
return $this->session; return $this->session;
} }
@ -614,7 +615,7 @@ class MTProto extends AsyncConstruct implements TLCallback
'hook_url', 'hook_url',
// Web login template // Web login template
'web_template', 'webTemplate',
// Settings // Settings
'settings', 'settings',

View File

@ -193,6 +193,7 @@ abstract class Serialization
if ($isNew) { if ($isNew) {
$unserialized = yield from $session->unserialize(); $unserialized = yield from $session->unserialize();
if ($unserialized instanceof DriverArray) { if ($unserialized instanceof DriverArray) {
Logger::log("Extracting session from database...");
yield from $unserialized->initConnection($unserialized->dbSettings); yield from $unserialized->initConnection($unserialized->dbSettings);
$unserialized = \unserialize(yield $unserialized['data']); $unserialized = \unserialize(yield $unserialized['data']);
} }

View File

@ -18,6 +18,7 @@ use danog\MadelineProto\Settings\Pwr;
use danog\MadelineProto\Settings\RPC; use danog\MadelineProto\Settings\RPC;
use danog\MadelineProto\Settings\SecretChats; use danog\MadelineProto\Settings\SecretChats;
use danog\MadelineProto\Settings\Serialization; use danog\MadelineProto\Settings\Serialization;
use danog\MadelineProto\Settings\Templates;
use danog\MadelineProto\Settings\TLSchema; use danog\MadelineProto\Settings\TLSchema;
class Settings extends SettingsAbstract class Settings extends SettingsAbstract
@ -74,6 +75,10 @@ class Settings extends SettingsAbstract
* DatabaseAbstract settings. * DatabaseAbstract settings.
*/ */
protected DatabaseAbstract $db; protected DatabaseAbstract $db;
/**
* Template settings.
*/
protected Templates $templates;
/** /**
* Create settings object from possibly legacy settings array. * Create settings object from possibly legacy settings array.
@ -111,6 +116,7 @@ class Settings extends SettingsAbstract
$this->serialization = new Serialization; $this->serialization = new Serialization;
$this->schema = new TLSchema; $this->schema = new TLSchema;
$this->db = new DatabaseMemory; $this->db = new DatabaseMemory;
$this->templates = new Templates;
$this->ipc = new IPc; $this->ipc = new IPc;
} }
/** /**
@ -185,6 +191,8 @@ class Settings extends SettingsAbstract
$this->schema->merge($settings); $this->schema->merge($settings);
} elseif ($settings instanceof Ipc) { } elseif ($settings instanceof Ipc) {
$this->ipc->merge($settings); $this->ipc->merge($settings);
} elseif ($settings instanceof Templates) {
$this->templates->merge($settings);
} elseif ($settings instanceof DatabaseAbstract) { } elseif ($settings instanceof DatabaseAbstract) {
if (!$this->db instanceof $settings) { if (!$this->db instanceof $settings) {
$this->db = $settings; $this->db = $settings;
@ -206,6 +214,7 @@ class Settings extends SettingsAbstract
$this->serialization->merge($settings->serialization); $this->serialization->merge($settings->serialization);
$this->schema->merge($settings->schema); $this->schema->merge($settings->schema);
$this->ipc->merge($settings->ipc); $this->ipc->merge($settings->ipc);
$this->templates->merge($settings->templates);
if (!$this->db instanceof $settings->db) { if (!$this->db instanceof $settings->db) {
$this->db = $settings->db; $this->db = $settings->db;
@ -561,8 +570,34 @@ class Settings extends SettingsAbstract
public function applyChanges(): SettingsAbstract public function applyChanges(): SettingsAbstract
{ {
foreach (\get_object_vars($this) as $setting) { foreach (\get_object_vars($this) as $setting) {
if ($setting instanceof SettingsAbstract) {
$setting->applyChanges(); $setting->applyChanges();
} }
}
return $this;
}
/**
* Get template settings.
*
* @return Templates
*/
public function getTemplates(): Templates
{
return $this->templates;
}
/**
* Set template settings.
*
* @param Templates $templates Template settings
*
* @return self
*/
public function setTemplates(Templates $templates): self
{
$this->templates = $templates;
return $this; return $this;
} }
} }

View File

@ -70,6 +70,9 @@ class AppInfo extends SettingsAbstract
{ {
Magic::classExists(true); Magic::classExists(true);
// Detect language pack // Detect language pack
if (isset(Lang::$lang[$this->langCode])) {
Lang::$current_lang =& Lang::$lang[$this->langCode];
}
$this->appVersion = MTProto::RELEASE.' ('.MTProto::V.', '.\str_replace(' (AN UPDATE IS REQUIRED)', '', Magic::$revision).')'; $this->appVersion = MTProto::RELEASE.' ('.MTProto::V.', '.\str_replace(' (AN UPDATE IS REQUIRED)', '', Magic::$revision).')';
} }

View File

@ -86,10 +86,6 @@ class Connection extends SettingsAbstract
*/ */
protected bool $retry = true; protected bool $retry = true;
/**
* Whether the connection settings changed.
*/
private bool $changed = true;
/** /**
* Subdomains of web.telegram.org for https protocol. * Subdomains of web.telegram.org for https protocol.
*/ */
@ -217,24 +213,6 @@ class Connection extends SettingsAbstract
$this->addProxy(HttpProxy::class, ['address' => 'localhost', 'port' => 80]); $this->addProxy(HttpProxy::class, ['address' => 'localhost', 'port' => 80]);
} }
} }
/**
* Whether the settings have changed.
*
* @return boolean
*/
public function haveChanged(): bool
{
return $this->changed;
}
/**
* Signal that changes have been applied.
*
* @return void
*/
public function applyChanges(): void
{
$this->changed = false;
}
/** /**
* Get protocol identifier. * Get protocol identifier.
* *
@ -257,7 +235,6 @@ class Connection extends SettingsAbstract
if (!isset(\class_implements($protocol)[MTProtoBufferInterface::class])) { if (!isset(\class_implements($protocol)[MTProtoBufferInterface::class])) {
throw new Exception("An invalid protocol was specified!"); throw new Exception("An invalid protocol was specified!");
} }
$this->changed = true;
$this->protocol = $protocol; $this->protocol = $protocol;
return $this; return $this;
@ -282,7 +259,6 @@ class Connection extends SettingsAbstract
*/ */
public function setIpv6(bool $ipv6): self public function setIpv6(bool $ipv6): self
{ {
$this->changed = true;
$this->ipv6 = $ipv6; $this->ipv6 = $ipv6;
return $this; return $this;
@ -307,7 +283,6 @@ class Connection extends SettingsAbstract
*/ */
public function setSslSubdomains(array $sslSubdomains): self public function setSslSubdomains(array $sslSubdomains): self
{ {
$this->changed = true;
$this->sslSubdomains = $sslSubdomains; $this->sslSubdomains = $sslSubdomains;
return $this; return $this;
@ -332,7 +307,6 @@ class Connection extends SettingsAbstract
*/ */
public function setMinMediaSocketCount(int $minMediaSocketCount): self public function setMinMediaSocketCount(int $minMediaSocketCount): self
{ {
$this->changed = true;
$this->minMediaSocketCount = $minMediaSocketCount; $this->minMediaSocketCount = $minMediaSocketCount;
return $this; return $this;
@ -357,7 +331,6 @@ class Connection extends SettingsAbstract
*/ */
public function setMaxMediaSocketCount(int $maxMediaSocketCount): self public function setMaxMediaSocketCount(int $maxMediaSocketCount): self
{ {
$this->changed = true;
$this->maxMediaSocketCount = $maxMediaSocketCount; $this->maxMediaSocketCount = $maxMediaSocketCount;
return $this; return $this;
@ -382,7 +355,6 @@ class Connection extends SettingsAbstract
*/ */
public function setRobinPeriod(int $robinPeriod): self public function setRobinPeriod(int $robinPeriod): self
{ {
$this->changed = true;
$this->robinPeriod = $robinPeriod; $this->robinPeriod = $robinPeriod;
return $this; return $this;
@ -416,7 +388,6 @@ class Connection extends SettingsAbstract
*/ */
public function setDefaultDc(int $defaultDc): self public function setDefaultDc(int $defaultDc): self
{ {
$this->changed = true;
$this->defaultDc = $defaultDc; $this->defaultDc = $defaultDc;
$this->defaultDcParams = ['datacenter' => $defaultDc]; $this->defaultDcParams = ['datacenter' => $defaultDc];
@ -449,7 +420,6 @@ class Connection extends SettingsAbstract
if (!isset($this->proxy[$proxy])) { if (!isset($this->proxy[$proxy])) {
$this->proxy[$proxy] = []; $this->proxy[$proxy] = [];
} }
$this->changed = true;
$this->proxy[$proxy][] = $extra; $this->proxy[$proxy][] = $extra;
return $this; return $this;
@ -483,7 +453,6 @@ class Connection extends SettingsAbstract
if (false === $index = \array_search($extra, $this->proxy[$proxy])) { if (false === $index = \array_search($extra, $this->proxy[$proxy])) {
return $this; return $this;
} }
$this->changed = true;
unset($this->proxy[$proxy][$index]); unset($this->proxy[$proxy][$index]);
if (empty($this->proxy[$proxy])) { if (empty($this->proxy[$proxy])) {
unset($this->proxy[$proxy]); unset($this->proxy[$proxy]);
@ -509,7 +478,6 @@ class Connection extends SettingsAbstract
*/ */
public function setObfuscated(bool $obfuscated): self public function setObfuscated(bool $obfuscated): self
{ {
$this->changed = true;
$this->obfuscated = $obfuscated; $this->obfuscated = $obfuscated;
return $this; return $this;
@ -534,7 +502,6 @@ class Connection extends SettingsAbstract
*/ */
public function setTestMode(bool $testMode): self public function setTestMode(bool $testMode): self
{ {
$this->changed = true;
$this->testMode = $testMode; $this->testMode = $testMode;
return $this; return $this;
@ -562,7 +529,6 @@ class Connection extends SettingsAbstract
if (!isset(\class_implements($transport)[RawStreamInterface::class])) { if (!isset(\class_implements($transport)[RawStreamInterface::class])) {
throw new Exception("An invalid transport was specified!"); throw new Exception("An invalid transport was specified!");
} }
$this->changed = true;
$this->transport = $transport; $this->transport = $transport;
return $this; return $this;
@ -587,7 +553,6 @@ class Connection extends SettingsAbstract
*/ */
public function setRetry(bool $retry): self public function setRetry(bool $retry): self
{ {
$this->changed = true;
$this->retry = $retry; $this->retry = $retry;
return $this; return $this;
@ -612,7 +577,6 @@ class Connection extends SettingsAbstract
*/ */
public function setTimeout(int $timeout): self public function setTimeout(int $timeout): self
{ {
$this->changed = true;
$this->timeout = $timeout; $this->timeout = $timeout;
return $this; return $this;

View File

@ -100,6 +100,10 @@ class Logger extends SettingsAbstract
$this->type = (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') $this->type = (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg')
? MadelineProtoLogger::ECHO_LOGGER ? MadelineProtoLogger::ECHO_LOGGER
: MadelineProtoLogger::FILE_LOGGER; : MadelineProtoLogger::FILE_LOGGER;
if (!$this->extra && $this->type === MadelineProtoLogger::FILE_LOGGER) {
$this->extra = Magic::$script_cwd.'/MadelineProto.log';
}
$this->init(); $this->init();
} }
/** /**

View File

@ -2,60 +2,39 @@
namespace danog\MadelineProto\Settings; namespace danog\MadelineProto\Settings;
use danog\MadelineProto\SettingsAbstract;
/** /**
* Web and CLI template settings for login. * Web and CLI template settings for login.
*/ */
class Templates class Templates extends SettingsAbstract
{ {
/** /**
* Web template used for querying app information. * Web template used for querying app information.
*/ */
protected string $apiHtmlTemplate = '<!DOCTYPE html><html><head><title>MadelineProto</title></head><body><h1>MadelineProto</h1><p>%s</p><form method="POST">%s<button type="submit"/>Go</button></form></body></html>'; protected string $htmlTemplate = '<!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>';
/** /**
* Prompt user to choose manual or automatic API ID generation. * Get web template used for querying app information.
*/
protected string $apiChooseManualAuto = 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)';
/**
* Settings tip for API ID generation.
*/
protected string $apiChooseManualAutoTip = 'Note that you can also provide the API parameters directly in the code using the settings: %s';
/**
* Final prompt to choose mode.
*/
protected string $apiChoosePrompt = 'Your choice (m/a): ';
/**
* Instructions for manual API ID generation.
* *
* @var array{0: string, 1: string, 2: array{0: string, 1: string, 2: string, 3: string, 4: string}, 3: string} * @return string
*/ */
protected array $apiManualInstructions = [ public function getHtmlTemplate(): string
'Login to my.telegram.org', {
'Go to API development tools', return $this->htmlTemplate;
[ }
'App title: your app\'s name, can be anything',
'Short name: your app\'s short name, can be anything', /**
'URL: your app/website\'s URL, or t.me/yourusername', * Set web template used for querying app information.
'Platform: anything', *
'Description: Describe your app here', * @param string $htmlTemplate Web template used for querying app information.
], *
'Click on create application' * @return self
]; */
/** public function setHtmlTemplate(string $htmlTemplate): self
* Manual API ID/hash prompts. {
*/ $this->htmlTemplate = $htmlTemplate;
protected array $apiManualPrompts = [
'Enter your API ID: ', return $this;
'Enter your API hash: ' }
];
/**
* Auto API ID/hash prompts.
*/
protected array $apiAutoPrompts = [
'Enter a phone number that is already registered on Telegram: ',
'Enter the verification code you received in Telegram: ',
'Enter the app\'s name, can be anything: ',
'Enter the app\'s short name, can be anything: ',
'Enter the app/website\'s URL, or t.me/yourusername: ',
'Describe your app: ',
];
} }

View File

@ -20,7 +20,9 @@ abstract class SettingsAbstract
* *
* @return void * @return void
*/ */
abstract public function mergeArray(array $settings): void; public function mergeArray(array $settings): void
{
}
/** /**
* Merge with other settings instance. * Merge with other settings instance.
@ -35,6 +37,9 @@ abstract class SettingsAbstract
$defaults = $class->getDefaultProperties(); $defaults = $class->getDefaultProperties();
foreach ($class->getProperties(ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PUBLIC) as $property) { foreach ($class->getProperties(ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PUBLIC) as $property) {
$name = $property->getName(); $name = $property->getName();
if ($name === 'changed') {
continue;
}
$uc = \ucfirst($name); $uc = \ucfirst($name);
if (isset($other->{$name}) if (isset($other->{$name})
&& ( && (

View File

@ -19,6 +19,7 @@
namespace danog\MadelineProto\Wrappers; namespace danog\MadelineProto\Wrappers;
use danog\MadelineProto\Lang;
use danog\MadelineProto\MTProto; use danog\MadelineProto\MTProto;
use danog\MadelineProto\Settings; use danog\MadelineProto\Settings;
@ -41,17 +42,20 @@ trait Start
if ((yield $this->getAuthorization()) === MTProto::LOGGED_IN) { if ((yield $this->getAuthorization()) === MTProto::LOGGED_IN) {
return $this instanceof \danog\MadelineProto\Ipc\Client ? yield from $this->getSelf() : yield from $this->fullGetSelf(); return $this instanceof \danog\MadelineProto\Ipc\Client ? yield from $this->getSelf() : yield from $this->fullGetSelf();
} }
if ($this->getWebTemplate() === 'legacy') {
$this->setWebTemplate((yield $this->getSettings())->getTemplates()->getHtmlTemplate());
}
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
if (\strpos(yield Tools::readLine('Do you want to login as user or bot (u/b)? '), 'b') !== false) { if (\strpos(yield Tools::readLine(Lang::$current_lang['loginChoosePrompt']), 'b') !== false) {
yield from $this->botLogin(yield Tools::readLine('Enter your bot token: ')); yield from $this->botLogin(yield Tools::readLine(Lang::$current_lang['loginBot']));
} else { } else {
yield from $this->phoneLogin(yield Tools::readLine('Enter your phone number: ')); yield from $this->phoneLogin(yield Tools::readLine(Lang::$current_lang['loginUser']));
$authorization = (yield from $this->completePhoneLogin(yield Tools::readLine('Enter the phone code: '))); $authorization = (yield from $this->completePhoneLogin(yield Tools::readLine(Lang::$current_lang['loginUserCode'])));
if ($authorization['_'] === 'account.password') { if ($authorization['_'] === 'account.password') {
$authorization = (yield from $this->complete2faLogin(yield Tools::readLine('Please enter your password (hint '.$authorization['hint'].'): '))); $authorization = (yield from $this->complete2faLogin(yield Tools::readLine(\sprintf(Lang::$current_lang['loginUserPass'], $authorization['hint']))));
} }
if ($authorization['_'] === 'account.needSignup') { if ($authorization['_'] === 'account.needSignup') {
$authorization = (yield from $this->completeSignup(yield Tools::readLine('Please enter your first name: '), yield Tools::readLine('Please enter your last name (can be empty): '))); $authorization = (yield from $this->completeSignup(yield Tools::readLine(Lang::$current_lang['signupFirstName']), yield Tools::readLine(Lang::$current_lang['signupLastName'])));
} }
} }
$this->serialize(); $this->serialize();
@ -69,19 +73,19 @@ trait Start
if (isset($_POST['phone_code'])) { if (isset($_POST['phone_code'])) {
yield from $this->webCompletePhoneLogin(); yield from $this->webCompletePhoneLogin();
} else { } else {
yield from $this->webEcho("You didn't provide a phone code!"); yield from $this->webEcho(Lang::$current_lang['loginNoCode']);
} }
} elseif ((yield $this->getAuthorization()) === MTProto::WAITING_PASSWORD) { } elseif ((yield $this->getAuthorization()) === MTProto::WAITING_PASSWORD) {
if (isset($_POST['password'])) { if (isset($_POST['password'])) {
yield from $this->webComplete2faLogin(); yield from $this->webComplete2faLogin();
} else { } else {
yield from $this->webEcho("You didn't provide the password!"); yield from $this->webEcho(Lang::$current_lang['loginNoPass']);
} }
} elseif ((yield $this->getAuthorization()) === MTProto::WAITING_SIGNUP) { } elseif ((yield $this->getAuthorization()) === MTProto::WAITING_SIGNUP) {
if (isset($_POST['first_name'])) { if (isset($_POST['first_name'])) {
yield from $this->webCompleteSignup(); yield from $this->webCompleteSignup();
} else { } else {
yield from $this->webEcho("You didn't provide the first name!"); yield from $this->webEcho(Lang::$current_lang['loginNoName']);
} }
} }
if ((yield $this->getAuthorization()) === MTProto::LOGGED_IN) { if ((yield $this->getAuthorization()) === MTProto::LOGGED_IN) {
@ -96,9 +100,9 @@ trait Start
yield from $this->phoneLogin($_POST['phone_number']); yield from $this->phoneLogin($_POST['phone_number']);
yield from $this->webEcho(); yield from $this->webEcho();
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
private function webCompletePhoneLogin(): \Generator private function webCompletePhoneLogin(): \Generator
@ -107,9 +111,9 @@ trait Start
yield from $this->completePhoneLogin($_POST['phone_code']); yield from $this->completePhoneLogin($_POST['phone_code']);
yield from $this->webEcho(); yield from $this->webEcho();
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
private function webComplete2faLogin(): \Generator private function webComplete2faLogin(): \Generator
@ -118,9 +122,9 @@ trait Start
yield from $this->complete2faLogin($_POST['password']); yield from $this->complete2faLogin($_POST['password']);
yield from $this->webEcho(); yield from $this->webEcho();
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
private function webCompleteSignup(): \Generator private function webCompleteSignup(): \Generator
@ -129,9 +133,9 @@ trait Start
yield from $this->completeSignup($_POST['first_name'], isset($_POST['last_name']) ? $_POST['last_name'] : ''); yield from $this->completeSignup($_POST['first_name'], isset($_POST['last_name']) ? $_POST['last_name'] : '');
yield from $this->webEcho(); yield from $this->webEcho();
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
private function webBotLogin(): \Generator private function webBotLogin(): \Generator
@ -140,9 +144,9 @@ trait Start
yield from $this->botLogin($_POST['token']); yield from $this->botLogin($_POST['token']);
yield from $this->webEcho(); yield from $this->webEcho();
} catch (\danog\MadelineProto\RPCErrorException $e) { } catch (\danog\MadelineProto\RPCErrorException $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} catch (\danog\MadelineProto\Exception $e) { } catch (\danog\MadelineProto\Exception $e) {
yield from $this->webEcho('ERROR: '.$e->getMessage().'. Try again.'); yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
} }
} }
} }

View File

@ -20,6 +20,7 @@
namespace danog\MadelineProto\Wrappers; namespace danog\MadelineProto\Wrappers;
use \danog\MadelineProto\MTProto; use \danog\MadelineProto\MTProto;
use danog\MadelineProto\Lang;
use function Amp\ByteStream\getOutputBufferStream; use function Amp\ByteStream\getOutputBufferStream;
trait Templates trait Templates
@ -33,36 +34,48 @@ trait Templates
*/ */
private function webEcho(string $message = ''): \Generator private function webEcho(string $message = ''): \Generator
{ {
$stdout = getOutputBufferStream(); $auth = yield $this->getAuthorization();
switch (yield $this->getAuthorization()) { if ($auth === MTProto::NOT_LOGGED_IN) {
case MTProto::NOT_LOGGED_IN:
if (isset($_POST['type'])) { if (isset($_POST['type'])) {
if ($_POST['type'] === 'phone') { if ($_POST['type'] === 'phone') {
yield $stdout->write($this->webEchoTemplate('Enter your phone number<br><b>'.$message.'</b>', '<input type="text" name="phone_number" placeholder="Phone number" required/>')); $title = \str_replace(':', '', Lang::$current_lang['loginUser']);
$phone = \htmlentities(Lang::$current_lang['loginUserPhoneWeb']);
$form = "<input type='text' name='phone_number' placeholder='$phone' required/>";
} else { } else {
yield $stdout->write($this->webEchoTemplate('Enter your bot token<br><b>'.$message.'</b>', '<input type="text" name="token" placeholder="Bot token" required/>')); $title = \str_replace(':', '', Lang::$current_lang['loginBot']);
$token = \htmlentities(Lang::$current_lang['loginBotTokenWeb']);
$form = "<input type='text' name='token' placeholder='$token' required/>";
} }
} else { } else {
yield $stdout->write($this->webEchoTemplate('Do you want to login as user or bot?<br><b>'.$message.'</b>', '<select name="type"><option value="phone">User</option><option value="bot">Bot</option></select>')); $title = Lang::$current_lang['loginChoosePromptWeb'];
$optionBot = \htmlentities(Lang::$current_lang['loginOptionBot']);
$optionUser = \htmlentities(Lang::$current_lang['loginOptionUser']);
$form = "<select name='type'><option value='phone'>$optionUser</option><option value='bot'>$optionBot</option></select>";
} }
break; } elseif ($auth === MTProto::WAITING_CODE) {
case MTProto::WAITING_CODE: $title = \str_replace(':', '', Lang::$current_lang['loginUserCode']);
yield $stdout->write($this->webEchoTemplate('Enter your code<br><b>'.$message.'</b>', '<input type="text" name="phone_code" placeholder="Phone code" required/>')); $phone = \htmlentities(Lang::$current_lang['loginUserPhoneCodeWeb']);
break; $form = "<input type='text' name='phone_code' placeholder='$phone' required/>";
case MTProto::WAITING_PASSWORD: } elseif ($auth === MTProto::WAITING_PASSWORD) {
yield $stdout->write($this->webEchoTemplate('Enter your password<br><b>'.$message.'</b>', '<input type="password" name="password" placeholder="Hint: '.$this->authorization['hint'].'" required/>')); $title = Lang::$current_lang['loginUserPassWeb'];
break; $hint = \htmlentities(\sprintf(Lang::$current_lang['loginUserPassHint'], $this->authorization['hint']));
case MTProto::WAITING_SIGNUP: $form = "<input type='password' name='password' placeholder='$hint' required/>";
yield $stdout->write($this->webEchoTemplate('Sign up please<br><b>'.$message.'</b>', '<input type="text" name="first_name" placeholder="First name" required/><input type="text" name="last_name" placeholder="Last name"/>')); } elseif ($auth === MTProto::WAITING_SIGNUP) {
break; $title = Lang::$current_lang['signupWeb'];
$firstName = Lang::$current_lang['signupFirstNameWeb'];
$lastName = Lang::$current_lang['signupLastNameWeb'];
$form = "<input type='text' name='first_name' placeholder='$firstName' required/><input type='text' name='last_name' placeholder='$lastName'/>";
} }
$title = \htmlentities($title);
$message = \htmlentities($message);
return getOutputBufferStream()->write($this->webEchoTemplate("$title<br><b>$message</b>", $form));
} }
/** /**
* Web template. * Web template.
* *
* @var string * @var string
*/ */
private $web_template = '<!DOCTYPE html><html><head><title>MadelineProto</title></head><body><h1>MadelineProto</h1><form method="POST">%s<button type="submit"/>Go</button></form><p>%s</p></body></html>'; private $webTemplate = 'legacy';
/** /**
* Format message according to template. * Format message according to template.
* *
@ -73,7 +86,7 @@ trait Templates
*/ */
private function webEchoTemplate(string $message, string $form): string private function webEchoTemplate(string $message, string $form): string
{ {
return \sprintf($this->web_template, $form, $message); return \sprintf($this->webTemplate, $message, $form, Lang::$current_lang['go']);
} }
/** /**
* Get web template. * Get web template.
@ -82,7 +95,7 @@ trait Templates
*/ */
public function getWebTemplate(): string public function getWebTemplate(): string
{ {
return $this->web_template; return $this->webTemplate;
} }
/** /**
* Set web template. * Set web template.
@ -93,6 +106,6 @@ trait Templates
*/ */
public function setWebTemplate(string $template): void public function setWebTemplate(string $template): void
{ {
$this->web_template = $template; $this->webTemplate = $template;
} }
} }